Michael Merickel
2018-10-15 0c29cf2df41600d3906d521c72991c7686018b71
commit | author | age
5e3439 1 import os
5bf23f 2 import unittest
CM 3 from pyramid import testing
4
dd3cc8 5 from . import IDummy
49f082 6
dd3cc8 7 from . import dummy_view
b2fbe5 8
0c29cf 9 from pyramid.compat import im_func, text_
79ef3d 10 from pyramid.exceptions import ConfigurationError
CM 11 from pyramid.exceptions import ConfigurationExecutionError
12 from pyramid.exceptions import ConfigurationConflictError
13
0c29cf 14
49f082 15 class TestViewsConfigurationMixin(unittest.TestCase):
CM 16     def _makeOne(self, *arg, **kw):
17         from pyramid.config import Configurator
0c29cf 18
49f082 19         config = Configurator(*arg, **kw)
313c25 20         config.set_default_csrf_options(require_csrf=False)
49f082 21         return config
CM 22
0c29cf 23     def _getViewCallable(
MM 24         self,
25         config,
26         ctx_iface=None,
27         exc_iface=None,
28         request_iface=None,
29         name='',
30     ):
49f082 31         from zope.interface import Interface
CM 32         from pyramid.interfaces import IRequest
33         from pyramid.interfaces import IView
34         from pyramid.interfaces import IViewClassifier
35         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 36
e8c66a 37         if exc_iface:
49f082 38             classifier = IExceptionViewClassifier
e8c66a 39             ctx_iface = exc_iface
49f082 40         else:
CM 41             classifier = IViewClassifier
42         if ctx_iface is None:
43             ctx_iface = Interface
44         if request_iface is None:
45             request_iface = IRequest
46         return config.registry.adapters.lookup(
0c29cf 47             (classifier, request_iface, ctx_iface),
MM 48             IView,
49             name=name,
50             default=None,
51         )
49f082 52
CM 53     def _registerRenderer(self, config, name='.txt'):
54         from pyramid.interfaces import IRendererFactory
0c29cf 55
49f082 56         class Renderer:
CM 57             def __init__(self, info):
58                 self.__class__.info = info
0c29cf 59
49f082 60             def __call__(self, *arg):
42afb0 61                 return b'Hello!'
0c29cf 62
49f082 63         config.registry.registerUtility(Renderer, IRendererFactory, name=name)
CM 64         return Renderer
65
66     def _makeRequest(self, config):
67         request = DummyRequest()
68         request.registry = config.registry
69         return request
70
71     def _assertNotFound(self, wrapper, *arg):
72         from pyramid.httpexceptions import HTTPNotFound
0c29cf 73
49f082 74         self.assertRaises(HTTPNotFound, wrapper, *arg)
CM 75
76     def _getRouteRequestIface(self, config, name):
77         from pyramid.interfaces import IRouteRequest
0c29cf 78
49f082 79         iface = config.registry.getUtility(IRouteRequest, name)
CM 80         return iface
81
6cc22a 82     def _assertRoute(self, config, name, path, num_predicates=0):
CM 83         from pyramid.interfaces import IRoutesMapper
0c29cf 84
6cc22a 85         mapper = config.registry.getUtility(IRoutesMapper)
CM 86         routes = mapper.get_routes()
87         route = routes[0]
88         self.assertEqual(len(routes), 1)
89         self.assertEqual(route.name, name)
90         self.assertEqual(route.path, path)
91         self.assertEqual(len(routes[0].predicates), num_predicates)
92         return route
93
49f082 94     def test_add_view_view_callable_None_no_renderer(self):
CM 95         config = self._makeOne(autocommit=True)
96         self.assertRaises(ConfigurationError, config.add_view)
97
98     def test_add_view_with_request_type_and_route_name(self):
99         config = self._makeOne(autocommit=True)
100         view = lambda *arg: 'OK'
0c29cf 101         self.assertRaises(
MM 102             ConfigurationError,
103             config.add_view,
104             view,
105             '',
106             None,
107             None,
108             True,
109             True,
110         )
49f082 111
CM 112     def test_add_view_with_request_type(self):
113         from pyramid.renderers import null_renderer
114         from zope.interface import directlyProvides
115         from pyramid.interfaces import IRequest
0c29cf 116
49f082 117         view = lambda *arg: 'OK'
CM 118         config = self._makeOne(autocommit=True)
0c29cf 119         config.add_view(
MM 120             view=view,
121             request_type='pyramid.interfaces.IRequest',
122             renderer=null_renderer,
123         )
49f082 124         wrapper = self._getViewCallable(config)
CM 125         request = DummyRequest()
126         self._assertNotFound(wrapper, None, request)
127         directlyProvides(request, IRequest)
128         result = wrapper(None, request)
129         self.assertEqual(result, 'OK')
130
131     def test_add_view_view_callable_None_with_renderer(self):
132         config = self._makeOne(autocommit=True)
133         self._registerRenderer(config, name='dummy')
134         config.add_view(renderer='dummy')
135         view = self._getViewCallable(config)
8e606d 136         self.assertTrue(b'Hello!' in view(None, None).body)
49f082 137
3d42aa 138     def test_add_view_with_tmpl_renderer_factory_introspector_missing(self):
CM 139         config = self._makeOne(autocommit=True)
140         config.introspection = False
141         config.introspector = None
142         config.add_view(renderer='dummy.pt')
143         view = self._getViewCallable(config)
144         self.assertRaises(ValueError, view, None, None)
cac23b 145
3d42aa 146     def test_add_view_with_tmpl_renderer_factory_no_renderer_factory(self):
CM 147         config = self._makeOne(autocommit=True)
148         introspector = DummyIntrospector()
149         config.introspector = introspector
150         config.add_view(renderer='dummy.pt')
0c29cf 151         self.assertFalse(
MM 152             ('renderer factories', '.pt') in introspector.related[-1]
153         )
3d42aa 154         view = self._getViewCallable(config)
CM 155         self.assertRaises(ValueError, view, None, None)
156
157     def test_add_view_with_tmpl_renderer_factory_with_renderer_factory(self):
158         config = self._makeOne(autocommit=True)
159         introspector = DummyIntrospector(True)
160         config.introspector = introspector
0c29cf 161
3d42aa 162         def dummy_factory(helper):
CM 163             return lambda val, system_vals: 'Hello!'
0c29cf 164
3d42aa 165         config.add_renderer('.pt', dummy_factory)
CM 166         config.add_view(renderer='dummy.pt')
167         self.assertTrue(
0c29cf 168             ('renderer factories', '.pt') in introspector.related[-1]
MM 169         )
3d42aa 170         view = self._getViewCallable(config)
CM 171         self.assertTrue(b'Hello!' in view(None, None).body)
cac23b 172
49f082 173     def test_add_view_wrapped_view_is_decorated(self):
0c29cf 174         def view(request):  # request-only wrapper
49f082 175             """ """
0c29cf 176
49f082 177         config = self._makeOne(autocommit=True)
CM 178         config.add_view(view=view)
179         wrapper = self._getViewCallable(config)
180         self.assertEqual(wrapper.__module__, view.__module__)
181         self.assertEqual(wrapper.__name__, view.__name__)
182         self.assertEqual(wrapper.__doc__, view.__doc__)
0c29cf 183         self.assertEqual(
MM 184             wrapper.__discriminator__(None, None).resolve()[0], 'view'
185         )
49f082 186
CM 187     def test_add_view_view_callable_dottedname(self):
188         from pyramid.renderers import null_renderer
0c29cf 189
49f082 190         config = self._makeOne(autocommit=True)
0c29cf 191         config.add_view(
MM 192             view='tests.test_config.dummy_view', renderer=null_renderer
193         )
49f082 194         wrapper = self._getViewCallable(config)
CM 195         self.assertEqual(wrapper(None, None), 'OK')
196
197     def test_add_view_with_function_callable(self):
198         from pyramid.renderers import null_renderer
0c29cf 199
49f082 200         view = lambda *arg: 'OK'
CM 201         config = self._makeOne(autocommit=True)
202         config.add_view(view=view, renderer=null_renderer)
203         wrapper = self._getViewCallable(config)
204         result = wrapper(None, None)
205         self.assertEqual(result, 'OK')
206
207     def test_add_view_with_function_callable_requestonly(self):
208         from pyramid.renderers import null_renderer
0c29cf 209
49f082 210         def view(request):
CM 211             return 'OK'
0c29cf 212
49f082 213         config = self._makeOne(autocommit=True)
CM 214         config.add_view(view=view, renderer=null_renderer)
215         wrapper = self._getViewCallable(config)
216         result = wrapper(None, None)
217         self.assertEqual(result, 'OK')
218
3c59ce 219     def test_add_view_with_name(self):
CM 220         from pyramid.renderers import null_renderer
0c29cf 221
3c59ce 222         view = lambda *arg: 'OK'
CM 223         config = self._makeOne(autocommit=True)
224         config.add_view(view=view, name='abc', renderer=null_renderer)
225         wrapper = self._getViewCallable(config, name='abc')
226         result = wrapper(None, None)
227         self.assertEqual(result, 'OK')
228
229     def test_add_view_with_name_unicode(self):
230         from pyramid.renderers import null_renderer
0c29cf 231
3c59ce 232         view = lambda *arg: 'OK'
CM 233         config = self._makeOne(autocommit=True)
234         name = text_(b'La Pe\xc3\xb1a', 'utf-8')
235         config.add_view(view=view, name=name, renderer=null_renderer)
236         wrapper = self._getViewCallable(config, name=name)
237         result = wrapper(None, None)
238         self.assertEqual(result, 'OK')
239
49f082 240     def test_add_view_with_decorator(self):
CM 241         from pyramid.renderers import null_renderer
0c29cf 242
49f082 243         def view(request):
CM 244             """ ABC """
245             return 'OK'
0c29cf 246
49f082 247         def view_wrapper(fn):
CM 248             def inner(context, request):
249                 return fn(context, request)
0c29cf 250
49f082 251             return inner
0c29cf 252
49f082 253         config = self._makeOne(autocommit=True)
0c29cf 254         config.add_view(
MM 255             view=view, decorator=view_wrapper, renderer=null_renderer
256         )
49f082 257         wrapper = self._getViewCallable(config)
CM 258         self.assertFalse(wrapper is view)
259         self.assertEqual(wrapper.__doc__, view.__doc__)
260         result = wrapper(None, None)
261         self.assertEqual(result, 'OK')
262
76c9c2 263     def test_add_view_with_decorator_tuple(self):
R 264         from pyramid.renderers import null_renderer
0c29cf 265
76c9c2 266         def view(request):
R 267             """ ABC """
268             return 'OK'
0c29cf 269
76c9c2 270         def view_wrapper1(fn):
R 271             def inner(context, request):
272                 return 'wrapped1' + fn(context, request)
0c29cf 273
76c9c2 274             return inner
0c29cf 275
76c9c2 276         def view_wrapper2(fn):
R 277             def inner(context, request):
278                 return 'wrapped2' + fn(context, request)
0c29cf 279
76c9c2 280             return inner
0c29cf 281
76c9c2 282         config = self._makeOne(autocommit=True)
0c29cf 283         config.add_view(
MM 284             view=view,
285             decorator=(view_wrapper2, view_wrapper1),
286             renderer=null_renderer,
287         )
76c9c2 288         wrapper = self._getViewCallable(config)
R 289         self.assertFalse(wrapper is view)
290         self.assertEqual(wrapper.__doc__, view.__doc__)
291         result = wrapper(None, None)
292         self.assertEqual(result, 'wrapped2wrapped1OK')
293
49f082 294     def test_add_view_with_http_cache(self):
CM 295         import datetime
296         from pyramid.response import Response
0c29cf 297
49f082 298         response = Response('OK')
0c29cf 299
49f082 300         def view(request):
CM 301             """ ABC """
302             return response
0c29cf 303
49f082 304         config = self._makeOne(autocommit=True)
0c29cf 305         config.add_view(view=view, http_cache=(86400, {'public': True}))
49f082 306         wrapper = self._getViewCallable(config)
CM 307         self.assertFalse(wrapper is view)
308         self.assertEqual(wrapper.__doc__, view.__doc__)
309         request = testing.DummyRequest()
310         when = datetime.datetime.utcnow() + datetime.timedelta(days=1)
311         result = wrapper(None, request)
312         self.assertEqual(result, response)
313         headers = dict(response.headerlist)
314         self.assertEqual(headers['Cache-Control'], 'max-age=86400, public')
315         expires = parse_httpdate(headers['Expires'])
316         assert_similar_datetime(expires, when)
317
318     def test_add_view_as_instance(self):
319         from pyramid.renderers import null_renderer
0c29cf 320
49f082 321         class AView:
CM 322             def __call__(self, context, request):
323                 """ """
324                 return 'OK'
0c29cf 325
49f082 326         view = AView()
CM 327         config = self._makeOne(autocommit=True)
328         config.add_view(view=view, renderer=null_renderer)
329         wrapper = self._getViewCallable(config)
330         result = wrapper(None, None)
331         self.assertEqual(result, 'OK')
332
df3bea 333     def test_add_view_as_instancemethod(self):
H 334         from pyramid.renderers import null_renderer
0c29cf 335
df3bea 336         class View:
4a6f53 337             def index(self, context, request):
CM 338                 return 'OK'
0c29cf 339
df3bea 340         view = View()
0c29cf 341         config = self._makeOne(autocommit=True)
df3bea 342         config.add_view(view=view.index, renderer=null_renderer)
4a6f53 343         wrapper = self._getViewCallable(config)
CM 344         result = wrapper(None, None)
345         self.assertEqual(result, 'OK')
df3bea 346
6c1597 347     def test_add_view_as_instancemethod_requestonly(self):
CM 348         from pyramid.renderers import null_renderer
0c29cf 349
6c1597 350         class View:
CM 351             def index(self, request):
352                 return 'OK'
0c29cf 353
6c1597 354         view = View()
0c29cf 355         config = self._makeOne(autocommit=True)
6c1597 356         config.add_view(view=view.index, renderer=null_renderer)
CM 357         wrapper = self._getViewCallable(config)
358         result = wrapper(None, None)
359         self.assertEqual(result, 'OK')
42afb0 360
49f082 361     def test_add_view_as_instance_requestonly(self):
CM 362         from pyramid.renderers import null_renderer
0c29cf 363
49f082 364         class AView:
CM 365             def __call__(self, request):
366                 """ """
367                 return 'OK'
0c29cf 368
49f082 369         view = AView()
CM 370         config = self._makeOne(autocommit=True)
371         config.add_view(view=view, renderer=null_renderer)
372         wrapper = self._getViewCallable(config)
373         result = wrapper(None, None)
374         self.assertEqual(result, 'OK')
375
376     def test_add_view_as_oldstyle_class(self):
377         from pyramid.renderers import null_renderer
0c29cf 378
49f082 379         class view:
CM 380             def __init__(self, context, request):
381                 self.context = context
382                 self.request = request
383
384             def __call__(self):
385                 return 'OK'
0c29cf 386
49f082 387         config = self._makeOne(autocommit=True)
CM 388         config.add_view(view=view, renderer=null_renderer)
389         wrapper = self._getViewCallable(config)
390         request = self._makeRequest(config)
391         result = wrapper(None, request)
392         self.assertEqual(result, 'OK')
393         self.assertEqual(request.__view__.__class__, view)
394
395     def test_add_view_as_oldstyle_class_requestonly(self):
396         from pyramid.renderers import null_renderer
0c29cf 397
49f082 398         class view:
CM 399             def __init__(self, request):
400                 self.request = request
401
402             def __call__(self):
403                 return 'OK'
0c29cf 404
49f082 405         config = self._makeOne(autocommit=True)
CM 406         config.add_view(view=view, renderer=null_renderer)
407         wrapper = self._getViewCallable(config)
408
409         request = self._makeRequest(config)
410         result = wrapper(None, request)
411         self.assertEqual(result, 'OK')
412         self.assertEqual(request.__view__.__class__, view)
413
414     def test_add_view_context_as_class(self):
415         from pyramid.renderers import null_renderer
416         from zope.interface import implementedBy
0c29cf 417
49f082 418         view = lambda *arg: 'OK'
0c29cf 419
49f082 420         class Foo:
CM 421             pass
0c29cf 422
49f082 423         config = self._makeOne(autocommit=True)
CM 424         config.add_view(context=Foo, view=view, renderer=null_renderer)
425         foo = implementedBy(Foo)
426         wrapper = self._getViewCallable(config, foo)
427         self.assertEqual(wrapper, view)
428
429     def test_add_view_context_as_iface(self):
430         from pyramid.renderers import null_renderer
0c29cf 431
49f082 432         view = lambda *arg: 'OK'
CM 433         config = self._makeOne(autocommit=True)
434         config.add_view(context=IDummy, view=view, renderer=null_renderer)
435         wrapper = self._getViewCallable(config, IDummy)
436         self.assertEqual(wrapper, view)
437
438     def test_add_view_context_as_dottedname(self):
439         from pyramid.renderers import null_renderer
0c29cf 440
49f082 441         view = lambda *arg: 'OK'
CM 442         config = self._makeOne(autocommit=True)
0c29cf 443         config.add_view(
MM 444             context='tests.test_config.IDummy',
445             view=view,
446             renderer=null_renderer,
447         )
49f082 448         wrapper = self._getViewCallable(config, IDummy)
CM 449         self.assertEqual(wrapper, view)
450
451     def test_add_view_for__as_dottedname(self):
452         from pyramid.renderers import null_renderer
0c29cf 453
49f082 454         view = lambda *arg: 'OK'
CM 455         config = self._makeOne(autocommit=True)
0c29cf 456         config.add_view(
MM 457             for_='tests.test_config.IDummy', view=view, renderer=null_renderer
458         )
49f082 459         wrapper = self._getViewCallable(config, IDummy)
CM 460         self.assertEqual(wrapper, view)
461
462     def test_add_view_for_as_class(self):
463         # ``for_`` is older spelling for ``context``
464         from pyramid.renderers import null_renderer
465         from zope.interface import implementedBy
0c29cf 466
49f082 467         view = lambda *arg: 'OK'
0c29cf 468
49f082 469         class Foo:
CM 470             pass
0c29cf 471
49f082 472         config = self._makeOne(autocommit=True)
CM 473         config.add_view(for_=Foo, view=view, renderer=null_renderer)
474         foo = implementedBy(Foo)
475         wrapper = self._getViewCallable(config, foo)
476         self.assertEqual(wrapper, view)
477
478     def test_add_view_for_as_iface(self):
479         # ``for_`` is older spelling for ``context``
480         from pyramid.renderers import null_renderer
0c29cf 481
49f082 482         view = lambda *arg: 'OK'
CM 483         config = self._makeOne(autocommit=True)
484         config.add_view(for_=IDummy, view=view, renderer=null_renderer)
485         wrapper = self._getViewCallable(config, IDummy)
486         self.assertEqual(wrapper, view)
487
488     def test_add_view_context_trumps_for(self):
489         # ``for_`` is older spelling for ``context``
490         from pyramid.renderers import null_renderer
0c29cf 491
49f082 492         view = lambda *arg: 'OK'
CM 493         config = self._makeOne(autocommit=True)
0c29cf 494
49f082 495         class Foo:
CM 496             pass
0c29cf 497
MM 498         config.add_view(
499             context=IDummy, for_=Foo, view=view, renderer=null_renderer
500         )
49f082 501         wrapper = self._getViewCallable(config, IDummy)
CM 502         self.assertEqual(wrapper, view)
503
504     def test_add_view_register_secured_view(self):
505         from pyramid.renderers import null_renderer
506         from zope.interface import Interface
507         from pyramid.interfaces import IRequest
508         from pyramid.interfaces import ISecuredView
509         from pyramid.interfaces import IViewClassifier
0c29cf 510
49f082 511         view = lambda *arg: 'OK'
CM 512         view.__call_permissive__ = view
513         config = self._makeOne(autocommit=True)
514         config.add_view(view=view, renderer=null_renderer)
515         wrapper = config.registry.adapters.lookup(
516             (IViewClassifier, IRequest, Interface),
0c29cf 517             ISecuredView,
MM 518             name='',
519             default=None,
520         )
49f082 521         self.assertEqual(wrapper, view)
CM 522
523     def test_add_view_exception_register_secured_view(self):
524         from pyramid.renderers import null_renderer
525         from zope.interface import implementedBy
526         from pyramid.interfaces import IRequest
527         from pyramid.interfaces import IView
528         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 529
49f082 530         view = lambda *arg: 'OK'
CM 531         view.__call_permissive__ = view
532         config = self._makeOne(autocommit=True)
0c29cf 533         config.add_view(
MM 534             view=view, context=RuntimeError, renderer=null_renderer
535         )
49f082 536         wrapper = config.registry.adapters.lookup(
CM 537             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 538             IView,
MM 539             name='',
540             default=None,
541         )
49f082 542         self.assertEqual(wrapper, view)
CM 543
544     def test_add_view_same_phash_overrides_existing_single_view(self):
545         from pyramid.renderers import null_renderer
546         from hashlib import md5
547         from zope.interface import Interface
548         from pyramid.interfaces import IRequest
549         from pyramid.interfaces import IView
550         from pyramid.interfaces import IViewClassifier
551         from pyramid.interfaces import IMultiView
0c29cf 552
49f082 553         phash = md5()
4d2602 554         phash.update(b'xhr = True')
49f082 555         view = lambda *arg: 'NOT OK'
CM 556         view.__phash__ = phash.hexdigest()
557         config = self._makeOne(autocommit=True)
558         config.registry.registerAdapter(
0c29cf 559             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 560         )
561
49f082 562         def newview(context, request):
CM 563             return 'OK'
0c29cf 564
49f082 565         config.add_view(view=newview, xhr=True, renderer=null_renderer)
CM 566         wrapper = self._getViewCallable(config)
567         self.assertFalse(IMultiView.providedBy(wrapper))
568         request = DummyRequest()
569         request.is_xhr = True
570         self.assertEqual(wrapper(None, request), 'OK')
571
572     def test_add_view_exc_same_phash_overrides_existing_single_view(self):
573         from pyramid.renderers import null_renderer
574         from hashlib import md5
575         from zope.interface import implementedBy
576         from pyramid.interfaces import IRequest
577         from pyramid.interfaces import IView
578         from pyramid.interfaces import IExceptionViewClassifier
579         from pyramid.interfaces import IMultiView
0c29cf 580
49f082 581         phash = md5()
4d2602 582         phash.update(b'xhr = True')
49f082 583         view = lambda *arg: 'NOT OK'
CM 584         view.__phash__ = phash.hexdigest()
585         config = self._makeOne(autocommit=True)
586         config.registry.registerAdapter(
587             view,
588             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 589             IView,
MM 590             name='',
591         )
592
49f082 593         def newview(context, request):
CM 594             return 'OK'
0c29cf 595
MM 596         config.add_view(
597             view=newview,
598             xhr=True,
599             context=RuntimeError,
600             renderer=null_renderer,
601         )
49f082 602         wrapper = self._getViewCallable(
0c29cf 603             config, exc_iface=implementedBy(RuntimeError)
MM 604         )
49f082 605         self.assertFalse(IMultiView.providedBy(wrapper))
CM 606         request = DummyRequest()
607         request.is_xhr = True
608         self.assertEqual(wrapper(None, request), 'OK')
609
610     def test_add_view_default_phash_overrides_no_phash(self):
611         from pyramid.renderers import null_renderer
612         from zope.interface import Interface
613         from pyramid.interfaces import IRequest
614         from pyramid.interfaces import IView
615         from pyramid.interfaces import IViewClassifier
616         from pyramid.interfaces import IMultiView
0c29cf 617
49f082 618         view = lambda *arg: 'NOT OK'
CM 619         config = self._makeOne(autocommit=True)
620         config.registry.registerAdapter(
0c29cf 621             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 622         )
623
49f082 624         def newview(context, request):
CM 625             return 'OK'
0c29cf 626
49f082 627         config.add_view(view=newview, renderer=null_renderer)
CM 628         wrapper = self._getViewCallable(config)
629         self.assertFalse(IMultiView.providedBy(wrapper))
630         request = DummyRequest()
631         request.is_xhr = True
632         self.assertEqual(wrapper(None, request), 'OK')
633
634     def test_add_view_exc_default_phash_overrides_no_phash(self):
635         from pyramid.renderers import null_renderer
636         from zope.interface import implementedBy
637         from pyramid.interfaces import IRequest
638         from pyramid.interfaces import IView
639         from pyramid.interfaces import IExceptionViewClassifier
640         from pyramid.interfaces import IMultiView
0c29cf 641
49f082 642         view = lambda *arg: 'NOT OK'
CM 643         config = self._makeOne(autocommit=True)
644         config.registry.registerAdapter(
645             view,
646             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 647             IView,
MM 648             name='',
649         )
650
49f082 651         def newview(context, request):
CM 652             return 'OK'
0c29cf 653
MM 654         config.add_view(
655             view=newview, context=RuntimeError, renderer=null_renderer
656         )
49f082 657         wrapper = self._getViewCallable(
0c29cf 658             config, exc_iface=implementedBy(RuntimeError)
MM 659         )
49f082 660         self.assertFalse(IMultiView.providedBy(wrapper))
CM 661         request = DummyRequest()
662         request.is_xhr = True
663         self.assertEqual(wrapper(None, request), 'OK')
664
665     def test_add_view_default_phash_overrides_default_phash(self):
666         from pyramid.config.util import DEFAULT_PHASH
52fde9 667         from pyramid.renderers import null_renderer
49f082 668         from zope.interface import Interface
CM 669         from pyramid.interfaces import IRequest
670         from pyramid.interfaces import IView
671         from pyramid.interfaces import IViewClassifier
672         from pyramid.interfaces import IMultiView
0c29cf 673
49f082 674         view = lambda *arg: 'NOT OK'
CM 675         view.__phash__ = DEFAULT_PHASH
676         config = self._makeOne(autocommit=True)
677         config.registry.registerAdapter(
0c29cf 678             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 679         )
680
49f082 681         def newview(context, request):
CM 682             return 'OK'
0c29cf 683
49f082 684         config.add_view(view=newview, renderer=null_renderer)
CM 685         wrapper = self._getViewCallable(config)
686         self.assertFalse(IMultiView.providedBy(wrapper))
687         request = DummyRequest()
688         request.is_xhr = True
689         self.assertEqual(wrapper(None, request), 'OK')
690
691     def test_add_view_exc_default_phash_overrides_default_phash(self):
692         from pyramid.config.util import DEFAULT_PHASH
52fde9 693         from pyramid.renderers import null_renderer
49f082 694         from zope.interface import implementedBy
CM 695         from pyramid.interfaces import IRequest
696         from pyramid.interfaces import IView
697         from pyramid.interfaces import IExceptionViewClassifier
698         from pyramid.interfaces import IMultiView
0c29cf 699
49f082 700         view = lambda *arg: 'NOT OK'
CM 701         view.__phash__ = DEFAULT_PHASH
702         config = self._makeOne(autocommit=True)
703         config.registry.registerAdapter(
704             view,
705             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 706             IView,
MM 707             name='',
708         )
709
49f082 710         def newview(context, request):
CM 711             return 'OK'
0c29cf 712
MM 713         config.add_view(
714             view=newview, context=RuntimeError, renderer=null_renderer
715         )
49f082 716         wrapper = self._getViewCallable(
0c29cf 717             config, exc_iface=implementedBy(RuntimeError)
MM 718         )
49f082 719         self.assertFalse(IMultiView.providedBy(wrapper))
CM 720         request = DummyRequest()
721         request.is_xhr = True
722         self.assertEqual(wrapper(None, request), 'OK')
723
724     def test_add_view_multiview_replaces_existing_view(self):
725         from pyramid.renderers import null_renderer
726         from zope.interface import Interface
727         from pyramid.interfaces import IRequest
728         from pyramid.interfaces import IView
729         from pyramid.interfaces import IViewClassifier
730         from pyramid.interfaces import IMultiView
0c29cf 731
49f082 732         view = lambda *arg: 'OK'
CM 733         view.__phash__ = 'abc'
734         config = self._makeOne(autocommit=True)
735         config.registry.registerAdapter(
0c29cf 736             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 737         )
49f082 738         config.add_view(view=view, renderer=null_renderer)
CM 739         wrapper = self._getViewCallable(config)
740         self.assertTrue(IMultiView.providedBy(wrapper))
741         self.assertEqual(wrapper(None, None), 'OK')
742
743     def test_add_view_exc_multiview_replaces_existing_view(self):
744         from pyramid.renderers import null_renderer
745         from zope.interface import implementedBy
746         from pyramid.interfaces import IRequest
747         from pyramid.interfaces import IView
748         from pyramid.interfaces import IExceptionViewClassifier
749         from pyramid.interfaces import IViewClassifier
750         from pyramid.interfaces import IMultiView
0c29cf 751
49f082 752         view = lambda *arg: 'OK'
CM 753         view.__phash__ = 'abc'
754         config = self._makeOne(autocommit=True)
755         config.registry.registerAdapter(
756             view,
757             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 758             IView,
MM 759             name='',
760         )
49f082 761         config.registry.registerAdapter(
CM 762             view,
763             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 764             IView,
MM 765             name='',
766         )
767         config.add_view(
768             view=view, context=RuntimeError, renderer=null_renderer
769         )
49f082 770         wrapper = self._getViewCallable(
0c29cf 771             config, exc_iface=implementedBy(RuntimeError)
MM 772         )
49f082 773         self.assertTrue(IMultiView.providedBy(wrapper))
CM 774         self.assertEqual(wrapper(None, None), 'OK')
775
776     def test_add_view_multiview_replaces_existing_securedview(self):
777         from pyramid.renderers import null_renderer
778         from zope.interface import Interface
779         from pyramid.interfaces import IRequest
780         from pyramid.interfaces import ISecuredView
781         from pyramid.interfaces import IMultiView
782         from pyramid.interfaces import IViewClassifier
0c29cf 783
49f082 784         view = lambda *arg: 'OK'
CM 785         view.__phash__ = 'abc'
786         config = self._makeOne(autocommit=True)
787         config.registry.registerAdapter(
0c29cf 788             view, (IViewClassifier, IRequest, Interface), ISecuredView, name=''
MM 789         )
49f082 790         config.add_view(view=view, renderer=null_renderer)
CM 791         wrapper = self._getViewCallable(config)
792         self.assertTrue(IMultiView.providedBy(wrapper))
793         self.assertEqual(wrapper(None, None), 'OK')
794
795     def test_add_view_exc_multiview_replaces_existing_securedview(self):
796         from pyramid.renderers import null_renderer
797         from zope.interface import implementedBy
798         from pyramid.interfaces import IRequest
799         from pyramid.interfaces import ISecuredView
800         from pyramid.interfaces import IMultiView
801         from pyramid.interfaces import IViewClassifier
802         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 803
49f082 804         view = lambda *arg: 'OK'
CM 805         view.__phash__ = 'abc'
806         config = self._makeOne(autocommit=True)
807         config.registry.registerAdapter(
808             view,
809             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 810             ISecuredView,
MM 811             name='',
812         )
49f082 813         config.registry.registerAdapter(
CM 814             view,
815             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 816             ISecuredView,
MM 817             name='',
818         )
819         config.add_view(
820             view=view, context=RuntimeError, renderer=null_renderer
821         )
49f082 822         wrapper = self._getViewCallable(
0c29cf 823             config, exc_iface=implementedBy(RuntimeError)
MM 824         )
49f082 825         self.assertTrue(IMultiView.providedBy(wrapper))
CM 826         self.assertEqual(wrapper(None, None), 'OK')
827
828     def test_add_view_with_accept_multiview_replaces_existing_view(self):
829         from pyramid.renderers import null_renderer
830         from zope.interface import Interface
831         from pyramid.interfaces import IRequest
832         from pyramid.interfaces import IView
833         from pyramid.interfaces import IMultiView
834         from pyramid.interfaces import IViewClassifier
0c29cf 835
49f082 836         def view(context, request):
CM 837             return 'OK'
0c29cf 838
49f082 839         def view2(context, request):
CM 840             return 'OK2'
0c29cf 841
49f082 842         config = self._makeOne(autocommit=True)
CM 843         config.registry.registerAdapter(
0c29cf 844             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 845         )
49f082 846         config.add_view(view=view2, accept='text/html', renderer=null_renderer)
CM 847         wrapper = self._getViewCallable(config)
848         self.assertTrue(IMultiView.providedBy(wrapper))
849         self.assertEqual(len(wrapper.views), 1)
850         self.assertEqual(len(wrapper.media_views), 1)
851         self.assertEqual(wrapper(None, None), 'OK')
852         request = DummyRequest()
853         request.accept = DummyAccept('text/html', 'text/html')
854         self.assertEqual(wrapper(None, request), 'OK2')
855
34f00a 856     def test_add_view_mixed_case_replaces_existing_view(self):
LMC 857         from pyramid.renderers import null_renderer
0c29cf 858
MM 859         def view(context, request):
860             return 'OK'
861
862         def view2(context, request):
863             return 'OK2'
864
865         def view3(context, request):
866             return 'OK3'
867
34f00a 868         config = self._makeOne(autocommit=True)
LMC 869         config.add_view(view=view, renderer=null_renderer)
870         config.add_view(view=view2, accept='text/html', renderer=null_renderer)
871         config.add_view(view=view3, accept='text/HTML', renderer=null_renderer)
872         wrapper = self._getViewCallable(config)
873         self.assertTrue(IMultiView.providedBy(wrapper))
0c29cf 874         self.assertEqual(len(wrapper.media_views.items()), 1)
9822a1 875         self.assertFalse('text/HTML' in wrapper.media_views)
34f00a 876         self.assertEqual(wrapper(None, None), 'OK')
LMC 877         request = DummyRequest()
878         request.accept = DummyAccept('text/html', 'text/html')
879         self.assertEqual(wrapper(None, request), 'OK3')
880
8ea3f3 881     def test_add_views_with_accept_multiview_replaces_existing(self):
DN 882         from pyramid.renderers import null_renderer
0c29cf 883
MM 884         def view(context, request):
885             return 'OK'
886
887         def view2(context, request):
888             return 'OK2'
889
890         def view3(context, request):
891             return 'OK3'
892
8ea3f3 893         config = self._makeOne(autocommit=True)
DN 894         config.add_view(view=view, renderer=null_renderer)
895         config.add_view(view=view2, accept='text/html', renderer=null_renderer)
896         config.add_view(view=view3, accept='text/html', renderer=null_renderer)
897         wrapper = self._getViewCallable(config)
f4b7fd 898         self.assertEqual(len(wrapper.media_views['text/html']), 1)
8ea3f3 899         self.assertEqual(wrapper(None, None), 'OK')
DN 900         request = DummyRequest()
901         request.accept = DummyAccept('text/html', 'text/html')
902         self.assertEqual(wrapper(None, request), 'OK3')
903
49f082 904     def test_add_view_exc_with_accept_multiview_replaces_existing_view(self):
CM 905         from pyramid.renderers import null_renderer
906         from zope.interface import implementedBy
907         from pyramid.interfaces import IRequest
908         from pyramid.interfaces import IView
909         from pyramid.interfaces import IMultiView
910         from pyramid.interfaces import IViewClassifier
911         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 912
49f082 913         def view(context, request):
CM 914             return 'OK'
0c29cf 915
49f082 916         def view2(context, request):
CM 917             return 'OK2'
0c29cf 918
49f082 919         config = self._makeOne(autocommit=True)
CM 920         config.registry.registerAdapter(
921             view,
922             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 923             IView,
MM 924             name='',
925         )
49f082 926         config.registry.registerAdapter(
CM 927             view,
928             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 929             IView,
MM 930             name='',
931         )
932         config.add_view(
933             view=view2,
934             accept='text/html',
935             context=RuntimeError,
936             renderer=null_renderer,
937         )
49f082 938         wrapper = self._getViewCallable(
0c29cf 939             config, exc_iface=implementedBy(RuntimeError)
MM 940         )
49f082 941         self.assertTrue(IMultiView.providedBy(wrapper))
CM 942         self.assertEqual(len(wrapper.views), 1)
943         self.assertEqual(len(wrapper.media_views), 1)
944         self.assertEqual(wrapper(None, None), 'OK')
945         request = DummyRequest()
946         request.accept = DummyAccept('text/html', 'text/html')
947         self.assertEqual(wrapper(None, request), 'OK2')
948
949     def test_add_view_multiview_replaces_existing_view_with___accept__(self):
950         from pyramid.renderers import null_renderer
951         from zope.interface import Interface
952         from pyramid.interfaces import IRequest
953         from pyramid.interfaces import IView
954         from pyramid.interfaces import IMultiView
955         from pyramid.interfaces import IViewClassifier
0c29cf 956
49f082 957         def view(context, request):
CM 958             return 'OK'
0c29cf 959
49f082 960         def view2(context, request):
CM 961             return 'OK2'
0c29cf 962
49f082 963         view.__accept__ = 'text/html'
CM 964         view.__phash__ = 'abc'
965         config = self._makeOne(autocommit=True)
966         config.registry.registerAdapter(
0c29cf 967             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 968         )
49f082 969         config.add_view(view=view2, renderer=null_renderer)
CM 970         wrapper = self._getViewCallable(config)
971         self.assertTrue(IMultiView.providedBy(wrapper))
972         self.assertEqual(len(wrapper.views), 1)
973         self.assertEqual(len(wrapper.media_views), 1)
974         self.assertEqual(wrapper(None, None), 'OK2')
975         request = DummyRequest()
976         request.accept = DummyAccept('text/html')
977         self.assertEqual(wrapper(None, request), 'OK')
978
979     def test_add_view_exc_mulview_replaces_existing_view_with___accept__(self):
980         from pyramid.renderers import null_renderer
981         from zope.interface import implementedBy
982         from pyramid.interfaces import IRequest
983         from pyramid.interfaces import IView
984         from pyramid.interfaces import IMultiView
985         from pyramid.interfaces import IViewClassifier
986         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 987
49f082 988         def view(context, request):
CM 989             return 'OK'
0c29cf 990
49f082 991         def view2(context, request):
CM 992             return 'OK2'
0c29cf 993
49f082 994         view.__accept__ = 'text/html'
CM 995         view.__phash__ = 'abc'
996         config = self._makeOne(autocommit=True)
997         config.registry.registerAdapter(
998             view,
999             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1000             IView,
MM 1001             name='',
1002         )
49f082 1003         config.registry.registerAdapter(
CM 1004             view,
1005             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1006             IView,
MM 1007             name='',
1008         )
1009         config.add_view(
1010             view=view2, context=RuntimeError, renderer=null_renderer
1011         )
49f082 1012         wrapper = self._getViewCallable(
0c29cf 1013             config, exc_iface=implementedBy(RuntimeError)
MM 1014         )
49f082 1015         self.assertTrue(IMultiView.providedBy(wrapper))
CM 1016         self.assertEqual(len(wrapper.views), 1)
1017         self.assertEqual(len(wrapper.media_views), 1)
1018         self.assertEqual(wrapper(None, None), 'OK2')
1019         request = DummyRequest()
1020         request.accept = DummyAccept('text/html')
1021         self.assertEqual(wrapper(None, request), 'OK')
1022
1023     def test_add_view_multiview_replaces_multiview(self):
1024         from pyramid.renderers import null_renderer
1025         from zope.interface import Interface
1026         from pyramid.interfaces import IRequest
1027         from pyramid.interfaces import IMultiView
1028         from pyramid.interfaces import IViewClassifier
0c29cf 1029
49f082 1030         view = DummyMultiView()
CM 1031         config = self._makeOne(autocommit=True)
1032         config.registry.registerAdapter(
0c29cf 1033             view, (IViewClassifier, IRequest, Interface), IMultiView, name=''
MM 1034         )
49f082 1035         view2 = lambda *arg: 'OK2'
CM 1036         config.add_view(view=view2, renderer=null_renderer)
1037         wrapper = self._getViewCallable(config)
1038         self.assertTrue(IMultiView.providedBy(wrapper))
0c29cf 1039         self.assertEqual(
MM 1040             [(x[0], x[2]) for x in wrapper.views], [(view2, None)]
1041         )
49f082 1042         self.assertEqual(wrapper(None, None), 'OK1')
CM 1043
e8c66a 1044     def test_add_view_exc_multiview_replaces_multiviews(self):
49f082 1045         from pyramid.renderers import null_renderer
CM 1046         from zope.interface import implementedBy
1047         from pyramid.interfaces import IRequest
1048         from pyramid.interfaces import IMultiView
1049         from pyramid.interfaces import IViewClassifier
1050         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 1051
e8c66a 1052         hot_view = DummyMultiView()
MM 1053         exc_view = DummyMultiView()
49f082 1054         config = self._makeOne(autocommit=True)
CM 1055         config.registry.registerAdapter(
e8c66a 1056             hot_view,
49f082 1057             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1058             IMultiView,
MM 1059             name='',
1060         )
49f082 1061         config.registry.registerAdapter(
e8c66a 1062             exc_view,
49f082 1063             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1064             IMultiView,
MM 1065             name='',
1066         )
49f082 1067         view2 = lambda *arg: 'OK2'
0c29cf 1068         config.add_view(
MM 1069             view=view2, context=RuntimeError, renderer=null_renderer
1070         )
e8c66a 1071         hot_wrapper = self._getViewCallable(
0c29cf 1072             config, ctx_iface=implementedBy(RuntimeError)
MM 1073         )
e8c66a 1074         self.assertTrue(IMultiView.providedBy(hot_wrapper))
0c29cf 1075         self.assertEqual(
MM 1076             [(x[0], x[2]) for x in hot_wrapper.views], [(view2, None)]
1077         )
e8c66a 1078         self.assertEqual(hot_wrapper(None, None), 'OK1')
MM 1079
1080         exc_wrapper = self._getViewCallable(
0c29cf 1081             config, exc_iface=implementedBy(RuntimeError)
MM 1082         )
e8c66a 1083         self.assertTrue(IMultiView.providedBy(exc_wrapper))
0c29cf 1084         self.assertEqual(
MM 1085             [(x[0], x[2]) for x in exc_wrapper.views], [(view2, None)]
1086         )
e8c66a 1087         self.assertEqual(exc_wrapper(None, None), 'OK1')
MM 1088
1089     def test_add_view_exc_multiview_replaces_only_exc_multiview(self):
1090         from pyramid.renderers import null_renderer
1091         from zope.interface import implementedBy
1092         from pyramid.interfaces import IRequest
1093         from pyramid.interfaces import IMultiView
1094         from pyramid.interfaces import IViewClassifier
1095         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 1096
e8c66a 1097         hot_view = DummyMultiView()
MM 1098         exc_view = DummyMultiView()
1099         config = self._makeOne(autocommit=True)
1100         config.registry.registerAdapter(
1101             hot_view,
1102             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1103             IMultiView,
MM 1104             name='',
1105         )
e8c66a 1106         config.registry.registerAdapter(
MM 1107             exc_view,
1108             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1109             IMultiView,
MM 1110             name='',
1111         )
e8c66a 1112         view2 = lambda *arg: 'OK2'
0c29cf 1113         config.add_view(
MM 1114             view=view2,
1115             context=RuntimeError,
1116             exception_only=True,
1117             renderer=null_renderer,
1118         )
e8c66a 1119         hot_wrapper = self._getViewCallable(
0c29cf 1120             config, ctx_iface=implementedBy(RuntimeError)
MM 1121         )
e8c66a 1122         self.assertTrue(IMultiView.providedBy(hot_wrapper))
MM 1123         self.assertEqual(len(hot_wrapper.views), 0)
1124         self.assertEqual(hot_wrapper(None, None), 'OK1')
1125
1126         exc_wrapper = self._getViewCallable(
0c29cf 1127             config, exc_iface=implementedBy(RuntimeError)
MM 1128         )
e8c66a 1129         self.assertTrue(IMultiView.providedBy(exc_wrapper))
0c29cf 1130         self.assertEqual(
MM 1131             [(x[0], x[2]) for x in exc_wrapper.views], [(view2, None)]
1132         )
e8c66a 1133         self.assertEqual(exc_wrapper(None, None), 'OK1')
49f082 1134
CM 1135     def test_add_view_multiview_context_superclass_then_subclass(self):
1136         from pyramid.renderers import null_renderer
1137         from zope.interface import Interface
1138         from pyramid.interfaces import IRequest
1139         from pyramid.interfaces import IView
1140         from pyramid.interfaces import IMultiView
1141         from pyramid.interfaces import IViewClassifier
0c29cf 1142
49f082 1143         class ISuper(Interface):
CM 1144             pass
0c29cf 1145
49f082 1146         class ISub(ISuper):
CM 1147             pass
0c29cf 1148
49f082 1149         view = lambda *arg: 'OK'
CM 1150         view2 = lambda *arg: 'OK2'
1151         config = self._makeOne(autocommit=True)
1152         config.registry.registerAdapter(
0c29cf 1153             view, (IViewClassifier, IRequest, ISuper), IView, name=''
MM 1154         )
49f082 1155         config.add_view(view=view2, for_=ISub, renderer=null_renderer)
0c29cf 1156         wrapper = self._getViewCallable(
MM 1157             config, ctx_iface=ISuper, request_iface=IRequest
1158         )
49f082 1159         self.assertFalse(IMultiView.providedBy(wrapper))
CM 1160         self.assertEqual(wrapper(None, None), 'OK')
0c29cf 1161         wrapper = self._getViewCallable(
MM 1162             config, ctx_iface=ISub, request_iface=IRequest
1163         )
49f082 1164         self.assertFalse(IMultiView.providedBy(wrapper))
CM 1165         self.assertEqual(wrapper(None, None), 'OK2')
1166
1167     def test_add_view_multiview_exception_superclass_then_subclass(self):
1168         from pyramid.renderers import null_renderer
1169         from zope.interface import implementedBy
1170         from pyramid.interfaces import IRequest
1171         from pyramid.interfaces import IView
1172         from pyramid.interfaces import IMultiView
1173         from pyramid.interfaces import IViewClassifier
1174         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 1175
49f082 1176         class Super(Exception):
CM 1177             pass
0c29cf 1178
49f082 1179         class Sub(Super):
CM 1180             pass
0c29cf 1181
49f082 1182         view = lambda *arg: 'OK'
CM 1183         view2 = lambda *arg: 'OK2'
1184         config = self._makeOne(autocommit=True)
1185         config.registry.registerAdapter(
0c29cf 1186             view, (IViewClassifier, IRequest, Super), IView, name=''
MM 1187         )
49f082 1188         config.registry.registerAdapter(
0c29cf 1189             view, (IExceptionViewClassifier, IRequest, Super), IView, name=''
MM 1190         )
49f082 1191         config.add_view(view=view2, for_=Sub, renderer=null_renderer)
CM 1192         wrapper = self._getViewCallable(
0c29cf 1193             config, ctx_iface=implementedBy(Super), request_iface=IRequest
MM 1194         )
49f082 1195         wrapper_exc_view = self._getViewCallable(
0c29cf 1196             config, exc_iface=implementedBy(Super), request_iface=IRequest
MM 1197         )
49f082 1198         self.assertEqual(wrapper_exc_view, wrapper)
CM 1199         self.assertFalse(IMultiView.providedBy(wrapper_exc_view))
1200         self.assertEqual(wrapper_exc_view(None, None), 'OK')
1201         wrapper = self._getViewCallable(
0c29cf 1202             config, ctx_iface=implementedBy(Sub), request_iface=IRequest
MM 1203         )
49f082 1204         wrapper_exc_view = self._getViewCallable(
0c29cf 1205             config, exc_iface=implementedBy(Sub), request_iface=IRequest
MM 1206         )
49f082 1207         self.assertEqual(wrapper_exc_view, wrapper)
CM 1208         self.assertFalse(IMultiView.providedBy(wrapper_exc_view))
1209         self.assertEqual(wrapper_exc_view(None, None), 'OK2')
1210
1211     def test_add_view_multiview_call_ordering(self):
1212         from pyramid.renderers import null_renderer as nr
1213         from zope.interface import directlyProvides
0c29cf 1214
MM 1215         def view1(context, request):
1216             return 'view1'
1217
1218         def view2(context, request):
1219             return 'view2'
1220
1221         def view3(context, request):
1222             return 'view3'
1223
1224         def view4(context, request):
1225             return 'view4'
1226
1227         def view5(context, request):
1228             return 'view5'
1229
1230         def view6(context, request):
1231             return 'view6'
1232
1233         def view7(context, request):
1234             return 'view7'
1235
1236         def view8(context, request):
1237             return 'view8'
1238
49f082 1239         config = self._makeOne(autocommit=True)
CM 1240         config.add_view(view=view1, renderer=nr)
1241         config.add_view(view=view2, request_method='POST', renderer=nr)
0c29cf 1242         config.add_view(view=view3, request_param='param', renderer=nr)
49f082 1243         config.add_view(view=view4, containment=IDummy, renderer=nr)
0c29cf 1244         config.add_view(
MM 1245             view=view5,
1246             request_method='POST',
1247             request_param='param',
1248             renderer=nr,
1249         )
1250         config.add_view(
1251             view=view6, request_method='POST', containment=IDummy, renderer=nr
1252         )
1253         config.add_view(
1254             view=view7, request_param='param', containment=IDummy, renderer=nr
1255         )
1256         config.add_view(
1257             view=view8,
1258             request_method='POST',
1259             request_param='param',
1260             containment=IDummy,
1261             renderer=nr,
1262         )
49f082 1263
CM 1264         wrapper = self._getViewCallable(config)
1265
1266         ctx = DummyContext()
1267         request = self._makeRequest(config)
1268         request.method = 'GET'
1269         request.params = {}
1270         self.assertEqual(wrapper(ctx, request), 'view1')
1271
1272         ctx = DummyContext()
1273         request = self._makeRequest(config)
1274         request.params = {}
1275         request.method = 'POST'
1276         self.assertEqual(wrapper(ctx, request), 'view2')
1277
1278         ctx = DummyContext()
1279         request = self._makeRequest(config)
0c29cf 1280         request.params = {'param': '1'}
49f082 1281         request.method = 'GET'
CM 1282         self.assertEqual(wrapper(ctx, request), 'view3')
1283
1284         ctx = DummyContext()
1285         directlyProvides(ctx, IDummy)
1286         request = self._makeRequest(config)
1287         request.method = 'GET'
1288         request.params = {}
1289         self.assertEqual(wrapper(ctx, request), 'view4')
1290
1291         ctx = DummyContext()
1292         request = self._makeRequest(config)
1293         request.method = 'POST'
0c29cf 1294         request.params = {'param': '1'}
49f082 1295         self.assertEqual(wrapper(ctx, request), 'view5')
CM 1296
1297         ctx = DummyContext()
1298         directlyProvides(ctx, IDummy)
1299         request = self._makeRequest(config)
1300         request.params = {}
1301         request.method = 'POST'
1302         self.assertEqual(wrapper(ctx, request), 'view6')
1303
1304         ctx = DummyContext()
1305         directlyProvides(ctx, IDummy)
1306         request = self._makeRequest(config)
1307         request.method = 'GET'
0c29cf 1308         request.params = {'param': '1'}
49f082 1309         self.assertEqual(wrapper(ctx, request), 'view7')
CM 1310
1311         ctx = DummyContext()
1312         directlyProvides(ctx, IDummy)
1313         request = self._makeRequest(config)
1314         request.method = 'POST'
0c29cf 1315         request.params = {'param': '1'}
49f082 1316         self.assertEqual(wrapper(ctx, request), 'view8')
CM 1317
0b03c3 1318     def test_view_with_most_specific_predicate(self):
JA 1319         from pyramid.renderers import null_renderer as nr
1320         from pyramid.router import Router
1321
0c29cf 1322         class OtherBase(object):
MM 1323             pass
1324
1325         class Int1(object):
1326             pass
1327
1328         class Int2(object):
1329             pass
0b03c3 1330
JA 1331         class Resource(OtherBase, Int1, Int2):
0c29cf 1332             def __init__(self, request):
MM 1333                 pass
0b03c3 1334
0c29cf 1335         def unknown(context, request):
MM 1336             return 'unknown'
1337
1338         def view(context, request):
1339             return 'hello'
0b03c3 1340
JA 1341         config = self._makeOne(autocommit=True)
1342         config.add_route('root', '/', factory=Resource)
1343         config.add_view(unknown, route_name='root', renderer=nr)
1344         config.add_view(
0c29cf 1345             view,
MM 1346             renderer=nr,
1347             route_name='root',
1348             context=Int1,
1349             request_method='GET',
0b03c3 1350         )
JA 1351         config.add_view(
0c29cf 1352             view=view,
MM 1353             renderer=nr,
1354             route_name='root',
1355             context=Int2,
1356             request_method='POST',
0b03c3 1357         )
JA 1358         request = self._makeRequest(config)
1359         request.method = 'POST'
1360         request.params = {}
1361         router = Router(config.registry)
1362         response = router.handle_request(request)
1363         self.assertEqual(response, 'hello')
1364
1365     def test_view_with_most_specific_predicate_with_mismatch(self):
1366         from pyramid.renderers import null_renderer as nr
1367         from pyramid.router import Router
1368
0c29cf 1369         class OtherBase(object):
MM 1370             pass
1371
1372         class Int1(object):
1373             pass
1374
1375         class Int2(object):
1376             pass
0b03c3 1377
JA 1378         class Resource(OtherBase, Int1, Int2):
0c29cf 1379             def __init__(self, request):
MM 1380                 pass
0b03c3 1381
0c29cf 1382         def unknown(context, request):
MM 1383             return 'unknown'
1384
1385         def view(context, request):
1386             return 'hello'
0b03c3 1387
JA 1388         config = self._makeOne(autocommit=True)
1389         config.add_route('root', '/', factory=Resource)
1390
1391         config.add_view(
1392             unknown,
1393             route_name='root',
1394             renderer=nr,
1395             request_method=('POST',),
1396             xhr=True,
1397         )
1398
1399         config.add_view(
0c29cf 1400             view,
MM 1401             renderer=nr,
1402             route_name='root',
1403             context=Int1,
1404             request_method='GET',
0b03c3 1405         )
JA 1406         config.add_view(
0c29cf 1407             view=view,
MM 1408             renderer=nr,
1409             route_name='root',
1410             context=Int2,
1411             request_method='POST',
0b03c3 1412         )
JA 1413         request = self._makeRequest(config)
1414         request.method = 'POST'
1415         request.params = {}
1416         router = Router(config.registry)
1417         response = router.handle_request(request)
1418         self.assertEqual(response, 'hello')
1419
ba2a3f 1420     def test_add_view_multiview___discriminator__(self):
CM 1421         from pyramid.renderers import null_renderer
1422         from zope.interface import Interface
0c29cf 1423
ba2a3f 1424         class IFoo(Interface):
CM 1425             pass
0c29cf 1426
ba2a3f 1427         class IBar(Interface):
CM 1428             pass
0c29cf 1429
ba2a3f 1430         @implementer(IFoo)
CM 1431         class Foo(object):
1432             pass
0c29cf 1433
ba2a3f 1434         @implementer(IBar)
CM 1435         class Bar(object):
1436             pass
0c29cf 1437
ba2a3f 1438         foo = Foo()
CM 1439         bar = Bar()
42afb0 1440
ba2a3f 1441         from pyramid.interfaces import IRequest
CM 1442         from pyramid.interfaces import IView
1443         from pyramid.interfaces import IViewClassifier
1444         from pyramid.interfaces import IMultiView
0c29cf 1445
ba2a3f 1446         view = lambda *arg: 'OK'
CM 1447         view.__phash__ = 'abc'
1448         config = self._makeOne(autocommit=True)
1449         config.registry.registerAdapter(
0c29cf 1450             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 1451         )
1452         config.add_view(view=view, renderer=null_renderer, containment=IFoo)
1453         config.add_view(view=view, renderer=null_renderer, containment=IBar)
ba2a3f 1454         wrapper = self._getViewCallable(config)
CM 1455         self.assertTrue(IMultiView.providedBy(wrapper))
1456         request = self._makeRequest(config)
9c8ec5 1457         self.assertNotEqual(
CM 1458             wrapper.__discriminator__(foo, request),
1459             wrapper.__discriminator__(bar, request),
0c29cf 1460         )
ba2a3f 1461
49f082 1462     def test_add_view_with_template_renderer(self):
dd3cc8 1463         from tests import test_config
49f082 1464         from pyramid.interfaces import ISettings
0c29cf 1465
49f082 1466         class view(object):
CM 1467             def __init__(self, context, request):
1468                 self.request = request
1469                 self.context = context
1470
1471             def __call__(self):
0c29cf 1472                 return {'a': '1'}
MM 1473
49f082 1474         config = self._makeOne(autocommit=True)
CM 1475         renderer = self._registerRenderer(config)
dd3cc8 1476         fixture = 'tests.test_config:files/minimal.txt'
b368d7 1477         config.introspection = False
49f082 1478         config.add_view(view=view, renderer=fixture)
CM 1479         wrapper = self._getViewCallable(config)
1480         request = self._makeRequest(config)
1481         result = wrapper(None, request)
8e606d 1482         self.assertEqual(result.body, b'Hello!')
49f082 1483         settings = config.registry.queryUtility(ISettings)
CM 1484         result = renderer.info
1485         self.assertEqual(result.registry, config.registry)
1486         self.assertEqual(result.type, '.txt')
1487         self.assertEqual(result.package, test_config)
1488         self.assertEqual(result.name, fixture)
1489         self.assertEqual(result.settings, settings)
1490
1491     def test_add_view_with_default_renderer(self):
1492         class view(object):
1493             def __init__(self, context, request):
1494                 self.request = request
1495                 self.context = context
1496
1497             def __call__(self):
0c29cf 1498                 return {'a': '1'}
MM 1499
49f082 1500         config = self._makeOne(autocommit=True)
0c29cf 1501
49f082 1502         class moo(object):
CM 1503             def __init__(self, *arg, **kw):
1504                 pass
0c29cf 1505
49f082 1506             def __call__(self, *arg, **kw):
42afb0 1507                 return b'moo'
0c29cf 1508
49f082 1509         config.add_renderer(None, moo)
CM 1510         config.add_view(view=view)
1511         wrapper = self._getViewCallable(config)
1512         request = self._makeRequest(config)
1513         result = wrapper(None, request)
8e606d 1514         self.assertEqual(result.body, b'moo')
49f082 1515
CM 1516     def test_add_view_with_template_renderer_no_callable(self):
dd3cc8 1517         from tests import test_config
49f082 1518         from pyramid.interfaces import ISettings
0c29cf 1519
49f082 1520         config = self._makeOne(autocommit=True)
CM 1521         renderer = self._registerRenderer(config)
dd3cc8 1522         fixture = 'tests.test_config:files/minimal.txt'
b368d7 1523         config.introspection = False
49f082 1524         config.add_view(view=None, renderer=fixture)
CM 1525         wrapper = self._getViewCallable(config)
1526         request = self._makeRequest(config)
1527         result = wrapper(None, request)
8e606d 1528         self.assertEqual(result.body, b'Hello!')
49f082 1529         settings = config.registry.queryUtility(ISettings)
CM 1530         result = renderer.info
1531         self.assertEqual(result.registry, config.registry)
1532         self.assertEqual(result.type, '.txt')
1533         self.assertEqual(result.package, test_config)
1534         self.assertEqual(result.name, fixture)
1535         self.assertEqual(result.settings, settings)
1536
1537     def test_add_view_with_request_type_as_iface(self):
1538         from pyramid.renderers import null_renderer
1539         from zope.interface import directlyProvides
0c29cf 1540
49f082 1541         def view(context, request):
CM 1542             return 'OK'
0c29cf 1543
49f082 1544         config = self._makeOne(autocommit=True)
CM 1545         config.add_view(request_type=IDummy, view=view, renderer=null_renderer)
1546         wrapper = self._getViewCallable(config, None)
1547         request = self._makeRequest(config)
1548         directlyProvides(request, IDummy)
1549         result = wrapper(None, request)
1550         self.assertEqual(result, 'OK')
1551
1552     def test_add_view_with_request_type_as_noniface(self):
1553         view = lambda *arg: 'OK'
1554         config = self._makeOne()
0c29cf 1555         self.assertRaises(
MM 1556             ConfigurationError, config.add_view, view, '', None, None, object
1557         )
49f082 1558
CM 1559     def test_add_view_with_route_name(self):
1560         from pyramid.renderers import null_renderer
0c29cf 1561
49f082 1562         view = lambda *arg: 'OK'
CM 1563         config = self._makeOne(autocommit=True)
1564         config.add_route('foo', '/a/b')
1565         config.add_view(view=view, route_name='foo', renderer=null_renderer)
1566         request_iface = self._getRouteRequestIface(config, 'foo')
1567         self.assertNotEqual(request_iface, None)
1568         wrapper = self._getViewCallable(config, request_iface=request_iface)
1569         self.assertNotEqual(wrapper, None)
1570         self.assertEqual(wrapper(None, None), 'OK')
1571
1572     def test_add_view_with_nonexistant_route_name(self):
1573         from pyramid.renderers import null_renderer
0c29cf 1574
49f082 1575         view = lambda *arg: 'OK'
CM 1576         config = self._makeOne()
1577         config.add_view(view=view, route_name='foo', renderer=null_renderer)
1578         self.assertRaises(ConfigurationExecutionError, config.commit)
1579
1580     def test_add_view_with_route_name_exception(self):
1581         from pyramid.renderers import null_renderer
1582         from zope.interface import implementedBy
0c29cf 1583
49f082 1584         view = lambda *arg: 'OK'
CM 1585         config = self._makeOne(autocommit=True)
1586         config.add_route('foo', '/a/b')
0c29cf 1587         config.add_view(
MM 1588             view=view,
1589             route_name='foo',
1590             context=RuntimeError,
1591             renderer=null_renderer,
1592         )
49f082 1593         request_iface = self._getRouteRequestIface(config, 'foo')
CM 1594         wrapper_exc_view = self._getViewCallable(
0c29cf 1595             config,
MM 1596             exc_iface=implementedBy(RuntimeError),
1597             request_iface=request_iface,
1598         )
49f082 1599         self.assertNotEqual(wrapper_exc_view, None)
CM 1600         wrapper = self._getViewCallable(
0c29cf 1601             config,
MM 1602             ctx_iface=implementedBy(RuntimeError),
1603             request_iface=request_iface,
1604         )
49f082 1605         self.assertEqual(wrapper_exc_view, wrapper)
CM 1606         self.assertEqual(wrapper_exc_view(None, None), 'OK')
1607
1608     def test_add_view_with_request_method_true(self):
1609         from pyramid.renderers import null_renderer
0c29cf 1610
49f082 1611         view = lambda *arg: 'OK'
CM 1612         config = self._makeOne(autocommit=True)
0c29cf 1613         config.add_view(
MM 1614             view=view, request_method='POST', renderer=null_renderer
1615         )
49f082 1616         wrapper = self._getViewCallable(config)
CM 1617         request = self._makeRequest(config)
1618         request.method = 'POST'
1619         self.assertEqual(wrapper(None, request), 'OK')
1620
1621     def test_add_view_with_request_method_false(self):
1622         view = lambda *arg: 'OK'
1623         config = self._makeOne(autocommit=True)
1624         config.add_view(view=view, request_method='POST')
1625         wrapper = self._getViewCallable(config)
1626         request = self._makeRequest(config)
1627         request.method = 'GET'
1628         self._assertNotFound(wrapper, None, request)
1629
1630     def test_add_view_with_request_method_sequence_true(self):
1631         from pyramid.renderers import null_renderer
0c29cf 1632
49f082 1633         view = lambda *arg: 'OK'
CM 1634         config = self._makeOne(autocommit=True)
0c29cf 1635         config.add_view(
MM 1636             view=view, request_method=('POST', 'GET'), renderer=null_renderer
1637         )
49f082 1638         wrapper = self._getViewCallable(config)
CM 1639         request = self._makeRequest(config)
1640         request.method = 'POST'
1641         self.assertEqual(wrapper(None, request), 'OK')
1642
1643     def test_add_view_with_request_method_sequence_conflict(self):
1644         from pyramid.renderers import null_renderer
0c29cf 1645
49f082 1646         view = lambda *arg: 'OK'
CM 1647         config = self._makeOne()
0c29cf 1648         config.add_view(
MM 1649             view=view, request_method=('POST', 'GET'), renderer=null_renderer
1650         )
1651         config.add_view(
1652             view=view, request_method=('GET', 'POST'), renderer=null_renderer
1653         )
49f082 1654         self.assertRaises(ConfigurationConflictError, config.commit)
CM 1655
1656     def test_add_view_with_request_method_sequence_false(self):
1657         view = lambda *arg: 'OK'
1658         config = self._makeOne(autocommit=True)
1659         config.add_view(view=view, request_method=('POST', 'HEAD'))
1660         wrapper = self._getViewCallable(config)
1661         request = self._makeRequest(config)
1662         request.method = 'GET'
1663         self._assertNotFound(wrapper, None, request)
1664
360f25 1665     def test_add_view_with_request_method_get_implies_head(self):
CM 1666         from pyramid.renderers import null_renderer
0c29cf 1667
360f25 1668         view = lambda *arg: 'OK'
CM 1669         config = self._makeOne(autocommit=True)
0c29cf 1670         config.add_view(
MM 1671             view=view, request_method='GET', renderer=null_renderer
1672         )
360f25 1673         wrapper = self._getViewCallable(config)
CM 1674         request = self._makeRequest(config)
1675         request.method = 'HEAD'
1676         self.assertEqual(wrapper(None, request), 'OK')
42afb0 1677
49f082 1678     def test_add_view_with_request_param_noval_true(self):
CM 1679         from pyramid.renderers import null_renderer
0c29cf 1680
49f082 1681         view = lambda *arg: 'OK'
CM 1682         config = self._makeOne(autocommit=True)
1683         config.add_view(view=view, request_param='abc', renderer=null_renderer)
1684         wrapper = self._getViewCallable(config)
1685         request = self._makeRequest(config)
0c29cf 1686         request.params = {'abc': ''}
49f082 1687         self.assertEqual(wrapper(None, request), 'OK')
CM 1688
1689     def test_add_view_with_request_param_noval_false(self):
1690         view = lambda *arg: 'OK'
1691         config = self._makeOne(autocommit=True)
1692         config.add_view(view=view, request_param='abc')
1693         wrapper = self._getViewCallable(config)
1694         request = self._makeRequest(config)
1695         request.params = {}
1696         self._assertNotFound(wrapper, None, request)
1697
1698     def test_add_view_with_request_param_val_true(self):
1699         from pyramid.renderers import null_renderer
0c29cf 1700
49f082 1701         view = lambda *arg: 'OK'
CM 1702         config = self._makeOne(autocommit=True)
0c29cf 1703         config.add_view(
MM 1704             view=view, request_param='abc=123', renderer=null_renderer
1705         )
49f082 1706         wrapper = self._getViewCallable(config)
CM 1707         request = self._makeRequest(config)
0c29cf 1708         request.params = {'abc': '123'}
49f082 1709         self.assertEqual(wrapper(None, request), 'OK')
CM 1710
1711     def test_add_view_with_request_param_val_false(self):
1712         view = lambda *arg: 'OK'
1713         config = self._makeOne(autocommit=True)
1714         config.add_view(view=view, request_param='abc=123')
1715         wrapper = self._getViewCallable(config)
1716         request = self._makeRequest(config)
0c29cf 1717         request.params = {'abc': ''}
49f082 1718         self._assertNotFound(wrapper, None, request)
CM 1719
1720     def test_add_view_with_xhr_true(self):
1721         from pyramid.renderers import null_renderer
0c29cf 1722
49f082 1723         view = lambda *arg: 'OK'
CM 1724         config = self._makeOne(autocommit=True)
1725         config.add_view(view=view, xhr=True, renderer=null_renderer)
1726         wrapper = self._getViewCallable(config)
1727         request = self._makeRequest(config)
1728         request.is_xhr = True
1729         self.assertEqual(wrapper(None, request), 'OK')
1730
1731     def test_add_view_with_xhr_false(self):
1732         view = lambda *arg: 'OK'
1733         config = self._makeOne(autocommit=True)
1734         config.add_view(view=view, xhr=True)
1735         wrapper = self._getViewCallable(config)
1736         request = self._makeRequest(config)
1737         request.is_xhr = False
1738         self._assertNotFound(wrapper, None, request)
1739
1740     def test_add_view_with_header_badregex(self):
1741         view = lambda *arg: 'OK'
1742         config = self._makeOne()
a00621 1743         config.add_view(view, header='Host:a\\')
CM 1744         self.assertRaises(ConfigurationError, config.commit)
49f082 1745
CM 1746     def test_add_view_with_header_noval_match(self):
1747         from pyramid.renderers import null_renderer
0c29cf 1748
49f082 1749         view = lambda *arg: 'OK'
CM 1750         config = self._makeOne(autocommit=True)
1751         config.add_view(view=view, header='Host', renderer=null_renderer)
1752         wrapper = self._getViewCallable(config)
1753         request = self._makeRequest(config)
0c29cf 1754         request.headers = {'Host': 'whatever'}
49f082 1755         self.assertEqual(wrapper(None, request), 'OK')
CM 1756
1757     def test_add_view_with_header_noval_nomatch(self):
1758         view = lambda *arg: 'OK'
1759         config = self._makeOne(autocommit=True)
1760         config.add_view(view=view, header='Host')
1761         wrapper = self._getViewCallable(config)
1762         request = self._makeRequest(config)
0c29cf 1763         request.headers = {'NotHost': 'whatever'}
49f082 1764         self._assertNotFound(wrapper, None, request)
CM 1765
1766     def test_add_view_with_header_val_match(self):
1767         from pyramid.renderers import null_renderer
0c29cf 1768
49f082 1769         view = lambda *arg: 'OK'
CM 1770         config = self._makeOne(autocommit=True)
1771         config.add_view(view=view, header=r'Host:\d', renderer=null_renderer)
1772         wrapper = self._getViewCallable(config)
1773         request = self._makeRequest(config)
0c29cf 1774         request.headers = {'Host': '1'}
49f082 1775         self.assertEqual(wrapper(None, request), 'OK')
CM 1776
1777     def test_add_view_with_header_val_nomatch(self):
1778         view = lambda *arg: 'OK'
1779         config = self._makeOne(autocommit=True)
1780         config.add_view(view=view, header=r'Host:\d')
1781         wrapper = self._getViewCallable(config)
1782         request = self._makeRequest(config)
0c29cf 1783         request.headers = {'Host': 'abc'}
49f082 1784         self._assertNotFound(wrapper, None, request)
CM 1785
1786     def test_add_view_with_header_val_missing(self):
1787         from pyramid.httpexceptions import HTTPNotFound
0c29cf 1788
49f082 1789         view = lambda *arg: 'OK'
CM 1790         config = self._makeOne(autocommit=True)
1791         config.add_view(view=view, header=r'Host:\d')
1792         wrapper = self._getViewCallable(config)
1793         request = self._makeRequest(config)
0c29cf 1794         request.headers = {'NoHost': '1'}
49f082 1795         self.assertRaises(HTTPNotFound, wrapper, None, request)
CM 1796
1797     def test_add_view_with_accept_match(self):
1798         from pyramid.renderers import null_renderer
0c29cf 1799
49f082 1800         view = lambda *arg: 'OK'
CM 1801         config = self._makeOne(autocommit=True)
1802         config.add_view(view=view, accept='text/xml', renderer=null_renderer)
1803         wrapper = self._getViewCallable(config)
1804         request = self._makeRequest(config)
c3c83e 1805         request.accept = DummyAccept('text/xml')
49f082 1806         self.assertEqual(wrapper(None, request), 'OK')
CM 1807
1808     def test_add_view_with_accept_nomatch(self):
1809         view = lambda *arg: 'OK'
1810         config = self._makeOne(autocommit=True)
1811         config.add_view(view=view, accept='text/xml')
1812         wrapper = self._getViewCallable(config)
1813         request = self._makeRequest(config)
c3c83e 1814         request.accept = DummyAccept('text/html')
49f082 1815         self._assertNotFound(wrapper, None, request)
CM 1816
4a9f4f 1817     def test_add_view_with_range_accept_match(self):
MM 1818         from pyramid.renderers import null_renderer
0c29cf 1819
4a9f4f 1820         view = lambda *arg: 'OK'
MM 1821         config = self._makeOne(autocommit=True)
1822         config.add_view(view=view, accept='text/*', renderer=null_renderer)
1823         wrapper = self._getViewCallable(config)
1824         request = self._makeRequest(config)
1825         request.accept = DummyAccept('text/html', contains=True)
1826         self.assertEqual(wrapper(None, request), 'OK')
1827
1828     def test_add_view_with_range_accept_nomatch(self):
1829         view = lambda *arg: 'OK'
1830         config = self._makeOne(autocommit=True)
1831         config.add_view(view=view, accept='text/*')
1832         wrapper = self._getViewCallable(config)
1833         request = self._makeRequest(config)
1834         request.accept = DummyAccept('application/json', contains=False)
1835         self._assertNotFound(wrapper, None, request)
1836
49f082 1837     def test_add_view_with_containment_true(self):
CM 1838         from pyramid.renderers import null_renderer
1839         from zope.interface import directlyProvides
0c29cf 1840
49f082 1841         view = lambda *arg: 'OK'
CM 1842         config = self._makeOne(autocommit=True)
1843         config.add_view(view=view, containment=IDummy, renderer=null_renderer)
1844         wrapper = self._getViewCallable(config)
1845         context = DummyContext()
1846         directlyProvides(context, IDummy)
1847         self.assertEqual(wrapper(context, None), 'OK')
1848
1849     def test_add_view_with_containment_false(self):
1850         view = lambda *arg: 'OK'
1851         config = self._makeOne(autocommit=True)
1852         config.add_view(view=view, containment=IDummy)
1853         wrapper = self._getViewCallable(config)
1854         context = DummyContext()
1855         self._assertNotFound(wrapper, context, None)
1856
1857     def test_add_view_with_containment_dottedname(self):
1858         from pyramid.renderers import null_renderer
1859         from zope.interface import directlyProvides
0c29cf 1860
49f082 1861         view = lambda *arg: 'OK'
CM 1862         config = self._makeOne(autocommit=True)
1863         config.add_view(
1864             view=view,
dd3cc8 1865             containment='tests.test_config.IDummy',
0c29cf 1866             renderer=null_renderer,
MM 1867         )
49f082 1868         wrapper = self._getViewCallable(config)
CM 1869         context = DummyContext()
1870         directlyProvides(context, IDummy)
1871         self.assertEqual(wrapper(context, None), 'OK')
1872
1873     def test_add_view_with_path_info_badregex(self):
1874         view = lambda *arg: 'OK'
1875         config = self._makeOne()
a00621 1876         config.add_view(view, path_info='\\')
CM 1877         self.assertRaises(ConfigurationError, config.commit)
49f082 1878
CM 1879     def test_add_view_with_path_info_match(self):
1880         from pyramid.renderers import null_renderer
0c29cf 1881
49f082 1882         view = lambda *arg: 'OK'
CM 1883         config = self._makeOne(autocommit=True)
1884         config.add_view(view=view, path_info='/foo', renderer=null_renderer)
1885         wrapper = self._getViewCallable(config)
1886         request = self._makeRequest(config)
a5d994 1887         request.upath_info = text_(b'/foo')
49f082 1888         self.assertEqual(wrapper(None, request), 'OK')
CM 1889
1890     def test_add_view_with_path_info_nomatch(self):
1891         view = lambda *arg: 'OK'
1892         config = self._makeOne(autocommit=True)
1893         config.add_view(view=view, path_info='/foo')
1894         wrapper = self._getViewCallable(config)
1895         request = self._makeRequest(config)
a5d994 1896         request.upath_info = text_('/')
49f082 1897         self._assertNotFound(wrapper, None, request)
CM 1898
15b97d 1899     def test_add_view_with_check_csrf_predicates_match(self):
MM 1900         import warnings
1901         from pyramid.renderers import null_renderer
0c29cf 1902
15b97d 1903         view = lambda *arg: 'OK'
MM 1904         config = self._makeOne(autocommit=True)
1905         with warnings.catch_warnings(record=True) as w:
1906             warnings.filterwarnings('always')
1907             config.add_view(view=view, check_csrf=True, renderer=null_renderer)
1908             self.assertEqual(len(w), 1)
1909         wrapper = self._getViewCallable(config)
1910         request = self._makeRequest(config)
f12005 1911         request.method = "POST"
15b97d 1912         request.session = DummySession({'csrf_token': 'foo'})
f12005 1913         request.POST = {'csrf_token': 'foo'}
15b97d 1914         request.headers = {}
MM 1915         self.assertEqual(wrapper(None, request), 'OK')
1916
49f082 1917     def test_add_view_with_custom_predicates_match(self):
b01f1d 1918         import warnings
49f082 1919         from pyramid.renderers import null_renderer
0c29cf 1920
49f082 1921         view = lambda *arg: 'OK'
CM 1922         config = self._makeOne(autocommit=True)
0c29cf 1923
49f082 1924         def pred1(context, request):
CM 1925             return True
0c29cf 1926
49f082 1927         def pred2(context, request):
CM 1928             return True
0c29cf 1929
49f082 1930         predicates = (pred1, pred2)
b01f1d 1931         with warnings.catch_warnings(record=True) as w:
CM 1932             warnings.filterwarnings('always')
0c29cf 1933             config.add_view(
MM 1934                 view=view, custom_predicates=predicates, renderer=null_renderer
1935             )
b01f1d 1936             self.assertEqual(len(w), 1)
49f082 1937         wrapper = self._getViewCallable(config)
CM 1938         request = self._makeRequest(config)
1939         self.assertEqual(wrapper(None, request), 'OK')
1940
1941     def test_add_view_with_custom_predicates_nomatch(self):
b01f1d 1942         import warnings
0c29cf 1943
49f082 1944         view = lambda *arg: 'OK'
CM 1945         config = self._makeOne(autocommit=True)
0c29cf 1946
49f082 1947         def pred1(context, request):
CM 1948             return True
0c29cf 1949
49f082 1950         def pred2(context, request):
CM 1951             return False
0c29cf 1952
49f082 1953         predicates = (pred1, pred2)
b01f1d 1954         with warnings.catch_warnings(record=True) as w:
CM 1955             warnings.filterwarnings('always')
1956             config.add_view(view=view, custom_predicates=predicates)
1957             self.assertEqual(len(w), 1)
49f082 1958         wrapper = self._getViewCallable(config)
CM 1959         request = self._makeRequest(config)
1960         self._assertNotFound(wrapper, None, request)
1961
1962     def test_add_view_custom_predicate_bests_standard_predicate(self):
b01f1d 1963         import warnings
49f082 1964         from pyramid.renderers import null_renderer
0c29cf 1965
49f082 1966         view = lambda *arg: 'OK'
CM 1967         view2 = lambda *arg: 'NOT OK'
1968         config = self._makeOne(autocommit=True)
0c29cf 1969
49f082 1970         def pred1(context, request):
CM 1971             return True
0c29cf 1972
b01f1d 1973         with warnings.catch_warnings(record=True) as w:
CM 1974             warnings.filterwarnings('always')
0c29cf 1975             config.add_view(
MM 1976                 view=view, custom_predicates=(pred1,), renderer=null_renderer
1977             )
1978             config.add_view(
1979                 view=view2, request_method='GET', renderer=null_renderer
1980             )
b01f1d 1981             self.assertEqual(len(w), 1)
49f082 1982         wrapper = self._getViewCallable(config)
CM 1983         request = self._makeRequest(config)
1984         request.method = 'GET'
1985         self.assertEqual(wrapper(None, request), 'OK')
1986
1987     def test_add_view_custom_more_preds_first_bests_fewer_preds_last(self):
1988         from pyramid.renderers import null_renderer
0c29cf 1989
49f082 1990         view = lambda *arg: 'OK'
CM 1991         view2 = lambda *arg: 'NOT OK'
1992         config = self._makeOne(autocommit=True)
0c29cf 1993         config.add_view(
MM 1994             view=view, request_method='GET', xhr=True, renderer=null_renderer
1995         )
1996         config.add_view(
1997             view=view2, request_method='GET', renderer=null_renderer
1998         )
49f082 1999         wrapper = self._getViewCallable(config)
CM 2000         request = self._makeRequest(config)
2001         request.method = 'GET'
2002         request.is_xhr = True
2003         self.assertEqual(wrapper(None, request), 'OK')
2004
2005     def test_add_view_same_predicates(self):
2006         view2 = lambda *arg: 'second'
2007         view1 = lambda *arg: 'first'
2008         config = self._makeOne()
2009         config.add_view(view=view1)
2010         config.add_view(view=view2)
2011         self.assertRaises(ConfigurationConflictError, config.commit)
2012
9e9fa9 2013     def test_add_view_with_csrf_param(self):
MM 2014         from pyramid.renderers import null_renderer
0c29cf 2015
9e9fa9 2016         def view(request):
MM 2017             return 'OK'
0c29cf 2018
9e9fa9 2019         config = self._makeOne(autocommit=True)
MM 2020         config.add_view(view, require_csrf='st', renderer=null_renderer)
2021         view = self._getViewCallable(config)
2022         request = self._makeRequest(config)
65dee6 2023         request.scheme = "http"
6b35eb 2024         request.method = 'POST'
f12005 2025         request.POST = {'st': 'foo'}
9e9fa9 2026         request.headers = {}
6b35eb 2027         request.session = DummySession({'csrf_token': 'foo'})
MM 2028         self.assertEqual(view(None, request), 'OK')
2029
2030     def test_add_view_with_csrf_header(self):
2031         from pyramid.renderers import null_renderer
0c29cf 2032
6b35eb 2033         def view(request):
MM 2034             return 'OK'
0c29cf 2035
6b35eb 2036         config = self._makeOne(autocommit=True)
MM 2037         config.add_view(view, require_csrf=True, renderer=null_renderer)
2038         view = self._getViewCallable(config)
2039         request = self._makeRequest(config)
65dee6 2040         request.scheme = "http"
6b35eb 2041         request.method = 'POST'
f12005 2042         request.POST = {}
6b35eb 2043         request.headers = {'X-CSRF-Token': 'foo'}
9e9fa9 2044         request.session = DummySession({'csrf_token': 'foo'})
MM 2045         self.assertEqual(view(None, request), 'OK')
2046
2047     def test_add_view_with_missing_csrf_header(self):
2048         from pyramid.exceptions import BadCSRFToken
2049         from pyramid.renderers import null_renderer
0c29cf 2050
MM 2051         def view(request):
2052             return 'OK'
2053
9e9fa9 2054         config = self._makeOne(autocommit=True)
MM 2055         config.add_view(view, require_csrf=True, renderer=null_renderer)
2056         view = self._getViewCallable(config)
2057         request = self._makeRequest(config)
65dee6 2058         request.scheme = "http"
6b35eb 2059         request.method = 'POST'
f12005 2060         request.POST = {}
9e9fa9 2061         request.headers = {}
MM 2062         request.session = DummySession({'csrf_token': 'foo'})
2063         self.assertRaises(BadCSRFToken, lambda: view(None, request))
2064
49f082 2065     def test_add_view_with_permission(self):
CM 2066         from pyramid.renderers import null_renderer
0c29cf 2067
49f082 2068         view1 = lambda *arg: 'OK'
CM 2069         outerself = self
0c29cf 2070
49f082 2071         class DummyPolicy(object):
CM 2072             def effective_principals(self, r):
2073                 outerself.assertEqual(r, request)
2074                 return ['abc']
0c29cf 2075
49f082 2076             def permits(self, context, principals, permission):
CM 2077                 outerself.assertEqual(context, None)
2078                 outerself.assertEqual(principals, ['abc'])
2079                 outerself.assertEqual(permission, 'view')
2080                 return True
0c29cf 2081
49f082 2082         policy = DummyPolicy()
0c29cf 2083         config = self._makeOne(
MM 2084             authorization_policy=policy,
2085             authentication_policy=policy,
2086             autocommit=True,
2087         )
49f082 2088         config.add_view(view=view1, permission='view', renderer=null_renderer)
CM 2089         view = self._getViewCallable(config)
2090         request = self._makeRequest(config)
2091         self.assertEqual(view(None, request), 'OK')
2092
2093     def test_add_view_with_default_permission_no_explicit_permission(self):
2094         from pyramid.renderers import null_renderer
0c29cf 2095
49f082 2096         view1 = lambda *arg: 'OK'
CM 2097         outerself = self
0c29cf 2098
49f082 2099         class DummyPolicy(object):
CM 2100             def effective_principals(self, r):
2101                 outerself.assertEqual(r, request)
2102                 return ['abc']
0c29cf 2103
49f082 2104             def permits(self, context, principals, permission):
CM 2105                 outerself.assertEqual(context, None)
2106                 outerself.assertEqual(principals, ['abc'])
2107                 outerself.assertEqual(permission, 'view')
2108                 return True
0c29cf 2109
49f082 2110         policy = DummyPolicy()
0c29cf 2111         config = self._makeOne(
MM 2112             authorization_policy=policy,
2113             authentication_policy=policy,
2114             default_permission='view',
2115             autocommit=True,
2116         )
49f082 2117         config.add_view(view=view1, renderer=null_renderer)
CM 2118         view = self._getViewCallable(config)
2119         request = self._makeRequest(config)
2120         self.assertEqual(view(None, request), 'OK')
2121
2122     def test_add_view_with_no_default_permission_no_explicit_permission(self):
2123         from pyramid.renderers import null_renderer
0c29cf 2124
49f082 2125         view1 = lambda *arg: 'OK'
0c29cf 2126
MM 2127         class DummyPolicy(object):
2128             pass  # wont be called
2129
49f082 2130         policy = DummyPolicy()
0c29cf 2131         config = self._makeOne(
MM 2132             authorization_policy=policy,
2133             authentication_policy=policy,
2134             autocommit=True,
2135         )
49f082 2136         config.add_view(view=view1, renderer=null_renderer)
CM 2137         view = self._getViewCallable(config)
2138         request = self._makeRequest(config)
2139         self.assertEqual(view(None, request), 'OK')
b2fbe5 2140
522405 2141     def test_add_view_with_mapper(self):
CM 2142         from pyramid.renderers import null_renderer
0c29cf 2143
522405 2144         class Mapper(object):
CM 2145             def __init__(self, **kw):
2146                 self.__class__.kw = kw
0c29cf 2147
522405 2148             def __call__(self, view):
CM 2149                 return view
0c29cf 2150
522405 2151         config = self._makeOne(autocommit=True)
0c29cf 2152
MM 2153         def view(context, request):
2154             return 'OK'
2155
522405 2156         config.add_view(view=view, mapper=Mapper, renderer=null_renderer)
CM 2157         view = self._getViewCallable(config)
2158         self.assertEqual(view(None, None), 'OK')
2159         self.assertEqual(Mapper.kw['mapper'], Mapper)
2160
bb462e 2161     def test_add_view_with_view_defaults(self):
CM 2162         from pyramid.renderers import null_renderer
2163         from pyramid.exceptions import PredicateMismatch
2164         from zope.interface import directlyProvides
0c29cf 2165
bb462e 2166         class view(object):
0c29cf 2167             __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 2168
bb462e 2169             def __init__(self, request):
CM 2170                 pass
0c29cf 2171
bb462e 2172             def __call__(self):
CM 2173                 return 'OK'
0c29cf 2174
bb462e 2175         config = self._makeOne(autocommit=True)
0c29cf 2176         config.add_view(view=view, renderer=null_renderer)
bb462e 2177         wrapper = self._getViewCallable(config)
CM 2178         context = DummyContext()
2179         directlyProvides(context, IDummy)
2180         request = self._makeRequest(config)
2181         self.assertEqual(wrapper(context, request), 'OK')
2182         context = DummyContext()
2183         request = self._makeRequest(config)
2184         self.assertRaises(PredicateMismatch, wrapper, context, request)
134388 2185
CM 2186     def test_add_view_with_view_defaults_viewname_is_dottedname_kwarg(self):
2187         from pyramid.renderers import null_renderer
2188         from pyramid.exceptions import PredicateMismatch
2189         from zope.interface import directlyProvides
0c29cf 2190
134388 2191         config = self._makeOne(autocommit=True)
CM 2192         config.add_view(
dd3cc8 2193             view='tests.test_config.test_views.DummyViewDefaultsClass',
0c29cf 2194             renderer=null_renderer,
MM 2195         )
134388 2196         wrapper = self._getViewCallable(config)
CM 2197         context = DummyContext()
2198         directlyProvides(context, IDummy)
2199         request = self._makeRequest(config)
2200         self.assertEqual(wrapper(context, request), 'OK')
2201         context = DummyContext()
2202         request = self._makeRequest(config)
2203         self.assertRaises(PredicateMismatch, wrapper, context, request)
2204
2205     def test_add_view_with_view_defaults_viewname_is_dottedname_nonkwarg(self):
2206         from pyramid.renderers import null_renderer
2207         from pyramid.exceptions import PredicateMismatch
2208         from zope.interface import directlyProvides
0c29cf 2209
134388 2210         config = self._makeOne(autocommit=True)
CM 2211         config.add_view(
dd3cc8 2212             'tests.test_config.test_views.DummyViewDefaultsClass',
0c29cf 2213             renderer=null_renderer,
MM 2214         )
134388 2215         wrapper = self._getViewCallable(config)
CM 2216         context = DummyContext()
2217         directlyProvides(context, IDummy)
2218         request = self._makeRequest(config)
2219         self.assertEqual(wrapper(context, request), 'OK')
2220         context = DummyContext()
2221         request = self._makeRequest(config)
2222         self.assertRaises(PredicateMismatch, wrapper, context, request)
42afb0 2223
4c29ef 2224     def test_add_view_with_view_config_and_view_defaults_doesnt_conflict(self):
CM 2225         from pyramid.renderers import null_renderer
0c29cf 2226
4c29ef 2227         class view(object):
0c29cf 2228             __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 2229
4c29ef 2230         class view2(object):
0c29cf 2231             __view_defaults__ = {'containment': 'tests.test_config.IFactory'}
MM 2232
4c29ef 2233         config = self._makeOne(autocommit=False)
0c29cf 2234         config.add_view(view=view, renderer=null_renderer)
MM 2235         config.add_view(view=view2, renderer=null_renderer)
2236         config.commit()  # does not raise
4c29ef 2237
CM 2238     def test_add_view_with_view_config_and_view_defaults_conflicts(self):
2239         from pyramid.renderers import null_renderer
0c29cf 2240
4c29ef 2241         class view(object):
0c29cf 2242             __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 2243
4c29ef 2244         class view2(object):
0c29cf 2245             __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 2246
4c29ef 2247         config = self._makeOne(autocommit=False)
0c29cf 2248         config.add_view(view=view, renderer=null_renderer)
MM 2249         config.add_view(view=view2, renderer=null_renderer)
4c29ef 2250         self.assertRaises(ConfigurationConflictError, config.commit)
bb462e 2251
bc26de 2252     def test_add_view_class_method_no_attr(self):
JA 2253         from pyramid.renderers import null_renderer
2254         from zope.interface import directlyProvides
4a7029 2255         from pyramid.exceptions import ConfigurationError
bc26de 2256
JA 2257         config = self._makeOne(autocommit=True)
0c29cf 2258
4a7029 2259         class DummyViewClass(object):
0c29cf 2260             def run(self):
MM 2261                 pass
bc26de 2262
4a7029 2263         def configure_view():
JA 2264             config.add_view(view=DummyViewClass.run, renderer=null_renderer)
2265
2266         self.assertRaises(ConfigurationError, configure_view)
bc26de 2267
b0d20b 2268     def test_add_view_exception_only_no_regular_view(self):
AL 2269         from zope.interface import implementedBy
2270         from pyramid.renderers import null_renderer
0c29cf 2271
b0d20b 2272         view1 = lambda *arg: 'OK'
AL 2273         config = self._makeOne(autocommit=True)
0c29cf 2274         config.add_view(
MM 2275             view=view1,
2276             context=Exception,
2277             exception_only=True,
2278             renderer=null_renderer,
2279         )
2280         view = self._getViewCallable(
2281             config, ctx_iface=implementedBy(Exception)
2282         )
b0d20b 2283         self.assertTrue(view is None)
AL 2284
2285     def test_add_view_exception_only(self):
2286         from zope.interface import implementedBy
2287         from pyramid.renderers import null_renderer
0c29cf 2288
b0d20b 2289         view1 = lambda *arg: 'OK'
AL 2290         config = self._makeOne(autocommit=True)
0c29cf 2291         config.add_view(
MM 2292             view=view1,
2293             context=Exception,
2294             exception_only=True,
2295             renderer=null_renderer,
2296         )
b0d20b 2297         view = self._getViewCallable(
0c29cf 2298             config, exc_iface=implementedBy(Exception)
MM 2299         )
b0d20b 2300         self.assertEqual(view1, view)
AL 2301
2302     def test_add_view_exception_only_misconfiguration(self):
2303         view = lambda *arg: 'OK'
2304         config = self._makeOne(autocommit=True)
0c29cf 2305
b0d20b 2306         class NotAnException(object):
AL 2307             pass
0c29cf 2308
b0d20b 2309         self.assertRaises(
AL 2310             ConfigurationError,
0c29cf 2311             config.add_view,
MM 2312             view,
2313             context=NotAnException,
2314             exception_only=True,
2315         )
b0d20b 2316
d6c90d 2317     def test_add_exception_view(self):
AL 2318         from zope.interface import implementedBy
2319         from pyramid.renderers import null_renderer
0c29cf 2320
d6c90d 2321         view1 = lambda *arg: 'OK'
AL 2322         config = self._makeOne(autocommit=True)
e8c66a 2323         config.add_exception_view(view=view1, renderer=null_renderer)
d6c90d 2324         wrapper = self._getViewCallable(
0c29cf 2325             config, exc_iface=implementedBy(Exception)
MM 2326         )
d6c90d 2327         context = Exception()
e8c66a 2328         request = self._makeRequest(config)
MM 2329         self.assertEqual(wrapper(context, request), 'OK')
2330
2331     def test_add_exception_view_with_subclass(self):
2332         from zope.interface import implementedBy
2333         from pyramid.renderers import null_renderer
0c29cf 2334
e8c66a 2335         view1 = lambda *arg: 'OK'
MM 2336         config = self._makeOne(autocommit=True)
0c29cf 2337         config.add_exception_view(
MM 2338             view=view1, context=ValueError, renderer=null_renderer
2339         )
e8c66a 2340         wrapper = self._getViewCallable(
0c29cf 2341             config, exc_iface=implementedBy(ValueError)
MM 2342         )
e8c66a 2343         context = ValueError()
d6c90d 2344         request = self._makeRequest(config)
AL 2345         self.assertEqual(wrapper(context, request), 'OK')
2346
2347     def test_add_exception_view_disallows_name(self):
2348         config = self._makeOne(autocommit=True)
0c29cf 2349         self.assertRaises(
MM 2350             ConfigurationError,
2351             config.add_exception_view,
2352             context=Exception(),
2353             name='foo',
2354         )
d6c90d 2355
AL 2356     def test_add_exception_view_disallows_permission(self):
2357         config = self._makeOne(autocommit=True)
0c29cf 2358         self.assertRaises(
MM 2359             ConfigurationError,
2360             config.add_exception_view,
2361             context=Exception(),
2362             permission='foo',
2363         )
d6c90d 2364
e8c66a 2365     def test_add_exception_view_disallows_require_csrf(self):
MM 2366         config = self._makeOne(autocommit=True)
0c29cf 2367         self.assertRaises(
MM 2368             ConfigurationError,
2369             config.add_exception_view,
2370             context=Exception(),
2371             require_csrf=True,
2372         )
e8c66a 2373
d6c90d 2374     def test_add_exception_view_disallows_for_(self):
AL 2375         config = self._makeOne(autocommit=True)
0c29cf 2376         self.assertRaises(
MM 2377             ConfigurationError,
2378             config.add_exception_view,
2379             context=Exception(),
2380             for_='foo',
2381         )
d6c90d 2382
AL 2383     def test_add_exception_view_disallows_exception_only(self):
2384         config = self._makeOne(autocommit=True)
0c29cf 2385         self.assertRaises(
MM 2386             ConfigurationError,
2387             config.add_exception_view,
2388             context=Exception(),
2389             exception_only=True,
2390         )
d6c90d 2391
AL 2392     def test_add_exception_view_with_view_defaults(self):
2393         from pyramid.renderers import null_renderer
2394         from pyramid.exceptions import PredicateMismatch
2395         from zope.interface import directlyProvides
2396         from zope.interface import implementedBy
0c29cf 2397
d6c90d 2398         class view(object):
0c29cf 2399             __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 2400
d6c90d 2401             def __init__(self, request):
AL 2402                 pass
0c29cf 2403
d6c90d 2404             def __call__(self):
AL 2405                 return 'OK'
0c29cf 2406
d6c90d 2407         config = self._makeOne(autocommit=True)
AL 2408         config.add_exception_view(
0c29cf 2409             view=view, context=Exception, renderer=null_renderer
MM 2410         )
d6c90d 2411         wrapper = self._getViewCallable(
0c29cf 2412             config, exc_iface=implementedBy(Exception)
MM 2413         )
d6c90d 2414         context = DummyContext()
AL 2415         directlyProvides(context, IDummy)
2416         request = self._makeRequest(config)
2417         self.assertEqual(wrapper(context, request), 'OK')
2418         context = DummyContext()
2419         request = self._makeRequest(config)
2420         self.assertRaises(PredicateMismatch, wrapper, context, request)
2421
b2fbe5 2422     def test_derive_view_function(self):
CM 2423         from pyramid.renderers import null_renderer
0c29cf 2424
b2fbe5 2425         def view(request):
CM 2426             return 'OK'
0c29cf 2427
b2fbe5 2428         config = self._makeOne()
CM 2429         result = config.derive_view(view, renderer=null_renderer)
2430         self.assertFalse(result is view)
2431         self.assertEqual(result(None, None), 'OK')
2432
2433     def test_derive_view_dottedname(self):
2434         from pyramid.renderers import null_renderer
0c29cf 2435
b2fbe5 2436         config = self._makeOne()
CM 2437         result = config.derive_view(
0c29cf 2438             'tests.test_config.dummy_view', renderer=null_renderer
MM 2439         )
b2fbe5 2440         self.assertFalse(result is dummy_view)
CM 2441         self.assertEqual(result(None, None), 'OK')
2442
2443     def test_derive_view_with_default_renderer_no_explicit_renderer(self):
2444         config = self._makeOne()
0c29cf 2445
b2fbe5 2446         class moo(object):
CM 2447             def __init__(self, view):
2448                 pass
0c29cf 2449
b2fbe5 2450             def __call__(self, *arg, **kw):
CM 2451                 return 'moo'
0c29cf 2452
b2fbe5 2453         config.add_renderer(None, moo)
CM 2454         config.commit()
0c29cf 2455
b2fbe5 2456         def view(request):
CM 2457             return 'OK'
0c29cf 2458
b2fbe5 2459         result = config.derive_view(view)
CM 2460         self.assertFalse(result is view)
8e606d 2461         self.assertEqual(result(None, None).body, b'moo')
b2fbe5 2462
CM 2463     def test_derive_view_with_default_renderer_with_explicit_renderer(self):
0c29cf 2464         class moo(object):
MM 2465             pass
2466
b2fbe5 2467         class foo(object):
CM 2468             def __init__(self, view):
2469                 pass
0c29cf 2470
b2fbe5 2471             def __call__(self, *arg, **kw):
42afb0 2472                 return b'foo'
0c29cf 2473
b2fbe5 2474         def view(request):
CM 2475             return 'OK'
0c29cf 2476
b2fbe5 2477         config = self._makeOne()
CM 2478         config.add_renderer(None, moo)
2479         config.add_renderer('foo', foo)
2480         config.commit()
2481         result = config.derive_view(view, renderer='foo')
2482         self.assertFalse(result is view)
2483         request = self._makeRequest(config)
8e606d 2484         self.assertEqual(result(None, request).body, b'foo')
b2fbe5 2485
6cc22a 2486     def test_add_static_view_here_no_utility_registered(self):
CM 2487         from pyramid.renderers import null_renderer
2488         from zope.interface import Interface
2489         from pyramid.interfaces import IView
2490         from pyramid.interfaces import IViewClassifier
0c29cf 2491
6cc22a 2492         config = self._makeOne(autocommit=True)
f2ef79 2493         config.add_static_view('static', 'files', renderer=null_renderer)
bc9357 2494         request_type = self._getRouteRequestIface(config, '__static/')
CM 2495         self._assertRoute(config, '__static/', 'static/*subpath')
6cc22a 2496         wrapped = config.registry.adapters.lookup(
0c29cf 2497             (IViewClassifier, request_type, Interface), IView, name=''
MM 2498         )
f2ef79 2499         from pyramid.request import Request
0c29cf 2500
b368d7 2501         request = Request.blank('/static/minimal.txt')
0c29cf 2502         request.subpath = ('minimal.txt',)
6cc22a 2503         result = wrapped(None, request)
f2ef79 2504         self.assertEqual(result.status, '200 OK')
9f7de6 2505         self.assertTrue(result.body.startswith(b'<div'))
6cc22a 2506
CM 2507     def test_add_static_view_package_relative(self):
2508         from pyramid.interfaces import IStaticURLInfo
0c29cf 2509
6cc22a 2510         info = DummyStaticURLInfo()
CM 2511         config = self._makeOne(autocommit=True)
2512         config.registry.registerUtility(info, IStaticURLInfo)
0c29cf 2513         config.add_static_view('static', 'tests.test_config:files')
6cc22a 2514         self.assertEqual(
0c29cf 2515             info.added, [(config, 'static', 'tests.test_config:files', {})]
MM 2516         )
6cc22a 2517
CM 2518     def test_add_static_view_package_here_relative(self):
2519         from pyramid.interfaces import IStaticURLInfo
0c29cf 2520
6cc22a 2521         info = DummyStaticURLInfo()
CM 2522         config = self._makeOne(autocommit=True)
2523         config.registry.registerUtility(info, IStaticURLInfo)
2524         config.add_static_view('static', 'files')
2525         self.assertEqual(
0c29cf 2526             info.added, [(config, 'static', 'tests.test_config:files', {})]
MM 2527         )
6cc22a 2528
CM 2529     def test_add_static_view_absolute(self):
2530         import os
2531         from pyramid.interfaces import IStaticURLInfo
0c29cf 2532
6cc22a 2533         info = DummyStaticURLInfo()
CM 2534         config = self._makeOne(autocommit=True)
2535         config.registry.registerUtility(info, IStaticURLInfo)
2536         here = os.path.dirname(__file__)
2537         static_path = os.path.join(here, 'files')
2538         config.add_static_view('static', static_path)
0c29cf 2539         self.assertEqual(info.added, [(config, 'static', static_path, {})])
42afb0 2540
a7fe30 2541     def test_add_forbidden_view(self):
2c1f9e 2542         from pyramid.renderers import null_renderer
CM 2543         from zope.interface import implementedBy
2544         from pyramid.interfaces import IRequest
2545         from pyramid.httpexceptions import HTTPForbidden
0c29cf 2546
2c1f9e 2547         config = self._makeOne(autocommit=True)
CM 2548         view = lambda *arg: 'OK'
a7fe30 2549         config.add_forbidden_view(view, renderer=null_renderer)
2c1f9e 2550         request = self._makeRequest(config)
0c29cf 2551         view = self._getViewCallable(
MM 2552             config,
2553             exc_iface=implementedBy(HTTPForbidden),
2554             request_iface=IRequest,
2555         )
2c1f9e 2556         result = view(None, request)
CM 2557         self.assertEqual(result, 'OK')
2558
dfa449 2559     def test_add_forbidden_view_no_view_argument(self):
DK 2560         from zope.interface import implementedBy
2561         from pyramid.interfaces import IRequest
2562         from pyramid.httpexceptions import HTTPForbidden
0c29cf 2563
dfa449 2564         config = self._makeOne(autocommit=True)
DK 2565         config.setup_registry()
2566         config.add_forbidden_view()
2567         request = self._makeRequest(config)
0c29cf 2568         view = self._getViewCallable(
MM 2569             config,
2570             exc_iface=implementedBy(HTTPForbidden),
2571             request_iface=IRequest,
2572         )
dfa449 2573         context = HTTPForbidden()
DK 2574         result = view(context, request)
2575         self.assertEqual(result, context)
2576
8ec8e2 2577     def test_add_forbidden_view_allows_other_predicates(self):
CM 2578         from pyramid.renderers import null_renderer
0c29cf 2579
8ec8e2 2580         config = self._makeOne(autocommit=True)
CM 2581         # doesnt blow up
2582         config.add_view_predicate('dummy', DummyPredicate)
2583         config.add_forbidden_view(renderer=null_renderer, dummy='abc')
2584
2585     def test_add_forbidden_view_disallows_name(self):
2586         config = self._makeOne(autocommit=True)
0c29cf 2587         self.assertRaises(
MM 2588             ConfigurationError, config.add_forbidden_view, name='foo'
2589         )
8ec8e2 2590
CM 2591     def test_add_forbidden_view_disallows_permission(self):
2592         config = self._makeOne(autocommit=True)
0c29cf 2593         self.assertRaises(
MM 2594             ConfigurationError, config.add_forbidden_view, permission='foo'
2595         )
8ec8e2 2596
e8c66a 2597     def test_add_forbidden_view_disallows_require_csrf(self):
MM 2598         config = self._makeOne(autocommit=True)
0c29cf 2599         self.assertRaises(
MM 2600             ConfigurationError, config.add_forbidden_view, require_csrf=True
2601         )
e8c66a 2602
8ec8e2 2603     def test_add_forbidden_view_disallows_context(self):
CM 2604         config = self._makeOne(autocommit=True)
0c29cf 2605         self.assertRaises(
MM 2606             ConfigurationError, config.add_forbidden_view, context='foo'
2607         )
8ec8e2 2608
CM 2609     def test_add_forbidden_view_disallows_for_(self):
2610         config = self._makeOne(autocommit=True)
0c29cf 2611         self.assertRaises(
MM 2612             ConfigurationError, config.add_forbidden_view, for_='foo'
2613         )
8ec8e2 2614
7c9624 2615     def test_add_forbidden_view_with_view_defaults(self):
MM 2616         from pyramid.interfaces import IRequest
2617         from pyramid.renderers import null_renderer
2618         from pyramid.exceptions import PredicateMismatch
2619         from pyramid.httpexceptions import HTTPForbidden
2620         from zope.interface import directlyProvides
2621         from zope.interface import implementedBy
0c29cf 2622
7c9624 2623         class view(object):
0c29cf 2624             __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 2625
7c9624 2626             def __init__(self, request):
MM 2627                 pass
0c29cf 2628
7c9624 2629             def __call__(self):
MM 2630                 return 'OK'
0c29cf 2631
7c9624 2632         config = self._makeOne(autocommit=True)
0c29cf 2633         config.add_forbidden_view(view=view, renderer=null_renderer)
7c9624 2634         wrapper = self._getViewCallable(
0c29cf 2635             config,
MM 2636             exc_iface=implementedBy(HTTPForbidden),
2637             request_iface=IRequest,
2638         )
7c9624 2639         context = DummyContext()
MM 2640         directlyProvides(context, IDummy)
2641         request = self._makeRequest(config)
2642         self.assertEqual(wrapper(context, request), 'OK')
2643         context = DummyContext()
2644         request = self._makeRequest(config)
2645         self.assertRaises(PredicateMismatch, wrapper, context, request)
2646
0db4a1 2647     def test_add_notfound_view(self):
2c1f9e 2648         from pyramid.renderers import null_renderer
CM 2649         from zope.interface import implementedBy
2650         from pyramid.interfaces import IRequest
2651         from pyramid.httpexceptions import HTTPNotFound
0c29cf 2652
2c1f9e 2653         config = self._makeOne(autocommit=True)
CM 2654         view = lambda *arg: arg
0db4a1 2655         config.add_notfound_view(view, renderer=null_renderer)
2c1f9e 2656         request = self._makeRequest(config)
0c29cf 2657         view = self._getViewCallable(
MM 2658             config,
2659             exc_iface=implementedBy(HTTPNotFound),
2660             request_iface=IRequest,
2661         )
2c1f9e 2662         result = view(None, request)
CM 2663         self.assertEqual(result, (None, request))
2664
f10d1e 2665     def test_add_notfound_view_no_view_argument(self):
DK 2666         from zope.interface import implementedBy
2667         from pyramid.interfaces import IRequest
2668         from pyramid.httpexceptions import HTTPNotFound
0c29cf 2669
f10d1e 2670         config = self._makeOne(autocommit=True)
DK 2671         config.setup_registry()
2672         config.add_notfound_view()
2673         request = self._makeRequest(config)
0c29cf 2674         view = self._getViewCallable(
MM 2675             config,
2676             exc_iface=implementedBy(HTTPNotFound),
2677             request_iface=IRequest,
2678         )
f10d1e 2679         context = HTTPNotFound()
DK 2680         result = view(context, request)
2681         self.assertEqual(result, context)
2682
8ec8e2 2683     def test_add_notfound_view_allows_other_predicates(self):
CM 2684         from pyramid.renderers import null_renderer
0c29cf 2685
8ec8e2 2686         config = self._makeOne(autocommit=True)
CM 2687         # doesnt blow up
2688         config.add_view_predicate('dummy', DummyPredicate)
2689         config.add_notfound_view(renderer=null_renderer, dummy='abc')
2690
2691     def test_add_notfound_view_disallows_name(self):
2692         config = self._makeOne(autocommit=True)
0c29cf 2693         self.assertRaises(
MM 2694             ConfigurationError, config.add_notfound_view, name='foo'
2695         )
8ec8e2 2696
CM 2697     def test_add_notfound_view_disallows_permission(self):
2698         config = self._makeOne(autocommit=True)
0c29cf 2699         self.assertRaises(
MM 2700             ConfigurationError, config.add_notfound_view, permission='foo'
2701         )
8ec8e2 2702
e8c66a 2703     def test_add_notfound_view_disallows_require_csrf(self):
MM 2704         config = self._makeOne(autocommit=True)
0c29cf 2705         self.assertRaises(
MM 2706             ConfigurationError, config.add_notfound_view, require_csrf=True
2707         )
e8c66a 2708
8ec8e2 2709     def test_add_notfound_view_disallows_context(self):
CM 2710         config = self._makeOne(autocommit=True)
0c29cf 2711         self.assertRaises(
MM 2712             ConfigurationError, config.add_notfound_view, context='foo'
2713         )
8ec8e2 2714
CM 2715     def test_add_notfound_view_disallows_for_(self):
2716         config = self._makeOne(autocommit=True)
0c29cf 2717         self.assertRaises(
MM 2718             ConfigurationError, config.add_notfound_view, for_='foo'
2719         )
42afb0 2720
0db4a1 2721     def test_add_notfound_view_append_slash(self):
CM 2722         from pyramid.response import Response
2c1f9e 2723         from pyramid.renderers import null_renderer
CM 2724         from zope.interface import implementedBy
2725         from pyramid.interfaces import IRequest
b5422e 2726         from pyramid.httpexceptions import HTTPTemporaryRedirect, HTTPNotFound
0c29cf 2727
2c1f9e 2728         config = self._makeOne(autocommit=True)
0db4a1 2729         config.add_route('foo', '/foo/')
0c29cf 2730
MM 2731         def view(request):
2732             return Response('OK')
2733
2734         config.add_notfound_view(
2735             view, renderer=null_renderer, append_slash=True
2736         )
2c1f9e 2737         request = self._makeRequest(config)
0db4a1 2738         request.environ['PATH_INFO'] = '/foo'
CM 2739         request.query_string = 'a=1&b=2'
2740         request.path = '/scriptname/foo'
0c29cf 2741         view = self._getViewCallable(
MM 2742             config,
2743             exc_iface=implementedBy(HTTPNotFound),
2744             request_iface=IRequest,
2745         )
2c1f9e 2746         result = view(None, request)
b5422e 2747         self.assertTrue(isinstance(result, HTTPTemporaryRedirect))
12b6f5 2748         self.assertEqual(result.location, '/scriptname/foo/?a=1&b=2')
DS 2749
2750     def test_add_notfound_view_append_slash_custom_response(self):
2751         from pyramid.response import Response
2752         from pyramid.renderers import null_renderer
2753         from zope.interface import implementedBy
2754         from pyramid.interfaces import IRequest
2755         from pyramid.httpexceptions import HTTPMovedPermanently, HTTPNotFound
0c29cf 2756
12b6f5 2757         config = self._makeOne(autocommit=True)
DS 2758         config.add_route('foo', '/foo/')
0c29cf 2759
MM 2760         def view(request):
2761             return Response('OK')
2762
12b6f5 2763         config.add_notfound_view(
0c29cf 2764             view, renderer=null_renderer, append_slash=HTTPMovedPermanently
12b6f5 2765         )
DS 2766         request = self._makeRequest(config)
2767         request.environ['PATH_INFO'] = '/foo'
2768         request.query_string = 'a=1&b=2'
2769         request.path = '/scriptname/foo'
0c29cf 2770         view = self._getViewCallable(
MM 2771             config,
2772             exc_iface=implementedBy(HTTPNotFound),
2773             request_iface=IRequest,
2774         )
12b6f5 2775         result = view(None, request)
DS 2776         self.assertTrue(isinstance(result, HTTPMovedPermanently))
0db4a1 2777         self.assertEqual(result.location, '/scriptname/foo/?a=1&b=2')
42afb0 2778
7c9624 2779     def test_add_notfound_view_with_view_defaults(self):
MM 2780         from pyramid.interfaces import IRequest
2781         from pyramid.renderers import null_renderer
2782         from pyramid.exceptions import PredicateMismatch
2783         from pyramid.httpexceptions import HTTPNotFound
2784         from zope.interface import directlyProvides
2785         from zope.interface import implementedBy
0c29cf 2786
7c9624 2787         class view(object):
0c29cf 2788             __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 2789
7c9624 2790             def __init__(self, request):
MM 2791                 pass
0c29cf 2792
7c9624 2793             def __call__(self):
MM 2794                 return 'OK'
0c29cf 2795
7c9624 2796         config = self._makeOne(autocommit=True)
0c29cf 2797         config.add_notfound_view(view=view, renderer=null_renderer)
7c9624 2798         wrapper = self._getViewCallable(
0c29cf 2799             config,
MM 2800             exc_iface=implementedBy(HTTPNotFound),
2801             request_iface=IRequest,
2802         )
7c9624 2803         context = DummyContext()
MM 2804         directlyProvides(context, IDummy)
2805         request = self._makeRequest(config)
2806         self.assertEqual(wrapper(context, request), 'OK')
2807         context = DummyContext()
2808         request = self._makeRequest(config)
2809         self.assertRaises(PredicateMismatch, wrapper, context, request)
2810
42afb0 2811     # Since Python 3 has to be all cool and fancy and different...
BJR 2812     def _assertBody(self, response, value):
2813         from pyramid.compat import text_type
0c29cf 2814
af01a5 2815         if isinstance(value, text_type):  # pragma: no cover
42afb0 2816             self.assertEqual(response.text, value)
af01a5 2817         else:  # pragma: no cover
42afb0 2818             self.assertEqual(response.body, value)
BJR 2819
5fc893 2820     def test_add_notfound_view_with_renderer(self):
BJR 2821         from zope.interface import implementedBy
2822         from pyramid.interfaces import IRequest
2823         from pyramid.httpexceptions import HTTPNotFound
0c29cf 2824
5fc893 2825         config = self._makeOne(autocommit=True)
BJR 2826         view = lambda *arg: {}
2827         config.introspection = False
0c29cf 2828         config.add_notfound_view(view, renderer='json')
89917f 2829         request = self._makeRequest(config)
0c29cf 2830         view = self._getViewCallable(
MM 2831             config,
2832             exc_iface=implementedBy(HTTPNotFound),
2833             request_iface=IRequest,
2834         )
89917f 2835         result = view(None, request)
42afb0 2836         self._assertBody(result, '{}')
5fc893 2837
BJR 2838     def test_add_forbidden_view_with_renderer(self):
2839         from zope.interface import implementedBy
2840         from pyramid.interfaces import IRequest
2841         from pyramid.httpexceptions import HTTPForbidden
0c29cf 2842
5fc893 2843         config = self._makeOne(autocommit=True)
BJR 2844         view = lambda *arg: {}
2845         config.introspection = False
0c29cf 2846         config.add_forbidden_view(view, renderer='json')
89917f 2847         request = self._makeRequest(config)
0c29cf 2848         view = self._getViewCallable(
MM 2849             config,
2850             exc_iface=implementedBy(HTTPForbidden),
2851             request_iface=IRequest,
2852         )
89917f 2853         result = view(None, request)
42afb0 2854         self._assertBody(result, '{}')
2c1f9e 2855
845d7b 2856     def test_set_view_mapper(self):
CM 2857         from pyramid.interfaces import IViewMapperFactory
0c29cf 2858
845d7b 2859         config = self._makeOne(autocommit=True)
CM 2860         mapper = object()
2861         config.set_view_mapper(mapper)
2862         result = config.registry.getUtility(IViewMapperFactory)
2863         self.assertEqual(result, mapper)
2864
2865     def test_set_view_mapper_dottedname(self):
2866         from pyramid.interfaces import IViewMapperFactory
0c29cf 2867
845d7b 2868         config = self._makeOne(autocommit=True)
dd3cc8 2869         config.set_view_mapper('tests.test_config')
845d7b 2870         result = config.registry.getUtility(IViewMapperFactory)
dd3cc8 2871         from tests import test_config
0c29cf 2872
845d7b 2873         self.assertEqual(result, test_config)
CM 2874
e8c66a 2875     def test_add_normal_and_exception_view_intr_derived_callable(self):
MM 2876         from pyramid.renderers import null_renderer
2877         from pyramid.exceptions import BadCSRFToken
0c29cf 2878
e8c66a 2879         config = self._makeOne(autocommit=True)
MM 2880         introspector = DummyIntrospector()
2881         config.introspector = introspector
2882         view = lambda r: 'OK'
2883         config.set_default_csrf_options(require_csrf=True)
2884         config.add_view(view, context=Exception, renderer=null_renderer)
a2c7c7 2885         view_intr = introspector.introspectables[-1]
e8c66a 2886         self.assertTrue(view_intr.type_name, 'view')
MM 2887         self.assertEqual(view_intr['callable'], view)
2888         derived_view = view_intr['derived_callable']
2889
2890         request = self._makeRequest(config)
2891         request.method = 'POST'
2892         request.scheme = 'http'
2893         request.POST = {}
2894         request.headers = {}
2895         request.session = DummySession({'csrf_token': 'foo'})
2896         self.assertRaises(BadCSRFToken, lambda: derived_view(None, request))
2897         request.exception = Exception()
2898         self.assertEqual(derived_view(None, request), 'OK')
2899
bd82c8 2900     def test_add_view_does_not_accept_iterable_accept(self):
MM 2901         from pyramid.exceptions import ConfigurationError
0c29cf 2902
bd82c8 2903         config = self._makeOne(autocommit=True)
MM 2904         self.assertRaises(
0c29cf 2905             ConfigurationError, config.add_view, accept=['image/*', 'text/*']
bd82c8 2906         )
MM 2907
2908     def test_default_accept_view_order(self):
2909         from pyramid.interfaces import IAcceptOrder
0c29cf 2910
bd82c8 2911         config = self._makeOne(autocommit=True)
MM 2912         order = config.registry.getUtility(IAcceptOrder)
2913         result = [v for _, v in order.sorted()]
0c29cf 2914         self.assertEqual(
MM 2915             result,
2916             [
2917                 'text/html',
2918                 'application/xhtml+xml',
2919                 'application/xml',
2920                 'text/xml',
2921                 'text/plain',
2922                 'application/json',
2923             ],
2924         )
bd82c8 2925
MM 2926     def test_add_accept_view_order_override(self):
2927         from pyramid.interfaces import IAcceptOrder
0c29cf 2928
bd82c8 2929         config = self._makeOne(autocommit=False)
MM 2930         config.add_accept_view_order(
2931             'text/html',
2932             weighs_more_than='text/xml',
2933             weighs_less_than='application/xml',
2934         )
2935         config.commit()
2936         order = config.registry.getUtility(IAcceptOrder)
2937         result = [v for _, v in order.sorted()]
0c29cf 2938         self.assertEqual(
MM 2939             result,
2940             [
2941                 'application/xhtml+xml',
2942                 'application/xml',
2943                 'text/html',
2944                 'text/xml',
2945                 'text/plain',
2946                 'application/json',
2947             ],
2948         )
bd82c8 2949
MM 2950     def test_add_accept_view_order_throws_on_wildcard(self):
2951         config = self._makeOne(autocommit=True)
0c29cf 2952         self.assertRaises(ValueError, config.add_accept_view_order, '*/*')
bd82c8 2953
MM 2954     def test_add_accept_view_order_throws_on_type_mismatch(self):
2955         config = self._makeOne(autocommit=True)
2956         self.assertRaises(
0c29cf 2957             ValueError,
MM 2958             config.add_accept_view_order,
2959             'text/*',
2960             weighs_more_than='text/html',
bd82c8 2961         )
MM 2962         self.assertRaises(
0c29cf 2963             ValueError,
MM 2964             config.add_accept_view_order,
2965             'text/html',
2966             weighs_less_than='application/*',
bd82c8 2967         )
MM 2968         self.assertRaises(
0c29cf 2969             ConfigurationError,
MM 2970             config.add_accept_view_order,
2971             'text/html',
2972             weighs_more_than='text/html;charset=utf8',
bd82c8 2973         )
MM 2974         self.assertRaises(
0c29cf 2975             ConfigurationError,
MM 2976             config.add_accept_view_order,
bd82c8 2977             'text/html;charset=utf8',
MM 2978             weighs_more_than='text/plain;charset=utf8',
2979         )
2980
0c29cf 2981
e8c66a 2982 class Test_runtime_exc_view(unittest.TestCase):
MM 2983     def _makeOne(self, view1, view2):
2984         from pyramid.config.views import runtime_exc_view
0c29cf 2985
e8c66a 2986         return runtime_exc_view(view1, view2)
MM 2987
2988     def test_call(self):
0c29cf 2989         def view1(context, request):
MM 2990             return 'OK'
2991
2992         def view2(context, request):
2993             raise AssertionError
2994
e8c66a 2995         result_view = self._makeOne(view1, view2)
MM 2996         request = DummyRequest()
2997         result = result_view(None, request)
2998         self.assertEqual(result, 'OK')
2999
3000     def test_call_dispatches_on_exception(self):
0c29cf 3001         def view1(context, request):
MM 3002             raise AssertionError
3003
3004         def view2(context, request):
3005             return 'OK'
3006
e8c66a 3007         result_view = self._makeOne(view1, view2)
MM 3008         request = DummyRequest()
3009         request.exception = Exception()
3010         result = result_view(None, request)
3011         self.assertEqual(result, 'OK')
3012
3013     def test_permitted(self):
0c29cf 3014         def errfn(context, request):
MM 3015             raise AssertionError
3016
3017         def view1(context, request):
3018             raise AssertionError
3019
e8c66a 3020         view1.__permitted__ = lambda c, r: 'OK'
0c29cf 3021
MM 3022         def view2(context, request):
3023             raise AssertionError
3024
e8c66a 3025         view2.__permitted__ = errfn
MM 3026         result_view = self._makeOne(view1, view2)
3027         request = DummyRequest()
3028         result = result_view.__permitted__(None, request)
3029         self.assertEqual(result, 'OK')
3030
3031     def test_permitted_dispatches_on_exception(self):
0c29cf 3032         def errfn(context, request):
MM 3033             raise AssertionError
3034
3035         def view1(context, request):
3036             raise AssertionError
3037
e8c66a 3038         view1.__permitted__ = errfn
0c29cf 3039
MM 3040         def view2(context, request):
3041             raise AssertionError
3042
e8c66a 3043         view2.__permitted__ = lambda c, r: 'OK'
MM 3044         result_view = self._makeOne(view1, view2)
3045         request = DummyRequest()
3046         request.exception = Exception()
3047         result = result_view.__permitted__(None, request)
3048         self.assertEqual(result, 'OK')
3049
0c29cf 3050
5bf23f 3051 class Test_requestonly(unittest.TestCase):
CM 3052     def _callFUT(self, view, attr=None):
3053         from pyramid.config.views import requestonly
0c29cf 3054
28fc3d 3055         return requestonly(view, attr=attr)
5bf23f 3056
28fc3d 3057     def test_defaults(self):
0c29cf 3058         def aview(request, a=1, b=2):
MM 3059             pass
3060
28fc3d 3061         self.assertTrue(self._callFUT(aview))
5bf23f 3062
28fc3d 3063     def test_otherattr(self):
CM 3064         class AView(object):
0c29cf 3065             def __init__(self, request, a=1, b=2):
MM 3066                 pass
3067
3068             def bleh(self):
3069                 pass
3070
28fc3d 3071         self.assertTrue(self._callFUT(AView, 'bleh'))
0c29cf 3072
5bf23f 3073
CM 3074 class Test_isexception(unittest.TestCase):
3075     def _callFUT(self, ob):
3076         from pyramid.config.views import isexception
0c29cf 3077
5bf23f 3078         return isexception(ob)
CM 3079
3080     def test_is_exception_instance(self):
3081         class E(Exception):
3082             pass
0c29cf 3083
5bf23f 3084         e = E()
CM 3085         self.assertEqual(self._callFUT(e), True)
3086
3087     def test_is_exception_class(self):
3088         class E(Exception):
3089             pass
0c29cf 3090
5bf23f 3091         self.assertEqual(self._callFUT(E), True)
CM 3092
3093     def test_is_IException(self):
3094         from pyramid.interfaces import IException
0c29cf 3095
5bf23f 3096         self.assertEqual(self._callFUT(IException), True)
CM 3097
3098     def test_is_IException_subinterface(self):
3099         from pyramid.interfaces import IException
0c29cf 3100
5bf23f 3101         class ISubException(IException):
CM 3102             pass
0c29cf 3103
5bf23f 3104         self.assertEqual(self._callFUT(ISubException), True)
0c29cf 3105
5bf23f 3106
CM 3107 class TestMultiView(unittest.TestCase):
3108     def _getTargetClass(self):
3109         from pyramid.config.views import MultiView
0c29cf 3110
5bf23f 3111         return MultiView
CM 3112
3113     def _makeOne(self, name='name'):
3114         return self._getTargetClass()(name)
3115
3116     def test_class_implements_ISecuredView(self):
3117         from zope.interface.verify import verifyClass
3118         from pyramid.interfaces import ISecuredView
0c29cf 3119
5bf23f 3120         verifyClass(ISecuredView, self._getTargetClass())
CM 3121
3122     def test_instance_implements_ISecuredView(self):
3123         from zope.interface.verify import verifyObject
3124         from pyramid.interfaces import ISecuredView
0c29cf 3125
5bf23f 3126         verifyObject(ISecuredView, self._makeOne())
CM 3127
3128     def test_add(self):
3129         mv = self._makeOne()
3130         mv.add('view', 100)
3131         self.assertEqual(mv.views, [(100, 'view', None)])
3132         mv.add('view2', 99)
3133         self.assertEqual(mv.views, [(99, 'view2', None), (100, 'view', None)])
c3c83e 3134         mv.add('view3', 100, accept='text/html')
5bf23f 3135         self.assertEqual(mv.media_views['text/html'], [(100, 'view3', None)])
c3c83e 3136         mv.add('view4', 99, 'abc', accept='text/html')
0c29cf 3137         self.assertEqual(
MM 3138             mv.media_views['text/html'],
3139             [(99, 'view4', 'abc'), (100, 'view3', None)],
3140         )
c3c83e 3141         mv.add('view5', 100, accept='text/xml')
f4b7fd 3142         self.assertEqual(mv.media_views['text/xml'], [(100, 'view5', None)])
5bf23f 3143         self.assertEqual(set(mv.accepts), set(['text/xml', 'text/html']))
CM 3144         self.assertEqual(mv.views, [(99, 'view2', None), (100, 'view', None)])
c3c83e 3145         mv.add('view6', 98, accept='text/*')
0c29cf 3146         self.assertEqual(
MM 3147             mv.views,
3148             [(98, 'view6', None), (99, 'view2', None), (100, 'view', None)],
3149         )
5bf23f 3150
CM 3151     def test_add_with_phash(self):
3152         mv = self._makeOne()
3153         mv.add('view', 100, phash='abc')
3154         self.assertEqual(mv.views, [(100, 'view', 'abc')])
3155         mv.add('view', 100, phash='abc')
3156         self.assertEqual(mv.views, [(100, 'view', 'abc')])
3157         mv.add('view', 100, phash='def')
0c29cf 3158         self.assertEqual(
MM 3159             mv.views, [(100, 'view', 'abc'), (100, 'view', 'def')]
3160         )
5bf23f 3161         mv.add('view', 100, phash='abc')
0c29cf 3162         self.assertEqual(
MM 3163             mv.views, [(100, 'view', 'abc'), (100, 'view', 'def')]
3164         )
392937 3165
f4b7fd 3166     def test_add_with_phash_override_accept(self):
DN 3167         mv = self._makeOne()
0c29cf 3168
MM 3169         def view1():
3170             pass
3171
3172         def view2():
3173             pass
3174
3175         def view3():
3176             pass
3177
a9289d 3178         mv.add(view1, 100, accept='text/html', phash='abc')
CM 3179         mv.add(view2, 100, accept='text/html', phash='abc')
3180         mv.add(view3, 99, accept='text/html', phash='def')
0c29cf 3181         self.assertEqual(
MM 3182             mv.media_views['text/html'],
3183             [(99, view3, 'def'), (100, view2, 'abc')],
3184         )
a9289d 3185
CM 3186     def test_add_with_phash_override_accept2(self):
3187         mv = self._makeOne()
0c29cf 3188
MM 3189         def view1():
3190             pass
3191
3192         def view2():
3193             pass
3194
3195         def view3():
3196             pass
3197
a9289d 3198         mv.add(view1, 100, accept='text/html', phash='abc')
CM 3199         mv.add(view2, 100, accept='text/html', phash='def')
3200         mv.add(view3, 99, accept='text/html', phash='ghi')
0c29cf 3201         self.assertEqual(
MM 3202             mv.media_views['text/html'],
3203             [(99, view3, 'ghi'), (100, view1, 'abc'), (100, view2, 'def')],
3204         )
f4b7fd 3205
392937 3206     def test_multiple_with_functions_as_views(self):
CM 3207         # this failed on py3 at one point, because functions aren't orderable
3208         # and we were sorting the views via a plain sort() rather than
3209         # sort(key=itemgetter(0)).
0c29cf 3210         def view1(request):
MM 3211             pass
3212
3213         def view2(request):
3214             pass
3215
392937 3216         mv = self._makeOne()
CM 3217         mv.add(view1, 100, None)
3218         self.assertEqual(mv.views, [(100, view1, None)])
3219         mv.add(view2, 100, None)
3220         self.assertEqual(mv.views, [(100, view1, None), (100, view2, None)])
5bf23f 3221
CM 3222     def test_get_views_request_has_no_accept(self):
3223         request = DummyRequest()
3224         mv = self._makeOne()
3225         mv.views = [(99, lambda *arg: None)]
3226         self.assertEqual(mv.get_views(request), mv.views)
3227
3228     def test_get_views_no_self_accepts(self):
3229         request = DummyRequest()
3230         request.accept = True
3231         mv = self._makeOne()
3232         mv.accepts = []
3233         mv.views = [(99, lambda *arg: None)]
3234         self.assertEqual(mv.get_views(request), mv.views)
3235
3236     def test_get_views(self):
3237         request = DummyRequest()
3238         request.accept = DummyAccept('text/html')
3239         mv = self._makeOne()
3240         mv.accepts = ['text/html']
3241         mv.views = [(99, lambda *arg: None)]
3242         html_views = [(98, lambda *arg: None)]
3243         mv.media_views['text/html'] = html_views
3244         self.assertEqual(mv.get_views(request), html_views + mv.views)
3245
3246     def test_get_views_best_match_returns_None(self):
3247         request = DummyRequest()
3248         request.accept = DummyAccept(None)
3249         mv = self._makeOne()
3250         mv.accepts = ['text/html']
3251         mv.views = [(99, lambda *arg: None)]
3252         self.assertEqual(mv.get_views(request), mv.views)
3253
3254     def test_match_not_found(self):
3255         from pyramid.httpexceptions import HTTPNotFound
0c29cf 3256
5bf23f 3257         mv = self._makeOne()
CM 3258         context = DummyContext()
3259         request = DummyRequest()
3260         self.assertRaises(HTTPNotFound, mv.match, context, request)
3261
3262     def test_match_predicate_fails(self):
3263         from pyramid.httpexceptions import HTTPNotFound
0c29cf 3264
5bf23f 3265         mv = self._makeOne()
0c29cf 3266
5bf23f 3267         def view(context, request):
CM 3268             """ """
0c29cf 3269
5bf23f 3270         view.__predicated__ = lambda *arg: False
CM 3271         mv.views = [(100, view, None)]
3272         context = DummyContext()
3273         request = DummyRequest()
3274         self.assertRaises(HTTPNotFound, mv.match, context, request)
3275
3276     def test_match_predicate_succeeds(self):
3277         mv = self._makeOne()
0c29cf 3278
5bf23f 3279         def view(context, request):
CM 3280             """ """
0c29cf 3281
5bf23f 3282         view.__predicated__ = lambda *arg: True
CM 3283         mv.views = [(100, view, None)]
3284         context = DummyContext()
3285         request = DummyRequest()
3286         result = mv.match(context, request)
3287         self.assertEqual(result, view)
3288
3289     def test_permitted_no_views(self):
3290         from pyramid.httpexceptions import HTTPNotFound
0c29cf 3291
5bf23f 3292         mv = self._makeOne()
CM 3293         context = DummyContext()
3294         request = DummyRequest()
3295         self.assertRaises(HTTPNotFound, mv.__permitted__, context, request)
3296
3297     def test_permitted_no_match_with__permitted__(self):
3298         mv = self._makeOne()
0c29cf 3299
5bf23f 3300         def view(context, request):
CM 3301             """ """
0c29cf 3302
5bf23f 3303         mv.views = [(100, view, None)]
CM 3304         self.assertEqual(mv.__permitted__(None, None), True)
3305
3306     def test_permitted(self):
3307         mv = self._makeOne()
0c29cf 3308
5bf23f 3309         def view(context, request):
CM 3310             """ """
0c29cf 3311
5bf23f 3312         def permitted(context, request):
CM 3313             return False
0c29cf 3314
5bf23f 3315         view.__permitted__ = permitted
CM 3316         mv.views = [(100, view, None)]
3317         context = DummyContext()
3318         request = DummyRequest()
3319         result = mv.__permitted__(context, request)
3320         self.assertEqual(result, False)
3321
3322     def test__call__not_found(self):
3323         from pyramid.httpexceptions import HTTPNotFound
0c29cf 3324
5bf23f 3325         mv = self._makeOne()
CM 3326         context = DummyContext()
3327         request = DummyRequest()
3328         self.assertRaises(HTTPNotFound, mv, context, request)
3329
3330     def test___call__intermediate_not_found(self):
3331         from pyramid.exceptions import PredicateMismatch
0c29cf 3332
5bf23f 3333         mv = self._makeOne()
CM 3334         context = DummyContext()
3335         request = DummyRequest()
3336         request.view_name = ''
3337         expected_response = DummyResponse()
0c29cf 3338
5bf23f 3339         def view1(context, request):
CM 3340             raise PredicateMismatch
0c29cf 3341
5bf23f 3342         def view2(context, request):
CM 3343             return expected_response
0c29cf 3344
5bf23f 3345         mv.views = [(100, view1, None), (99, view2, None)]
CM 3346         response = mv(context, request)
3347         self.assertEqual(response, expected_response)
3348
3349     def test___call__raise_not_found_isnt_interpreted_as_pred_mismatch(self):
3350         from pyramid.httpexceptions import HTTPNotFound
0c29cf 3351
5bf23f 3352         mv = self._makeOne()
CM 3353         context = DummyContext()
3354         request = DummyRequest()
3355         request.view_name = ''
0c29cf 3356
5bf23f 3357         def view1(context, request):
0c29cf 3358             raise HTTPNotFound
MM 3359
5bf23f 3360         def view2(context, request):
CM 3361             """ """
0c29cf 3362
5bf23f 3363         mv.views = [(100, view1, None), (99, view2, None)]
CM 3364         self.assertRaises(HTTPNotFound, mv, context, request)
3365
3366     def test___call__(self):
3367         mv = self._makeOne()
3368         context = DummyContext()
3369         request = DummyRequest()
3370         request.view_name = ''
3371         expected_response = DummyResponse()
0c29cf 3372
5bf23f 3373         def view(context, request):
CM 3374             return expected_response
0c29cf 3375
5bf23f 3376         mv.views = [(100, view, None)]
CM 3377         response = mv(context, request)
3378         self.assertEqual(response, expected_response)
3379
3380     def test__call_permissive__not_found(self):
3381         from pyramid.httpexceptions import HTTPNotFound
0c29cf 3382
5bf23f 3383         mv = self._makeOne()
CM 3384         context = DummyContext()
3385         request = DummyRequest()
3386         self.assertRaises(HTTPNotFound, mv, context, request)
3387
3388     def test___call_permissive_has_call_permissive(self):
3389         mv = self._makeOne()
3390         context = DummyContext()
3391         request = DummyRequest()
3392         request.view_name = ''
3393         expected_response = DummyResponse()
0c29cf 3394
5bf23f 3395         def view(context, request):
CM 3396             """ """
0c29cf 3397
5bf23f 3398         def permissive(context, request):
CM 3399             return expected_response
0c29cf 3400
5bf23f 3401         view.__call_permissive__ = permissive
CM 3402         mv.views = [(100, view, None)]
3403         response = mv.__call_permissive__(context, request)
3404         self.assertEqual(response, expected_response)
3405
3406     def test___call_permissive_has_no_call_permissive(self):
3407         mv = self._makeOne()
3408         context = DummyContext()
3409         request = DummyRequest()
3410         request.view_name = ''
3411         expected_response = DummyResponse()
0c29cf 3412
5bf23f 3413         def view(context, request):
CM 3414             return expected_response
0c29cf 3415
5bf23f 3416         mv.views = [(100, view, None)]
CM 3417         response = mv.__call_permissive__(context, request)
3418         self.assertEqual(response, expected_response)
3419
3420     def test__call__with_accept_match(self):
3421         mv = self._makeOne()
3422         context = DummyContext()
3423         request = DummyRequest()
3424         request.accept = DummyAccept('text/html', 'text/xml')
3425         expected_response = DummyResponse()
0c29cf 3426
5bf23f 3427         def view(context, request):
CM 3428             return expected_response
0c29cf 3429
5bf23f 3430         mv.views = [(100, None)]
CM 3431         mv.media_views['text/xml'] = [(100, view, None)]
3432         mv.accepts = ['text/xml']
3433         response = mv(context, request)
3434         self.assertEqual(response, expected_response)
3435
3436     def test__call__with_accept_miss(self):
3437         mv = self._makeOne()
3438         context = DummyContext()
3439         request = DummyRequest()
3440         request.accept = DummyAccept('text/plain', 'text/html')
3441         expected_response = DummyResponse()
0c29cf 3442
5bf23f 3443         def view(context, request):
CM 3444             return expected_response
0c29cf 3445
5bf23f 3446         mv.views = [(100, view, None)]
CM 3447         mv.media_views['text/xml'] = [(100, None, None)]
3448         mv.accepts = ['text/xml']
3449         response = mv(context, request)
3450         self.assertEqual(response, expected_response)
3451
3452
3453 class TestDefaultViewMapper(unittest.TestCase):
3454     def setUp(self):
3455         self.config = testing.setUp()
42afb0 3456         self.registry = self.config.registry
5bf23f 3457
CM 3458     def tearDown(self):
3459         del self.registry
3460         testing.tearDown()
3461
3462     def _makeOne(self, **kw):
3463         from pyramid.config.views import DefaultViewMapper
0c29cf 3464
5bf23f 3465         kw['registry'] = self.registry
CM 3466         return DefaultViewMapper(**kw)
3467
3468     def _makeRequest(self):
3469         request = DummyRequest()
3470         request.registry = self.registry
3471         return request
3472
3473     def test_view_as_function_context_and_request(self):
3474         def view(context, request):
3475             return 'OK'
0c29cf 3476
5bf23f 3477         mapper = self._makeOne()
CM 3478         result = mapper(view)
3479         self.assertTrue(result is view)
3480         request = self._makeRequest()
3481         self.assertEqual(result(None, request), 'OK')
3482
3483     def test__view_as_function_with_attr(self):
3484         def view(context, request):
3485             """ """
0c29cf 3486
5bf23f 3487         mapper = self._makeOne(attr='__name__')
CM 3488         result = mapper(view)
3489         self.assertFalse(result is view)
3490         request = self._makeRequest()
3491         self.assertRaises(TypeError, result, None, request)
3492
3493     def test_view_as_function_requestonly(self):
3494         def view(request):
3495             return 'OK'
0c29cf 3496
5bf23f 3497         mapper = self._makeOne()
CM 3498         result = mapper(view)
3499         self.assertFalse(result is view)
3500         request = self._makeRequest()
3501         self.assertEqual(result(None, request), 'OK')
3502
3503     def test_view_as_function_requestonly_with_attr(self):
3504         def view(request):
3505             """ """
0c29cf 3506
5bf23f 3507         mapper = self._makeOne(attr='__name__')
CM 3508         result = mapper(view)
3509         self.assertFalse(result is view)
3510         request = self._makeRequest()
3511         self.assertRaises(TypeError, result, None, request)
3512
3513     def test_view_as_newstyle_class_context_and_request(self):
3514         class view(object):
3515             def __init__(self, context, request):
3516                 pass
0c29cf 3517
5bf23f 3518             def __call__(self):
CM 3519                 return 'OK'
0c29cf 3520
5bf23f 3521         mapper = self._makeOne()
CM 3522         result = mapper(view)
3523         self.assertFalse(result is view)
3524         request = self._makeRequest()
3525         self.assertEqual(result(None, request), 'OK')
3526
3527     def test_view_as_newstyle_class_context_and_request_with_attr(self):
3528         class view(object):
3529             def __init__(self, context, request):
3530                 pass
0c29cf 3531
5bf23f 3532             def index(self):
CM 3533                 return 'OK'
0c29cf 3534
5bf23f 3535         mapper = self._makeOne(attr='index')
CM 3536         result = mapper(view)
3537         self.assertFalse(result is view)
3538         request = self._makeRequest()
3539         self.assertEqual(result(None, request), 'OK')
3540
3541     def test_view_as_newstyle_class_requestonly(self):
3542         class view(object):
3543             def __init__(self, request):
3544                 pass
0c29cf 3545
5bf23f 3546             def __call__(self):
CM 3547                 return 'OK'
0c29cf 3548
5bf23f 3549         mapper = self._makeOne()
CM 3550         result = mapper(view)
3551         self.assertFalse(result is view)
3552         request = self._makeRequest()
3553         self.assertEqual(result(None, request), 'OK')
3554
3555     def test_view_as_newstyle_class_requestonly_with_attr(self):
3556         class view(object):
3557             def __init__(self, request):
3558                 pass
0c29cf 3559
5bf23f 3560             def index(self):
CM 3561                 return 'OK'
0c29cf 3562
5bf23f 3563         mapper = self._makeOne(attr='index')
CM 3564         result = mapper(view)
3565         self.assertFalse(result is view)
3566         request = self._makeRequest()
3567         self.assertEqual(result(None, request), 'OK')
3568
3569     def test_view_as_oldstyle_class_context_and_request(self):
3570         class view:
3571             def __init__(self, context, request):
3572                 pass
0c29cf 3573
5bf23f 3574             def __call__(self):
CM 3575                 return 'OK'
0c29cf 3576
5bf23f 3577         mapper = self._makeOne()
CM 3578         result = mapper(view)
3579         self.assertFalse(result is view)
3580         request = self._makeRequest()
3581         self.assertEqual(result(None, request), 'OK')
3582
3583     def test_view_as_oldstyle_class_context_and_request_with_attr(self):
3584         class view:
3585             def __init__(self, context, request):
3586                 pass
0c29cf 3587
5bf23f 3588             def index(self):
CM 3589                 return 'OK'
0c29cf 3590
5bf23f 3591         mapper = self._makeOne(attr='index')
CM 3592         result = mapper(view)
3593         self.assertFalse(result is view)
3594         request = self._makeRequest()
3595         self.assertEqual(result(None, request), 'OK')
3596
3597     def test_view_as_oldstyle_class_requestonly(self):
3598         class view:
3599             def __init__(self, request):
3600                 pass
0c29cf 3601
5bf23f 3602             def __call__(self):
CM 3603                 return 'OK'
0c29cf 3604
5bf23f 3605         mapper = self._makeOne()
CM 3606         result = mapper(view)
3607         self.assertFalse(result is view)
3608         request = self._makeRequest()
3609         self.assertEqual(result(None, request), 'OK')
3610
3611     def test_view_as_oldstyle_class_requestonly_with_attr(self):
3612         class view:
3613             def __init__(self, request):
3614                 pass
0c29cf 3615
5bf23f 3616             def index(self):
CM 3617                 return 'OK'
0c29cf 3618
5bf23f 3619         mapper = self._makeOne(attr='index')
CM 3620         result = mapper(view)
3621         self.assertFalse(result is view)
3622         request = self._makeRequest()
3623         self.assertEqual(result(None, request), 'OK')
3624
3625     def test_view_as_instance_context_and_request(self):
3626         class View:
3627             def __call__(self, context, request):
3628                 return 'OK'
0c29cf 3629
5bf23f 3630         view = View()
CM 3631         mapper = self._makeOne()
3632         result = mapper(view)
3633         self.assertTrue(result is view)
3634         request = self._makeRequest()
3635         self.assertEqual(result(None, request), 'OK')
3636
3637     def test_view_as_instance_context_and_request_and_attr(self):
3638         class View:
3639             def index(self, context, request):
3640                 return 'OK'
0c29cf 3641
5bf23f 3642         view = View()
CM 3643         mapper = self._makeOne(attr='index')
3644         result = mapper(view)
3645         self.assertFalse(result is view)
3646         request = self._makeRequest()
3647         self.assertEqual(result(None, request), 'OK')
3648
3649     def test_view_as_instance_requestonly(self):
3650         class View:
3651             def __call__(self, request):
3652                 return 'OK'
0c29cf 3653
5bf23f 3654         view = View()
CM 3655         mapper = self._makeOne()
3656         result = mapper(view)
3657         self.assertFalse(result is view)
3658         request = self._makeRequest()
3659         self.assertEqual(result(None, request), 'OK')
3660
3661     def test_view_as_instance_requestonly_with_attr(self):
3662         class View:
3663             def index(self, request):
3664                 return 'OK'
0c29cf 3665
5bf23f 3666         view = View()
CM 3667         mapper = self._makeOne(attr='index')
3668         result = mapper(view)
3669         self.assertFalse(result is view)
3670         request = self._makeRequest()
3671         self.assertEqual(result(None, request), 'OK')
3672
0c29cf 3673
5bf23f 3674 class Test_preserve_view_attrs(unittest.TestCase):
CM 3675     def _callFUT(self, view, wrapped_view):
3676         from pyramid.config.views import preserve_view_attrs
0c29cf 3677
5bf23f 3678         return preserve_view_attrs(view, wrapped_view)
CM 3679
3680     def test_it_same(self):
3681         def view(context, request):
3682             """ """
0c29cf 3683
5bf23f 3684         result = self._callFUT(view, view)
CM 3685         self.assertTrue(result is view)
3686
d9ea46 3687     def test_it_view_is_None(self):
CM 3688         def view(context, request):
3689             """ """
0c29cf 3690
d9ea46 3691         result = self._callFUT(None, view)
CM 3692         self.assertTrue(result is view)
3693
5bf23f 3694     def test_it_different_with_existing_original_view(self):
0c29cf 3695         def view1(context, request):
MM 3696             pass
3697
5bf23f 3698         view1.__original_view__ = 'abc'
0c29cf 3699
MM 3700         def view2(context, request):
3701             pass
3702
5bf23f 3703         result = self._callFUT(view1, view2)
CM 3704         self.assertEqual(result.__original_view__, 'abc')
3705         self.assertFalse(result is view1)
3706
3707     def test_it_different(self):
3708         class DummyView1:
3709             """ 1 """
0c29cf 3710
5bf23f 3711             __name__ = '1'
CM 3712             __module__ = '1'
0c29cf 3713
5bf23f 3714             def __call__(self, context, request):
CM 3715                 """ """
0c29cf 3716
5bf23f 3717             def __call_permissive__(self, context, request):
CM 3718                 """ """
0c29cf 3719
5bf23f 3720             def __predicated__(self, context, request):
CM 3721                 """ """
0c29cf 3722
5bf23f 3723             def __permitted__(self, context, request):
CM 3724                 """ """
0c29cf 3725
5bf23f 3726         class DummyView2:
CM 3727             """ 2 """
0c29cf 3728
5bf23f 3729             __name__ = '2'
CM 3730             __module__ = '2'
0c29cf 3731
5bf23f 3732             def __call__(self, context, request):
CM 3733                 """ """
0c29cf 3734
5bf23f 3735             def __call_permissive__(self, context, request):
CM 3736                 """ """
0c29cf 3737
5bf23f 3738             def __predicated__(self, context, request):
CM 3739                 """ """
0c29cf 3740
5bf23f 3741             def __permitted__(self, context, request):
CM 3742                 """ """
0c29cf 3743
5bf23f 3744         view1 = DummyView1()
CM 3745         view2 = DummyView2()
3746         result = self._callFUT(view2, view1)
3747         self.assertEqual(result, view1)
3748         self.assertTrue(view1.__original_view__ is view2)
3749         self.assertTrue(view1.__doc__ is view2.__doc__)
3750         self.assertTrue(view1.__module__ is view2.__module__)
3751         self.assertTrue(view1.__name__ is view2.__name__)
0c29cf 3752         self.assertTrue(
MM 3753             getattr(view1.__call_permissive__, im_func)
3754             is getattr(view2.__call_permissive__, im_func)
3755         )
3756         self.assertTrue(
3757             getattr(view1.__permitted__, im_func)
3758             is getattr(view2.__permitted__, im_func)
3759         )
3760         self.assertTrue(
3761             getattr(view1.__predicated__, im_func)
3762             is getattr(view2.__predicated__, im_func)
3763         )
5bf23f 3764
CM 3765
53d9d4 3766 class TestStaticURLInfo(unittest.TestCase):
CM 3767     def _getTargetClass(self):
3768         from pyramid.config.views import StaticURLInfo
0c29cf 3769
53d9d4 3770         return StaticURLInfo
42afb0 3771
cda7f6 3772     def _makeOne(self):
CM 3773         return self._getTargetClass()()
3774
3775     def _makeRequest(self):
3776         request = DummyRequest()
3777         request.registry = DummyRegistry()
3778         return request
53d9d4 3779
CM 3780     def test_verifyClass(self):
3781         from pyramid.interfaces import IStaticURLInfo
3782         from zope.interface.verify import verifyClass
0c29cf 3783
53d9d4 3784         verifyClass(IStaticURLInfo, self._getTargetClass())
CM 3785
3786     def test_verifyObject(self):
3787         from pyramid.interfaces import IStaticURLInfo
3788         from zope.interface.verify import verifyObject
0c29cf 3789
cda7f6 3790         verifyObject(IStaticURLInfo, self._makeOne())
53d9d4 3791
CM 3792     def test_generate_missing(self):
cda7f6 3793         inst = self._makeOne()
CM 3794         request = self._makeRequest()
53d9d4 3795         self.assertRaises(ValueError, inst.generate, 'path', request)
CM 3796
3797     def test_generate_registration_miss(self):
cda7f6 3798         inst = self._makeOne()
5e3439 3799         inst.registrations = [
MM 3800             (None, 'spec', 'route_name'),
0c29cf 3801             ('http://example.com/foo/', 'package:path/', None),
MM 3802         ]
cda7f6 3803         request = self._makeRequest()
f3b6a3 3804         result = inst.generate('package:path/abc', request)
CM 3805         self.assertEqual(result, 'http://example.com/foo/abc')
3806
53d9d4 3807     def test_generate_slash_in_name1(self):
cda7f6 3808         inst = self._makeOne()
0c29cf 3809         inst.registrations = [
MM 3810             ('http://example.com/foo/', 'package:path/', None)
3811         ]
cda7f6 3812         request = self._makeRequest()
53d9d4 3813         result = inst.generate('package:path/abc', request)
CM 3814         self.assertEqual(result, 'http://example.com/foo/abc')
3815
3816     def test_generate_slash_in_name2(self):
cda7f6 3817         inst = self._makeOne()
0c29cf 3818         inst.registrations = [
MM 3819             ('http://example.com/foo/', 'package:path/', None)
3820         ]
cda7f6 3821         request = self._makeRequest()
53d9d4 3822         result = inst.generate('package:path/', request)
CM 3823         self.assertEqual(result, 'http://example.com/foo/')
3824
05f462 3825     def test_generate_quoting(self):
5e3439 3826         from pyramid.interfaces import IStaticURLInfo
0c29cf 3827
05f462 3828         config = testing.setUp()
CM 3829         try:
3830             config.add_static_view('images', path='mypkg:templates')
3831             request = testing.DummyRequest()
3832             request.registry = config.registry
5e3439 3833             inst = config.registry.getUtility(IStaticURLInfo)
05f462 3834             result = inst.generate('mypkg:templates/foo%2Fbar', request)
CM 3835             self.assertEqual(result, 'http://example.com/images/foo%252Fbar')
3836         finally:
3837             testing.tearDown()
3838
53d9d4 3839     def test_generate_route_url(self):
cda7f6 3840         inst = self._makeOne()
5e3439 3841         inst.registrations = [(None, 'package:path/', '__viewname/')]
0c29cf 3842
cda7f6 3843         def route_url(n, **kw):
bc9357 3844             self.assertEqual(n, '__viewname/')
0c29cf 3845             self.assertEqual(kw, {'subpath': 'abc', 'a': 1})
53d9d4 3846             return 'url'
0c29cf 3847
cda7f6 3848         request = self._makeRequest()
CM 3849         request.route_url = route_url
53d9d4 3850         result = inst.generate('package:path/abc', request, a=1)
CM 3851         self.assertEqual(result, 'url')
3852
05f462 3853     def test_generate_url_unquoted_local(self):
1c39ae 3854         inst = self._makeOne()
5e3439 3855         inst.registrations = [(None, 'package:path/', '__viewname/')]
0c29cf 3856
1c39ae 3857         def route_url(n, **kw):
CM 3858             self.assertEqual(n, '__viewname/')
0c29cf 3859             self.assertEqual(kw, {'subpath': 'abc def', 'a': 1})
1c39ae 3860             return 'url'
0c29cf 3861
1c39ae 3862         request = self._makeRequest()
CM 3863         request.route_url = route_url
3864         result = inst.generate('package:path/abc def', request, a=1)
3865         self.assertEqual(result, 'url')
3866
3867     def test_generate_url_quoted_remote(self):
3868         inst = self._makeOne()
5e3439 3869         inst.registrations = [('http://example.com/', 'package:path/', None)]
1c39ae 3870         request = self._makeRequest()
CM 3871         result = inst.generate('package:path/abc def', request, a=1)
3872         self.assertEqual(result, 'http://example.com/abc%20def')
3873
8f3bf6 3874     def test_generate_url_with_custom_query(self):
MM 3875         inst = self._makeOne()
5e3439 3876         registrations = [('http://example.com/', 'package:path/', None)]
MM 3877         inst.registrations = registrations
8f3bf6 3878         request = self._makeRequest()
0c29cf 3879         result = inst.generate(
MM 3880             'package:path/abc def', request, a=1, _query='(openlayers)'
3881         )
3882         self.assertEqual(result, 'http://example.com/abc%20def?(openlayers)')
8f3bf6 3883
fc30e8 3884     def test_generate_url_with_custom_anchor(self):
MM 3885         inst = self._makeOne()
5e3439 3886         inst.registrations = [('http://example.com/', 'package:path/', None)]
fc30e8 3887         request = self._makeRequest()
MM 3888         uc = text_(b'La Pe\xc3\xb1a', 'utf-8')
0c29cf 3889         result = inst.generate(
MM 3890             'package:path/abc def', request, a=1, _anchor=uc
3891         )
3892         self.assertEqual(result, 'http://example.com/abc%20def#La%20Pe%C3%B1a')
fc30e8 3893
15b979 3894     def test_generate_url_cachebust(self):
6e29b4 3895         def cachebust(request, subpath, kw):
535015 3896             kw['foo'] = 'bar'
CR 3897             return 'foo' + '/' + subpath, kw
0c29cf 3898
535015 3899         inst = self._makeOne()
5e3439 3900         inst.registrations = [(None, 'package:path/', '__viewname')]
4d19b8 3901         inst.cache_busters = [('package:path/', cachebust, False)]
535015 3902         request = self._makeRequest()
5e3439 3903         called = [False]
0c29cf 3904
535015 3905         def route_url(n, **kw):
5e3439 3906             called[0] = True
535015 3907             self.assertEqual(n, '__viewname')
0c29cf 3908             self.assertEqual(
MM 3909                 kw,
3910                 {
3911                     'subpath': 'foo/abc',
3912                     'foo': 'bar',
3913                     'pathspec': 'package:path/abc',
3914                     'rawspec': 'package:path/abc',
3915                 },
3916             )
3917
535015 3918         request.route_url = route_url
CR 3919         inst.generate('package:path/abc', request)
5e3439 3920         self.assertTrue(called[0])
MM 3921
3922     def test_generate_url_cachebust_abspath(self):
3923         here = os.path.dirname(__file__) + os.sep
0c29cf 3924
5e3439 3925         def cachebust(pathspec, subpath, kw):
MM 3926             kw['foo'] = 'bar'
3927             return 'foo' + '/' + subpath, kw
0c29cf 3928
5e3439 3929         inst = self._makeOne()
MM 3930         inst.registrations = [(None, here, '__viewname')]
4d19b8 3931         inst.cache_busters = [(here, cachebust, False)]
5e3439 3932         request = self._makeRequest()
MM 3933         called = [False]
0c29cf 3934
5e3439 3935         def route_url(n, **kw):
MM 3936             called[0] = True
3937             self.assertEqual(n, '__viewname')
0c29cf 3938             self.assertEqual(
MM 3939                 kw,
3940                 {
3941                     'subpath': 'foo/abc',
3942                     'foo': 'bar',
3943                     'pathspec': here + 'abc',
3944                     'rawspec': here + 'abc',
3945                 },
3946             )
3947
5e3439 3948         request.route_url = route_url
MM 3949         inst.generate(here + 'abc', request)
3950         self.assertTrue(called[0])
3951
3952     def test_generate_url_cachebust_nomatch(self):
0c29cf 3953         def fake_cb(*a, **kw):
MM 3954             raise AssertionError
3955
5e3439 3956         inst = self._makeOne()
MM 3957         inst.registrations = [(None, 'package:path/', '__viewname')]
4d19b8 3958         inst.cache_busters = [('package:path2/', fake_cb, False)]
5e3439 3959         request = self._makeRequest()
MM 3960         called = [False]
0c29cf 3961
5e3439 3962         def route_url(n, **kw):
MM 3963             called[0] = True
3964             self.assertEqual(n, '__viewname')
0c29cf 3965             self.assertEqual(
MM 3966                 kw,
3967                 {
3968                     'subpath': 'abc',
3969                     'pathspec': 'package:path/abc',
3970                     'rawspec': 'package:path/abc',
3971                 },
3972             )
3973
5e3439 3974         request.route_url = route_url
MM 3975         inst.generate('package:path/abc', request)
3976         self.assertTrue(called[0])
3977
3978     def test_generate_url_cachebust_with_overrides(self):
3979         config = testing.setUp()
3980         try:
4d19b8 3981             request = testing.DummyRequest()
5e3439 3982             config.add_static_view('static', 'path')
MM 3983             config.override_asset(
0c29cf 3984                 'tests.test_config:path/', 'tests.test_config:other_path/'
MM 3985             )
3986
4d19b8 3987             def cb(val):
MM 3988                 def cb_(request, subpath, kw):
3989                     kw['_query'] = {'x': val}
3990                     return subpath, kw
0c29cf 3991
4d19b8 3992                 return cb_
0c29cf 3993
4d19b8 3994             config.add_cache_buster('path', cb('foo'))
5e3439 3995             result = request.static_url('path/foo.png')
MM 3996             self.assertEqual(result, 'http://example.com/static/foo.png?x=foo')
4d19b8 3997             config.add_cache_buster('other_path', cb('bar'), explicit=True)
MM 3998             result = request.static_url('path/foo.png')
3999             self.assertEqual(result, 'http://example.com/static/foo.png?x=bar')
5e3439 4000         finally:
MM 4001             testing.tearDown()
535015 4002
53d9d4 4003     def test_add_already_exists(self):
6e29b4 4004         config = DummyConfig()
cda7f6 4005         inst = self._makeOne()
6e29b4 4006         inst.registrations = [('http://example.com/', 'package:path/', None)]
cda7f6 4007         inst.add(config, 'http://example.com', 'anotherpackage:path')
5e3439 4008         expected = [('http://example.com/', 'anotherpackage:path/', None)]
6e29b4 4009         self.assertEqual(inst.registrations, expected)
53d9d4 4010
940a7a 4011     def test_add_package_root(self):
6e29b4 4012         config = DummyConfig()
940a7a 4013         inst = self._makeOne()
RL 4014         inst.add(config, 'http://example.com', 'package:')
5e3439 4015         expected = [('http://example.com/', 'package:', None)]
6e29b4 4016         self.assertEqual(inst.registrations, expected)
940a7a 4017
53d9d4 4018     def test_add_url_withendslash(self):
6e29b4 4019         config = DummyConfig()
cda7f6 4020         inst = self._makeOne()
CM 4021         inst.add(config, 'http://example.com/', 'anotherpackage:path')
5e3439 4022         expected = [('http://example.com/', 'anotherpackage:path/', None)]
6e29b4 4023         self.assertEqual(inst.registrations, expected)
53d9d4 4024
CM 4025     def test_add_url_noendslash(self):
6e29b4 4026         config = DummyConfig()
cda7f6 4027         inst = self._makeOne()
CM 4028         inst.add(config, 'http://example.com', 'anotherpackage:path')
5e3439 4029         expected = [('http://example.com/', 'anotherpackage:path/', None)]
6e29b4 4030         self.assertEqual(inst.registrations, expected)
53d9d4 4031
ff41f8 4032     def test_add_url_noscheme(self):
6e29b4 4033         config = DummyConfig()
ff41f8 4034         inst = self._makeOne()
WS 4035         inst.add(config, '//example.com', 'anotherpackage:path')
5e3439 4036         expected = [('//example.com/', 'anotherpackage:path/', None)]
6e29b4 4037         self.assertEqual(inst.registrations, expected)
ff41f8 4038
53d9d4 4039     def test_add_viewname(self):
CM 4040         from pyramid.security import NO_PERMISSION_REQUIRED
4041         from pyramid.static import static_view
0c29cf 4042
6e29b4 4043         config = DummyConfig()
cda7f6 4044         inst = self._makeOne()
CM 4045         inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1)
5e3439 4046         expected = [(None, 'anotherpackage:path/', '__view/')]
6e29b4 4047         self.assertEqual(inst.registrations, expected)
bc9357 4048         self.assertEqual(config.route_args, ('__view/', 'view/*subpath'))
53d9d4 4049         self.assertEqual(config.view_kw['permission'], NO_PERMISSION_REQUIRED)
CM 4050         self.assertEqual(config.view_kw['view'].__class__, static_view)
bc9357 4051
CM 4052     def test_add_viewname_with_route_prefix(self):
6e29b4 4053         config = DummyConfig()
bc9357 4054         config.route_prefix = '/abc'
CM 4055         inst = self._makeOne()
0c29cf 4056         inst.add(config, 'view', 'anotherpackage:path')
5e3439 4057         expected = [(None, 'anotherpackage:path/', '__/abc/view/')]
6e29b4 4058         self.assertEqual(inst.registrations, expected)
bc9357 4059         self.assertEqual(config.route_args, ('__/abc/view/', 'view/*subpath'))
53d9d4 4060
CM 4061     def test_add_viewname_with_permission(self):
6e29b4 4062         config = DummyConfig()
cda7f6 4063         inst = self._makeOne()
0c29cf 4064         inst.add(
MM 4065             config,
4066             'view',
4067             'anotherpackage:path',
4068             cache_max_age=1,
4069             permission='abc',
4070         )
53d9d4 4071         self.assertEqual(config.view_kw['permission'], 'abc')
CM 4072
fdf30b 4073     def test_add_viewname_with_context(self):
6e29b4 4074         config = DummyConfig()
cda7f6 4075         inst = self._makeOne()
0c29cf 4076         inst.add(
MM 4077             config,
4078             'view',
4079             'anotherpackage:path',
4080             cache_max_age=1,
4081             context=DummyContext,
4082         )
53d9d4 4083         self.assertEqual(config.view_kw['context'], DummyContext)
cac23b 4084
53d9d4 4085     def test_add_viewname_with_for_(self):
6e29b4 4086         config = DummyConfig()
cda7f6 4087         inst = self._makeOne()
0c29cf 4088         inst.add(
MM 4089             config,
4090             'view',
4091             'anotherpackage:path',
4092             cache_max_age=1,
4093             for_=DummyContext,
4094         )
53d9d4 4095         self.assertEqual(config.view_kw['context'], DummyContext)
CM 4096
4097     def test_add_viewname_with_renderer(self):
6e29b4 4098         config = DummyConfig()
cda7f6 4099         inst = self._makeOne()
0c29cf 4100         inst.add(
MM 4101             config,
4102             'view',
4103             'anotherpackage:path',
4104             cache_max_age=1,
4105             renderer='mypackage:templates/index.pt',
4106         )
4107         self.assertEqual(
4108             config.view_kw['renderer'], 'mypackage:templates/index.pt'
4109         )
53d9d4 4110
659630 4111     def test_add_cachebust_prevented(self):
6e29b4 4112         config = DummyConfig()
15b979 4113         config.registry.settings['pyramid.prevent_cachebust'] = True
659630 4114         inst = self._makeOne()
5e3439 4115         cachebust = DummyCacheBuster('foo')
MM 4116         inst.add_cache_buster(config, 'mypackage:path', cachebust)
4117         self.assertEqual(inst.cache_busters, [])
659630 4118
5e3439 4119     def test_add_cachebuster(self):
6e29b4 4120         config = DummyConfig()
535015 4121         inst = self._makeOne()
0c29cf 4122         inst.add_cache_buster(
MM 4123             config, 'mypackage:path', DummyCacheBuster('foo')
4124         )
5e3439 4125         cachebust = inst.cache_busters[-1][1]
4d19b8 4126         subpath, kw = cachebust(None, 'some/path', {})
535015 4127         self.assertEqual(subpath, 'some/path')
CR 4128         self.assertEqual(kw['x'], 'foo')
5e3439 4129
MM 4130     def test_add_cachebuster_abspath(self):
4131         here = os.path.dirname(__file__)
4132         config = DummyConfig()
4133         inst = self._makeOne()
4134         cb = DummyCacheBuster('foo')
4135         inst.add_cache_buster(config, here, cb)
4e6f98 4136         self.assertEqual(inst.cache_busters, [(here + os.sep, cb, False)])
5e3439 4137
MM 4138     def test_add_cachebuster_overwrite(self):
4139         config = DummyConfig()
4140         inst = self._makeOne()
4141         cb1 = DummyCacheBuster('foo')
4142         cb2 = DummyCacheBuster('bar')
4143         inst.add_cache_buster(config, 'mypackage:path/', cb1)
4144         inst.add_cache_buster(config, 'mypackage:path', cb2)
0c29cf 4145         self.assertEqual(inst.cache_busters, [('mypackage:path/', cb2, False)])
4d19b8 4146
MM 4147     def test_add_cachebuster_overwrite_explicit(self):
4148         config = DummyConfig()
4149         inst = self._makeOne()
4150         cb1 = DummyCacheBuster('foo')
4151         cb2 = DummyCacheBuster('bar')
4152         inst.add_cache_buster(config, 'mypackage:path/', cb1)
4153         inst.add_cache_buster(config, 'mypackage:path', cb2, True)
0c29cf 4154         self.assertEqual(
MM 4155             inst.cache_busters,
4156             [('mypackage:path/', cb1, False), ('mypackage:path/', cb2, True)],
4157         )
5e3439 4158
MM 4159     def test_add_cachebuster_for_more_specific_path(self):
4160         config = DummyConfig()
4161         inst = self._makeOne()
4162         cb1 = DummyCacheBuster('foo')
4163         cb2 = DummyCacheBuster('bar')
4d19b8 4164         cb3 = DummyCacheBuster('baz')
MM 4165         cb4 = DummyCacheBuster('xyz')
4166         cb5 = DummyCacheBuster('w')
5e3439 4167         inst.add_cache_buster(config, 'mypackage:path', cb1)
4d19b8 4168         inst.add_cache_buster(config, 'mypackage:path/sub', cb2, True)
MM 4169         inst.add_cache_buster(config, 'mypackage:path/sub/other', cb3)
4170         inst.add_cache_buster(config, 'mypackage:path/sub/other', cb4, True)
4171         inst.add_cache_buster(config, 'mypackage:path/sub/less', cb5, True)
4172         self.assertEqual(
4173             inst.cache_busters,
0c29cf 4174             [
MM 4175                 ('mypackage:path/', cb1, False),
4176                 ('mypackage:path/sub/other/', cb3, False),
4177                 ('mypackage:path/sub/', cb2, True),
4178                 ('mypackage:path/sub/less/', cb5, True),
4179                 ('mypackage:path/sub/other/', cb4, True),
4180             ],
4181         )
4182
535015 4183
af24f7 4184 class Test_view_description(unittest.TestCase):
CM 4185     def _callFUT(self, view):
4186         from pyramid.config.views import view_description
0c29cf 4187
af24f7 4188         return view_description(view)
42afb0 4189
af24f7 4190     def test_with_text(self):
0c29cf 4191         def view():
MM 4192             pass
4193
af24f7 4194         view.__text__ = 'some text'
CM 4195         result = self._callFUT(view)
4196         self.assertEqual(result, 'some text')
42afb0 4197
af24f7 4198     def test_without_text(self):
0c29cf 4199         def view():
MM 4200             pass
4201
af24f7 4202         result = self._callFUT(view)
0c29cf 4203         self.assertEqual(result, 'function tests.test_config.test_views.view')
MM 4204
42afb0 4205
52fde9 4206 class Test_viewdefaults(unittest.TestCase):
MM 4207     def _makeOne(self, wrapped):
4208         from pyramid.decorator import reify
0c29cf 4209
52fde9 4210         return reify(wrapped)
MM 4211
4212     def test_dunder_attrs_copied(self):
4213         from pyramid.config.views import viewdefaults
0c29cf 4214
52fde9 4215         decorator = self._makeOne(viewdefaults)
MM 4216         self.assertEqual(decorator.__doc__, viewdefaults.__doc__)
4217         self.assertEqual(decorator.__name__, viewdefaults.__name__)
4218         self.assertEqual(decorator.__module__, viewdefaults.__module__)
4219
af24f7 4220
cda7f6 4221 class DummyRegistry:
5e3439 4222     utility = None
MM 4223
659630 4224     def __init__(self):
CR 4225         self.settings = {}
5e3439 4226
MM 4227     def queryUtility(self, type_or_iface, name=None, default=None):
4228         return self.utility or default
53d9d4 4229
0c29cf 4230
5fc893 4231 from zope.interface import implementer
0c29cf 4232 from pyramid.interfaces import IResponse, IRequest
MM 4233
849196 4234
5fc893 4235 @implementer(IResponse)
BJR 4236 class DummyResponse(object):
4237     content_type = None
4238     default_content_type = None
42afb0 4239     body = None
5fc893 4240
0c29cf 4241
5bf23f 4242 class DummyRequest:
CM 4243     subpath = ()
4244     matchdict = None
0c29cf 4245     request_iface = IRequest
498342 4246     application_url = 'http://example.com/foo'
5fc893 4247
5bf23f 4248     def __init__(self, environ=None):
CM 4249         if environ is None:
4250             environ = {}
4251         self.environ = environ
4252         self.params = {}
4253         self.cookies = {}
6ef10d 4254         self.response = DummyResponse()
5bf23f 4255
0c29cf 4256
5bf23f 4257 class DummyContext:
3b7334 4258     pass
0c29cf 4259
5bf23f 4260
CM 4261 class DummyAccept(object):
4a9f4f 4262     def __init__(self, *matches, **kw):
5bf23f 4263         self.matches = list(matches)
4a9f4f 4264         self.contains = kw.pop('contains', False)
5bf23f 4265
c3c83e 4266     def acceptable_offers(self, offers):
MM 4267         results = []
4268         for match in self.matches:
4269             if match in offers:
4270                 results.append((match, 1.0))
4271         return results
5bf23f 4272
4a9f4f 4273     def __contains__(self, value):
MM 4274         return self.contains
4275
0c29cf 4276
53d9d4 4277 class DummyConfig:
5e3439 4278     def __init__(self):
MM 4279         self.registry = DummyRegistry()
4280
bc9357 4281     route_prefix = ''
0c29cf 4282
53d9d4 4283     def add_route(self, *args, **kw):
CM 4284         self.route_args = args
4285         self.route_kw = kw
4286
4287     def add_view(self, *args, **kw):
4288         self.view_args = args
4289         self.view_kw = kw
4290
773948 4291     def action(self, discriminator, callable, introspectables=()):
bc9357 4292         callable()
CM 4293
773948 4294     def introspectable(self, *arg):
CM 4295         return {}
4296
0c29cf 4297
3b7334 4298 from zope.interface import implementer
49f082 4299 from pyramid.interfaces import IMultiView
0c29cf 4300
MM 4301
3b7334 4302 @implementer(IMultiView)
49f082 4303 class DummyMultiView:
CM 4304     def __init__(self):
4305         self.views = []
4306         self.name = 'name'
0c29cf 4307
c3c83e 4308     def add(self, view, order, phash=None, accept=None, accept_order=None):
MM 4309         self.views.append((view, phash, accept, accept_order))
0c29cf 4310
49f082 4311     def __call__(self, context, request):
CM 4312         return 'OK1'
0c29cf 4313
49f082 4314     def __permitted__(self, context, request):
CM 4315         """ """
0c29cf 4316
49f082 4317
aa96dd 4318 class DummyCacheBuster(object):
780889 4319     def __init__(self, token):
MM 4320         self.token = token
6e29b4 4321
4d19b8 4322     def __call__(self, request, subpath, kw):
780889 4323         kw['x'] = self.token
aa96dd 4324         return subpath, kw
CR 4325
0c29cf 4326
5bf23f 4327 def parse_httpdate(s):
CM 4328     import datetime
0c29cf 4329
5bf23f 4330     # cannot use %Z, must use literal GMT; Jython honors timezone
CM 4331     # but CPython does not
4332     return datetime.datetime.strptime(s, "%a, %d %b %Y %H:%M:%S GMT")
0c29cf 4333
5bf23f 4334
CM 4335 def assert_similar_datetime(one, two):
4336     for attr in ('year', 'month', 'day', 'hour', 'minute'):
4337         one_attr = getattr(one, attr)
4338         two_attr = getattr(two, attr)
0c29cf 4339         if not one_attr == two_attr:  # pragma: no cover
5bf23f 4340             raise AssertionError('%r != %r in %s' % (one_attr, two_attr, attr))
0c29cf 4341
49f082 4342
6cc22a 4343 class DummyStaticURLInfo:
CM 4344     def __init__(self):
4345         self.added = []
4346
cda7f6 4347     def add(self, config, name, spec, **kw):
CM 4348         self.added.append((config, name, spec, kw))
134388 4349
0c29cf 4350
134388 4351 class DummyViewDefaultsClass(object):
0c29cf 4352     __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 4353
134388 4354     def __init__(self, request):
CM 4355         pass
0c29cf 4356
134388 4357     def __call__(self):
CM 4358         return 'OK'
0c29cf 4359
8ec8e2 4360
CM 4361 class DummyPredicate(object):
4362     def __init__(self, val, config):
4363         self.val = val
4364
4365     def text(self):
4366         return 'dummy'
4367
4368     phash = text
4369
0c29cf 4370
3d42aa 4371 class DummyIntrospector(object):
CM 4372     def __init__(self, getval=None):
4373         self.related = []
4374         self.introspectables = []
4375         self.getval = getval
0c29cf 4376
3d42aa 4377     def add(self, introspectable):
CM 4378         self.introspectables.append(introspectable)
0c29cf 4379
3d42aa 4380     def get(self, name, discrim):
CM 4381         return self.getval
0c29cf 4382
3d42aa 4383     def relate(self, a, b):
CM 4384         self.related.append((a, b))
9e9fa9 4385
0c29cf 4386
9e9fa9 4387 class DummySession(dict):
MM 4388     def get_csrf_token(self):
4389         return self['csrf_token']