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