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