Michael Merickel
2018-10-19 d579f2104de139e0b0fc5d6c81aabb2f826e5e54
commit | author | age
5e3439 1 import os
5bf23f 2 import unittest
10ddb6 3 from zope.interface import implementer
MM 4
5bf23f 5 from pyramid import testing
0c29cf 6 from pyramid.compat import im_func, text_
79ef3d 7 from pyramid.exceptions import ConfigurationError
CM 8 from pyramid.exceptions import ConfigurationExecutionError
9 from pyramid.exceptions import ConfigurationConflictError
10ddb6 10 from pyramid.interfaces import IResponse, IRequest, IMultiView
MM 11
12 from . import IDummy
13 from . import dummy_view
79ef3d 14
0c29cf 15
49f082 16 class TestViewsConfigurationMixin(unittest.TestCase):
CM 17     def _makeOne(self, *arg, **kw):
18         from pyramid.config import Configurator
0c29cf 19
49f082 20         config = Configurator(*arg, **kw)
313c25 21         config.set_default_csrf_options(require_csrf=False)
49f082 22         return config
CM 23
0c29cf 24     def _getViewCallable(
MM 25         self,
26         config,
27         ctx_iface=None,
28         exc_iface=None,
29         request_iface=None,
30         name='',
31     ):
49f082 32         from zope.interface import Interface
CM 33         from pyramid.interfaces import IRequest
34         from pyramid.interfaces import IView
35         from pyramid.interfaces import IViewClassifier
36         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 37
e8c66a 38         if exc_iface:
49f082 39             classifier = IExceptionViewClassifier
e8c66a 40             ctx_iface = exc_iface
49f082 41         else:
CM 42             classifier = IViewClassifier
43         if ctx_iface is None:
44             ctx_iface = Interface
45         if request_iface is None:
46             request_iface = IRequest
47         return config.registry.adapters.lookup(
0c29cf 48             (classifier, request_iface, ctx_iface),
MM 49             IView,
50             name=name,
51             default=None,
52         )
49f082 53
CM 54     def _registerRenderer(self, config, name='.txt'):
55         from pyramid.interfaces import IRendererFactory
0c29cf 56
49f082 57         class Renderer:
CM 58             def __init__(self, info):
59                 self.__class__.info = info
0c29cf 60
49f082 61             def __call__(self, *arg):
42afb0 62                 return b'Hello!'
0c29cf 63
49f082 64         config.registry.registerUtility(Renderer, IRendererFactory, name=name)
CM 65         return Renderer
66
67     def _makeRequest(self, config):
68         request = DummyRequest()
69         request.registry = config.registry
70         return request
71
72     def _assertNotFound(self, wrapper, *arg):
73         from pyramid.httpexceptions import HTTPNotFound
0c29cf 74
49f082 75         self.assertRaises(HTTPNotFound, wrapper, *arg)
CM 76
77     def _getRouteRequestIface(self, config, name):
78         from pyramid.interfaces import IRouteRequest
0c29cf 79
49f082 80         iface = config.registry.getUtility(IRouteRequest, name)
CM 81         return iface
82
6cc22a 83     def _assertRoute(self, config, name, path, num_predicates=0):
CM 84         from pyramid.interfaces import IRoutesMapper
0c29cf 85
6cc22a 86         mapper = config.registry.getUtility(IRoutesMapper)
CM 87         routes = mapper.get_routes()
88         route = routes[0]
89         self.assertEqual(len(routes), 1)
90         self.assertEqual(route.name, name)
91         self.assertEqual(route.path, path)
92         self.assertEqual(len(routes[0].predicates), num_predicates)
93         return route
94
49f082 95     def test_add_view_view_callable_None_no_renderer(self):
CM 96         config = self._makeOne(autocommit=True)
97         self.assertRaises(ConfigurationError, config.add_view)
98
99     def test_add_view_with_request_type_and_route_name(self):
100         config = self._makeOne(autocommit=True)
101         view = lambda *arg: 'OK'
0c29cf 102         self.assertRaises(
MM 103             ConfigurationError,
104             config.add_view,
105             view,
106             '',
107             None,
108             None,
109             True,
110             True,
111         )
49f082 112
CM 113     def test_add_view_with_request_type(self):
114         from pyramid.renderers import null_renderer
115         from zope.interface import directlyProvides
116         from pyramid.interfaces import IRequest
0c29cf 117
49f082 118         view = lambda *arg: 'OK'
CM 119         config = self._makeOne(autocommit=True)
0c29cf 120         config.add_view(
MM 121             view=view,
122             request_type='pyramid.interfaces.IRequest',
123             renderer=null_renderer,
124         )
49f082 125         wrapper = self._getViewCallable(config)
CM 126         request = DummyRequest()
127         self._assertNotFound(wrapper, None, request)
128         directlyProvides(request, IRequest)
129         result = wrapper(None, request)
130         self.assertEqual(result, 'OK')
131
132     def test_add_view_view_callable_None_with_renderer(self):
133         config = self._makeOne(autocommit=True)
134         self._registerRenderer(config, name='dummy')
135         config.add_view(renderer='dummy')
136         view = self._getViewCallable(config)
8e606d 137         self.assertTrue(b'Hello!' in view(None, None).body)
49f082 138
3d42aa 139     def test_add_view_with_tmpl_renderer_factory_introspector_missing(self):
CM 140         config = self._makeOne(autocommit=True)
141         config.introspection = False
142         config.introspector = None
143         config.add_view(renderer='dummy.pt')
144         view = self._getViewCallable(config)
145         self.assertRaises(ValueError, view, None, None)
cac23b 146
3d42aa 147     def test_add_view_with_tmpl_renderer_factory_no_renderer_factory(self):
CM 148         config = self._makeOne(autocommit=True)
149         introspector = DummyIntrospector()
150         config.introspector = introspector
151         config.add_view(renderer='dummy.pt')
0c29cf 152         self.assertFalse(
MM 153             ('renderer factories', '.pt') in introspector.related[-1]
154         )
3d42aa 155         view = self._getViewCallable(config)
CM 156         self.assertRaises(ValueError, view, None, None)
157
158     def test_add_view_with_tmpl_renderer_factory_with_renderer_factory(self):
159         config = self._makeOne(autocommit=True)
160         introspector = DummyIntrospector(True)
161         config.introspector = introspector
0c29cf 162
3d42aa 163         def dummy_factory(helper):
CM 164             return lambda val, system_vals: 'Hello!'
0c29cf 165
3d42aa 166         config.add_renderer('.pt', dummy_factory)
CM 167         config.add_view(renderer='dummy.pt')
168         self.assertTrue(
0c29cf 169             ('renderer factories', '.pt') in introspector.related[-1]
MM 170         )
3d42aa 171         view = self._getViewCallable(config)
CM 172         self.assertTrue(b'Hello!' in view(None, None).body)
cac23b 173
49f082 174     def test_add_view_wrapped_view_is_decorated(self):
0c29cf 175         def view(request):  # request-only wrapper
49f082 176             """ """
0c29cf 177
49f082 178         config = self._makeOne(autocommit=True)
CM 179         config.add_view(view=view)
180         wrapper = self._getViewCallable(config)
181         self.assertEqual(wrapper.__module__, view.__module__)
182         self.assertEqual(wrapper.__name__, view.__name__)
183         self.assertEqual(wrapper.__doc__, view.__doc__)
0c29cf 184         self.assertEqual(
MM 185             wrapper.__discriminator__(None, None).resolve()[0], 'view'
186         )
49f082 187
CM 188     def test_add_view_view_callable_dottedname(self):
189         from pyramid.renderers import null_renderer
0c29cf 190
49f082 191         config = self._makeOne(autocommit=True)
0c29cf 192         config.add_view(
MM 193             view='tests.test_config.dummy_view', renderer=null_renderer
194         )
49f082 195         wrapper = self._getViewCallable(config)
CM 196         self.assertEqual(wrapper(None, None), 'OK')
197
198     def test_add_view_with_function_callable(self):
199         from pyramid.renderers import null_renderer
0c29cf 200
49f082 201         view = lambda *arg: 'OK'
CM 202         config = self._makeOne(autocommit=True)
203         config.add_view(view=view, renderer=null_renderer)
204         wrapper = self._getViewCallable(config)
205         result = wrapper(None, None)
206         self.assertEqual(result, 'OK')
207
208     def test_add_view_with_function_callable_requestonly(self):
209         from pyramid.renderers import null_renderer
0c29cf 210
49f082 211         def view(request):
CM 212             return 'OK'
0c29cf 213
49f082 214         config = self._makeOne(autocommit=True)
CM 215         config.add_view(view=view, renderer=null_renderer)
216         wrapper = self._getViewCallable(config)
217         result = wrapper(None, None)
218         self.assertEqual(result, 'OK')
219
3c59ce 220     def test_add_view_with_name(self):
CM 221         from pyramid.renderers import null_renderer
0c29cf 222
3c59ce 223         view = lambda *arg: 'OK'
CM 224         config = self._makeOne(autocommit=True)
225         config.add_view(view=view, name='abc', renderer=null_renderer)
226         wrapper = self._getViewCallable(config, name='abc')
227         result = wrapper(None, None)
228         self.assertEqual(result, 'OK')
229
230     def test_add_view_with_name_unicode(self):
231         from pyramid.renderers import null_renderer
0c29cf 232
3c59ce 233         view = lambda *arg: 'OK'
CM 234         config = self._makeOne(autocommit=True)
235         name = text_(b'La Pe\xc3\xb1a', 'utf-8')
236         config.add_view(view=view, name=name, renderer=null_renderer)
237         wrapper = self._getViewCallable(config, name=name)
238         result = wrapper(None, None)
239         self.assertEqual(result, 'OK')
240
49f082 241     def test_add_view_with_decorator(self):
CM 242         from pyramid.renderers import null_renderer
0c29cf 243
49f082 244         def view(request):
CM 245             """ ABC """
246             return 'OK'
0c29cf 247
49f082 248         def view_wrapper(fn):
CM 249             def inner(context, request):
250                 return fn(context, request)
0c29cf 251
49f082 252             return inner
0c29cf 253
49f082 254         config = self._makeOne(autocommit=True)
0c29cf 255         config.add_view(
MM 256             view=view, decorator=view_wrapper, renderer=null_renderer
257         )
49f082 258         wrapper = self._getViewCallable(config)
CM 259         self.assertFalse(wrapper is view)
260         self.assertEqual(wrapper.__doc__, view.__doc__)
261         result = wrapper(None, None)
262         self.assertEqual(result, 'OK')
263
76c9c2 264     def test_add_view_with_decorator_tuple(self):
R 265         from pyramid.renderers import null_renderer
0c29cf 266
76c9c2 267         def view(request):
R 268             """ ABC """
269             return 'OK'
0c29cf 270
76c9c2 271         def view_wrapper1(fn):
R 272             def inner(context, request):
273                 return 'wrapped1' + fn(context, request)
0c29cf 274
76c9c2 275             return inner
0c29cf 276
76c9c2 277         def view_wrapper2(fn):
R 278             def inner(context, request):
279                 return 'wrapped2' + fn(context, request)
0c29cf 280
76c9c2 281             return inner
0c29cf 282
76c9c2 283         config = self._makeOne(autocommit=True)
0c29cf 284         config.add_view(
MM 285             view=view,
286             decorator=(view_wrapper2, view_wrapper1),
287             renderer=null_renderer,
288         )
76c9c2 289         wrapper = self._getViewCallable(config)
R 290         self.assertFalse(wrapper is view)
291         self.assertEqual(wrapper.__doc__, view.__doc__)
292         result = wrapper(None, None)
293         self.assertEqual(result, 'wrapped2wrapped1OK')
294
49f082 295     def test_add_view_with_http_cache(self):
CM 296         import datetime
297         from pyramid.response import Response
0c29cf 298
49f082 299         response = Response('OK')
0c29cf 300
49f082 301         def view(request):
CM 302             """ ABC """
303             return response
0c29cf 304
49f082 305         config = self._makeOne(autocommit=True)
0c29cf 306         config.add_view(view=view, http_cache=(86400, {'public': True}))
49f082 307         wrapper = self._getViewCallable(config)
CM 308         self.assertFalse(wrapper is view)
309         self.assertEqual(wrapper.__doc__, view.__doc__)
310         request = testing.DummyRequest()
311         when = datetime.datetime.utcnow() + datetime.timedelta(days=1)
312         result = wrapper(None, request)
313         self.assertEqual(result, response)
314         headers = dict(response.headerlist)
315         self.assertEqual(headers['Cache-Control'], 'max-age=86400, public')
316         expires = parse_httpdate(headers['Expires'])
317         assert_similar_datetime(expires, when)
318
319     def test_add_view_as_instance(self):
320         from pyramid.renderers import null_renderer
0c29cf 321
49f082 322         class AView:
CM 323             def __call__(self, context, request):
324                 """ """
325                 return 'OK'
0c29cf 326
49f082 327         view = AView()
CM 328         config = self._makeOne(autocommit=True)
329         config.add_view(view=view, renderer=null_renderer)
330         wrapper = self._getViewCallable(config)
331         result = wrapper(None, None)
332         self.assertEqual(result, 'OK')
333
df3bea 334     def test_add_view_as_instancemethod(self):
H 335         from pyramid.renderers import null_renderer
0c29cf 336
df3bea 337         class View:
4a6f53 338             def index(self, context, request):
CM 339                 return 'OK'
0c29cf 340
df3bea 341         view = View()
0c29cf 342         config = self._makeOne(autocommit=True)
df3bea 343         config.add_view(view=view.index, renderer=null_renderer)
4a6f53 344         wrapper = self._getViewCallable(config)
CM 345         result = wrapper(None, None)
346         self.assertEqual(result, 'OK')
df3bea 347
6c1597 348     def test_add_view_as_instancemethod_requestonly(self):
CM 349         from pyramid.renderers import null_renderer
0c29cf 350
6c1597 351         class View:
CM 352             def index(self, request):
353                 return 'OK'
0c29cf 354
6c1597 355         view = View()
0c29cf 356         config = self._makeOne(autocommit=True)
6c1597 357         config.add_view(view=view.index, renderer=null_renderer)
CM 358         wrapper = self._getViewCallable(config)
359         result = wrapper(None, None)
360         self.assertEqual(result, 'OK')
42afb0 361
49f082 362     def test_add_view_as_instance_requestonly(self):
CM 363         from pyramid.renderers import null_renderer
0c29cf 364
49f082 365         class AView:
CM 366             def __call__(self, request):
367                 """ """
368                 return 'OK'
0c29cf 369
49f082 370         view = AView()
CM 371         config = self._makeOne(autocommit=True)
372         config.add_view(view=view, renderer=null_renderer)
373         wrapper = self._getViewCallable(config)
374         result = wrapper(None, None)
375         self.assertEqual(result, 'OK')
376
377     def test_add_view_as_oldstyle_class(self):
378         from pyramid.renderers import null_renderer
0c29cf 379
49f082 380         class view:
CM 381             def __init__(self, context, request):
382                 self.context = context
383                 self.request = request
384
385             def __call__(self):
386                 return 'OK'
0c29cf 387
49f082 388         config = self._makeOne(autocommit=True)
CM 389         config.add_view(view=view, renderer=null_renderer)
390         wrapper = self._getViewCallable(config)
391         request = self._makeRequest(config)
392         result = wrapper(None, request)
393         self.assertEqual(result, 'OK')
394         self.assertEqual(request.__view__.__class__, view)
395
396     def test_add_view_as_oldstyle_class_requestonly(self):
397         from pyramid.renderers import null_renderer
0c29cf 398
49f082 399         class view:
CM 400             def __init__(self, request):
401                 self.request = request
402
403             def __call__(self):
404                 return 'OK'
0c29cf 405
49f082 406         config = self._makeOne(autocommit=True)
CM 407         config.add_view(view=view, renderer=null_renderer)
408         wrapper = self._getViewCallable(config)
409
410         request = self._makeRequest(config)
411         result = wrapper(None, request)
412         self.assertEqual(result, 'OK')
413         self.assertEqual(request.__view__.__class__, view)
414
415     def test_add_view_context_as_class(self):
416         from pyramid.renderers import null_renderer
417         from zope.interface import implementedBy
0c29cf 418
49f082 419         view = lambda *arg: 'OK'
0c29cf 420
49f082 421         class Foo:
CM 422             pass
0c29cf 423
49f082 424         config = self._makeOne(autocommit=True)
CM 425         config.add_view(context=Foo, view=view, renderer=null_renderer)
426         foo = implementedBy(Foo)
427         wrapper = self._getViewCallable(config, foo)
428         self.assertEqual(wrapper, view)
429
430     def test_add_view_context_as_iface(self):
431         from pyramid.renderers import null_renderer
0c29cf 432
49f082 433         view = lambda *arg: 'OK'
CM 434         config = self._makeOne(autocommit=True)
435         config.add_view(context=IDummy, view=view, renderer=null_renderer)
436         wrapper = self._getViewCallable(config, IDummy)
437         self.assertEqual(wrapper, view)
438
439     def test_add_view_context_as_dottedname(self):
440         from pyramid.renderers import null_renderer
0c29cf 441
49f082 442         view = lambda *arg: 'OK'
CM 443         config = self._makeOne(autocommit=True)
0c29cf 444         config.add_view(
MM 445             context='tests.test_config.IDummy',
446             view=view,
447             renderer=null_renderer,
448         )
49f082 449         wrapper = self._getViewCallable(config, IDummy)
CM 450         self.assertEqual(wrapper, view)
451
452     def test_add_view_for__as_dottedname(self):
453         from pyramid.renderers import null_renderer
0c29cf 454
49f082 455         view = lambda *arg: 'OK'
CM 456         config = self._makeOne(autocommit=True)
0c29cf 457         config.add_view(
MM 458             for_='tests.test_config.IDummy', view=view, renderer=null_renderer
459         )
49f082 460         wrapper = self._getViewCallable(config, IDummy)
CM 461         self.assertEqual(wrapper, view)
462
463     def test_add_view_for_as_class(self):
464         # ``for_`` is older spelling for ``context``
465         from pyramid.renderers import null_renderer
466         from zope.interface import implementedBy
0c29cf 467
49f082 468         view = lambda *arg: 'OK'
0c29cf 469
49f082 470         class Foo:
CM 471             pass
0c29cf 472
49f082 473         config = self._makeOne(autocommit=True)
CM 474         config.add_view(for_=Foo, view=view, renderer=null_renderer)
475         foo = implementedBy(Foo)
476         wrapper = self._getViewCallable(config, foo)
477         self.assertEqual(wrapper, view)
478
479     def test_add_view_for_as_iface(self):
480         # ``for_`` is older spelling for ``context``
481         from pyramid.renderers import null_renderer
0c29cf 482
49f082 483         view = lambda *arg: 'OK'
CM 484         config = self._makeOne(autocommit=True)
485         config.add_view(for_=IDummy, view=view, renderer=null_renderer)
486         wrapper = self._getViewCallable(config, IDummy)
487         self.assertEqual(wrapper, view)
488
489     def test_add_view_context_trumps_for(self):
490         # ``for_`` is older spelling for ``context``
491         from pyramid.renderers import null_renderer
0c29cf 492
49f082 493         view = lambda *arg: 'OK'
CM 494         config = self._makeOne(autocommit=True)
0c29cf 495
49f082 496         class Foo:
CM 497             pass
0c29cf 498
MM 499         config.add_view(
500             context=IDummy, for_=Foo, view=view, renderer=null_renderer
501         )
49f082 502         wrapper = self._getViewCallable(config, IDummy)
CM 503         self.assertEqual(wrapper, view)
504
505     def test_add_view_register_secured_view(self):
506         from pyramid.renderers import null_renderer
507         from zope.interface import Interface
508         from pyramid.interfaces import IRequest
509         from pyramid.interfaces import ISecuredView
510         from pyramid.interfaces import IViewClassifier
0c29cf 511
49f082 512         view = lambda *arg: 'OK'
CM 513         view.__call_permissive__ = view
514         config = self._makeOne(autocommit=True)
515         config.add_view(view=view, renderer=null_renderer)
516         wrapper = config.registry.adapters.lookup(
517             (IViewClassifier, IRequest, Interface),
0c29cf 518             ISecuredView,
MM 519             name='',
520             default=None,
521         )
49f082 522         self.assertEqual(wrapper, view)
CM 523
524     def test_add_view_exception_register_secured_view(self):
525         from pyramid.renderers import null_renderer
526         from zope.interface import implementedBy
527         from pyramid.interfaces import IRequest
528         from pyramid.interfaces import IView
529         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 530
49f082 531         view = lambda *arg: 'OK'
CM 532         view.__call_permissive__ = view
533         config = self._makeOne(autocommit=True)
0c29cf 534         config.add_view(
MM 535             view=view, context=RuntimeError, renderer=null_renderer
536         )
49f082 537         wrapper = config.registry.adapters.lookup(
CM 538             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 539             IView,
MM 540             name='',
541             default=None,
542         )
49f082 543         self.assertEqual(wrapper, view)
CM 544
545     def test_add_view_same_phash_overrides_existing_single_view(self):
546         from pyramid.renderers import null_renderer
547         from hashlib import md5
548         from zope.interface import Interface
549         from pyramid.interfaces import IRequest
550         from pyramid.interfaces import IView
551         from pyramid.interfaces import IViewClassifier
552         from pyramid.interfaces import IMultiView
0c29cf 553
49f082 554         phash = md5()
4d2602 555         phash.update(b'xhr = True')
49f082 556         view = lambda *arg: 'NOT OK'
CM 557         view.__phash__ = phash.hexdigest()
558         config = self._makeOne(autocommit=True)
559         config.registry.registerAdapter(
0c29cf 560             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 561         )
562
49f082 563         def newview(context, request):
CM 564             return 'OK'
0c29cf 565
49f082 566         config.add_view(view=newview, xhr=True, renderer=null_renderer)
CM 567         wrapper = self._getViewCallable(config)
568         self.assertFalse(IMultiView.providedBy(wrapper))
569         request = DummyRequest()
570         request.is_xhr = True
571         self.assertEqual(wrapper(None, request), 'OK')
572
573     def test_add_view_exc_same_phash_overrides_existing_single_view(self):
574         from pyramid.renderers import null_renderer
575         from hashlib import md5
576         from zope.interface import implementedBy
577         from pyramid.interfaces import IRequest
578         from pyramid.interfaces import IView
579         from pyramid.interfaces import IExceptionViewClassifier
580         from pyramid.interfaces import IMultiView
0c29cf 581
49f082 582         phash = md5()
4d2602 583         phash.update(b'xhr = True')
49f082 584         view = lambda *arg: 'NOT OK'
CM 585         view.__phash__ = phash.hexdigest()
586         config = self._makeOne(autocommit=True)
587         config.registry.registerAdapter(
588             view,
589             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 590             IView,
MM 591             name='',
592         )
593
49f082 594         def newview(context, request):
CM 595             return 'OK'
0c29cf 596
MM 597         config.add_view(
598             view=newview,
599             xhr=True,
600             context=RuntimeError,
601             renderer=null_renderer,
602         )
49f082 603         wrapper = self._getViewCallable(
0c29cf 604             config, exc_iface=implementedBy(RuntimeError)
MM 605         )
49f082 606         self.assertFalse(IMultiView.providedBy(wrapper))
CM 607         request = DummyRequest()
608         request.is_xhr = True
609         self.assertEqual(wrapper(None, request), 'OK')
610
611     def test_add_view_default_phash_overrides_no_phash(self):
612         from pyramid.renderers import null_renderer
613         from zope.interface import Interface
614         from pyramid.interfaces import IRequest
615         from pyramid.interfaces import IView
616         from pyramid.interfaces import IViewClassifier
617         from pyramid.interfaces import IMultiView
0c29cf 618
49f082 619         view = lambda *arg: 'NOT OK'
CM 620         config = self._makeOne(autocommit=True)
621         config.registry.registerAdapter(
0c29cf 622             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 623         )
624
49f082 625         def newview(context, request):
CM 626             return 'OK'
0c29cf 627
49f082 628         config.add_view(view=newview, renderer=null_renderer)
CM 629         wrapper = self._getViewCallable(config)
630         self.assertFalse(IMultiView.providedBy(wrapper))
631         request = DummyRequest()
632         request.is_xhr = True
633         self.assertEqual(wrapper(None, request), 'OK')
634
635     def test_add_view_exc_default_phash_overrides_no_phash(self):
636         from pyramid.renderers import null_renderer
637         from zope.interface import implementedBy
638         from pyramid.interfaces import IRequest
639         from pyramid.interfaces import IView
640         from pyramid.interfaces import IExceptionViewClassifier
641         from pyramid.interfaces import IMultiView
0c29cf 642
49f082 643         view = lambda *arg: 'NOT OK'
CM 644         config = self._makeOne(autocommit=True)
645         config.registry.registerAdapter(
646             view,
647             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 648             IView,
MM 649             name='',
650         )
651
49f082 652         def newview(context, request):
CM 653             return 'OK'
0c29cf 654
MM 655         config.add_view(
656             view=newview, context=RuntimeError, renderer=null_renderer
657         )
49f082 658         wrapper = self._getViewCallable(
0c29cf 659             config, exc_iface=implementedBy(RuntimeError)
MM 660         )
49f082 661         self.assertFalse(IMultiView.providedBy(wrapper))
CM 662         request = DummyRequest()
663         request.is_xhr = True
664         self.assertEqual(wrapper(None, request), 'OK')
665
666     def test_add_view_default_phash_overrides_default_phash(self):
d579f2 667         from pyramid.config.predicates import DEFAULT_PHASH
52fde9 668         from pyramid.renderers import null_renderer
49f082 669         from zope.interface import Interface
CM 670         from pyramid.interfaces import IRequest
671         from pyramid.interfaces import IView
672         from pyramid.interfaces import IViewClassifier
673         from pyramid.interfaces import IMultiView
0c29cf 674
49f082 675         view = lambda *arg: 'NOT OK'
CM 676         view.__phash__ = DEFAULT_PHASH
677         config = self._makeOne(autocommit=True)
678         config.registry.registerAdapter(
0c29cf 679             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 680         )
681
49f082 682         def newview(context, request):
CM 683             return 'OK'
0c29cf 684
49f082 685         config.add_view(view=newview, renderer=null_renderer)
CM 686         wrapper = self._getViewCallable(config)
687         self.assertFalse(IMultiView.providedBy(wrapper))
688         request = DummyRequest()
689         request.is_xhr = True
690         self.assertEqual(wrapper(None, request), 'OK')
691
692     def test_add_view_exc_default_phash_overrides_default_phash(self):
d579f2 693         from pyramid.config.predicates import DEFAULT_PHASH
52fde9 694         from pyramid.renderers import null_renderer
49f082 695         from zope.interface import implementedBy
CM 696         from pyramid.interfaces import IRequest
697         from pyramid.interfaces import IView
698         from pyramid.interfaces import IExceptionViewClassifier
699         from pyramid.interfaces import IMultiView
0c29cf 700
49f082 701         view = lambda *arg: 'NOT OK'
CM 702         view.__phash__ = DEFAULT_PHASH
703         config = self._makeOne(autocommit=True)
704         config.registry.registerAdapter(
705             view,
706             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 707             IView,
MM 708             name='',
709         )
710
49f082 711         def newview(context, request):
CM 712             return 'OK'
0c29cf 713
MM 714         config.add_view(
715             view=newview, context=RuntimeError, renderer=null_renderer
716         )
49f082 717         wrapper = self._getViewCallable(
0c29cf 718             config, exc_iface=implementedBy(RuntimeError)
MM 719         )
49f082 720         self.assertFalse(IMultiView.providedBy(wrapper))
CM 721         request = DummyRequest()
722         request.is_xhr = True
723         self.assertEqual(wrapper(None, request), 'OK')
724
725     def test_add_view_multiview_replaces_existing_view(self):
726         from pyramid.renderers import null_renderer
727         from zope.interface import Interface
728         from pyramid.interfaces import IRequest
729         from pyramid.interfaces import IView
730         from pyramid.interfaces import IViewClassifier
731         from pyramid.interfaces import IMultiView
0c29cf 732
49f082 733         view = lambda *arg: 'OK'
CM 734         view.__phash__ = 'abc'
735         config = self._makeOne(autocommit=True)
736         config.registry.registerAdapter(
0c29cf 737             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 738         )
49f082 739         config.add_view(view=view, renderer=null_renderer)
CM 740         wrapper = self._getViewCallable(config)
741         self.assertTrue(IMultiView.providedBy(wrapper))
742         self.assertEqual(wrapper(None, None), 'OK')
743
744     def test_add_view_exc_multiview_replaces_existing_view(self):
745         from pyramid.renderers import null_renderer
746         from zope.interface import implementedBy
747         from pyramid.interfaces import IRequest
748         from pyramid.interfaces import IView
749         from pyramid.interfaces import IExceptionViewClassifier
750         from pyramid.interfaces import IViewClassifier
751         from pyramid.interfaces import IMultiView
0c29cf 752
49f082 753         view = lambda *arg: 'OK'
CM 754         view.__phash__ = 'abc'
755         config = self._makeOne(autocommit=True)
756         config.registry.registerAdapter(
757             view,
758             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 759             IView,
MM 760             name='',
761         )
49f082 762         config.registry.registerAdapter(
CM 763             view,
764             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 765             IView,
MM 766             name='',
767         )
768         config.add_view(
769             view=view, context=RuntimeError, renderer=null_renderer
770         )
49f082 771         wrapper = self._getViewCallable(
0c29cf 772             config, exc_iface=implementedBy(RuntimeError)
MM 773         )
49f082 774         self.assertTrue(IMultiView.providedBy(wrapper))
CM 775         self.assertEqual(wrapper(None, None), 'OK')
776
777     def test_add_view_multiview_replaces_existing_securedview(self):
778         from pyramid.renderers import null_renderer
779         from zope.interface import Interface
780         from pyramid.interfaces import IRequest
781         from pyramid.interfaces import ISecuredView
782         from pyramid.interfaces import IMultiView
783         from pyramid.interfaces import IViewClassifier
0c29cf 784
49f082 785         view = lambda *arg: 'OK'
CM 786         view.__phash__ = 'abc'
787         config = self._makeOne(autocommit=True)
788         config.registry.registerAdapter(
0c29cf 789             view, (IViewClassifier, IRequest, Interface), ISecuredView, name=''
MM 790         )
49f082 791         config.add_view(view=view, renderer=null_renderer)
CM 792         wrapper = self._getViewCallable(config)
793         self.assertTrue(IMultiView.providedBy(wrapper))
794         self.assertEqual(wrapper(None, None), 'OK')
795
796     def test_add_view_exc_multiview_replaces_existing_securedview(self):
797         from pyramid.renderers import null_renderer
798         from zope.interface import implementedBy
799         from pyramid.interfaces import IRequest
800         from pyramid.interfaces import ISecuredView
801         from pyramid.interfaces import IMultiView
802         from pyramid.interfaces import IViewClassifier
803         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 804
49f082 805         view = lambda *arg: 'OK'
CM 806         view.__phash__ = 'abc'
807         config = self._makeOne(autocommit=True)
808         config.registry.registerAdapter(
809             view,
810             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 811             ISecuredView,
MM 812             name='',
813         )
49f082 814         config.registry.registerAdapter(
CM 815             view,
816             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 817             ISecuredView,
MM 818             name='',
819         )
820         config.add_view(
821             view=view, context=RuntimeError, renderer=null_renderer
822         )
49f082 823         wrapper = self._getViewCallable(
0c29cf 824             config, exc_iface=implementedBy(RuntimeError)
MM 825         )
49f082 826         self.assertTrue(IMultiView.providedBy(wrapper))
CM 827         self.assertEqual(wrapper(None, None), 'OK')
828
829     def test_add_view_with_accept_multiview_replaces_existing_view(self):
830         from pyramid.renderers import null_renderer
831         from zope.interface import Interface
832         from pyramid.interfaces import IRequest
833         from pyramid.interfaces import IView
834         from pyramid.interfaces import IMultiView
835         from pyramid.interfaces import IViewClassifier
0c29cf 836
49f082 837         def view(context, request):
CM 838             return 'OK'
0c29cf 839
49f082 840         def view2(context, request):
CM 841             return 'OK2'
0c29cf 842
49f082 843         config = self._makeOne(autocommit=True)
CM 844         config.registry.registerAdapter(
0c29cf 845             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 846         )
49f082 847         config.add_view(view=view2, accept='text/html', renderer=null_renderer)
CM 848         wrapper = self._getViewCallable(config)
849         self.assertTrue(IMultiView.providedBy(wrapper))
850         self.assertEqual(len(wrapper.views), 1)
851         self.assertEqual(len(wrapper.media_views), 1)
852         self.assertEqual(wrapper(None, None), 'OK')
853         request = DummyRequest()
854         request.accept = DummyAccept('text/html', 'text/html')
855         self.assertEqual(wrapper(None, request), 'OK2')
856
34f00a 857     def test_add_view_mixed_case_replaces_existing_view(self):
LMC 858         from pyramid.renderers import null_renderer
0c29cf 859
MM 860         def view(context, request):
861             return 'OK'
862
10ddb6 863         def view2(context, request):  # pragma: no cover
0c29cf 864             return 'OK2'
MM 865
866         def view3(context, request):
867             return 'OK3'
868
34f00a 869         config = self._makeOne(autocommit=True)
LMC 870         config.add_view(view=view, renderer=null_renderer)
871         config.add_view(view=view2, accept='text/html', renderer=null_renderer)
872         config.add_view(view=view3, accept='text/HTML', renderer=null_renderer)
873         wrapper = self._getViewCallable(config)
874         self.assertTrue(IMultiView.providedBy(wrapper))
0c29cf 875         self.assertEqual(len(wrapper.media_views.items()), 1)
9822a1 876         self.assertFalse('text/HTML' in wrapper.media_views)
34f00a 877         self.assertEqual(wrapper(None, None), 'OK')
LMC 878         request = DummyRequest()
879         request.accept = DummyAccept('text/html', 'text/html')
880         self.assertEqual(wrapper(None, request), 'OK3')
881
8ea3f3 882     def test_add_views_with_accept_multiview_replaces_existing(self):
DN 883         from pyramid.renderers import null_renderer
0c29cf 884
MM 885         def view(context, request):
886             return 'OK'
887
10ddb6 888         def view2(context, request):  # pragma: no cover
0c29cf 889             return 'OK2'
MM 890
891         def view3(context, request):
892             return 'OK3'
893
8ea3f3 894         config = self._makeOne(autocommit=True)
DN 895         config.add_view(view=view, renderer=null_renderer)
896         config.add_view(view=view2, accept='text/html', renderer=null_renderer)
897         config.add_view(view=view3, accept='text/html', renderer=null_renderer)
898         wrapper = self._getViewCallable(config)
f4b7fd 899         self.assertEqual(len(wrapper.media_views['text/html']), 1)
8ea3f3 900         self.assertEqual(wrapper(None, None), 'OK')
DN 901         request = DummyRequest()
902         request.accept = DummyAccept('text/html', 'text/html')
903         self.assertEqual(wrapper(None, request), 'OK3')
904
49f082 905     def test_add_view_exc_with_accept_multiview_replaces_existing_view(self):
CM 906         from pyramid.renderers import null_renderer
907         from zope.interface import implementedBy
908         from pyramid.interfaces import IRequest
909         from pyramid.interfaces import IView
910         from pyramid.interfaces import IMultiView
911         from pyramid.interfaces import IViewClassifier
912         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 913
49f082 914         def view(context, request):
CM 915             return 'OK'
0c29cf 916
49f082 917         def view2(context, request):
CM 918             return 'OK2'
0c29cf 919
49f082 920         config = self._makeOne(autocommit=True)
CM 921         config.registry.registerAdapter(
922             view,
923             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 924             IView,
MM 925             name='',
926         )
49f082 927         config.registry.registerAdapter(
CM 928             view,
929             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 930             IView,
MM 931             name='',
932         )
933         config.add_view(
934             view=view2,
935             accept='text/html',
936             context=RuntimeError,
937             renderer=null_renderer,
938         )
49f082 939         wrapper = self._getViewCallable(
0c29cf 940             config, exc_iface=implementedBy(RuntimeError)
MM 941         )
49f082 942         self.assertTrue(IMultiView.providedBy(wrapper))
CM 943         self.assertEqual(len(wrapper.views), 1)
944         self.assertEqual(len(wrapper.media_views), 1)
945         self.assertEqual(wrapper(None, None), 'OK')
946         request = DummyRequest()
947         request.accept = DummyAccept('text/html', 'text/html')
948         self.assertEqual(wrapper(None, request), 'OK2')
949
950     def test_add_view_multiview_replaces_existing_view_with___accept__(self):
951         from pyramid.renderers import null_renderer
952         from zope.interface import Interface
953         from pyramid.interfaces import IRequest
954         from pyramid.interfaces import IView
955         from pyramid.interfaces import IMultiView
956         from pyramid.interfaces import IViewClassifier
0c29cf 957
49f082 958         def view(context, request):
CM 959             return 'OK'
0c29cf 960
49f082 961         def view2(context, request):
CM 962             return 'OK2'
0c29cf 963
49f082 964         view.__accept__ = 'text/html'
CM 965         view.__phash__ = 'abc'
966         config = self._makeOne(autocommit=True)
967         config.registry.registerAdapter(
0c29cf 968             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 969         )
49f082 970         config.add_view(view=view2, renderer=null_renderer)
CM 971         wrapper = self._getViewCallable(config)
972         self.assertTrue(IMultiView.providedBy(wrapper))
973         self.assertEqual(len(wrapper.views), 1)
974         self.assertEqual(len(wrapper.media_views), 1)
975         self.assertEqual(wrapper(None, None), 'OK2')
976         request = DummyRequest()
977         request.accept = DummyAccept('text/html')
978         self.assertEqual(wrapper(None, request), 'OK')
979
980     def test_add_view_exc_mulview_replaces_existing_view_with___accept__(self):
981         from pyramid.renderers import null_renderer
982         from zope.interface import implementedBy
983         from pyramid.interfaces import IRequest
984         from pyramid.interfaces import IView
985         from pyramid.interfaces import IMultiView
986         from pyramid.interfaces import IViewClassifier
987         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 988
49f082 989         def view(context, request):
CM 990             return 'OK'
0c29cf 991
49f082 992         def view2(context, request):
CM 993             return 'OK2'
0c29cf 994
49f082 995         view.__accept__ = 'text/html'
CM 996         view.__phash__ = 'abc'
997         config = self._makeOne(autocommit=True)
998         config.registry.registerAdapter(
999             view,
1000             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1001             IView,
MM 1002             name='',
1003         )
49f082 1004         config.registry.registerAdapter(
CM 1005             view,
1006             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1007             IView,
MM 1008             name='',
1009         )
1010         config.add_view(
1011             view=view2, context=RuntimeError, renderer=null_renderer
1012         )
49f082 1013         wrapper = self._getViewCallable(
0c29cf 1014             config, exc_iface=implementedBy(RuntimeError)
MM 1015         )
49f082 1016         self.assertTrue(IMultiView.providedBy(wrapper))
CM 1017         self.assertEqual(len(wrapper.views), 1)
1018         self.assertEqual(len(wrapper.media_views), 1)
1019         self.assertEqual(wrapper(None, None), 'OK2')
1020         request = DummyRequest()
1021         request.accept = DummyAccept('text/html')
1022         self.assertEqual(wrapper(None, request), 'OK')
1023
1024     def test_add_view_multiview_replaces_multiview(self):
1025         from pyramid.renderers import null_renderer
1026         from zope.interface import Interface
1027         from pyramid.interfaces import IRequest
1028         from pyramid.interfaces import IMultiView
1029         from pyramid.interfaces import IViewClassifier
0c29cf 1030
49f082 1031         view = DummyMultiView()
CM 1032         config = self._makeOne(autocommit=True)
1033         config.registry.registerAdapter(
0c29cf 1034             view, (IViewClassifier, IRequest, Interface), IMultiView, name=''
MM 1035         )
49f082 1036         view2 = lambda *arg: 'OK2'
CM 1037         config.add_view(view=view2, renderer=null_renderer)
1038         wrapper = self._getViewCallable(config)
1039         self.assertTrue(IMultiView.providedBy(wrapper))
0c29cf 1040         self.assertEqual(
MM 1041             [(x[0], x[2]) for x in wrapper.views], [(view2, None)]
1042         )
49f082 1043         self.assertEqual(wrapper(None, None), 'OK1')
CM 1044
e8c66a 1045     def test_add_view_exc_multiview_replaces_multiviews(self):
49f082 1046         from pyramid.renderers import null_renderer
CM 1047         from zope.interface import implementedBy
1048         from pyramid.interfaces import IRequest
1049         from pyramid.interfaces import IMultiView
1050         from pyramid.interfaces import IViewClassifier
1051         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 1052
e8c66a 1053         hot_view = DummyMultiView()
MM 1054         exc_view = DummyMultiView()
49f082 1055         config = self._makeOne(autocommit=True)
CM 1056         config.registry.registerAdapter(
e8c66a 1057             hot_view,
49f082 1058             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1059             IMultiView,
MM 1060             name='',
1061         )
49f082 1062         config.registry.registerAdapter(
e8c66a 1063             exc_view,
49f082 1064             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1065             IMultiView,
MM 1066             name='',
1067         )
49f082 1068         view2 = lambda *arg: 'OK2'
0c29cf 1069         config.add_view(
MM 1070             view=view2, context=RuntimeError, renderer=null_renderer
1071         )
e8c66a 1072         hot_wrapper = self._getViewCallable(
0c29cf 1073             config, ctx_iface=implementedBy(RuntimeError)
MM 1074         )
e8c66a 1075         self.assertTrue(IMultiView.providedBy(hot_wrapper))
0c29cf 1076         self.assertEqual(
MM 1077             [(x[0], x[2]) for x in hot_wrapper.views], [(view2, None)]
1078         )
e8c66a 1079         self.assertEqual(hot_wrapper(None, None), 'OK1')
MM 1080
1081         exc_wrapper = self._getViewCallable(
0c29cf 1082             config, exc_iface=implementedBy(RuntimeError)
MM 1083         )
e8c66a 1084         self.assertTrue(IMultiView.providedBy(exc_wrapper))
0c29cf 1085         self.assertEqual(
MM 1086             [(x[0], x[2]) for x in exc_wrapper.views], [(view2, None)]
1087         )
e8c66a 1088         self.assertEqual(exc_wrapper(None, None), 'OK1')
MM 1089
1090     def test_add_view_exc_multiview_replaces_only_exc_multiview(self):
1091         from pyramid.renderers import null_renderer
1092         from zope.interface import implementedBy
1093         from pyramid.interfaces import IRequest
1094         from pyramid.interfaces import IMultiView
1095         from pyramid.interfaces import IViewClassifier
1096         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 1097
e8c66a 1098         hot_view = DummyMultiView()
MM 1099         exc_view = DummyMultiView()
1100         config = self._makeOne(autocommit=True)
1101         config.registry.registerAdapter(
1102             hot_view,
1103             (IViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1104             IMultiView,
MM 1105             name='',
1106         )
e8c66a 1107         config.registry.registerAdapter(
MM 1108             exc_view,
1109             (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
0c29cf 1110             IMultiView,
MM 1111             name='',
1112         )
e8c66a 1113         view2 = lambda *arg: 'OK2'
0c29cf 1114         config.add_view(
MM 1115             view=view2,
1116             context=RuntimeError,
1117             exception_only=True,
1118             renderer=null_renderer,
1119         )
e8c66a 1120         hot_wrapper = self._getViewCallable(
0c29cf 1121             config, ctx_iface=implementedBy(RuntimeError)
MM 1122         )
e8c66a 1123         self.assertTrue(IMultiView.providedBy(hot_wrapper))
MM 1124         self.assertEqual(len(hot_wrapper.views), 0)
1125         self.assertEqual(hot_wrapper(None, None), 'OK1')
1126
1127         exc_wrapper = self._getViewCallable(
0c29cf 1128             config, exc_iface=implementedBy(RuntimeError)
MM 1129         )
e8c66a 1130         self.assertTrue(IMultiView.providedBy(exc_wrapper))
0c29cf 1131         self.assertEqual(
MM 1132             [(x[0], x[2]) for x in exc_wrapper.views], [(view2, None)]
1133         )
e8c66a 1134         self.assertEqual(exc_wrapper(None, None), 'OK1')
49f082 1135
CM 1136     def test_add_view_multiview_context_superclass_then_subclass(self):
1137         from pyramid.renderers import null_renderer
1138         from zope.interface import Interface
1139         from pyramid.interfaces import IRequest
1140         from pyramid.interfaces import IView
1141         from pyramid.interfaces import IMultiView
1142         from pyramid.interfaces import IViewClassifier
0c29cf 1143
49f082 1144         class ISuper(Interface):
CM 1145             pass
0c29cf 1146
49f082 1147         class ISub(ISuper):
CM 1148             pass
0c29cf 1149
49f082 1150         view = lambda *arg: 'OK'
CM 1151         view2 = lambda *arg: 'OK2'
1152         config = self._makeOne(autocommit=True)
1153         config.registry.registerAdapter(
0c29cf 1154             view, (IViewClassifier, IRequest, ISuper), IView, name=''
MM 1155         )
49f082 1156         config.add_view(view=view2, for_=ISub, renderer=null_renderer)
0c29cf 1157         wrapper = self._getViewCallable(
MM 1158             config, ctx_iface=ISuper, request_iface=IRequest
1159         )
49f082 1160         self.assertFalse(IMultiView.providedBy(wrapper))
CM 1161         self.assertEqual(wrapper(None, None), 'OK')
0c29cf 1162         wrapper = self._getViewCallable(
MM 1163             config, ctx_iface=ISub, request_iface=IRequest
1164         )
49f082 1165         self.assertFalse(IMultiView.providedBy(wrapper))
CM 1166         self.assertEqual(wrapper(None, None), 'OK2')
1167
1168     def test_add_view_multiview_exception_superclass_then_subclass(self):
1169         from pyramid.renderers import null_renderer
1170         from zope.interface import implementedBy
1171         from pyramid.interfaces import IRequest
1172         from pyramid.interfaces import IView
1173         from pyramid.interfaces import IMultiView
1174         from pyramid.interfaces import IViewClassifier
1175         from pyramid.interfaces import IExceptionViewClassifier
0c29cf 1176
49f082 1177         class Super(Exception):
CM 1178             pass
0c29cf 1179
49f082 1180         class Sub(Super):
CM 1181             pass
0c29cf 1182
49f082 1183         view = lambda *arg: 'OK'
CM 1184         view2 = lambda *arg: 'OK2'
1185         config = self._makeOne(autocommit=True)
1186         config.registry.registerAdapter(
0c29cf 1187             view, (IViewClassifier, IRequest, Super), IView, name=''
MM 1188         )
49f082 1189         config.registry.registerAdapter(
0c29cf 1190             view, (IExceptionViewClassifier, IRequest, Super), IView, name=''
MM 1191         )
49f082 1192         config.add_view(view=view2, for_=Sub, renderer=null_renderer)
CM 1193         wrapper = self._getViewCallable(
0c29cf 1194             config, ctx_iface=implementedBy(Super), request_iface=IRequest
MM 1195         )
49f082 1196         wrapper_exc_view = self._getViewCallable(
0c29cf 1197             config, exc_iface=implementedBy(Super), request_iface=IRequest
MM 1198         )
49f082 1199         self.assertEqual(wrapper_exc_view, wrapper)
CM 1200         self.assertFalse(IMultiView.providedBy(wrapper_exc_view))
1201         self.assertEqual(wrapper_exc_view(None, None), 'OK')
1202         wrapper = self._getViewCallable(
0c29cf 1203             config, ctx_iface=implementedBy(Sub), request_iface=IRequest
MM 1204         )
49f082 1205         wrapper_exc_view = self._getViewCallable(
0c29cf 1206             config, exc_iface=implementedBy(Sub), request_iface=IRequest
MM 1207         )
49f082 1208         self.assertEqual(wrapper_exc_view, wrapper)
CM 1209         self.assertFalse(IMultiView.providedBy(wrapper_exc_view))
1210         self.assertEqual(wrapper_exc_view(None, None), 'OK2')
1211
1212     def test_add_view_multiview_call_ordering(self):
1213         from pyramid.renderers import null_renderer as nr
1214         from zope.interface import directlyProvides
0c29cf 1215
MM 1216         def view1(context, request):
1217             return 'view1'
1218
1219         def view2(context, request):
1220             return 'view2'
1221
1222         def view3(context, request):
1223             return 'view3'
1224
1225         def view4(context, request):
1226             return 'view4'
1227
1228         def view5(context, request):
1229             return 'view5'
1230
1231         def view6(context, request):
1232             return 'view6'
1233
1234         def view7(context, request):
1235             return 'view7'
1236
1237         def view8(context, request):
1238             return 'view8'
1239
49f082 1240         config = self._makeOne(autocommit=True)
CM 1241         config.add_view(view=view1, renderer=nr)
1242         config.add_view(view=view2, request_method='POST', renderer=nr)
0c29cf 1243         config.add_view(view=view3, request_param='param', renderer=nr)
49f082 1244         config.add_view(view=view4, containment=IDummy, renderer=nr)
0c29cf 1245         config.add_view(
MM 1246             view=view5,
1247             request_method='POST',
1248             request_param='param',
1249             renderer=nr,
1250         )
1251         config.add_view(
1252             view=view6, request_method='POST', containment=IDummy, renderer=nr
1253         )
1254         config.add_view(
1255             view=view7, request_param='param', containment=IDummy, renderer=nr
1256         )
1257         config.add_view(
1258             view=view8,
1259             request_method='POST',
1260             request_param='param',
1261             containment=IDummy,
1262             renderer=nr,
1263         )
49f082 1264
CM 1265         wrapper = self._getViewCallable(config)
1266
1267         ctx = DummyContext()
1268         request = self._makeRequest(config)
1269         request.method = 'GET'
1270         request.params = {}
1271         self.assertEqual(wrapper(ctx, request), 'view1')
1272
1273         ctx = DummyContext()
1274         request = self._makeRequest(config)
1275         request.params = {}
1276         request.method = 'POST'
1277         self.assertEqual(wrapper(ctx, request), 'view2')
1278
1279         ctx = DummyContext()
1280         request = self._makeRequest(config)
0c29cf 1281         request.params = {'param': '1'}
49f082 1282         request.method = 'GET'
CM 1283         self.assertEqual(wrapper(ctx, request), 'view3')
1284
1285         ctx = DummyContext()
1286         directlyProvides(ctx, IDummy)
1287         request = self._makeRequest(config)
1288         request.method = 'GET'
1289         request.params = {}
1290         self.assertEqual(wrapper(ctx, request), 'view4')
1291
1292         ctx = DummyContext()
1293         request = self._makeRequest(config)
1294         request.method = 'POST'
0c29cf 1295         request.params = {'param': '1'}
49f082 1296         self.assertEqual(wrapper(ctx, request), 'view5')
CM 1297
1298         ctx = DummyContext()
1299         directlyProvides(ctx, IDummy)
1300         request = self._makeRequest(config)
1301         request.params = {}
1302         request.method = 'POST'
1303         self.assertEqual(wrapper(ctx, request), 'view6')
1304
1305         ctx = DummyContext()
1306         directlyProvides(ctx, IDummy)
1307         request = self._makeRequest(config)
1308         request.method = 'GET'
0c29cf 1309         request.params = {'param': '1'}
49f082 1310         self.assertEqual(wrapper(ctx, request), 'view7')
CM 1311
1312         ctx = DummyContext()
1313         directlyProvides(ctx, IDummy)
1314         request = self._makeRequest(config)
1315         request.method = 'POST'
0c29cf 1316         request.params = {'param': '1'}
49f082 1317         self.assertEqual(wrapper(ctx, request), 'view8')
CM 1318
0b03c3 1319     def test_view_with_most_specific_predicate(self):
JA 1320         from pyramid.renderers import null_renderer as nr
1321         from pyramid.router import Router
1322
0c29cf 1323         class OtherBase(object):
MM 1324             pass
1325
1326         class Int1(object):
1327             pass
1328
1329         class Int2(object):
1330             pass
0b03c3 1331
JA 1332         class Resource(OtherBase, Int1, Int2):
0c29cf 1333             def __init__(self, request):
MM 1334                 pass
0b03c3 1335
10ddb6 1336         def unknown(context, request):  # pragma: no cover
0c29cf 1337             return 'unknown'
MM 1338
1339         def view(context, request):
1340             return 'hello'
0b03c3 1341
JA 1342         config = self._makeOne(autocommit=True)
1343         config.add_route('root', '/', factory=Resource)
1344         config.add_view(unknown, route_name='root', renderer=nr)
1345         config.add_view(
0c29cf 1346             view,
MM 1347             renderer=nr,
1348             route_name='root',
1349             context=Int1,
1350             request_method='GET',
0b03c3 1351         )
JA 1352         config.add_view(
0c29cf 1353             view=view,
MM 1354             renderer=nr,
1355             route_name='root',
1356             context=Int2,
1357             request_method='POST',
0b03c3 1358         )
JA 1359         request = self._makeRequest(config)
1360         request.method = 'POST'
1361         request.params = {}
1362         router = Router(config.registry)
1363         response = router.handle_request(request)
1364         self.assertEqual(response, 'hello')
1365
1366     def test_view_with_most_specific_predicate_with_mismatch(self):
1367         from pyramid.renderers import null_renderer as nr
1368         from pyramid.router import Router
1369
0c29cf 1370         class OtherBase(object):
MM 1371             pass
1372
1373         class Int1(object):
1374             pass
1375
1376         class Int2(object):
1377             pass
0b03c3 1378
JA 1379         class Resource(OtherBase, Int1, Int2):
0c29cf 1380             def __init__(self, request):
MM 1381                 pass
0b03c3 1382
10ddb6 1383         def unknown(context, request):  # pragma: no cover
0c29cf 1384             return 'unknown'
MM 1385
1386         def view(context, request):
1387             return 'hello'
0b03c3 1388
JA 1389         config = self._makeOne(autocommit=True)
1390         config.add_route('root', '/', factory=Resource)
1391
1392         config.add_view(
1393             unknown,
1394             route_name='root',
1395             renderer=nr,
1396             request_method=('POST',),
1397             xhr=True,
1398         )
1399
1400         config.add_view(
0c29cf 1401             view,
MM 1402             renderer=nr,
1403             route_name='root',
1404             context=Int1,
1405             request_method='GET',
0b03c3 1406         )
JA 1407         config.add_view(
0c29cf 1408             view=view,
MM 1409             renderer=nr,
1410             route_name='root',
1411             context=Int2,
1412             request_method='POST',
0b03c3 1413         )
JA 1414         request = self._makeRequest(config)
1415         request.method = 'POST'
1416         request.params = {}
1417         router = Router(config.registry)
1418         response = router.handle_request(request)
1419         self.assertEqual(response, 'hello')
1420
ba2a3f 1421     def test_add_view_multiview___discriminator__(self):
CM 1422         from pyramid.renderers import null_renderer
1423         from zope.interface import Interface
0c29cf 1424
ba2a3f 1425         class IFoo(Interface):
CM 1426             pass
0c29cf 1427
ba2a3f 1428         class IBar(Interface):
CM 1429             pass
0c29cf 1430
ba2a3f 1431         @implementer(IFoo)
CM 1432         class Foo(object):
1433             pass
0c29cf 1434
ba2a3f 1435         @implementer(IBar)
CM 1436         class Bar(object):
1437             pass
0c29cf 1438
ba2a3f 1439         foo = Foo()
CM 1440         bar = Bar()
42afb0 1441
ba2a3f 1442         from pyramid.interfaces import IRequest
CM 1443         from pyramid.interfaces import IView
1444         from pyramid.interfaces import IViewClassifier
1445         from pyramid.interfaces import IMultiView
0c29cf 1446
ba2a3f 1447         view = lambda *arg: 'OK'
CM 1448         view.__phash__ = 'abc'
1449         config = self._makeOne(autocommit=True)
1450         config.registry.registerAdapter(
0c29cf 1451             view, (IViewClassifier, IRequest, Interface), IView, name=''
MM 1452         )
1453         config.add_view(view=view, renderer=null_renderer, containment=IFoo)
1454         config.add_view(view=view, renderer=null_renderer, containment=IBar)
ba2a3f 1455         wrapper = self._getViewCallable(config)
CM 1456         self.assertTrue(IMultiView.providedBy(wrapper))
1457         request = self._makeRequest(config)
9c8ec5 1458         self.assertNotEqual(
CM 1459             wrapper.__discriminator__(foo, request),
1460             wrapper.__discriminator__(bar, request),
0c29cf 1461         )
ba2a3f 1462
49f082 1463     def test_add_view_with_template_renderer(self):
dd3cc8 1464         from tests import test_config
49f082 1465         from pyramid.interfaces import ISettings
0c29cf 1466
49f082 1467         class view(object):
CM 1468             def __init__(self, context, request):
1469                 self.request = request
1470                 self.context = context
1471
1472             def __call__(self):
0c29cf 1473                 return {'a': '1'}
MM 1474
49f082 1475         config = self._makeOne(autocommit=True)
CM 1476         renderer = self._registerRenderer(config)
dd3cc8 1477         fixture = 'tests.test_config:files/minimal.txt'
b368d7 1478         config.introspection = False
49f082 1479         config.add_view(view=view, renderer=fixture)
CM 1480         wrapper = self._getViewCallable(config)
1481         request = self._makeRequest(config)
1482         result = wrapper(None, request)
8e606d 1483         self.assertEqual(result.body, b'Hello!')
49f082 1484         settings = config.registry.queryUtility(ISettings)
CM 1485         result = renderer.info
1486         self.assertEqual(result.registry, config.registry)
1487         self.assertEqual(result.type, '.txt')
1488         self.assertEqual(result.package, test_config)
1489         self.assertEqual(result.name, fixture)
1490         self.assertEqual(result.settings, settings)
1491
1492     def test_add_view_with_default_renderer(self):
1493         class view(object):
1494             def __init__(self, context, request):
1495                 self.request = request
1496                 self.context = context
1497
1498             def __call__(self):
0c29cf 1499                 return {'a': '1'}
MM 1500
49f082 1501         config = self._makeOne(autocommit=True)
0c29cf 1502
49f082 1503         class moo(object):
CM 1504             def __init__(self, *arg, **kw):
1505                 pass
0c29cf 1506
49f082 1507             def __call__(self, *arg, **kw):
42afb0 1508                 return b'moo'
0c29cf 1509
49f082 1510         config.add_renderer(None, moo)
CM 1511         config.add_view(view=view)
1512         wrapper = self._getViewCallable(config)
1513         request = self._makeRequest(config)
1514         result = wrapper(None, request)
8e606d 1515         self.assertEqual(result.body, b'moo')
49f082 1516
CM 1517     def test_add_view_with_template_renderer_no_callable(self):
dd3cc8 1518         from tests import test_config
49f082 1519         from pyramid.interfaces import ISettings
0c29cf 1520
49f082 1521         config = self._makeOne(autocommit=True)
CM 1522         renderer = self._registerRenderer(config)
dd3cc8 1523         fixture = 'tests.test_config:files/minimal.txt'
b368d7 1524         config.introspection = False
49f082 1525         config.add_view(view=None, renderer=fixture)
CM 1526         wrapper = self._getViewCallable(config)
1527         request = self._makeRequest(config)
1528         result = wrapper(None, request)
8e606d 1529         self.assertEqual(result.body, b'Hello!')
49f082 1530         settings = config.registry.queryUtility(ISettings)
CM 1531         result = renderer.info
1532         self.assertEqual(result.registry, config.registry)
1533         self.assertEqual(result.type, '.txt')
1534         self.assertEqual(result.package, test_config)
1535         self.assertEqual(result.name, fixture)
1536         self.assertEqual(result.settings, settings)
1537
1538     def test_add_view_with_request_type_as_iface(self):
1539         from pyramid.renderers import null_renderer
1540         from zope.interface import directlyProvides
0c29cf 1541
49f082 1542         def view(context, request):
CM 1543             return 'OK'
0c29cf 1544
49f082 1545         config = self._makeOne(autocommit=True)
CM 1546         config.add_view(request_type=IDummy, view=view, renderer=null_renderer)
1547         wrapper = self._getViewCallable(config, None)
1548         request = self._makeRequest(config)
1549         directlyProvides(request, IDummy)
1550         result = wrapper(None, request)
1551         self.assertEqual(result, 'OK')
1552
1553     def test_add_view_with_request_type_as_noniface(self):
1554         view = lambda *arg: 'OK'
1555         config = self._makeOne()
0c29cf 1556         self.assertRaises(
MM 1557             ConfigurationError, config.add_view, view, '', None, None, object
1558         )
49f082 1559
CM 1560     def test_add_view_with_route_name(self):
1561         from pyramid.renderers import null_renderer
0c29cf 1562
49f082 1563         view = lambda *arg: 'OK'
CM 1564         config = self._makeOne(autocommit=True)
1565         config.add_route('foo', '/a/b')
1566         config.add_view(view=view, route_name='foo', renderer=null_renderer)
1567         request_iface = self._getRouteRequestIface(config, 'foo')
1568         self.assertNotEqual(request_iface, None)
1569         wrapper = self._getViewCallable(config, request_iface=request_iface)
1570         self.assertNotEqual(wrapper, None)
1571         self.assertEqual(wrapper(None, None), 'OK')
1572
1573     def test_add_view_with_nonexistant_route_name(self):
1574         from pyramid.renderers import null_renderer
0c29cf 1575
49f082 1576         view = lambda *arg: 'OK'
CM 1577         config = self._makeOne()
1578         config.add_view(view=view, route_name='foo', renderer=null_renderer)
1579         self.assertRaises(ConfigurationExecutionError, config.commit)
1580
1581     def test_add_view_with_route_name_exception(self):
1582         from pyramid.renderers import null_renderer
1583         from zope.interface import implementedBy
0c29cf 1584
49f082 1585         view = lambda *arg: 'OK'
CM 1586         config = self._makeOne(autocommit=True)
1587         config.add_route('foo', '/a/b')
0c29cf 1588         config.add_view(
MM 1589             view=view,
1590             route_name='foo',
1591             context=RuntimeError,
1592             renderer=null_renderer,
1593         )
49f082 1594         request_iface = self._getRouteRequestIface(config, 'foo')
CM 1595         wrapper_exc_view = self._getViewCallable(
0c29cf 1596             config,
MM 1597             exc_iface=implementedBy(RuntimeError),
1598             request_iface=request_iface,
1599         )
49f082 1600         self.assertNotEqual(wrapper_exc_view, None)
CM 1601         wrapper = self._getViewCallable(
0c29cf 1602             config,
MM 1603             ctx_iface=implementedBy(RuntimeError),
1604             request_iface=request_iface,
1605         )
49f082 1606         self.assertEqual(wrapper_exc_view, wrapper)
CM 1607         self.assertEqual(wrapper_exc_view(None, None), 'OK')
1608
1609     def test_add_view_with_request_method_true(self):
1610         from pyramid.renderers import null_renderer
0c29cf 1611
49f082 1612         view = lambda *arg: 'OK'
CM 1613         config = self._makeOne(autocommit=True)
0c29cf 1614         config.add_view(
MM 1615             view=view, request_method='POST', renderer=null_renderer
1616         )
49f082 1617         wrapper = self._getViewCallable(config)
CM 1618         request = self._makeRequest(config)
1619         request.method = 'POST'
1620         self.assertEqual(wrapper(None, request), 'OK')
1621
1622     def test_add_view_with_request_method_false(self):
1623         view = lambda *arg: 'OK'
1624         config = self._makeOne(autocommit=True)
1625         config.add_view(view=view, request_method='POST')
1626         wrapper = self._getViewCallable(config)
1627         request = self._makeRequest(config)
1628         request.method = 'GET'
1629         self._assertNotFound(wrapper, None, request)
1630
1631     def test_add_view_with_request_method_sequence_true(self):
1632         from pyramid.renderers import null_renderer
0c29cf 1633
49f082 1634         view = lambda *arg: 'OK'
CM 1635         config = self._makeOne(autocommit=True)
0c29cf 1636         config.add_view(
MM 1637             view=view, request_method=('POST', 'GET'), renderer=null_renderer
1638         )
49f082 1639         wrapper = self._getViewCallable(config)
CM 1640         request = self._makeRequest(config)
1641         request.method = 'POST'
1642         self.assertEqual(wrapper(None, request), 'OK')
1643
1644     def test_add_view_with_request_method_sequence_conflict(self):
1645         from pyramid.renderers import null_renderer
0c29cf 1646
49f082 1647         view = lambda *arg: 'OK'
CM 1648         config = self._makeOne()
0c29cf 1649         config.add_view(
MM 1650             view=view, request_method=('POST', 'GET'), renderer=null_renderer
1651         )
1652         config.add_view(
1653             view=view, request_method=('GET', 'POST'), renderer=null_renderer
1654         )
49f082 1655         self.assertRaises(ConfigurationConflictError, config.commit)
CM 1656
1657     def test_add_view_with_request_method_sequence_false(self):
1658         view = lambda *arg: 'OK'
1659         config = self._makeOne(autocommit=True)
1660         config.add_view(view=view, request_method=('POST', 'HEAD'))
1661         wrapper = self._getViewCallable(config)
1662         request = self._makeRequest(config)
1663         request.method = 'GET'
1664         self._assertNotFound(wrapper, None, request)
1665
360f25 1666     def test_add_view_with_request_method_get_implies_head(self):
CM 1667         from pyramid.renderers import null_renderer
0c29cf 1668
360f25 1669         view = lambda *arg: 'OK'
CM 1670         config = self._makeOne(autocommit=True)
0c29cf 1671         config.add_view(
MM 1672             view=view, request_method='GET', renderer=null_renderer
1673         )
360f25 1674         wrapper = self._getViewCallable(config)
CM 1675         request = self._makeRequest(config)
1676         request.method = 'HEAD'
1677         self.assertEqual(wrapper(None, request), 'OK')
42afb0 1678
49f082 1679     def test_add_view_with_request_param_noval_true(self):
CM 1680         from pyramid.renderers import null_renderer
0c29cf 1681
49f082 1682         view = lambda *arg: 'OK'
CM 1683         config = self._makeOne(autocommit=True)
1684         config.add_view(view=view, request_param='abc', renderer=null_renderer)
1685         wrapper = self._getViewCallable(config)
1686         request = self._makeRequest(config)
0c29cf 1687         request.params = {'abc': ''}
49f082 1688         self.assertEqual(wrapper(None, request), 'OK')
CM 1689
1690     def test_add_view_with_request_param_noval_false(self):
1691         view = lambda *arg: 'OK'
1692         config = self._makeOne(autocommit=True)
1693         config.add_view(view=view, request_param='abc')
1694         wrapper = self._getViewCallable(config)
1695         request = self._makeRequest(config)
1696         request.params = {}
1697         self._assertNotFound(wrapper, None, request)
1698
1699     def test_add_view_with_request_param_val_true(self):
1700         from pyramid.renderers import null_renderer
0c29cf 1701
49f082 1702         view = lambda *arg: 'OK'
CM 1703         config = self._makeOne(autocommit=True)
0c29cf 1704         config.add_view(
MM 1705             view=view, request_param='abc=123', renderer=null_renderer
1706         )
49f082 1707         wrapper = self._getViewCallable(config)
CM 1708         request = self._makeRequest(config)
0c29cf 1709         request.params = {'abc': '123'}
49f082 1710         self.assertEqual(wrapper(None, request), 'OK')
CM 1711
1712     def test_add_view_with_request_param_val_false(self):
1713         view = lambda *arg: 'OK'
1714         config = self._makeOne(autocommit=True)
1715         config.add_view(view=view, request_param='abc=123')
1716         wrapper = self._getViewCallable(config)
1717         request = self._makeRequest(config)
0c29cf 1718         request.params = {'abc': ''}
49f082 1719         self._assertNotFound(wrapper, None, request)
CM 1720
1721     def test_add_view_with_xhr_true(self):
1722         from pyramid.renderers import null_renderer
0c29cf 1723
49f082 1724         view = lambda *arg: 'OK'
CM 1725         config = self._makeOne(autocommit=True)
1726         config.add_view(view=view, xhr=True, renderer=null_renderer)
1727         wrapper = self._getViewCallable(config)
1728         request = self._makeRequest(config)
1729         request.is_xhr = True
1730         self.assertEqual(wrapper(None, request), 'OK')
1731
1732     def test_add_view_with_xhr_false(self):
1733         view = lambda *arg: 'OK'
1734         config = self._makeOne(autocommit=True)
1735         config.add_view(view=view, xhr=True)
1736         wrapper = self._getViewCallable(config)
1737         request = self._makeRequest(config)
1738         request.is_xhr = False
1739         self._assertNotFound(wrapper, None, request)
1740
1741     def test_add_view_with_header_badregex(self):
1742         view = lambda *arg: 'OK'
1743         config = self._makeOne()
a00621 1744         config.add_view(view, header='Host:a\\')
CM 1745         self.assertRaises(ConfigurationError, config.commit)
49f082 1746
CM 1747     def test_add_view_with_header_noval_match(self):
1748         from pyramid.renderers import null_renderer
0c29cf 1749
49f082 1750         view = lambda *arg: 'OK'
CM 1751         config = self._makeOne(autocommit=True)
1752         config.add_view(view=view, header='Host', renderer=null_renderer)
1753         wrapper = self._getViewCallable(config)
1754         request = self._makeRequest(config)
0c29cf 1755         request.headers = {'Host': 'whatever'}
49f082 1756         self.assertEqual(wrapper(None, request), 'OK')
CM 1757
1758     def test_add_view_with_header_noval_nomatch(self):
1759         view = lambda *arg: 'OK'
1760         config = self._makeOne(autocommit=True)
1761         config.add_view(view=view, header='Host')
1762         wrapper = self._getViewCallable(config)
1763         request = self._makeRequest(config)
0c29cf 1764         request.headers = {'NotHost': 'whatever'}
49f082 1765         self._assertNotFound(wrapper, None, request)
CM 1766
1767     def test_add_view_with_header_val_match(self):
1768         from pyramid.renderers import null_renderer
0c29cf 1769
49f082 1770         view = lambda *arg: 'OK'
CM 1771         config = self._makeOne(autocommit=True)
1772         config.add_view(view=view, header=r'Host:\d', renderer=null_renderer)
1773         wrapper = self._getViewCallable(config)
1774         request = self._makeRequest(config)
0c29cf 1775         request.headers = {'Host': '1'}
49f082 1776         self.assertEqual(wrapper(None, request), 'OK')
CM 1777
1778     def test_add_view_with_header_val_nomatch(self):
1779         view = lambda *arg: 'OK'
1780         config = self._makeOne(autocommit=True)
1781         config.add_view(view=view, header=r'Host:\d')
1782         wrapper = self._getViewCallable(config)
1783         request = self._makeRequest(config)
0c29cf 1784         request.headers = {'Host': 'abc'}
49f082 1785         self._assertNotFound(wrapper, None, request)
CM 1786
1787     def test_add_view_with_header_val_missing(self):
1788         from pyramid.httpexceptions import HTTPNotFound
0c29cf 1789
49f082 1790         view = lambda *arg: 'OK'
CM 1791         config = self._makeOne(autocommit=True)
1792         config.add_view(view=view, header=r'Host:\d')
1793         wrapper = self._getViewCallable(config)
1794         request = self._makeRequest(config)
0c29cf 1795         request.headers = {'NoHost': '1'}
49f082 1796         self.assertRaises(HTTPNotFound, wrapper, None, request)
CM 1797
1798     def test_add_view_with_accept_match(self):
1799         from pyramid.renderers import null_renderer
0c29cf 1800
49f082 1801         view = lambda *arg: 'OK'
CM 1802         config = self._makeOne(autocommit=True)
1803         config.add_view(view=view, accept='text/xml', renderer=null_renderer)
1804         wrapper = self._getViewCallable(config)
1805         request = self._makeRequest(config)
c3c83e 1806         request.accept = DummyAccept('text/xml')
49f082 1807         self.assertEqual(wrapper(None, request), 'OK')
CM 1808
1809     def test_add_view_with_accept_nomatch(self):
1810         view = lambda *arg: 'OK'
1811         config = self._makeOne(autocommit=True)
1812         config.add_view(view=view, accept='text/xml')
1813         wrapper = self._getViewCallable(config)
1814         request = self._makeRequest(config)
c3c83e 1815         request.accept = DummyAccept('text/html')
49f082 1816         self._assertNotFound(wrapper, None, request)
CM 1817
4a9f4f 1818     def test_add_view_with_range_accept_match(self):
MM 1819         from pyramid.renderers import null_renderer
0c29cf 1820
4a9f4f 1821         view = lambda *arg: 'OK'
MM 1822         config = self._makeOne(autocommit=True)
1823         config.add_view(view=view, accept='text/*', renderer=null_renderer)
1824         wrapper = self._getViewCallable(config)
1825         request = self._makeRequest(config)
1826         request.accept = DummyAccept('text/html', contains=True)
1827         self.assertEqual(wrapper(None, request), 'OK')
1828
1829     def test_add_view_with_range_accept_nomatch(self):
1830         view = lambda *arg: 'OK'
1831         config = self._makeOne(autocommit=True)
1832         config.add_view(view=view, accept='text/*')
1833         wrapper = self._getViewCallable(config)
1834         request = self._makeRequest(config)
1835         request.accept = DummyAccept('application/json', contains=False)
1836         self._assertNotFound(wrapper, None, request)
1837
49f082 1838     def test_add_view_with_containment_true(self):
CM 1839         from pyramid.renderers import null_renderer
1840         from zope.interface import directlyProvides
0c29cf 1841
49f082 1842         view = lambda *arg: 'OK'
CM 1843         config = self._makeOne(autocommit=True)
1844         config.add_view(view=view, containment=IDummy, renderer=null_renderer)
1845         wrapper = self._getViewCallable(config)
1846         context = DummyContext()
1847         directlyProvides(context, IDummy)
1848         self.assertEqual(wrapper(context, None), 'OK')
1849
1850     def test_add_view_with_containment_false(self):
1851         view = lambda *arg: 'OK'
1852         config = self._makeOne(autocommit=True)
1853         config.add_view(view=view, containment=IDummy)
1854         wrapper = self._getViewCallable(config)
1855         context = DummyContext()
1856         self._assertNotFound(wrapper, context, None)
1857
1858     def test_add_view_with_containment_dottedname(self):
1859         from pyramid.renderers import null_renderer
1860         from zope.interface import directlyProvides
0c29cf 1861
49f082 1862         view = lambda *arg: 'OK'
CM 1863         config = self._makeOne(autocommit=True)
1864         config.add_view(
1865             view=view,
dd3cc8 1866             containment='tests.test_config.IDummy',
0c29cf 1867             renderer=null_renderer,
MM 1868         )
49f082 1869         wrapper = self._getViewCallable(config)
CM 1870         context = DummyContext()
1871         directlyProvides(context, IDummy)
1872         self.assertEqual(wrapper(context, None), 'OK')
1873
1874     def test_add_view_with_path_info_badregex(self):
1875         view = lambda *arg: 'OK'
1876         config = self._makeOne()
a00621 1877         config.add_view(view, path_info='\\')
CM 1878         self.assertRaises(ConfigurationError, config.commit)
49f082 1879
CM 1880     def test_add_view_with_path_info_match(self):
1881         from pyramid.renderers import null_renderer
0c29cf 1882
49f082 1883         view = lambda *arg: 'OK'
CM 1884         config = self._makeOne(autocommit=True)
1885         config.add_view(view=view, path_info='/foo', renderer=null_renderer)
1886         wrapper = self._getViewCallable(config)
1887         request = self._makeRequest(config)
a5d994 1888         request.upath_info = text_(b'/foo')
49f082 1889         self.assertEqual(wrapper(None, request), 'OK')
CM 1890
1891     def test_add_view_with_path_info_nomatch(self):
1892         view = lambda *arg: 'OK'
1893         config = self._makeOne(autocommit=True)
1894         config.add_view(view=view, path_info='/foo')
1895         wrapper = self._getViewCallable(config)
1896         request = self._makeRequest(config)
a5d994 1897         request.upath_info = text_('/')
49f082 1898         self._assertNotFound(wrapper, None, request)
CM 1899
15b97d 1900     def test_add_view_with_check_csrf_predicates_match(self):
MM 1901         import warnings
1902         from pyramid.renderers import null_renderer
0c29cf 1903
15b97d 1904         view = lambda *arg: 'OK'
MM 1905         config = self._makeOne(autocommit=True)
1906         with warnings.catch_warnings(record=True) as w:
1907             warnings.filterwarnings('always')
1908             config.add_view(view=view, check_csrf=True, renderer=null_renderer)
1909             self.assertEqual(len(w), 1)
1910         wrapper = self._getViewCallable(config)
1911         request = self._makeRequest(config)
f12005 1912         request.method = "POST"
15b97d 1913         request.session = DummySession({'csrf_token': 'foo'})
f12005 1914         request.POST = {'csrf_token': 'foo'}
15b97d 1915         request.headers = {}
MM 1916         self.assertEqual(wrapper(None, request), 'OK')
1917
49f082 1918     def test_add_view_with_custom_predicates_match(self):
b01f1d 1919         import warnings
49f082 1920         from pyramid.renderers import null_renderer
0c29cf 1921
49f082 1922         view = lambda *arg: 'OK'
CM 1923         config = self._makeOne(autocommit=True)
0c29cf 1924
49f082 1925         def pred1(context, request):
CM 1926             return True
0c29cf 1927
49f082 1928         def pred2(context, request):
CM 1929             return True
0c29cf 1930
49f082 1931         predicates = (pred1, pred2)
b01f1d 1932         with warnings.catch_warnings(record=True) as w:
CM 1933             warnings.filterwarnings('always')
0c29cf 1934             config.add_view(
MM 1935                 view=view, custom_predicates=predicates, renderer=null_renderer
1936             )
b01f1d 1937             self.assertEqual(len(w), 1)
49f082 1938         wrapper = self._getViewCallable(config)
CM 1939         request = self._makeRequest(config)
1940         self.assertEqual(wrapper(None, request), 'OK')
1941
1942     def test_add_view_with_custom_predicates_nomatch(self):
b01f1d 1943         import warnings
0c29cf 1944
49f082 1945         view = lambda *arg: 'OK'
CM 1946         config = self._makeOne(autocommit=True)
0c29cf 1947
49f082 1948         def pred1(context, request):
CM 1949             return True
0c29cf 1950
49f082 1951         def pred2(context, request):
CM 1952             return False
0c29cf 1953
49f082 1954         predicates = (pred1, pred2)
b01f1d 1955         with warnings.catch_warnings(record=True) as w:
CM 1956             warnings.filterwarnings('always')
1957             config.add_view(view=view, custom_predicates=predicates)
1958             self.assertEqual(len(w), 1)
49f082 1959         wrapper = self._getViewCallable(config)
CM 1960         request = self._makeRequest(config)
1961         self._assertNotFound(wrapper, None, request)
1962
1963     def test_add_view_custom_predicate_bests_standard_predicate(self):
b01f1d 1964         import warnings
49f082 1965         from pyramid.renderers import null_renderer
0c29cf 1966
49f082 1967         view = lambda *arg: 'OK'
CM 1968         view2 = lambda *arg: 'NOT OK'
1969         config = self._makeOne(autocommit=True)
0c29cf 1970
49f082 1971         def pred1(context, request):
CM 1972             return True
0c29cf 1973
b01f1d 1974         with warnings.catch_warnings(record=True) as w:
CM 1975             warnings.filterwarnings('always')
0c29cf 1976             config.add_view(
MM 1977                 view=view, custom_predicates=(pred1,), renderer=null_renderer
1978             )
1979             config.add_view(
1980                 view=view2, request_method='GET', renderer=null_renderer
1981             )
b01f1d 1982             self.assertEqual(len(w), 1)
49f082 1983         wrapper = self._getViewCallable(config)
CM 1984         request = self._makeRequest(config)
1985         request.method = 'GET'
1986         self.assertEqual(wrapper(None, request), 'OK')
1987
1988     def test_add_view_custom_more_preds_first_bests_fewer_preds_last(self):
1989         from pyramid.renderers import null_renderer
0c29cf 1990
49f082 1991         view = lambda *arg: 'OK'
CM 1992         view2 = lambda *arg: 'NOT OK'
1993         config = self._makeOne(autocommit=True)
0c29cf 1994         config.add_view(
MM 1995             view=view, request_method='GET', xhr=True, renderer=null_renderer
1996         )
1997         config.add_view(
1998             view=view2, request_method='GET', renderer=null_renderer
1999         )
49f082 2000         wrapper = self._getViewCallable(config)
CM 2001         request = self._makeRequest(config)
2002         request.method = 'GET'
2003         request.is_xhr = True
2004         self.assertEqual(wrapper(None, request), 'OK')
2005
2006     def test_add_view_same_predicates(self):
2007         view2 = lambda *arg: 'second'
2008         view1 = lambda *arg: 'first'
2009         config = self._makeOne()
2010         config.add_view(view=view1)
2011         config.add_view(view=view2)
2012         self.assertRaises(ConfigurationConflictError, config.commit)
2013
9e9fa9 2014     def test_add_view_with_csrf_param(self):
MM 2015         from pyramid.renderers import null_renderer
0c29cf 2016
9e9fa9 2017         def view(request):
MM 2018             return 'OK'
0c29cf 2019
9e9fa9 2020         config = self._makeOne(autocommit=True)
MM 2021         config.add_view(view, require_csrf='st', renderer=null_renderer)
2022         view = self._getViewCallable(config)
2023         request = self._makeRequest(config)
65dee6 2024         request.scheme = "http"
6b35eb 2025         request.method = 'POST'
f12005 2026         request.POST = {'st': 'foo'}
9e9fa9 2027         request.headers = {}
6b35eb 2028         request.session = DummySession({'csrf_token': 'foo'})
MM 2029         self.assertEqual(view(None, request), 'OK')
2030
2031     def test_add_view_with_csrf_header(self):
2032         from pyramid.renderers import null_renderer
0c29cf 2033
6b35eb 2034         def view(request):
MM 2035             return 'OK'
0c29cf 2036
6b35eb 2037         config = self._makeOne(autocommit=True)
MM 2038         config.add_view(view, require_csrf=True, renderer=null_renderer)
2039         view = self._getViewCallable(config)
2040         request = self._makeRequest(config)
65dee6 2041         request.scheme = "http"
6b35eb 2042         request.method = 'POST'
f12005 2043         request.POST = {}
6b35eb 2044         request.headers = {'X-CSRF-Token': 'foo'}
9e9fa9 2045         request.session = DummySession({'csrf_token': 'foo'})
MM 2046         self.assertEqual(view(None, request), 'OK')
2047
2048     def test_add_view_with_missing_csrf_header(self):
2049         from pyramid.exceptions import BadCSRFToken
2050         from pyramid.renderers import null_renderer
0c29cf 2051
10ddb6 2052         def view(request):  # pragma: no cover
0c29cf 2053             return 'OK'
MM 2054
9e9fa9 2055         config = self._makeOne(autocommit=True)
MM 2056         config.add_view(view, require_csrf=True, renderer=null_renderer)
2057         view = self._getViewCallable(config)
2058         request = self._makeRequest(config)
65dee6 2059         request.scheme = "http"
6b35eb 2060         request.method = 'POST'
f12005 2061         request.POST = {}
9e9fa9 2062         request.headers = {}
MM 2063         request.session = DummySession({'csrf_token': 'foo'})
2064         self.assertRaises(BadCSRFToken, lambda: view(None, request))
2065
49f082 2066     def test_add_view_with_permission(self):
CM 2067         from pyramid.renderers import null_renderer
0c29cf 2068
49f082 2069         view1 = lambda *arg: 'OK'
CM 2070         outerself = self
0c29cf 2071
49f082 2072         class DummyPolicy(object):
CM 2073             def effective_principals(self, r):
2074                 outerself.assertEqual(r, request)
2075                 return ['abc']
0c29cf 2076
49f082 2077             def permits(self, context, principals, permission):
CM 2078                 outerself.assertEqual(context, None)
2079                 outerself.assertEqual(principals, ['abc'])
2080                 outerself.assertEqual(permission, 'view')
2081                 return True
0c29cf 2082
49f082 2083         policy = DummyPolicy()
0c29cf 2084         config = self._makeOne(
MM 2085             authorization_policy=policy,
2086             authentication_policy=policy,
2087             autocommit=True,
2088         )
49f082 2089         config.add_view(view=view1, permission='view', renderer=null_renderer)
CM 2090         view = self._getViewCallable(config)
2091         request = self._makeRequest(config)
2092         self.assertEqual(view(None, request), 'OK')
2093
2094     def test_add_view_with_default_permission_no_explicit_permission(self):
2095         from pyramid.renderers import null_renderer
0c29cf 2096
49f082 2097         view1 = lambda *arg: 'OK'
CM 2098         outerself = self
0c29cf 2099
49f082 2100         class DummyPolicy(object):
CM 2101             def effective_principals(self, r):
2102                 outerself.assertEqual(r, request)
2103                 return ['abc']
0c29cf 2104
49f082 2105             def permits(self, context, principals, permission):
CM 2106                 outerself.assertEqual(context, None)
2107                 outerself.assertEqual(principals, ['abc'])
2108                 outerself.assertEqual(permission, 'view')
2109                 return True
0c29cf 2110
49f082 2111         policy = DummyPolicy()
0c29cf 2112         config = self._makeOne(
MM 2113             authorization_policy=policy,
2114             authentication_policy=policy,
2115             default_permission='view',
2116             autocommit=True,
2117         )
49f082 2118         config.add_view(view=view1, renderer=null_renderer)
CM 2119         view = self._getViewCallable(config)
2120         request = self._makeRequest(config)
2121         self.assertEqual(view(None, request), 'OK')
2122
2123     def test_add_view_with_no_default_permission_no_explicit_permission(self):
2124         from pyramid.renderers import null_renderer
0c29cf 2125
49f082 2126         view1 = lambda *arg: 'OK'
0c29cf 2127
MM 2128         class DummyPolicy(object):
2129             pass  # wont be called
2130
49f082 2131         policy = DummyPolicy()
0c29cf 2132         config = self._makeOne(
MM 2133             authorization_policy=policy,
2134             authentication_policy=policy,
2135             autocommit=True,
2136         )
49f082 2137         config.add_view(view=view1, renderer=null_renderer)
CM 2138         view = self._getViewCallable(config)
2139         request = self._makeRequest(config)
2140         self.assertEqual(view(None, request), 'OK')
b2fbe5 2141
522405 2142     def test_add_view_with_mapper(self):
CM 2143         from pyramid.renderers import null_renderer
0c29cf 2144
522405 2145         class Mapper(object):
CM 2146             def __init__(self, **kw):
2147                 self.__class__.kw = kw
0c29cf 2148
522405 2149             def __call__(self, view):
CM 2150                 return view
0c29cf 2151
522405 2152         config = self._makeOne(autocommit=True)
0c29cf 2153
MM 2154         def view(context, request):
2155             return 'OK'
2156
522405 2157         config.add_view(view=view, mapper=Mapper, renderer=null_renderer)
CM 2158         view = self._getViewCallable(config)
2159         self.assertEqual(view(None, None), 'OK')
2160         self.assertEqual(Mapper.kw['mapper'], Mapper)
2161
bb462e 2162     def test_add_view_with_view_defaults(self):
CM 2163         from pyramid.renderers import null_renderer
2164         from pyramid.exceptions import PredicateMismatch
2165         from zope.interface import directlyProvides
0c29cf 2166
bb462e 2167         class view(object):
0c29cf 2168             __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 2169
bb462e 2170             def __init__(self, request):
CM 2171                 pass
0c29cf 2172
bb462e 2173             def __call__(self):
CM 2174                 return 'OK'
0c29cf 2175
bb462e 2176         config = self._makeOne(autocommit=True)
0c29cf 2177         config.add_view(view=view, renderer=null_renderer)
bb462e 2178         wrapper = self._getViewCallable(config)
CM 2179         context = DummyContext()
2180         directlyProvides(context, IDummy)
2181         request = self._makeRequest(config)
2182         self.assertEqual(wrapper(context, request), 'OK')
2183         context = DummyContext()
2184         request = self._makeRequest(config)
2185         self.assertRaises(PredicateMismatch, wrapper, context, request)
134388 2186
CM 2187     def test_add_view_with_view_defaults_viewname_is_dottedname_kwarg(self):
2188         from pyramid.renderers import null_renderer
2189         from pyramid.exceptions import PredicateMismatch
2190         from zope.interface import directlyProvides
0c29cf 2191
134388 2192         config = self._makeOne(autocommit=True)
CM 2193         config.add_view(
dd3cc8 2194             view='tests.test_config.test_views.DummyViewDefaultsClass',
0c29cf 2195             renderer=null_renderer,
MM 2196         )
134388 2197         wrapper = self._getViewCallable(config)
CM 2198         context = DummyContext()
2199         directlyProvides(context, IDummy)
2200         request = self._makeRequest(config)
2201         self.assertEqual(wrapper(context, request), 'OK')
2202         context = DummyContext()
2203         request = self._makeRequest(config)
2204         self.assertRaises(PredicateMismatch, wrapper, context, request)
2205
2206     def test_add_view_with_view_defaults_viewname_is_dottedname_nonkwarg(self):
2207         from pyramid.renderers import null_renderer
2208         from pyramid.exceptions import PredicateMismatch
2209         from zope.interface import directlyProvides
0c29cf 2210
134388 2211         config = self._makeOne(autocommit=True)
CM 2212         config.add_view(
dd3cc8 2213             'tests.test_config.test_views.DummyViewDefaultsClass',
0c29cf 2214             renderer=null_renderer,
MM 2215         )
134388 2216         wrapper = self._getViewCallable(config)
CM 2217         context = DummyContext()
2218         directlyProvides(context, IDummy)
2219         request = self._makeRequest(config)
2220         self.assertEqual(wrapper(context, request), 'OK')
2221         context = DummyContext()
2222         request = self._makeRequest(config)
2223         self.assertRaises(PredicateMismatch, wrapper, context, request)
42afb0 2224
4c29ef 2225     def test_add_view_with_view_config_and_view_defaults_doesnt_conflict(self):
CM 2226         from pyramid.renderers import null_renderer
0c29cf 2227
4c29ef 2228         class view(object):
0c29cf 2229             __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 2230
4c29ef 2231         class view2(object):
0c29cf 2232             __view_defaults__ = {'containment': 'tests.test_config.IFactory'}
MM 2233
4c29ef 2234         config = self._makeOne(autocommit=False)
0c29cf 2235         config.add_view(view=view, renderer=null_renderer)
MM 2236         config.add_view(view=view2, renderer=null_renderer)
2237         config.commit()  # does not raise
4c29ef 2238
CM 2239     def test_add_view_with_view_config_and_view_defaults_conflicts(self):
2240         from pyramid.renderers import null_renderer
0c29cf 2241
4c29ef 2242         class view(object):
0c29cf 2243             __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 2244
4c29ef 2245         class view2(object):
0c29cf 2246             __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 2247
4c29ef 2248         config = self._makeOne(autocommit=False)
0c29cf 2249         config.add_view(view=view, renderer=null_renderer)
MM 2250         config.add_view(view=view2, renderer=null_renderer)
4c29ef 2251         self.assertRaises(ConfigurationConflictError, config.commit)
bb462e 2252
bc26de 2253     def test_add_view_class_method_no_attr(self):
JA 2254         from pyramid.renderers import null_renderer
4a7029 2255         from pyramid.exceptions import ConfigurationError
bc26de 2256
JA 2257         config = self._makeOne(autocommit=True)
0c29cf 2258
4a7029 2259         class DummyViewClass(object):
10ddb6 2260             def run(self):  # pragma: no cover
0c29cf 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
10ddb6 2731         def view(request):  # pragma: no cover
0c29cf 2732             return Response('OK')
MM 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
10ddb6 2760         def view(request):  # pragma: no cover
0c29cf 2761             return Response('OK')
MM 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
10ddb6 2992         def view2(context, request):  # pragma: no cover
0c29cf 2993             raise AssertionError
MM 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):
10ddb6 3001         def view1(context, request):  # pragma: no cover
0c29cf 3002             raise AssertionError
MM 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):
10ddb6 3014         def errfn(context, request):  # pragma: no cover
0c29cf 3015             raise AssertionError
MM 3016
10ddb6 3017         def view1(context, request):  # pragma: no cover
0c29cf 3018             raise AssertionError
MM 3019
e8c66a 3020         view1.__permitted__ = lambda c, r: 'OK'
0c29cf 3021
10ddb6 3022         def view2(context, request):  # pragma: no cover
0c29cf 3023             raise AssertionError
MM 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):
10ddb6 3032         def errfn(context, request):  # pragma: no cover
0c29cf 3033             raise AssertionError
MM 3034
10ddb6 3035         def view1(context, request):  # pragma: no cover
0c29cf 3036             raise AssertionError
MM 3037
e8c66a 3038         view1.__permitted__ = errfn
0c29cf 3039
10ddb6 3040         def view2(context, request):  # pragma: no cover
0c29cf 3041             raise AssertionError
MM 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):
10ddb6 3058         def aview(request, a=1, b=2):  # pragma: no cover
0c29cf 3059             pass
MM 3060
28fc3d 3061         self.assertTrue(self._callFUT(aview))
5bf23f 3062
28fc3d 3063     def test_otherattr(self):
CM 3064         class AView(object):
10ddb6 3065             def __init__(self, request, a=1, b=2):  # pragma: no cover
0c29cf 3066                 pass
MM 3067
10ddb6 3068             def bleh(self):  # pragma: no cover
0c29cf 3069                 pass
MM 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
10ddb6 3169         def view1():  # pragma: no cover
0c29cf 3170             pass
MM 3171
10ddb6 3172         def view2():  # pragma: no cover
0c29cf 3173             pass
MM 3174
10ddb6 3175         def view3():  # pragma: no cover
0c29cf 3176             pass
MM 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
10ddb6 3189         def view1():  # pragma: no cover
0c29cf 3190             pass
MM 3191
10ddb6 3192         def view2():  # pragma: no cover
0c29cf 3193             pass
MM 3194
10ddb6 3195         def view3():  # pragma: no cover
0c29cf 3196             pass
MM 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)).
10ddb6 3210         def view1(request):  # pragma: no cover
0c29cf 3211             pass
MM 3212
10ddb6 3213         def view2(request):  # pragma: no cover
0c29cf 3214             pass
MM 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):
10ddb6 3695         def view1(context, request):  # pragma: no cover
0c29cf 3696             pass
MM 3697
5bf23f 3698         view1.__original_view__ = 'abc'
0c29cf 3699
10ddb6 3700         def view2(context, request):  # pragma: no cover
0c29cf 3701             pass
MM 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):
10ddb6 3953         def fake_cb(*a, **kw):  # pragma: no cover
0c29cf 3954             raise AssertionError
MM 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):
10ddb6 4191         def view():  # pragma: no cover
0c29cf 4192             pass
MM 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):
10ddb6 4199         def view():  # pragma: no cover
0c29cf 4200             pass
MM 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
0c29cf 4229
849196 4230
5fc893 4231 @implementer(IResponse)
BJR 4232 class DummyResponse(object):
4233     content_type = None
4234     default_content_type = None
42afb0 4235     body = None
5fc893 4236
0c29cf 4237
5bf23f 4238 class DummyRequest:
CM 4239     subpath = ()
4240     matchdict = None
0c29cf 4241     request_iface = IRequest
498342 4242     application_url = 'http://example.com/foo'
5fc893 4243
5bf23f 4244     def __init__(self, environ=None):
CM 4245         if environ is None:
4246             environ = {}
4247         self.environ = environ
4248         self.params = {}
4249         self.cookies = {}
6ef10d 4250         self.response = DummyResponse()
5bf23f 4251
0c29cf 4252
5bf23f 4253 class DummyContext:
3b7334 4254     pass
0c29cf 4255
5bf23f 4256
CM 4257 class DummyAccept(object):
4a9f4f 4258     def __init__(self, *matches, **kw):
5bf23f 4259         self.matches = list(matches)
4a9f4f 4260         self.contains = kw.pop('contains', False)
5bf23f 4261
c3c83e 4262     def acceptable_offers(self, offers):
MM 4263         results = []
4264         for match in self.matches:
4265             if match in offers:
4266                 results.append((match, 1.0))
4267         return results
5bf23f 4268
4a9f4f 4269     def __contains__(self, value):
MM 4270         return self.contains
4271
0c29cf 4272
53d9d4 4273 class DummyConfig:
5e3439 4274     def __init__(self):
MM 4275         self.registry = DummyRegistry()
4276
bc9357 4277     route_prefix = ''
0c29cf 4278
53d9d4 4279     def add_route(self, *args, **kw):
CM 4280         self.route_args = args
4281         self.route_kw = kw
4282
4283     def add_view(self, *args, **kw):
4284         self.view_args = args
4285         self.view_kw = kw
4286
773948 4287     def action(self, discriminator, callable, introspectables=()):
bc9357 4288         callable()
CM 4289
773948 4290     def introspectable(self, *arg):
CM 4291         return {}
0c29cf 4292
MM 4293
3b7334 4294 @implementer(IMultiView)
49f082 4295 class DummyMultiView:
CM 4296     def __init__(self):
4297         self.views = []
4298         self.name = 'name'
0c29cf 4299
c3c83e 4300     def add(self, view, order, phash=None, accept=None, accept_order=None):
MM 4301         self.views.append((view, phash, accept, accept_order))
0c29cf 4302
49f082 4303     def __call__(self, context, request):
CM 4304         return 'OK1'
0c29cf 4305
49f082 4306     def __permitted__(self, context, request):
CM 4307         """ """
0c29cf 4308
49f082 4309
aa96dd 4310 class DummyCacheBuster(object):
780889 4311     def __init__(self, token):
MM 4312         self.token = token
6e29b4 4313
4d19b8 4314     def __call__(self, request, subpath, kw):
780889 4315         kw['x'] = self.token
aa96dd 4316         return subpath, kw
CR 4317
0c29cf 4318
5bf23f 4319 def parse_httpdate(s):
CM 4320     import datetime
0c29cf 4321
5bf23f 4322     # cannot use %Z, must use literal GMT; Jython honors timezone
CM 4323     # but CPython does not
4324     return datetime.datetime.strptime(s, "%a, %d %b %Y %H:%M:%S GMT")
0c29cf 4325
5bf23f 4326
CM 4327 def assert_similar_datetime(one, two):
4328     for attr in ('year', 'month', 'day', 'hour', 'minute'):
4329         one_attr = getattr(one, attr)
4330         two_attr = getattr(two, attr)
0c29cf 4331         if not one_attr == two_attr:  # pragma: no cover
5bf23f 4332             raise AssertionError('%r != %r in %s' % (one_attr, two_attr, attr))
0c29cf 4333
49f082 4334
6cc22a 4335 class DummyStaticURLInfo:
CM 4336     def __init__(self):
4337         self.added = []
4338
cda7f6 4339     def add(self, config, name, spec, **kw):
CM 4340         self.added.append((config, name, spec, kw))
134388 4341
0c29cf 4342
134388 4343 class DummyViewDefaultsClass(object):
0c29cf 4344     __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
MM 4345
134388 4346     def __init__(self, request):
CM 4347         pass
0c29cf 4348
134388 4349     def __call__(self):
CM 4350         return 'OK'
0c29cf 4351
8ec8e2 4352
CM 4353 class DummyPredicate(object):
4354     def __init__(self, val, config):
4355         self.val = val
4356
4357     def text(self):
4358         return 'dummy'
4359
4360     phash = text
4361
0c29cf 4362
3d42aa 4363 class DummyIntrospector(object):
CM 4364     def __init__(self, getval=None):
4365         self.related = []
4366         self.introspectables = []
4367         self.getval = getval
0c29cf 4368
3d42aa 4369     def add(self, introspectable):
CM 4370         self.introspectables.append(introspectable)
0c29cf 4371
3d42aa 4372     def get(self, name, discrim):
CM 4373         return self.getval
0c29cf 4374
3d42aa 4375     def relate(self, a, b):
CM 4376         self.related.append((a, b))
9e9fa9 4377
0c29cf 4378
9e9fa9 4379 class DummySession(dict):
MM 4380     def get_csrf_token(self):
4381         return self['csrf_token']