Michael Merickel
2017-06-18 4983421128e2e0fc92c771510f7b3af57de6d855
commit | author | age
5e3439 1 import os
5bf23f 2 import unittest
CM 3 from pyramid import testing
4
49f082 5 from pyramid.tests.test_config import IDummy
CM 6
b2fbe5 7 from pyramid.tests.test_config import dummy_view
CM 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)
158         config.add_view(view='pyramid.tests.test_config.dummy_view',
159                         renderer=null_renderer)
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)
370         config.add_view(context='pyramid.tests.test_config.IDummy',
371                         view=view,  renderer=null_renderer)
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)
379         config.add_view(for_='pyramid.tests.test_config.IDummy',
380                         view=view, renderer=null_renderer)
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.renderers import null_renderer
546         from pyramid.config.util import DEFAULT_PHASH
547         from zope.interface import Interface
548         from pyramid.interfaces import IRequest
549         from pyramid.interfaces import IView
550         from pyramid.interfaces import IViewClassifier
551         from pyramid.interfaces import IMultiView
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.renderers import null_renderer
568         from pyramid.config.util import DEFAULT_PHASH
569         from zope.interface import implementedBy
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))
845         self.assertEqual([x[:2] for x in wrapper.views], [(view2, None)])
846         self.assertEqual(wrapper(None, None), 'OK1')
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))
872         self.assertEqual([x[:2] for x in hot_wrapper.views], [(view2, None)])
873         self.assertEqual(hot_wrapper(None, None), 'OK1')
874
875         exc_wrapper = self._getViewCallable(
876             config, exc_iface=implementedBy(RuntimeError))
877         self.assertTrue(IMultiView.providedBy(exc_wrapper))
878         self.assertEqual([x[:2] for x in exc_wrapper.views], [(view2, None)])
879         self.assertEqual(exc_wrapper(None, None), 'OK1')
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))
911         self.assertEqual([x[:2] for x in exc_wrapper.views], [(view2, None)])
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):
CM 1165         from pyramid.tests import test_config
1166         from pyramid.interfaces import ISettings
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)
1176         fixture = 'pyramid.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):
1213         from pyramid.tests import test_config
1214         from pyramid.interfaces import ISettings
1215         config = self._makeOne(autocommit=True)
1216         renderer = self._registerRenderer(config)
1217         fixture = 'pyramid.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)
1468         request.accept = ['text/xml']
1469         self.assertEqual(wrapper(None, request), 'OK')
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)
1477         request.accept = ['text/html']
1478         self._assertNotFound(wrapper, None, request)
1479
1480     def test_add_view_with_containment_true(self):
1481         from pyramid.renderers import null_renderer
1482         from zope.interface import directlyProvides
1483         view = lambda *arg: 'OK'
1484         config = self._makeOne(autocommit=True)
1485         config.add_view(view=view, containment=IDummy, renderer=null_renderer)
1486         wrapper = self._getViewCallable(config)
1487         context = DummyContext()
1488         directlyProvides(context, IDummy)
1489         self.assertEqual(wrapper(context, None), 'OK')
1490
1491     def test_add_view_with_containment_false(self):
1492         view = lambda *arg: 'OK'
1493         config = self._makeOne(autocommit=True)
1494         config.add_view(view=view, containment=IDummy)
1495         wrapper = self._getViewCallable(config)
1496         context = DummyContext()
1497         self._assertNotFound(wrapper, context, None)
1498
1499     def test_add_view_with_containment_dottedname(self):
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(
1505             view=view,
1506             containment='pyramid.tests.test_config.IDummy',
1507             renderer=null_renderer)
1508         wrapper = self._getViewCallable(config)
1509         context = DummyContext()
1510         directlyProvides(context, IDummy)
1511         self.assertEqual(wrapper(context, None), 'OK')
1512
1513     def test_add_view_with_path_info_badregex(self):
1514         view = lambda *arg: 'OK'
1515         config = self._makeOne()
a00621 1516         config.add_view(view, path_info='\\')
CM 1517         self.assertRaises(ConfigurationError, config.commit)
49f082 1518
CM 1519     def test_add_view_with_path_info_match(self):
1520         from pyramid.renderers import null_renderer
1521         view = lambda *arg: 'OK'
1522         config = self._makeOne(autocommit=True)
1523         config.add_view(view=view, path_info='/foo', renderer=null_renderer)
1524         wrapper = self._getViewCallable(config)
1525         request = self._makeRequest(config)
a5d994 1526         request.upath_info = text_(b'/foo')
49f082 1527         self.assertEqual(wrapper(None, request), 'OK')
CM 1528
1529     def test_add_view_with_path_info_nomatch(self):
1530         view = lambda *arg: 'OK'
1531         config = self._makeOne(autocommit=True)
1532         config.add_view(view=view, path_info='/foo')
1533         wrapper = self._getViewCallable(config)
1534         request = self._makeRequest(config)
a5d994 1535         request.upath_info = text_('/')
49f082 1536         self._assertNotFound(wrapper, None, request)
CM 1537
15b97d 1538     def test_add_view_with_check_csrf_predicates_match(self):
MM 1539         import warnings
1540         from pyramid.renderers import null_renderer
1541         view = lambda *arg: 'OK'
1542         config = self._makeOne(autocommit=True)
1543         with warnings.catch_warnings(record=True) as w:
1544             warnings.filterwarnings('always')
1545             config.add_view(view=view, check_csrf=True, renderer=null_renderer)
1546             self.assertEqual(len(w), 1)
1547         wrapper = self._getViewCallable(config)
1548         request = self._makeRequest(config)
f12005 1549         request.method = "POST"
15b97d 1550         request.session = DummySession({'csrf_token': 'foo'})
f12005 1551         request.POST = {'csrf_token': 'foo'}
15b97d 1552         request.headers = {}
MM 1553         self.assertEqual(wrapper(None, request), 'OK')
1554
49f082 1555     def test_add_view_with_custom_predicates_match(self):
b01f1d 1556         import warnings
49f082 1557         from pyramid.renderers import null_renderer
CM 1558         view = lambda *arg: 'OK'
1559         config = self._makeOne(autocommit=True)
1560         def pred1(context, request):
1561             return True
1562         def pred2(context, request):
1563             return True
1564         predicates = (pred1, pred2)
b01f1d 1565         with warnings.catch_warnings(record=True) as w:
CM 1566             warnings.filterwarnings('always')
1567             config.add_view(view=view, custom_predicates=predicates,
1568                             renderer=null_renderer)
1569             self.assertEqual(len(w), 1)
49f082 1570         wrapper = self._getViewCallable(config)
CM 1571         request = self._makeRequest(config)
1572         self.assertEqual(wrapper(None, request), 'OK')
1573
1574     def test_add_view_with_custom_predicates_nomatch(self):
b01f1d 1575         import warnings
49f082 1576         view = lambda *arg: 'OK'
CM 1577         config = self._makeOne(autocommit=True)
1578         def pred1(context, request):
1579             return True
1580         def pred2(context, request):
1581             return False
1582         predicates = (pred1, pred2)
b01f1d 1583         with warnings.catch_warnings(record=True) as w:
CM 1584             warnings.filterwarnings('always')
1585             config.add_view(view=view, custom_predicates=predicates)
1586             self.assertEqual(len(w), 1)
49f082 1587         wrapper = self._getViewCallable(config)
CM 1588         request = self._makeRequest(config)
1589         self._assertNotFound(wrapper, None, request)
1590
1591     def test_add_view_custom_predicate_bests_standard_predicate(self):
b01f1d 1592         import warnings
49f082 1593         from pyramid.renderers import null_renderer
CM 1594         view = lambda *arg: 'OK'
1595         view2 = lambda *arg: 'NOT OK'
1596         config = self._makeOne(autocommit=True)
1597         def pred1(context, request):
1598             return True
b01f1d 1599         with warnings.catch_warnings(record=True) as w:
CM 1600             warnings.filterwarnings('always')
1601             config.add_view(view=view, custom_predicates=(pred1,),
49f082 1602                         renderer=null_renderer)
b01f1d 1603             config.add_view(view=view2, request_method='GET',
CM 1604                             renderer=null_renderer)
1605             self.assertEqual(len(w), 1)
49f082 1606         wrapper = self._getViewCallable(config)
CM 1607         request = self._makeRequest(config)
1608         request.method = 'GET'
1609         self.assertEqual(wrapper(None, request), 'OK')
1610
1611     def test_add_view_custom_more_preds_first_bests_fewer_preds_last(self):
1612         from pyramid.renderers import null_renderer
1613         view = lambda *arg: 'OK'
1614         view2 = lambda *arg: 'NOT OK'
1615         config = self._makeOne(autocommit=True)
1616         config.add_view(view=view, request_method='GET', xhr=True,
1617                         renderer=null_renderer)
1618         config.add_view(view=view2, request_method='GET',
1619                         renderer=null_renderer)
1620         wrapper = self._getViewCallable(config)
1621         request = self._makeRequest(config)
1622         request.method = 'GET'
1623         request.is_xhr = True
1624         self.assertEqual(wrapper(None, request), 'OK')
1625
1626     def test_add_view_same_predicates(self):
1627         view2 = lambda *arg: 'second'
1628         view1 = lambda *arg: 'first'
1629         config = self._makeOne()
1630         config.add_view(view=view1)
1631         config.add_view(view=view2)
1632         self.assertRaises(ConfigurationConflictError, config.commit)
1633
9e9fa9 1634     def test_add_view_with_csrf_param(self):
MM 1635         from pyramid.renderers import null_renderer
1636         def view(request):
1637             return 'OK'
1638         config = self._makeOne(autocommit=True)
1639         config.add_view(view, require_csrf='st', renderer=null_renderer)
1640         view = self._getViewCallable(config)
1641         request = self._makeRequest(config)
65dee6 1642         request.scheme = "http"
6b35eb 1643         request.method = 'POST'
f12005 1644         request.POST = {'st': 'foo'}
9e9fa9 1645         request.headers = {}
6b35eb 1646         request.session = DummySession({'csrf_token': 'foo'})
MM 1647         self.assertEqual(view(None, request), 'OK')
1648
1649     def test_add_view_with_csrf_header(self):
1650         from pyramid.renderers import null_renderer
1651         def view(request):
1652             return 'OK'
1653         config = self._makeOne(autocommit=True)
1654         config.add_view(view, require_csrf=True, renderer=null_renderer)
1655         view = self._getViewCallable(config)
1656         request = self._makeRequest(config)
65dee6 1657         request.scheme = "http"
6b35eb 1658         request.method = 'POST'
f12005 1659         request.POST = {}
6b35eb 1660         request.headers = {'X-CSRF-Token': 'foo'}
9e9fa9 1661         request.session = DummySession({'csrf_token': 'foo'})
MM 1662         self.assertEqual(view(None, request), 'OK')
1663
1664     def test_add_view_with_missing_csrf_header(self):
1665         from pyramid.exceptions import BadCSRFToken
1666         from pyramid.renderers import null_renderer
1667         def view(request): return 'OK'
1668         config = self._makeOne(autocommit=True)
1669         config.add_view(view, require_csrf=True, renderer=null_renderer)
1670         view = self._getViewCallable(config)
1671         request = self._makeRequest(config)
65dee6 1672         request.scheme = "http"
6b35eb 1673         request.method = 'POST'
f12005 1674         request.POST = {}
9e9fa9 1675         request.headers = {}
MM 1676         request.session = DummySession({'csrf_token': 'foo'})
1677         self.assertRaises(BadCSRFToken, lambda: view(None, request))
1678
49f082 1679     def test_add_view_with_permission(self):
CM 1680         from pyramid.renderers import null_renderer
1681         view1 = lambda *arg: 'OK'
1682         outerself = self
1683         class DummyPolicy(object):
1684             def effective_principals(self, r):
1685                 outerself.assertEqual(r, request)
1686                 return ['abc']
1687             def permits(self, context, principals, permission):
1688                 outerself.assertEqual(context, None)
1689                 outerself.assertEqual(principals, ['abc'])
1690                 outerself.assertEqual(permission, 'view')
1691                 return True
1692         policy = DummyPolicy()
1693         config = self._makeOne(authorization_policy=policy,
1694                                authentication_policy=policy,
1695                                autocommit=True)
1696         config.add_view(view=view1, permission='view', renderer=null_renderer)
1697         view = self._getViewCallable(config)
1698         request = self._makeRequest(config)
1699         self.assertEqual(view(None, request), 'OK')
1700
1701     def test_add_view_with_default_permission_no_explicit_permission(self):
1702         from pyramid.renderers import null_renderer
1703         view1 = lambda *arg: 'OK'
1704         outerself = self
1705         class DummyPolicy(object):
1706             def effective_principals(self, r):
1707                 outerself.assertEqual(r, request)
1708                 return ['abc']
1709             def permits(self, context, principals, permission):
1710                 outerself.assertEqual(context, None)
1711                 outerself.assertEqual(principals, ['abc'])
1712                 outerself.assertEqual(permission, 'view')
1713                 return True
1714         policy = DummyPolicy()
1715         config = self._makeOne(authorization_policy=policy,
1716                                authentication_policy=policy,
1717                                default_permission='view',
1718                                autocommit=True)
1719         config.add_view(view=view1, renderer=null_renderer)
1720         view = self._getViewCallable(config)
1721         request = self._makeRequest(config)
1722         self.assertEqual(view(None, request), 'OK')
1723
1724     def test_add_view_with_no_default_permission_no_explicit_permission(self):
1725         from pyramid.renderers import null_renderer
1726         view1 = lambda *arg: 'OK'
1727         class DummyPolicy(object): pass # wont be called
1728         policy = DummyPolicy()
1729         config = self._makeOne(authorization_policy=policy,
1730                                authentication_policy=policy,
1731                                autocommit=True)
1732         config.add_view(view=view1, renderer=null_renderer)
1733         view = self._getViewCallable(config)
1734         request = self._makeRequest(config)
1735         self.assertEqual(view(None, request), 'OK')
b2fbe5 1736
522405 1737     def test_add_view_with_mapper(self):
CM 1738         from pyramid.renderers import null_renderer
1739         class Mapper(object):
1740             def __init__(self, **kw):
1741                 self.__class__.kw = kw
1742             def __call__(self, view):
1743                 return view
1744         config = self._makeOne(autocommit=True)
1745         def view(context, request): return 'OK'
1746         config.add_view(view=view, mapper=Mapper, renderer=null_renderer)
1747         view = self._getViewCallable(config)
1748         self.assertEqual(view(None, None), 'OK')
1749         self.assertEqual(Mapper.kw['mapper'], Mapper)
1750
bb462e 1751     def test_add_view_with_view_defaults(self):
CM 1752         from pyramid.renderers import null_renderer
1753         from pyramid.exceptions import PredicateMismatch
1754         from zope.interface import directlyProvides
1755         class view(object):
1756             __view_defaults__ = {
1757                 'containment':'pyramid.tests.test_config.IDummy'
1758                 }
1759             def __init__(self, request):
1760                 pass
1761             def __call__(self):
1762                 return 'OK'
1763         config = self._makeOne(autocommit=True)
1764         config.add_view(
1765             view=view,
1766             renderer=null_renderer)
1767         wrapper = self._getViewCallable(config)
1768         context = DummyContext()
1769         directlyProvides(context, IDummy)
1770         request = self._makeRequest(config)
1771         self.assertEqual(wrapper(context, request), 'OK')
1772         context = DummyContext()
1773         request = self._makeRequest(config)
1774         self.assertRaises(PredicateMismatch, wrapper, context, request)
134388 1775
CM 1776     def test_add_view_with_view_defaults_viewname_is_dottedname_kwarg(self):
1777         from pyramid.renderers import null_renderer
1778         from pyramid.exceptions import PredicateMismatch
1779         from zope.interface import directlyProvides
1780         config = self._makeOne(autocommit=True)
1781         config.add_view(
1782             view='pyramid.tests.test_config.test_views.DummyViewDefaultsClass',
1783             renderer=null_renderer)
1784         wrapper = self._getViewCallable(config)
1785         context = DummyContext()
1786         directlyProvides(context, IDummy)
1787         request = self._makeRequest(config)
1788         self.assertEqual(wrapper(context, request), 'OK')
1789         context = DummyContext()
1790         request = self._makeRequest(config)
1791         self.assertRaises(PredicateMismatch, wrapper, context, request)
1792
1793     def test_add_view_with_view_defaults_viewname_is_dottedname_nonkwarg(self):
1794         from pyramid.renderers import null_renderer
1795         from pyramid.exceptions import PredicateMismatch
1796         from zope.interface import directlyProvides
1797         config = self._makeOne(autocommit=True)
1798         config.add_view(
1799             'pyramid.tests.test_config.test_views.DummyViewDefaultsClass',
1800             renderer=null_renderer)
1801         wrapper = self._getViewCallable(config)
1802         context = DummyContext()
1803         directlyProvides(context, IDummy)
1804         request = self._makeRequest(config)
1805         self.assertEqual(wrapper(context, request), 'OK')
1806         context = DummyContext()
1807         request = self._makeRequest(config)
1808         self.assertRaises(PredicateMismatch, wrapper, context, request)
42afb0 1809
4c29ef 1810     def test_add_view_with_view_config_and_view_defaults_doesnt_conflict(self):
CM 1811         from pyramid.renderers import null_renderer
1812         class view(object):
1813             __view_defaults__ = {
1814                 'containment':'pyramid.tests.test_config.IDummy'
1815                 }
1816         class view2(object):
1817             __view_defaults__ = {
1818                 'containment':'pyramid.tests.test_config.IFactory'
1819                 }
1820         config = self._makeOne(autocommit=False)
1821         config.add_view(
1822             view=view,
1823             renderer=null_renderer)
1824         config.add_view(
1825             view=view2,
1826             renderer=null_renderer)
1827         config.commit() # does not raise
1828
1829     def test_add_view_with_view_config_and_view_defaults_conflicts(self):
1830         from pyramid.renderers import null_renderer
1831         class view(object):
1832             __view_defaults__ = {
1833                 'containment':'pyramid.tests.test_config.IDummy'
1834                 }
1835         class view2(object):
1836             __view_defaults__ = {
1837                 'containment':'pyramid.tests.test_config.IDummy'
1838                 }
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         self.assertRaises(ConfigurationConflictError, config.commit)
bb462e 1847
bc26de 1848     def test_add_view_class_method_no_attr(self):
JA 1849         from pyramid.renderers import null_renderer
1850         from zope.interface import directlyProvides
4a7029 1851         from pyramid.exceptions import ConfigurationError
bc26de 1852
JA 1853         config = self._makeOne(autocommit=True)
4a7029 1854         class DummyViewClass(object):
JA 1855             def run(self): pass
bc26de 1856
4a7029 1857         def configure_view():
JA 1858             config.add_view(view=DummyViewClass.run, renderer=null_renderer)
1859
1860         self.assertRaises(ConfigurationError, configure_view)
bc26de 1861
b0d20b 1862     def test_add_view_exception_only_no_regular_view(self):
AL 1863         from zope.interface import implementedBy
1864         from pyramid.renderers import null_renderer
1865         view1 = lambda *arg: 'OK'
1866         config = self._makeOne(autocommit=True)
e8c66a 1867         config.add_view(view=view1, context=Exception, exception_only=True,
MM 1868                         renderer=null_renderer)
b0d20b 1869         view = self._getViewCallable(config, ctx_iface=implementedBy(Exception))
AL 1870         self.assertTrue(view is None)
1871
1872     def test_add_view_exception_only(self):
1873         from zope.interface import implementedBy
1874         from pyramid.renderers import null_renderer
1875         view1 = lambda *arg: 'OK'
1876         config = self._makeOne(autocommit=True)
e8c66a 1877         config.add_view(view=view1, context=Exception, exception_only=True,
MM 1878                         renderer=null_renderer)
b0d20b 1879         view = self._getViewCallable(
e8c66a 1880             config, exc_iface=implementedBy(Exception))
b0d20b 1881         self.assertEqual(view1, view)
AL 1882
1883     def test_add_view_exception_only_misconfiguration(self):
1884         view = lambda *arg: 'OK'
1885         config = self._makeOne(autocommit=True)
1886         class NotAnException(object):
1887             pass
1888         self.assertRaises(
1889             ConfigurationError,
e8c66a 1890             config.add_view, view, context=NotAnException, exception_only=True)
b0d20b 1891
d6c90d 1892     def test_add_exception_view(self):
AL 1893         from zope.interface import implementedBy
1894         from pyramid.renderers import null_renderer
1895         view1 = lambda *arg: 'OK'
1896         config = self._makeOne(autocommit=True)
e8c66a 1897         config.add_exception_view(view=view1, renderer=null_renderer)
d6c90d 1898         wrapper = self._getViewCallable(
e8c66a 1899             config, exc_iface=implementedBy(Exception))
d6c90d 1900         context = Exception()
e8c66a 1901         request = self._makeRequest(config)
MM 1902         self.assertEqual(wrapper(context, request), 'OK')
1903
1904     def test_add_exception_view_with_subclass(self):
1905         from zope.interface import implementedBy
1906         from pyramid.renderers import null_renderer
1907         view1 = lambda *arg: 'OK'
1908         config = self._makeOne(autocommit=True)
1909         config.add_exception_view(view=view1, context=ValueError,
1910                                   renderer=null_renderer)
1911         wrapper = self._getViewCallable(
1912             config, exc_iface=implementedBy(ValueError))
1913         context = ValueError()
d6c90d 1914         request = self._makeRequest(config)
AL 1915         self.assertEqual(wrapper(context, request), 'OK')
1916
1917     def test_add_exception_view_disallows_name(self):
1918         config = self._makeOne(autocommit=True)
1919         self.assertRaises(ConfigurationError,
1920                           config.add_exception_view,
1921                           context=Exception(),
1922                           name='foo')
1923
1924     def test_add_exception_view_disallows_permission(self):
1925         config = self._makeOne(autocommit=True)
1926         self.assertRaises(ConfigurationError,
1927                           config.add_exception_view,
1928                           context=Exception(),
1929                           permission='foo')
1930
e8c66a 1931     def test_add_exception_view_disallows_require_csrf(self):
MM 1932         config = self._makeOne(autocommit=True)
1933         self.assertRaises(ConfigurationError,
1934                           config.add_exception_view,
1935                           context=Exception(),
1936                           require_csrf=True)
1937
d6c90d 1938     def test_add_exception_view_disallows_for_(self):
AL 1939         config = self._makeOne(autocommit=True)
1940         self.assertRaises(ConfigurationError,
1941                           config.add_exception_view,
1942                           context=Exception(),
1943                           for_='foo')
1944
1945     def test_add_exception_view_disallows_exception_only(self):
1946         config = self._makeOne(autocommit=True)
1947         self.assertRaises(ConfigurationError,
1948                           config.add_exception_view,
1949                           context=Exception(),
1950                           exception_only=True)
1951
1952     def test_add_exception_view_with_view_defaults(self):
1953         from pyramid.renderers import null_renderer
1954         from pyramid.exceptions import PredicateMismatch
1955         from zope.interface import directlyProvides
1956         from zope.interface import implementedBy
1957         class view(object):
1958             __view_defaults__ = {
e8c66a 1959                 'containment': 'pyramid.tests.test_config.IDummy'
d6c90d 1960                 }
AL 1961             def __init__(self, request):
1962                 pass
1963             def __call__(self):
1964                 return 'OK'
1965         config = self._makeOne(autocommit=True)
1966         config.add_exception_view(
1967             view=view,
1968             context=Exception,
1969             renderer=null_renderer)
1970         wrapper = self._getViewCallable(
e8c66a 1971             config, exc_iface=implementedBy(Exception))
d6c90d 1972         context = DummyContext()
AL 1973         directlyProvides(context, IDummy)
1974         request = self._makeRequest(config)
1975         self.assertEqual(wrapper(context, request), 'OK')
1976         context = DummyContext()
1977         request = self._makeRequest(config)
1978         self.assertRaises(PredicateMismatch, wrapper, context, request)
1979
b2fbe5 1980     def test_derive_view_function(self):
CM 1981         from pyramid.renderers import null_renderer
1982         def view(request):
1983             return 'OK'
1984         config = self._makeOne()
1985         result = config.derive_view(view, renderer=null_renderer)
1986         self.assertFalse(result is view)
1987         self.assertEqual(result(None, None), 'OK')
1988
1989     def test_derive_view_dottedname(self):
1990         from pyramid.renderers import null_renderer
1991         config = self._makeOne()
1992         result = config.derive_view(
1993             'pyramid.tests.test_config.dummy_view',
1994             renderer=null_renderer)
1995         self.assertFalse(result is dummy_view)
1996         self.assertEqual(result(None, None), 'OK')
1997
1998     def test_derive_view_with_default_renderer_no_explicit_renderer(self):
1999         config = self._makeOne()
2000         class moo(object):
2001             def __init__(self, view):
2002                 pass
2003             def __call__(self, *arg, **kw):
2004                 return 'moo'
2005         config.add_renderer(None, moo)
2006         config.commit()
2007         def view(request):
2008             return 'OK'
2009         result = config.derive_view(view)
2010         self.assertFalse(result is view)
8e606d 2011         self.assertEqual(result(None, None).body, b'moo')
b2fbe5 2012
CM 2013     def test_derive_view_with_default_renderer_with_explicit_renderer(self):
2014         class moo(object): pass
2015         class foo(object):
2016             def __init__(self, view):
2017                 pass
2018             def __call__(self, *arg, **kw):
42afb0 2019                 return b'foo'
b2fbe5 2020         def view(request):
CM 2021             return 'OK'
2022         config = self._makeOne()
2023         config.add_renderer(None, moo)
2024         config.add_renderer('foo', foo)
2025         config.commit()
2026         result = config.derive_view(view, renderer='foo')
2027         self.assertFalse(result is view)
2028         request = self._makeRequest(config)
8e606d 2029         self.assertEqual(result(None, request).body, b'foo')
b2fbe5 2030
6cc22a 2031     def test_add_static_view_here_no_utility_registered(self):
CM 2032         from pyramid.renderers import null_renderer
2033         from zope.interface import Interface
2034         from pyramid.interfaces import IView
2035         from pyramid.interfaces import IViewClassifier
2036         config = self._makeOne(autocommit=True)
f2ef79 2037         config.add_static_view('static', 'files', renderer=null_renderer)
bc9357 2038         request_type = self._getRouteRequestIface(config, '__static/')
CM 2039         self._assertRoute(config, '__static/', 'static/*subpath')
6cc22a 2040         wrapped = config.registry.adapters.lookup(
CM 2041             (IViewClassifier, request_type, Interface), IView, name='')
f2ef79 2042         from pyramid.request import Request
b368d7 2043         request = Request.blank('/static/minimal.txt')
BJR 2044         request.subpath = ('minimal.txt', )
6cc22a 2045         result = wrapped(None, request)
f2ef79 2046         self.assertEqual(result.status, '200 OK')
9f7de6 2047         self.assertTrue(result.body.startswith(b'<div'))
6cc22a 2048
CM 2049     def test_add_static_view_package_relative(self):
2050         from pyramid.interfaces import IStaticURLInfo
2051         info = DummyStaticURLInfo()
2052         config = self._makeOne(autocommit=True)
2053         config.registry.registerUtility(info, IStaticURLInfo)
2054         config.add_static_view('static',
2055                                'pyramid.tests.test_config:files')
2056         self.assertEqual(
2057             info.added,
cda7f6 2058             [(config, 'static', 'pyramid.tests.test_config:files', {})])
6cc22a 2059
CM 2060     def test_add_static_view_package_here_relative(self):
2061         from pyramid.interfaces import IStaticURLInfo
2062         info = DummyStaticURLInfo()
2063         config = self._makeOne(autocommit=True)
2064         config.registry.registerUtility(info, IStaticURLInfo)
2065         config.add_static_view('static', 'files')
2066         self.assertEqual(
2067             info.added,
cda7f6 2068             [(config, 'static', 'pyramid.tests.test_config:files', {})])
6cc22a 2069
CM 2070     def test_add_static_view_absolute(self):
2071         import os
2072         from pyramid.interfaces import IStaticURLInfo
2073         info = DummyStaticURLInfo()
2074         config = self._makeOne(autocommit=True)
2075         config.registry.registerUtility(info, IStaticURLInfo)
2076         here = os.path.dirname(__file__)
2077         static_path = os.path.join(here, 'files')
2078         config.add_static_view('static', static_path)
2079         self.assertEqual(info.added,
cda7f6 2080                          [(config, 'static', static_path, {})])
42afb0 2081
a7fe30 2082     def test_add_forbidden_view(self):
2c1f9e 2083         from pyramid.renderers import null_renderer
CM 2084         from zope.interface import implementedBy
2085         from pyramid.interfaces import IRequest
2086         from pyramid.httpexceptions import HTTPForbidden
2087         config = self._makeOne(autocommit=True)
2088         view = lambda *arg: 'OK'
a7fe30 2089         config.add_forbidden_view(view, renderer=null_renderer)
2c1f9e 2090         request = self._makeRequest(config)
CM 2091         view = self._getViewCallable(config,
e8c66a 2092                                      exc_iface=implementedBy(HTTPForbidden),
2c1f9e 2093                                      request_iface=IRequest)
CM 2094         result = view(None, request)
2095         self.assertEqual(result, 'OK')
2096
dfa449 2097     def test_add_forbidden_view_no_view_argument(self):
DK 2098         from zope.interface import implementedBy
2099         from pyramid.interfaces import IRequest
2100         from pyramid.httpexceptions import HTTPForbidden
2101         config = self._makeOne(autocommit=True)
2102         config.setup_registry()
2103         config.add_forbidden_view()
2104         request = self._makeRequest(config)
2105         view = self._getViewCallable(config,
e8c66a 2106                                      exc_iface=implementedBy(HTTPForbidden),
dfa449 2107                                      request_iface=IRequest)
DK 2108         context = HTTPForbidden()
2109         result = view(context, request)
2110         self.assertEqual(result, context)
2111
8ec8e2 2112     def test_add_forbidden_view_allows_other_predicates(self):
CM 2113         from pyramid.renderers import null_renderer
2114         config = self._makeOne(autocommit=True)
2115         # doesnt blow up
2116         config.add_view_predicate('dummy', DummyPredicate)
2117         config.add_forbidden_view(renderer=null_renderer, dummy='abc')
2118
2119     def test_add_forbidden_view_disallows_name(self):
2120         config = self._makeOne(autocommit=True)
2121         self.assertRaises(ConfigurationError,
2122                           config.add_forbidden_view, name='foo')
2123
2124     def test_add_forbidden_view_disallows_permission(self):
2125         config = self._makeOne(autocommit=True)
2126         self.assertRaises(ConfigurationError,
2127                           config.add_forbidden_view, permission='foo')
2128
e8c66a 2129     def test_add_forbidden_view_disallows_require_csrf(self):
MM 2130         config = self._makeOne(autocommit=True)
2131         self.assertRaises(ConfigurationError,
2132                           config.add_forbidden_view, require_csrf=True)
2133
8ec8e2 2134     def test_add_forbidden_view_disallows_context(self):
CM 2135         config = self._makeOne(autocommit=True)
2136         self.assertRaises(ConfigurationError,
2137                           config.add_forbidden_view, context='foo')
2138
2139     def test_add_forbidden_view_disallows_for_(self):
2140         config = self._makeOne(autocommit=True)
2141         self.assertRaises(ConfigurationError,
2142                           config.add_forbidden_view, for_='foo')
2143
7c9624 2144     def test_add_forbidden_view_with_view_defaults(self):
MM 2145         from pyramid.interfaces import IRequest
2146         from pyramid.renderers import null_renderer
2147         from pyramid.exceptions import PredicateMismatch
2148         from pyramid.httpexceptions import HTTPForbidden
2149         from zope.interface import directlyProvides
2150         from zope.interface import implementedBy
2151         class view(object):
2152             __view_defaults__ = {
2153                 'containment':'pyramid.tests.test_config.IDummy'
2154                 }
2155             def __init__(self, request):
2156                 pass
2157             def __call__(self):
2158                 return 'OK'
2159         config = self._makeOne(autocommit=True)
2160         config.add_forbidden_view(
2161             view=view,
2162             renderer=null_renderer)
2163         wrapper = self._getViewCallable(
e8c66a 2164             config, exc_iface=implementedBy(HTTPForbidden),
7c9624 2165             request_iface=IRequest)
MM 2166         context = DummyContext()
2167         directlyProvides(context, IDummy)
2168         request = self._makeRequest(config)
2169         self.assertEqual(wrapper(context, request), 'OK')
2170         context = DummyContext()
2171         request = self._makeRequest(config)
2172         self.assertRaises(PredicateMismatch, wrapper, context, request)
2173
0db4a1 2174     def test_add_notfound_view(self):
2c1f9e 2175         from pyramid.renderers import null_renderer
CM 2176         from zope.interface import implementedBy
2177         from pyramid.interfaces import IRequest
2178         from pyramid.httpexceptions import HTTPNotFound
2179         config = self._makeOne(autocommit=True)
2180         view = lambda *arg: arg
0db4a1 2181         config.add_notfound_view(view, renderer=null_renderer)
2c1f9e 2182         request = self._makeRequest(config)
CM 2183         view = self._getViewCallable(config,
e8c66a 2184                                      exc_iface=implementedBy(HTTPNotFound),
2c1f9e 2185                                      request_iface=IRequest)
CM 2186         result = view(None, request)
2187         self.assertEqual(result, (None, request))
2188
f10d1e 2189     def test_add_notfound_view_no_view_argument(self):
DK 2190         from zope.interface import implementedBy
2191         from pyramid.interfaces import IRequest
2192         from pyramid.httpexceptions import HTTPNotFound
2193         config = self._makeOne(autocommit=True)
2194         config.setup_registry()
2195         config.add_notfound_view()
2196         request = self._makeRequest(config)
2197         view = self._getViewCallable(config,
e8c66a 2198                                      exc_iface=implementedBy(HTTPNotFound),
f10d1e 2199                                      request_iface=IRequest)
DK 2200         context = HTTPNotFound()
2201         result = view(context, request)
2202         self.assertEqual(result, context)
2203
8ec8e2 2204     def test_add_notfound_view_allows_other_predicates(self):
CM 2205         from pyramid.renderers import null_renderer
2206         config = self._makeOne(autocommit=True)
2207         # doesnt blow up
2208         config.add_view_predicate('dummy', DummyPredicate)
2209         config.add_notfound_view(renderer=null_renderer, dummy='abc')
2210
2211     def test_add_notfound_view_disallows_name(self):
2212         config = self._makeOne(autocommit=True)
2213         self.assertRaises(ConfigurationError,
2214                           config.add_notfound_view, name='foo')
2215
2216     def test_add_notfound_view_disallows_permission(self):
2217         config = self._makeOne(autocommit=True)
2218         self.assertRaises(ConfigurationError,
2219                           config.add_notfound_view, permission='foo')
2220
e8c66a 2221     def test_add_notfound_view_disallows_require_csrf(self):
MM 2222         config = self._makeOne(autocommit=True)
2223         self.assertRaises(ConfigurationError,
2224                           config.add_notfound_view, require_csrf=True)
2225
8ec8e2 2226     def test_add_notfound_view_disallows_context(self):
CM 2227         config = self._makeOne(autocommit=True)
2228         self.assertRaises(ConfigurationError,
2229                           config.add_notfound_view, context='foo')
2230
2231     def test_add_notfound_view_disallows_for_(self):
2232         config = self._makeOne(autocommit=True)
2233         self.assertRaises(ConfigurationError,
2234                           config.add_notfound_view, for_='foo')
42afb0 2235
0db4a1 2236     def test_add_notfound_view_append_slash(self):
CM 2237         from pyramid.response import Response
2c1f9e 2238         from pyramid.renderers import null_renderer
CM 2239         from zope.interface import implementedBy
2240         from pyramid.interfaces import IRequest
12b6f5 2241         from pyramid.httpexceptions import HTTPFound, HTTPNotFound
2c1f9e 2242         config = self._makeOne(autocommit=True)
0db4a1 2243         config.add_route('foo', '/foo/')
CM 2244         def view(request): return Response('OK')
2245         config.add_notfound_view(view, renderer=null_renderer,append_slash=True)
2c1f9e 2246         request = self._makeRequest(config)
0db4a1 2247         request.environ['PATH_INFO'] = '/foo'
CM 2248         request.query_string = 'a=1&b=2'
2249         request.path = '/scriptname/foo'
2c1f9e 2250         view = self._getViewCallable(config,
e8c66a 2251                                      exc_iface=implementedBy(HTTPNotFound),
2c1f9e 2252                                      request_iface=IRequest)
CM 2253         result = view(None, request)
12b6f5 2254         self.assertTrue(isinstance(result, HTTPFound))
DS 2255         self.assertEqual(result.location, '/scriptname/foo/?a=1&b=2')
2256
2257     def test_add_notfound_view_append_slash_custom_response(self):
2258         from pyramid.response import Response
2259         from pyramid.renderers import null_renderer
2260         from zope.interface import implementedBy
2261         from pyramid.interfaces import IRequest
2262         from pyramid.httpexceptions import HTTPMovedPermanently, HTTPNotFound
2263         config = self._makeOne(autocommit=True)
2264         config.add_route('foo', '/foo/')
2265         def view(request): return Response('OK')
2266         config.add_notfound_view(
2267             view, renderer=null_renderer,append_slash=HTTPMovedPermanently
2268         )
2269         request = self._makeRequest(config)
2270         request.environ['PATH_INFO'] = '/foo'
2271         request.query_string = 'a=1&b=2'
2272         request.path = '/scriptname/foo'
2273         view = self._getViewCallable(config,
e8c66a 2274                                      exc_iface=implementedBy(HTTPNotFound),
12b6f5 2275                                      request_iface=IRequest)
DS 2276         result = view(None, request)
2277         self.assertTrue(isinstance(result, HTTPMovedPermanently))
0db4a1 2278         self.assertEqual(result.location, '/scriptname/foo/?a=1&b=2')
42afb0 2279
7c9624 2280     def test_add_notfound_view_with_view_defaults(self):
MM 2281         from pyramid.interfaces import IRequest
2282         from pyramid.renderers import null_renderer
2283         from pyramid.exceptions import PredicateMismatch
2284         from pyramid.httpexceptions import HTTPNotFound
2285         from zope.interface import directlyProvides
2286         from zope.interface import implementedBy
2287         class view(object):
2288             __view_defaults__ = {
2289                 'containment':'pyramid.tests.test_config.IDummy'
2290                 }
2291             def __init__(self, request):
2292                 pass
2293             def __call__(self):
2294                 return 'OK'
2295         config = self._makeOne(autocommit=True)
2296         config.add_notfound_view(
2297             view=view,
2298             renderer=null_renderer)
2299         wrapper = self._getViewCallable(
e8c66a 2300             config, exc_iface=implementedBy(HTTPNotFound),
7c9624 2301             request_iface=IRequest)
MM 2302         context = DummyContext()
2303         directlyProvides(context, IDummy)
2304         request = self._makeRequest(config)
2305         self.assertEqual(wrapper(context, request), 'OK')
2306         context = DummyContext()
2307         request = self._makeRequest(config)
2308         self.assertRaises(PredicateMismatch, wrapper, context, request)
2309
42afb0 2310     # Since Python 3 has to be all cool and fancy and different...
BJR 2311     def _assertBody(self, response, value):
2312         from pyramid.compat import text_type
af01a5 2313         if isinstance(value, text_type):  # pragma: no cover
42afb0 2314             self.assertEqual(response.text, value)
af01a5 2315         else:  # pragma: no cover
42afb0 2316             self.assertEqual(response.body, value)
BJR 2317
5fc893 2318     def test_add_notfound_view_with_renderer(self):
BJR 2319         from zope.interface import implementedBy
2320         from pyramid.interfaces import IRequest
2321         from pyramid.httpexceptions import HTTPNotFound
2322         config = self._makeOne(autocommit=True)
2323         view = lambda *arg: {}
2324         config.introspection = False
2325         config.add_notfound_view(
2326             view,
2327             renderer='json')
89917f 2328         request = self._makeRequest(config)
BJR 2329         view = self._getViewCallable(config,
e8c66a 2330                                      exc_iface=implementedBy(HTTPNotFound),
89917f 2331                                      request_iface=IRequest)
BJR 2332         result = view(None, request)
42afb0 2333         self._assertBody(result, '{}')
5fc893 2334
BJR 2335     def test_add_forbidden_view_with_renderer(self):
2336         from zope.interface import implementedBy
2337         from pyramid.interfaces import IRequest
2338         from pyramid.httpexceptions import HTTPForbidden
2339         config = self._makeOne(autocommit=True)
2340         view = lambda *arg: {}
2341         config.introspection = False
2342         config.add_forbidden_view(
2343             view,
2344             renderer='json')
89917f 2345         request = self._makeRequest(config)
BJR 2346         view = self._getViewCallable(config,
e8c66a 2347                                      exc_iface=implementedBy(HTTPForbidden),
89917f 2348                                      request_iface=IRequest)
BJR 2349         result = view(None, request)
42afb0 2350         self._assertBody(result, '{}')
2c1f9e 2351
845d7b 2352     def test_set_view_mapper(self):
CM 2353         from pyramid.interfaces import IViewMapperFactory
2354         config = self._makeOne(autocommit=True)
2355         mapper = object()
2356         config.set_view_mapper(mapper)
2357         result = config.registry.getUtility(IViewMapperFactory)
2358         self.assertEqual(result, mapper)
2359
2360     def test_set_view_mapper_dottedname(self):
2361         from pyramid.interfaces import IViewMapperFactory
2362         config = self._makeOne(autocommit=True)
2363         config.set_view_mapper('pyramid.tests.test_config')
2364         result = config.registry.getUtility(IViewMapperFactory)
2365         from pyramid.tests import test_config
2366         self.assertEqual(result, test_config)
2367
e8c66a 2368     def test_add_normal_and_exception_view_intr_derived_callable(self):
MM 2369         from pyramid.renderers import null_renderer
2370         from pyramid.exceptions import BadCSRFToken
2371         config = self._makeOne(autocommit=True)
2372         introspector = DummyIntrospector()
2373         config.introspector = introspector
2374         view = lambda r: 'OK'
2375         config.set_default_csrf_options(require_csrf=True)
2376         config.add_view(view, context=Exception, renderer=null_renderer)
a2c7c7 2377         view_intr = introspector.introspectables[-1]
e8c66a 2378         self.assertTrue(view_intr.type_name, 'view')
MM 2379         self.assertEqual(view_intr['callable'], view)
2380         derived_view = view_intr['derived_callable']
2381
2382         request = self._makeRequest(config)
2383         request.method = 'POST'
2384         request.scheme = 'http'
2385         request.POST = {}
2386         request.headers = {}
2387         request.session = DummySession({'csrf_token': 'foo'})
2388         self.assertRaises(BadCSRFToken, lambda: derived_view(None, request))
2389         request.exception = Exception()
2390         self.assertEqual(derived_view(None, request), 'OK')
2391
2392 class Test_runtime_exc_view(unittest.TestCase):
2393     def _makeOne(self, view1, view2):
2394         from pyramid.config.views import runtime_exc_view
2395         return runtime_exc_view(view1, view2)
2396
2397     def test_call(self):
2398         def view1(context, request): return 'OK'
2399         def view2(context, request): raise AssertionError
2400         result_view = self._makeOne(view1, view2)
2401         request = DummyRequest()
2402         result = result_view(None, request)
2403         self.assertEqual(result, 'OK')
2404
2405     def test_call_dispatches_on_exception(self):
2406         def view1(context, request): raise AssertionError
2407         def view2(context, request): return 'OK'
2408         result_view = self._makeOne(view1, view2)
2409         request = DummyRequest()
2410         request.exception = Exception()
2411         result = result_view(None, request)
2412         self.assertEqual(result, 'OK')
2413
2414     def test_permitted(self):
2415         def errfn(context, request): raise AssertionError
2416         def view1(context, request): raise AssertionError
2417         view1.__permitted__ = lambda c, r: 'OK'
2418         def view2(context, request): raise AssertionError
2419         view2.__permitted__ = errfn
2420         result_view = self._makeOne(view1, view2)
2421         request = DummyRequest()
2422         result = result_view.__permitted__(None, request)
2423         self.assertEqual(result, 'OK')
2424
2425     def test_permitted_dispatches_on_exception(self):
2426         def errfn(context, request): raise AssertionError
2427         def view1(context, request): raise AssertionError
2428         view1.__permitted__ = errfn
2429         def view2(context, request): raise AssertionError
2430         view2.__permitted__ = lambda c, r: 'OK'
2431         result_view = self._makeOne(view1, view2)
2432         request = DummyRequest()
2433         request.exception = Exception()
2434         result = result_view.__permitted__(None, request)
2435         self.assertEqual(result, 'OK')
2436
5bf23f 2437 class Test_requestonly(unittest.TestCase):
CM 2438     def _callFUT(self, view, attr=None):
2439         from pyramid.config.views import requestonly
28fc3d 2440         return requestonly(view, attr=attr)
5bf23f 2441
28fc3d 2442     def test_defaults(self):
CM 2443         def aview(request, a=1, b=2): pass
2444         self.assertTrue(self._callFUT(aview))
5bf23f 2445
28fc3d 2446     def test_otherattr(self):
CM 2447         class AView(object):
2448             def __init__(self, request, a=1, b=2): pass
2449             def bleh(self): pass
2450         self.assertTrue(self._callFUT(AView, 'bleh'))
5bf23f 2451
CM 2452 class Test_isexception(unittest.TestCase):
2453     def _callFUT(self, ob):
2454         from pyramid.config.views import isexception
2455         return isexception(ob)
2456
2457     def test_is_exception_instance(self):
2458         class E(Exception):
2459             pass
2460         e = E()
2461         self.assertEqual(self._callFUT(e), True)
2462
2463     def test_is_exception_class(self):
2464         class E(Exception):
2465             pass
2466         self.assertEqual(self._callFUT(E), True)
2467
2468     def test_is_IException(self):
2469         from pyramid.interfaces import IException
2470         self.assertEqual(self._callFUT(IException), True)
2471
2472     def test_is_IException_subinterface(self):
2473         from pyramid.interfaces import IException
2474         class ISubException(IException):
2475             pass
2476         self.assertEqual(self._callFUT(ISubException), True)
2477
2478 class TestMultiView(unittest.TestCase):
2479     def _getTargetClass(self):
2480         from pyramid.config.views import MultiView
2481         return MultiView
2482
2483     def _makeOne(self, name='name'):
2484         return self._getTargetClass()(name)
2485
2486     def test_class_implements_ISecuredView(self):
2487         from zope.interface.verify import verifyClass
2488         from pyramid.interfaces import ISecuredView
2489         verifyClass(ISecuredView, self._getTargetClass())
2490
2491     def test_instance_implements_ISecuredView(self):
2492         from zope.interface.verify import verifyObject
2493         from pyramid.interfaces import ISecuredView
2494         verifyObject(ISecuredView, self._makeOne())
2495
2496     def test_add(self):
2497         mv = self._makeOne()
2498         mv.add('view', 100)
2499         self.assertEqual(mv.views, [(100, 'view', None)])
2500         mv.add('view2', 99)
2501         self.assertEqual(mv.views, [(99, 'view2', None), (100, 'view', None)])
2502         mv.add('view3', 100, 'text/html')
2503         self.assertEqual(mv.media_views['text/html'], [(100, 'view3', None)])
f4b7fd 2504         mv.add('view4', 99, 'text/html', 'abc')
5bf23f 2505         self.assertEqual(mv.media_views['text/html'],
f4b7fd 2506                          [(99, 'view4', 'abc'), (100, 'view3', None)])
DN 2507         mv.add('view5', 100, 'text/xml')
2508         self.assertEqual(mv.media_views['text/xml'], [(100, 'view5', None)])
5bf23f 2509         self.assertEqual(set(mv.accepts), set(['text/xml', 'text/html']))
CM 2510         self.assertEqual(mv.views, [(99, 'view2', None), (100, 'view', None)])
f4b7fd 2511         mv.add('view6', 98, 'text/*')
DN 2512         self.assertEqual(mv.views, [(98, 'view6', None),
5bf23f 2513                                     (99, 'view2', None),
CM 2514                                     (100, 'view', None)])
2515
2516     def test_add_with_phash(self):
2517         mv = self._makeOne()
2518         mv.add('view', 100, phash='abc')
2519         self.assertEqual(mv.views, [(100, 'view', 'abc')])
2520         mv.add('view', 100, phash='abc')
2521         self.assertEqual(mv.views, [(100, 'view', 'abc')])
2522         mv.add('view', 100, phash='def')
392937 2523         self.assertEqual(mv.views, [(100, 'view', 'abc'),
CM 2524                                     (100, 'view', 'def')])
5bf23f 2525         mv.add('view', 100, phash='abc')
392937 2526         self.assertEqual(mv.views, [(100, 'view', 'abc'),
CM 2527                                     (100, 'view', 'def')])
2528
f4b7fd 2529     def test_add_with_phash_override_accept(self):
DN 2530         mv = self._makeOne()
a9289d 2531         def view1(): pass
CM 2532         def view2(): pass
2533         def view3(): pass
2534         mv.add(view1, 100, accept='text/html', phash='abc')
2535         mv.add(view2, 100, accept='text/html', phash='abc')
2536         mv.add(view3, 99, accept='text/html', phash='def')
f4b7fd 2537         self.assertEqual(mv.media_views['text/html'],
a9289d 2538                          [(99, view3, 'def'), (100, view2, 'abc')])
CM 2539
2540     def test_add_with_phash_override_accept2(self):
2541         mv = self._makeOne()
2542         def view1(): pass
2543         def view2(): pass
2544         def view3(): pass
2545         mv.add(view1, 100, accept='text/html', phash='abc')
2546         mv.add(view2, 100, accept='text/html', phash='def')
2547         mv.add(view3, 99, accept='text/html', phash='ghi')
2548         self.assertEqual(mv.media_views['text/html'],
2549                          [(99, view3, 'ghi'),
2550                           (100, view1, 'abc'),
2551                           (100, view2, 'def')]
2552                          )
f4b7fd 2553
392937 2554     def test_multiple_with_functions_as_views(self):
CM 2555         # this failed on py3 at one point, because functions aren't orderable
2556         # and we were sorting the views via a plain sort() rather than
2557         # sort(key=itemgetter(0)).
2558         def view1(request): pass
2559         def view2(request): pass
2560         mv = self._makeOne()
2561         mv.add(view1, 100, None)
2562         self.assertEqual(mv.views, [(100, view1, None)])
2563         mv.add(view2, 100, None)
2564         self.assertEqual(mv.views, [(100, view1, None), (100, view2, None)])
5bf23f 2565
CM 2566     def test_get_views_request_has_no_accept(self):
2567         request = DummyRequest()
2568         mv = self._makeOne()
2569         mv.views = [(99, lambda *arg: None)]
2570         self.assertEqual(mv.get_views(request), mv.views)
2571
2572     def test_get_views_no_self_accepts(self):
2573         request = DummyRequest()
2574         request.accept = True
2575         mv = self._makeOne()
2576         mv.accepts = []
2577         mv.views = [(99, lambda *arg: None)]
2578         self.assertEqual(mv.get_views(request), mv.views)
2579
2580     def test_get_views(self):
2581         request = DummyRequest()
2582         request.accept = DummyAccept('text/html')
2583         mv = self._makeOne()
2584         mv.accepts = ['text/html']
2585         mv.views = [(99, lambda *arg: None)]
2586         html_views = [(98, lambda *arg: None)]
2587         mv.media_views['text/html'] = html_views
2588         self.assertEqual(mv.get_views(request), html_views + mv.views)
2589
2590     def test_get_views_best_match_returns_None(self):
2591         request = DummyRequest()
2592         request.accept = DummyAccept(None)
2593         mv = self._makeOne()
2594         mv.accepts = ['text/html']
2595         mv.views = [(99, lambda *arg: None)]
2596         self.assertEqual(mv.get_views(request), mv.views)
2597
2598     def test_match_not_found(self):
2599         from pyramid.httpexceptions import HTTPNotFound
2600         mv = self._makeOne()
2601         context = DummyContext()
2602         request = DummyRequest()
2603         self.assertRaises(HTTPNotFound, mv.match, context, request)
2604
2605     def test_match_predicate_fails(self):
2606         from pyramid.httpexceptions import HTTPNotFound
2607         mv = self._makeOne()
2608         def view(context, request):
2609             """ """
2610         view.__predicated__ = lambda *arg: False
2611         mv.views = [(100, view, None)]
2612         context = DummyContext()
2613         request = DummyRequest()
2614         self.assertRaises(HTTPNotFound, mv.match, context, request)
2615
2616     def test_match_predicate_succeeds(self):
2617         mv = self._makeOne()
2618         def view(context, request):
2619             """ """
2620         view.__predicated__ = lambda *arg: True
2621         mv.views = [(100, view, None)]
2622         context = DummyContext()
2623         request = DummyRequest()
2624         result = mv.match(context, request)
2625         self.assertEqual(result, view)
2626
2627     def test_permitted_no_views(self):
2628         from pyramid.httpexceptions import HTTPNotFound
2629         mv = self._makeOne()
2630         context = DummyContext()
2631         request = DummyRequest()
2632         self.assertRaises(HTTPNotFound, mv.__permitted__, context, request)
2633
2634     def test_permitted_no_match_with__permitted__(self):
2635         mv = self._makeOne()
2636         def view(context, request):
2637             """ """
2638         mv.views = [(100, view, None)]
2639         self.assertEqual(mv.__permitted__(None, None), True)
2640
2641     def test_permitted(self):
2642         mv = self._makeOne()
2643         def view(context, request):
2644             """ """
2645         def permitted(context, request):
2646             return False
2647         view.__permitted__ = permitted
2648         mv.views = [(100, view, None)]
2649         context = DummyContext()
2650         request = DummyRequest()
2651         result = mv.__permitted__(context, request)
2652         self.assertEqual(result, False)
2653
2654     def test__call__not_found(self):
2655         from pyramid.httpexceptions import HTTPNotFound
2656         mv = self._makeOne()
2657         context = DummyContext()
2658         request = DummyRequest()
2659         self.assertRaises(HTTPNotFound, mv, context, request)
2660
2661     def test___call__intermediate_not_found(self):
2662         from pyramid.exceptions import PredicateMismatch
2663         mv = self._makeOne()
2664         context = DummyContext()
2665         request = DummyRequest()
2666         request.view_name = ''
2667         expected_response = DummyResponse()
2668         def view1(context, request):
2669             raise PredicateMismatch
2670         def view2(context, request):
2671             return expected_response
2672         mv.views = [(100, view1, None), (99, view2, None)]
2673         response = mv(context, request)
2674         self.assertEqual(response, expected_response)
2675
2676     def test___call__raise_not_found_isnt_interpreted_as_pred_mismatch(self):
2677         from pyramid.httpexceptions import HTTPNotFound
2678         mv = self._makeOne()
2679         context = DummyContext()
2680         request = DummyRequest()
2681         request.view_name = ''
2682         def view1(context, request):
2683             raise  HTTPNotFound
2684         def view2(context, request):
2685             """ """
2686         mv.views = [(100, view1, None), (99, view2, None)]
2687         self.assertRaises(HTTPNotFound, mv, context, request)
2688
2689     def test___call__(self):
2690         mv = self._makeOne()
2691         context = DummyContext()
2692         request = DummyRequest()
2693         request.view_name = ''
2694         expected_response = DummyResponse()
2695         def view(context, request):
2696             return expected_response
2697         mv.views = [(100, view, None)]
2698         response = mv(context, request)
2699         self.assertEqual(response, expected_response)
2700
2701     def test__call_permissive__not_found(self):
2702         from pyramid.httpexceptions import HTTPNotFound
2703         mv = self._makeOne()
2704         context = DummyContext()
2705         request = DummyRequest()
2706         self.assertRaises(HTTPNotFound, mv, context, request)
2707
2708     def test___call_permissive_has_call_permissive(self):
2709         mv = self._makeOne()
2710         context = DummyContext()
2711         request = DummyRequest()
2712         request.view_name = ''
2713         expected_response = DummyResponse()
2714         def view(context, request):
2715             """ """
2716         def permissive(context, request):
2717             return expected_response
2718         view.__call_permissive__ = permissive
2719         mv.views = [(100, view, None)]
2720         response = mv.__call_permissive__(context, request)
2721         self.assertEqual(response, expected_response)
2722
2723     def test___call_permissive_has_no_call_permissive(self):
2724         mv = self._makeOne()
2725         context = DummyContext()
2726         request = DummyRequest()
2727         request.view_name = ''
2728         expected_response = DummyResponse()
2729         def view(context, request):
2730             return expected_response
2731         mv.views = [(100, view, None)]
2732         response = mv.__call_permissive__(context, request)
2733         self.assertEqual(response, expected_response)
2734
2735     def test__call__with_accept_match(self):
2736         mv = self._makeOne()
2737         context = DummyContext()
2738         request = DummyRequest()
2739         request.accept = DummyAccept('text/html', 'text/xml')
2740         expected_response = DummyResponse()
2741         def view(context, request):
2742             return expected_response
2743         mv.views = [(100, None)]
2744         mv.media_views['text/xml'] = [(100, view, None)]
2745         mv.accepts = ['text/xml']
2746         response = mv(context, request)
2747         self.assertEqual(response, expected_response)
2748
2749     def test__call__with_accept_miss(self):
2750         mv = self._makeOne()
2751         context = DummyContext()
2752         request = DummyRequest()
2753         request.accept = DummyAccept('text/plain', 'text/html')
2754         expected_response = DummyResponse()
2755         def view(context, request):
2756             return expected_response
2757         mv.views = [(100, view, None)]
2758         mv.media_views['text/xml'] = [(100, None, None)]
2759         mv.accepts = ['text/xml']
2760         response = mv(context, request)
2761         self.assertEqual(response, expected_response)
2762
2763
2764
2765 class TestDefaultViewMapper(unittest.TestCase):
2766     def setUp(self):
2767         self.config = testing.setUp()
42afb0 2768         self.registry = self.config.registry
5bf23f 2769
CM 2770     def tearDown(self):
2771         del self.registry
2772         testing.tearDown()
2773
2774     def _makeOne(self, **kw):
2775         from pyramid.config.views import DefaultViewMapper
2776         kw['registry'] = self.registry
2777         return DefaultViewMapper(**kw)
2778
2779     def _makeRequest(self):
2780         request = DummyRequest()
2781         request.registry = self.registry
2782         return request
2783
2784     def test_view_as_function_context_and_request(self):
2785         def view(context, request):
2786             return 'OK'
2787         mapper = self._makeOne()
2788         result = mapper(view)
2789         self.assertTrue(result is view)
2790         request = self._makeRequest()
2791         self.assertEqual(result(None, request), 'OK')
2792
2793     def test__view_as_function_with_attr(self):
2794         def view(context, request):
2795             """ """
2796         mapper = self._makeOne(attr='__name__')
2797         result = mapper(view)
2798         self.assertFalse(result is view)
2799         request = self._makeRequest()
2800         self.assertRaises(TypeError, result, None, request)
2801
2802     def test_view_as_function_requestonly(self):
2803         def view(request):
2804             return 'OK'
2805         mapper = self._makeOne()
2806         result = mapper(view)
2807         self.assertFalse(result is view)
2808         request = self._makeRequest()
2809         self.assertEqual(result(None, request), 'OK')
2810
2811     def test_view_as_function_requestonly_with_attr(self):
2812         def view(request):
2813             """ """
2814         mapper = self._makeOne(attr='__name__')
2815         result = mapper(view)
2816         self.assertFalse(result is view)
2817         request = self._makeRequest()
2818         self.assertRaises(TypeError, result, None, request)
2819
2820     def test_view_as_newstyle_class_context_and_request(self):
2821         class view(object):
2822             def __init__(self, context, request):
2823                 pass
2824             def __call__(self):
2825                 return 'OK'
2826         mapper = self._makeOne()
2827         result = mapper(view)
2828         self.assertFalse(result is view)
2829         request = self._makeRequest()
2830         self.assertEqual(result(None, request), 'OK')
2831
2832     def test_view_as_newstyle_class_context_and_request_with_attr(self):
2833         class view(object):
2834             def __init__(self, context, request):
2835                 pass
2836             def index(self):
2837                 return 'OK'
2838         mapper = self._makeOne(attr='index')
2839         result = mapper(view)
2840         self.assertFalse(result is view)
2841         request = self._makeRequest()
2842         self.assertEqual(result(None, request), 'OK')
2843
2844     def test_view_as_newstyle_class_requestonly(self):
2845         class view(object):
2846             def __init__(self, request):
2847                 pass
2848             def __call__(self):
2849                 return 'OK'
2850         mapper = self._makeOne()
2851         result = mapper(view)
2852         self.assertFalse(result is view)
2853         request = self._makeRequest()
2854         self.assertEqual(result(None, request), 'OK')
2855
2856     def test_view_as_newstyle_class_requestonly_with_attr(self):
2857         class view(object):
2858             def __init__(self, request):
2859                 pass
2860             def index(self):
2861                 return 'OK'
2862         mapper = self._makeOne(attr='index')
2863         result = mapper(view)
2864         self.assertFalse(result is view)
2865         request = self._makeRequest()
2866         self.assertEqual(result(None, request), 'OK')
2867
2868     def test_view_as_oldstyle_class_context_and_request(self):
2869         class view:
2870             def __init__(self, context, request):
2871                 pass
2872             def __call__(self):
2873                 return 'OK'
2874         mapper = self._makeOne()
2875         result = mapper(view)
2876         self.assertFalse(result is view)
2877         request = self._makeRequest()
2878         self.assertEqual(result(None, request), 'OK')
2879
2880     def test_view_as_oldstyle_class_context_and_request_with_attr(self):
2881         class view:
2882             def __init__(self, context, request):
2883                 pass
2884             def index(self):
2885                 return 'OK'
2886         mapper = self._makeOne(attr='index')
2887         result = mapper(view)
2888         self.assertFalse(result is view)
2889         request = self._makeRequest()
2890         self.assertEqual(result(None, request), 'OK')
2891
2892     def test_view_as_oldstyle_class_requestonly(self):
2893         class view:
2894             def __init__(self, request):
2895                 pass
2896             def __call__(self):
2897                 return 'OK'
2898         mapper = self._makeOne()
2899         result = mapper(view)
2900         self.assertFalse(result is view)
2901         request = self._makeRequest()
2902         self.assertEqual(result(None, request), 'OK')
2903
2904     def test_view_as_oldstyle_class_requestonly_with_attr(self):
2905         class view:
2906             def __init__(self, request):
2907                 pass
2908             def index(self):
2909                 return 'OK'
2910         mapper = self._makeOne(attr='index')
2911         result = mapper(view)
2912         self.assertFalse(result is view)
2913         request = self._makeRequest()
2914         self.assertEqual(result(None, request), 'OK')
2915
2916     def test_view_as_instance_context_and_request(self):
2917         class View:
2918             def __call__(self, context, request):
2919                 return 'OK'
2920         view = View()
2921         mapper = self._makeOne()
2922         result = mapper(view)
2923         self.assertTrue(result is view)
2924         request = self._makeRequest()
2925         self.assertEqual(result(None, request), 'OK')
2926
2927     def test_view_as_instance_context_and_request_and_attr(self):
2928         class View:
2929             def index(self, context, request):
2930                 return 'OK'
2931         view = View()
2932         mapper = self._makeOne(attr='index')
2933         result = mapper(view)
2934         self.assertFalse(result is view)
2935         request = self._makeRequest()
2936         self.assertEqual(result(None, request), 'OK')
2937
2938     def test_view_as_instance_requestonly(self):
2939         class View:
2940             def __call__(self, request):
2941                 return 'OK'
2942         view = View()
2943         mapper = self._makeOne()
2944         result = mapper(view)
2945         self.assertFalse(result is view)
2946         request = self._makeRequest()
2947         self.assertEqual(result(None, request), 'OK')
2948
2949     def test_view_as_instance_requestonly_with_attr(self):
2950         class View:
2951             def index(self, request):
2952                 return 'OK'
2953         view = View()
2954         mapper = self._makeOne(attr='index')
2955         result = mapper(view)
2956         self.assertFalse(result is view)
2957         request = self._makeRequest()
2958         self.assertEqual(result(None, request), 'OK')
2959
2960 class Test_preserve_view_attrs(unittest.TestCase):
2961     def _callFUT(self, view, wrapped_view):
2962         from pyramid.config.views import preserve_view_attrs
2963         return preserve_view_attrs(view, wrapped_view)
2964
2965     def test_it_same(self):
2966         def view(context, request):
2967             """ """
2968         result = self._callFUT(view, view)
2969         self.assertTrue(result is view)
2970
d9ea46 2971     def test_it_view_is_None(self):
CM 2972         def view(context, request):
2973             """ """
2974         result = self._callFUT(None, view)
2975         self.assertTrue(result is view)
2976
5bf23f 2977     def test_it_different_with_existing_original_view(self):
CM 2978         def view1(context, request): pass
2979         view1.__original_view__ = 'abc'
2980         def view2(context, request): pass
2981         result = self._callFUT(view1, view2)
2982         self.assertEqual(result.__original_view__, 'abc')
2983         self.assertFalse(result is view1)
2984
2985     def test_it_different(self):
2986         class DummyView1:
2987             """ 1 """
2988             __name__ = '1'
2989             __module__ = '1'
2990             def __call__(self, context, request):
2991                 """ """
2992             def __call_permissive__(self, context, request):
2993                 """ """
2994             def __predicated__(self, context, request):
2995                 """ """
2996             def __permitted__(self, context, request):
2997                 """ """
2998         class DummyView2:
2999             """ 2 """
3000             __name__ = '2'
3001             __module__ = '2'
3002             def __call__(self, context, request):
3003                 """ """
3004             def __call_permissive__(self, context, request):
3005                 """ """
3006             def __predicated__(self, context, request):
3007                 """ """
3008             def __permitted__(self, context, request):
3009                 """ """
3010         view1 = DummyView1()
3011         view2 = DummyView2()
3012         result = self._callFUT(view2, view1)
3013         self.assertEqual(result, view1)
3014         self.assertTrue(view1.__original_view__ is view2)
3015         self.assertTrue(view1.__doc__ is view2.__doc__)
3016         self.assertTrue(view1.__module__ is view2.__module__)
3017         self.assertTrue(view1.__name__ is view2.__name__)
a84e17 3018         self.assertTrue(getattr(view1.__call_permissive__, im_func) is
CM 3019                         getattr(view2.__call_permissive__, im_func))
3020         self.assertTrue(getattr(view1.__permitted__, im_func) is
3021                         getattr(view2.__permitted__, im_func))
3022         self.assertTrue(getattr(view1.__predicated__, im_func) is
3023                         getattr(view2.__predicated__, im_func))
5bf23f 3024
CM 3025
53d9d4 3026 class TestStaticURLInfo(unittest.TestCase):
CM 3027     def _getTargetClass(self):
3028         from pyramid.config.views import StaticURLInfo
3029         return StaticURLInfo
42afb0 3030
cda7f6 3031     def _makeOne(self):
CM 3032         return self._getTargetClass()()
3033
3034     def _makeRequest(self):
3035         request = DummyRequest()
3036         request.registry = DummyRegistry()
3037         return request
53d9d4 3038
CM 3039     def test_verifyClass(self):
3040         from pyramid.interfaces import IStaticURLInfo
3041         from zope.interface.verify import verifyClass
3042         verifyClass(IStaticURLInfo, self._getTargetClass())
3043
3044     def test_verifyObject(self):
3045         from pyramid.interfaces import IStaticURLInfo
3046         from zope.interface.verify import verifyObject
cda7f6 3047         verifyObject(IStaticURLInfo, self._makeOne())
53d9d4 3048
CM 3049     def test_generate_missing(self):
cda7f6 3050         inst = self._makeOne()
CM 3051         request = self._makeRequest()
53d9d4 3052         self.assertRaises(ValueError, inst.generate, 'path', request)
CM 3053
3054     def test_generate_registration_miss(self):
cda7f6 3055         inst = self._makeOne()
5e3439 3056         inst.registrations = [
MM 3057             (None, 'spec', 'route_name'),
3058             ('http://example.com/foo/', 'package:path/', None)]
cda7f6 3059         request = self._makeRequest()
f3b6a3 3060         result = inst.generate('package:path/abc', request)
CM 3061         self.assertEqual(result, 'http://example.com/foo/abc')
3062
53d9d4 3063     def test_generate_slash_in_name1(self):
cda7f6 3064         inst = self._makeOne()
5e3439 3065         inst.registrations = [('http://example.com/foo/', 'package:path/', None)]
cda7f6 3066         request = self._makeRequest()
53d9d4 3067         result = inst.generate('package:path/abc', request)
CM 3068         self.assertEqual(result, 'http://example.com/foo/abc')
3069
3070     def test_generate_slash_in_name2(self):
cda7f6 3071         inst = self._makeOne()
5e3439 3072         inst.registrations = [('http://example.com/foo/', 'package:path/', None)]
cda7f6 3073         request = self._makeRequest()
53d9d4 3074         result = inst.generate('package:path/', request)
CM 3075         self.assertEqual(result, 'http://example.com/foo/')
3076
05f462 3077     def test_generate_quoting(self):
5e3439 3078         from pyramid.interfaces import IStaticURLInfo
05f462 3079         config = testing.setUp()
CM 3080         try:
3081             config.add_static_view('images', path='mypkg:templates')
3082             request = testing.DummyRequest()
3083             request.registry = config.registry
5e3439 3084             inst = config.registry.getUtility(IStaticURLInfo)
05f462 3085             result = inst.generate('mypkg:templates/foo%2Fbar', request)
CM 3086             self.assertEqual(result, 'http://example.com/images/foo%252Fbar')
3087         finally:
3088             testing.tearDown()
3089
53d9d4 3090     def test_generate_route_url(self):
cda7f6 3091         inst = self._makeOne()
5e3439 3092         inst.registrations = [(None, 'package:path/', '__viewname/')]
cda7f6 3093         def route_url(n, **kw):
bc9357 3094             self.assertEqual(n, '__viewname/')
53d9d4 3095             self.assertEqual(kw, {'subpath':'abc', 'a':1})
CM 3096             return 'url'
cda7f6 3097         request = self._makeRequest()
CM 3098         request.route_url = route_url
53d9d4 3099         result = inst.generate('package:path/abc', request, a=1)
CM 3100         self.assertEqual(result, 'url')
3101
05f462 3102     def test_generate_url_unquoted_local(self):
1c39ae 3103         inst = self._makeOne()
5e3439 3104         inst.registrations = [(None, 'package:path/', '__viewname/')]
1c39ae 3105         def route_url(n, **kw):
CM 3106             self.assertEqual(n, '__viewname/')
05f462 3107             self.assertEqual(kw, {'subpath':'abc def', 'a':1})
1c39ae 3108             return 'url'
CM 3109         request = self._makeRequest()
3110         request.route_url = route_url
3111         result = inst.generate('package:path/abc def', request, a=1)
3112         self.assertEqual(result, 'url')
3113
3114     def test_generate_url_quoted_remote(self):
3115         inst = self._makeOne()
5e3439 3116         inst.registrations = [('http://example.com/', 'package:path/', None)]
1c39ae 3117         request = self._makeRequest()
CM 3118         result = inst.generate('package:path/abc def', request, a=1)
3119         self.assertEqual(result, 'http://example.com/abc%20def')
3120
8f3bf6 3121     def test_generate_url_with_custom_query(self):
MM 3122         inst = self._makeOne()
5e3439 3123         registrations = [('http://example.com/', 'package:path/', None)]
MM 3124         inst.registrations = registrations
8f3bf6 3125         request = self._makeRequest()
MM 3126         result = inst.generate('package:path/abc def', request, a=1,
3127                                _query='(openlayers)')
3128         self.assertEqual(result,
af3134 3129                          'http://example.com/abc%20def?(openlayers)')
8f3bf6 3130
fc30e8 3131     def test_generate_url_with_custom_anchor(self):
MM 3132         inst = self._makeOne()
5e3439 3133         inst.registrations = [('http://example.com/', 'package:path/', None)]
fc30e8 3134         request = self._makeRequest()
MM 3135         uc = text_(b'La Pe\xc3\xb1a', 'utf-8')
5e3439 3136         result = inst.generate('package:path/abc def', request, a=1, _anchor=uc)
fc30e8 3137         self.assertEqual(result,
22f0eb 3138                          'http://example.com/abc%20def#La%20Pe%C3%B1a')
fc30e8 3139
15b979 3140     def test_generate_url_cachebust(self):
6e29b4 3141         def cachebust(request, subpath, kw):
535015 3142             kw['foo'] = 'bar'
CR 3143             return 'foo' + '/' + subpath, kw
3144         inst = self._makeOne()
5e3439 3145         inst.registrations = [(None, 'package:path/', '__viewname')]
4d19b8 3146         inst.cache_busters = [('package:path/', cachebust, False)]
535015 3147         request = self._makeRequest()
5e3439 3148         called = [False]
535015 3149         def route_url(n, **kw):
5e3439 3150             called[0] = True
535015 3151             self.assertEqual(n, '__viewname')
4d19b8 3152             self.assertEqual(kw, {'subpath': 'foo/abc', 'foo': 'bar',
MM 3153                                   'pathspec': 'package:path/abc',
3154                                   'rawspec': 'package:path/abc'})
535015 3155         request.route_url = route_url
CR 3156         inst.generate('package:path/abc', request)
5e3439 3157         self.assertTrue(called[0])
MM 3158
3159     def test_generate_url_cachebust_abspath(self):
3160         here = os.path.dirname(__file__) + os.sep
3161         def cachebust(pathspec, subpath, kw):
3162             kw['foo'] = 'bar'
3163             return 'foo' + '/' + subpath, kw
3164         inst = self._makeOne()
3165         inst.registrations = [(None, here, '__viewname')]
4d19b8 3166         inst.cache_busters = [(here, cachebust, False)]
5e3439 3167         request = self._makeRequest()
MM 3168         called = [False]
3169         def route_url(n, **kw):
3170             called[0] = True
3171             self.assertEqual(n, '__viewname')
4d19b8 3172             self.assertEqual(kw, {'subpath': 'foo/abc', 'foo': 'bar',
MM 3173                                   'pathspec': here + 'abc',
3174                                   'rawspec': here + 'abc'})
5e3439 3175         request.route_url = route_url
MM 3176         inst.generate(here + 'abc', request)
3177         self.assertTrue(called[0])
3178
3179     def test_generate_url_cachebust_nomatch(self):
3180         def fake_cb(*a, **kw): raise AssertionError
3181         inst = self._makeOne()
3182         inst.registrations = [(None, 'package:path/', '__viewname')]
4d19b8 3183         inst.cache_busters = [('package:path2/', fake_cb, False)]
5e3439 3184         request = self._makeRequest()
MM 3185         called = [False]
3186         def route_url(n, **kw):
3187             called[0] = True
3188             self.assertEqual(n, '__viewname')
4d19b8 3189             self.assertEqual(kw, {'subpath': 'abc',
MM 3190                                   'pathspec': 'package:path/abc',
3191                                   'rawspec': 'package:path/abc'})
5e3439 3192         request.route_url = route_url
MM 3193         inst.generate('package:path/abc', request)
3194         self.assertTrue(called[0])
3195
3196     def test_generate_url_cachebust_with_overrides(self):
3197         config = testing.setUp()
3198         try:
4d19b8 3199             request = testing.DummyRequest()
5e3439 3200             config.add_static_view('static', 'path')
MM 3201             config.override_asset(
3202                 'pyramid.tests.test_config:path/',
3203                 'pyramid.tests.test_config:other_path/')
4d19b8 3204             def cb(val):
MM 3205                 def cb_(request, subpath, kw):
3206                     kw['_query'] = {'x': val}
3207                     return subpath, kw
3208                 return cb_
3209             config.add_cache_buster('path', cb('foo'))
5e3439 3210             result = request.static_url('path/foo.png')
MM 3211             self.assertEqual(result, 'http://example.com/static/foo.png?x=foo')
4d19b8 3212             config.add_cache_buster('other_path', cb('bar'), explicit=True)
MM 3213             result = request.static_url('path/foo.png')
3214             self.assertEqual(result, 'http://example.com/static/foo.png?x=bar')
5e3439 3215         finally:
MM 3216             testing.tearDown()
535015 3217
53d9d4 3218     def test_add_already_exists(self):
6e29b4 3219         config = DummyConfig()
cda7f6 3220         inst = self._makeOne()
6e29b4 3221         inst.registrations = [('http://example.com/', 'package:path/', None)]
cda7f6 3222         inst.add(config, 'http://example.com', 'anotherpackage:path')
5e3439 3223         expected = [('http://example.com/', 'anotherpackage:path/', None)]
6e29b4 3224         self.assertEqual(inst.registrations, expected)
53d9d4 3225
940a7a 3226     def test_add_package_root(self):
6e29b4 3227         config = DummyConfig()
940a7a 3228         inst = self._makeOne()
RL 3229         inst.add(config, 'http://example.com', 'package:')
5e3439 3230         expected = [('http://example.com/', 'package:', None)]
6e29b4 3231         self.assertEqual(inst.registrations, expected)
940a7a 3232
53d9d4 3233     def test_add_url_withendslash(self):
6e29b4 3234         config = DummyConfig()
cda7f6 3235         inst = self._makeOne()
CM 3236         inst.add(config, 'http://example.com/', 'anotherpackage:path')
5e3439 3237         expected = [('http://example.com/', 'anotherpackage:path/', None)]
6e29b4 3238         self.assertEqual(inst.registrations, expected)
53d9d4 3239
CM 3240     def test_add_url_noendslash(self):
6e29b4 3241         config = DummyConfig()
cda7f6 3242         inst = self._makeOne()
CM 3243         inst.add(config, 'http://example.com', 'anotherpackage:path')
5e3439 3244         expected = [('http://example.com/', 'anotherpackage:path/', None)]
6e29b4 3245         self.assertEqual(inst.registrations, expected)
53d9d4 3246
ff41f8 3247     def test_add_url_noscheme(self):
6e29b4 3248         config = DummyConfig()
ff41f8 3249         inst = self._makeOne()
WS 3250         inst.add(config, '//example.com', 'anotherpackage:path')
5e3439 3251         expected = [('//example.com/', 'anotherpackage:path/', None)]
6e29b4 3252         self.assertEqual(inst.registrations, expected)
ff41f8 3253
53d9d4 3254     def test_add_viewname(self):
CM 3255         from pyramid.security import NO_PERMISSION_REQUIRED
3256         from pyramid.static import static_view
6e29b4 3257         config = DummyConfig()
cda7f6 3258         inst = self._makeOne()
CM 3259         inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1)
5e3439 3260         expected = [(None, 'anotherpackage:path/', '__view/')]
6e29b4 3261         self.assertEqual(inst.registrations, expected)
bc9357 3262         self.assertEqual(config.route_args, ('__view/', 'view/*subpath'))
53d9d4 3263         self.assertEqual(config.view_kw['permission'], NO_PERMISSION_REQUIRED)
CM 3264         self.assertEqual(config.view_kw['view'].__class__, static_view)
bc9357 3265
CM 3266     def test_add_viewname_with_route_prefix(self):
6e29b4 3267         config = DummyConfig()
bc9357 3268         config.route_prefix = '/abc'
CM 3269         inst = self._makeOne()
3270         inst.add(config, 'view', 'anotherpackage:path',)
5e3439 3271         expected = [(None, 'anotherpackage:path/', '__/abc/view/')]
6e29b4 3272         self.assertEqual(inst.registrations, expected)
bc9357 3273         self.assertEqual(config.route_args, ('__/abc/view/', 'view/*subpath'))
53d9d4 3274
CM 3275     def test_add_viewname_with_permission(self):
6e29b4 3276         config = DummyConfig()
cda7f6 3277         inst = self._makeOne()
CM 3278         inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1,
53d9d4 3279                  permission='abc')
CM 3280         self.assertEqual(config.view_kw['permission'], 'abc')
3281
fdf30b 3282     def test_add_viewname_with_context(self):
6e29b4 3283         config = DummyConfig()
cda7f6 3284         inst = self._makeOne()
CM 3285         inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1,
fdf30b 3286                  context=DummyContext)
53d9d4 3287         self.assertEqual(config.view_kw['context'], DummyContext)
cac23b 3288
53d9d4 3289     def test_add_viewname_with_for_(self):
6e29b4 3290         config = DummyConfig()
cda7f6 3291         inst = self._makeOne()
CM 3292         inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1,
53d9d4 3293                  for_=DummyContext)
CM 3294         self.assertEqual(config.view_kw['context'], DummyContext)
3295
3296     def test_add_viewname_with_renderer(self):
6e29b4 3297         config = DummyConfig()
cda7f6 3298         inst = self._makeOne()
CM 3299         inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1,
53d9d4 3300                  renderer='mypackage:templates/index.pt')
CM 3301         self.assertEqual(config.view_kw['renderer'],
3302                          'mypackage:templates/index.pt')
3303
659630 3304     def test_add_cachebust_prevented(self):
6e29b4 3305         config = DummyConfig()
15b979 3306         config.registry.settings['pyramid.prevent_cachebust'] = True
659630 3307         inst = self._makeOne()
5e3439 3308         cachebust = DummyCacheBuster('foo')
MM 3309         inst.add_cache_buster(config, 'mypackage:path', cachebust)
3310         self.assertEqual(inst.cache_busters, [])
659630 3311
5e3439 3312     def test_add_cachebuster(self):
6e29b4 3313         config = DummyConfig()
535015 3314         inst = self._makeOne()
5e3439 3315         inst.add_cache_buster(config, 'mypackage:path', DummyCacheBuster('foo'))
MM 3316         cachebust = inst.cache_busters[-1][1]
4d19b8 3317         subpath, kw = cachebust(None, 'some/path', {})
535015 3318         self.assertEqual(subpath, 'some/path')
CR 3319         self.assertEqual(kw['x'], 'foo')
5e3439 3320
MM 3321     def test_add_cachebuster_abspath(self):
3322         here = os.path.dirname(__file__)
3323         config = DummyConfig()
3324         inst = self._makeOne()
3325         cb = DummyCacheBuster('foo')
3326         inst.add_cache_buster(config, here, cb)
4e6f98 3327         self.assertEqual(inst.cache_busters, [(here + os.sep, cb, False)])
5e3439 3328
MM 3329     def test_add_cachebuster_overwrite(self):
3330         config = DummyConfig()
3331         inst = self._makeOne()
3332         cb1 = DummyCacheBuster('foo')
3333         cb2 = DummyCacheBuster('bar')
3334         inst.add_cache_buster(config, 'mypackage:path/', cb1)
3335         inst.add_cache_buster(config, 'mypackage:path', cb2)
3336         self.assertEqual(inst.cache_busters,
4d19b8 3337                          [('mypackage:path/', cb2, False)])
MM 3338
3339     def test_add_cachebuster_overwrite_explicit(self):
3340         config = DummyConfig()
3341         inst = self._makeOne()
3342         cb1 = DummyCacheBuster('foo')
3343         cb2 = DummyCacheBuster('bar')
3344         inst.add_cache_buster(config, 'mypackage:path/', cb1)
3345         inst.add_cache_buster(config, 'mypackage:path', cb2, True)
3346         self.assertEqual(inst.cache_busters,
3347                          [('mypackage:path/', cb1, False),
3348                           ('mypackage:path/', cb2, True)])
5e3439 3349
MM 3350     def test_add_cachebuster_for_more_specific_path(self):
3351         config = DummyConfig()
3352         inst = self._makeOne()
3353         cb1 = DummyCacheBuster('foo')
3354         cb2 = DummyCacheBuster('bar')
4d19b8 3355         cb3 = DummyCacheBuster('baz')
MM 3356         cb4 = DummyCacheBuster('xyz')
3357         cb5 = DummyCacheBuster('w')
5e3439 3358         inst.add_cache_buster(config, 'mypackage:path', cb1)
4d19b8 3359         inst.add_cache_buster(config, 'mypackage:path/sub', cb2, True)
MM 3360         inst.add_cache_buster(config, 'mypackage:path/sub/other', cb3)
3361         inst.add_cache_buster(config, 'mypackage:path/sub/other', cb4, True)
3362         inst.add_cache_buster(config, 'mypackage:path/sub/less', cb5, True)
3363         self.assertEqual(
3364             inst.cache_busters,
3365             [('mypackage:path/', cb1, False),
3366              ('mypackage:path/sub/other/', cb3, False),
3367              ('mypackage:path/sub/', cb2, True),
3368              ('mypackage:path/sub/less/', cb5, True),
3369              ('mypackage:path/sub/other/', cb4, True)])
535015 3370
af24f7 3371 class Test_view_description(unittest.TestCase):
CM 3372     def _callFUT(self, view):
3373         from pyramid.config.views import view_description
3374         return view_description(view)
42afb0 3375
af24f7 3376     def test_with_text(self):
CM 3377         def view(): pass
3378         view.__text__ = 'some text'
3379         result = self._callFUT(view)
3380         self.assertEqual(result, 'some text')
42afb0 3381
af24f7 3382     def test_without_text(self):
CM 3383         def view(): pass
3384         result = self._callFUT(view)
42afb0 3385         self.assertEqual(result,
af24f7 3386                          'function pyramid.tests.test_config.test_views.view')
42afb0 3387
af24f7 3388
cda7f6 3389 class DummyRegistry:
5e3439 3390     utility = None
MM 3391
659630 3392     def __init__(self):
CR 3393         self.settings = {}
5e3439 3394
MM 3395     def queryUtility(self, type_or_iface, name=None, default=None):
3396         return self.utility or default
53d9d4 3397
5fc893 3398 from zope.interface import implementer
849196 3399 from pyramid.interfaces import (
CM 3400     IResponse,
3401     IRequest,
3402     )
3403
5fc893 3404 @implementer(IResponse)
BJR 3405 class DummyResponse(object):
3406     content_type = None
3407     default_content_type = None
42afb0 3408     body = None
5fc893 3409
5bf23f 3410 class DummyRequest:
CM 3411     subpath = ()
3412     matchdict = None
849196 3413     request_iface  = IRequest
498342 3414     application_url = 'http://example.com/foo'
5fc893 3415
5bf23f 3416     def __init__(self, environ=None):
CM 3417         if environ is None:
3418             environ = {}
3419         self.environ = environ
3420         self.params = {}
3421         self.cookies = {}
6ef10d 3422         self.response = DummyResponse()
5bf23f 3423
CM 3424 class DummyContext:
3b7334 3425     pass
5bf23f 3426
CM 3427 class DummyAccept(object):
3428     def __init__(self, *matches):
3429         self.matches = list(matches)
3430
3431     def best_match(self, offered):
3432         if self.matches:
3433             for match in self.matches:
3434                 if match in offered:
3435                     self.matches.remove(match)
3436                     return match
49f082 3437     def __contains__(self, val):
CM 3438         return val in self.matches
5bf23f 3439
53d9d4 3440 class DummyConfig:
5e3439 3441     def __init__(self):
MM 3442         self.registry = DummyRegistry()
3443
bc9357 3444     route_prefix = ''
53d9d4 3445     def add_route(self, *args, **kw):
CM 3446         self.route_args = args
3447         self.route_kw = kw
3448
3449     def add_view(self, *args, **kw):
3450         self.view_args = args
3451         self.view_kw = kw
3452
773948 3453     def action(self, discriminator, callable, introspectables=()):
bc9357 3454         callable()
CM 3455
773948 3456     def introspectable(self, *arg):
CM 3457         return {}
3458
3b7334 3459 from zope.interface import implementer
49f082 3460 from pyramid.interfaces import IMultiView
3b7334 3461 @implementer(IMultiView)
49f082 3462 class DummyMultiView:
CM 3463     def __init__(self):
3464         self.views = []
3465         self.name = 'name'
3466     def add(self, view, order, accept=None, phash=None):
3467         self.views.append((view, accept, phash))
3468     def __call__(self, context, request):
3469         return 'OK1'
3470     def __permitted__(self, context, request):
3471         """ """
3472
aa96dd 3473 class DummyCacheBuster(object):
780889 3474     def __init__(self, token):
MM 3475         self.token = token
6e29b4 3476
4d19b8 3477     def __call__(self, request, subpath, kw):
780889 3478         kw['x'] = self.token
aa96dd 3479         return subpath, kw
CR 3480
5bf23f 3481 def parse_httpdate(s):
CM 3482     import datetime
3483     # cannot use %Z, must use literal GMT; Jython honors timezone
3484     # but CPython does not
3485     return datetime.datetime.strptime(s, "%a, %d %b %Y %H:%M:%S GMT")
3486
3487 def assert_similar_datetime(one, two):
3488     for attr in ('year', 'month', 'day', 'hour', 'minute'):
3489         one_attr = getattr(one, attr)
3490         two_attr = getattr(two, attr)
3491         if not one_attr == two_attr: # pragma: no cover
3492             raise AssertionError('%r != %r in %s' % (one_attr, two_attr, attr))
49f082 3493
6cc22a 3494 class DummyStaticURLInfo:
CM 3495     def __init__(self):
3496         self.added = []
3497
cda7f6 3498     def add(self, config, name, spec, **kw):
CM 3499         self.added.append((config, name, spec, kw))
134388 3500
CM 3501 class DummyViewDefaultsClass(object):
3502     __view_defaults__ = {
3503         'containment':'pyramid.tests.test_config.IDummy'
3504         }
3505     def __init__(self, request):
3506         pass
3507     def __call__(self):
3508         return 'OK'
8ec8e2 3509
CM 3510 class DummyPredicate(object):
3511     def __init__(self, val, config):
3512         self.val = val
3513
3514     def text(self):
3515         return 'dummy'
3516
3517     phash = text
3518
3d42aa 3519 class DummyIntrospector(object):
CM 3520     def __init__(self, getval=None):
3521         self.related = []
3522         self.introspectables = []
3523         self.getval = getval
3524     def add(self, introspectable):
3525         self.introspectables.append(introspectable)
3526     def get(self, name, discrim):
3527         return self.getval
3528     def relate(self, a, b):
3529         self.related.append((a, b))
9e9fa9 3530
MM 3531 class DummySession(dict):
3532     def get_csrf_token(self):
3533         return self['csrf_token']