Michael Merickel
2017-06-15 2ea943e690d8f09d07c13ca4d513cfafbfba33f1
commit | author | age
7e2c6c 1 import unittest
e6fa66 2 import sys
7e2c6c 3
3b7334 4 from zope.interface import implementer
CM 5
a00621 6 from pyramid import testing
7e2c6c 7
849196 8 from pyramid.interfaces import IRequest
CM 9
d20d09 10 class BaseTest(object):
7e2c6c 11     def setUp(self):
a00621 12         self.config = testing.setUp()
7e2c6c 13
CM 14     def tearDown(self):
a00621 15         testing.tearDown()
7e2c6c 16
333bd0 17     def _registerView(self, reg, app, name):
b60bdb 18         from pyramid.interfaces import IViewClassifier
ff1213 19         for_ = (IViewClassifier, IRequest, IContext)
b60bdb 20         from pyramid.interfaces import IView
1c0210 21         reg.registerAdapter(app, for_, IView, name)
7e2c6c 22
CM 23     def _makeEnviron(self, **extras):
24         environ = {
25             'wsgi.url_scheme':'http',
d20d09 26             'wsgi.version':(1,0),
7e2c6c 27             'SERVER_NAME':'localhost',
CM 28             'SERVER_PORT':'8080',
29             'REQUEST_METHOD':'GET',
b596e1 30             'PATH_INFO':'/',
7e2c6c 31             }
CM 32         environ.update(extras)
33         return environ
34
1c0210 35     def _makeRequest(self, **environ):
849196 36         from pyramid.request import Request
b60bdb 37         from pyramid.registry import Registry
1c0210 38         environ = self._makeEnviron(**environ)
CM 39         request = Request(environ)
40         request.registry = Registry()
41         return request
42
43     def _makeContext(self):
44         from zope.interface import directlyProvides
45         context = DummyContext()
46         directlyProvides(context, IContext)
47         return context
0db4a1 48
CM 49 class Test_notfound_view_config(BaseTest, unittest.TestCase):
50     def _makeOne(self, **kw):
51         from pyramid.view import notfound_view_config
52         return notfound_view_config(**kw)
53
54     def test_ctor(self):
55         inst = self._makeOne(attr='attr', path_info='path_info', 
56                              append_slash=True)
57         self.assertEqual(inst.__dict__,
58                          {'attr':'attr', 'path_info':'path_info',
59                           'append_slash':True})
60
61     def test_it_function(self):
62         def view(request): pass
63         decorator = self._makeOne(attr='attr', renderer='renderer',
64                                   append_slash=True)
65         venusian = DummyVenusian()
66         decorator.venusian = venusian
67         wrapped = decorator(view)
68         self.assertTrue(wrapped is view)
69         config = call_venusian(venusian)
70         settings = config.settings
71         self.assertEqual(
72             settings, 
73             [{'attr': 'attr', 'venusian': venusian, 'append_slash': True, 
74               'renderer': 'renderer', '_info': 'codeinfo', 'view': None}]
75             )
76
77     def test_it_class(self):
78         decorator = self._makeOne()
79         venusian = DummyVenusian()
80         decorator.venusian = venusian
81         decorator.venusian.info.scope = 'class'
82         class view(object): pass
83         wrapped = decorator(view)
84         self.assertTrue(wrapped is view)
85         config = call_venusian(venusian)
86         settings = config.settings
87         self.assertEqual(len(settings), 1)
8ec8e2 88         self.assertEqual(len(settings[0]), 4)
0db4a1 89         self.assertEqual(settings[0]['venusian'], venusian)
CM 90         self.assertEqual(settings[0]['view'], None) # comes from call_venusian
91         self.assertEqual(settings[0]['attr'], 'view')
92         self.assertEqual(settings[0]['_info'], 'codeinfo')
1c0210 93
a7fe30 94 class Test_forbidden_view_config(BaseTest, unittest.TestCase):
CM 95     def _makeOne(self, **kw):
96         from pyramid.view import forbidden_view_config
97         return forbidden_view_config(**kw)
98
99     def test_ctor(self):
100         inst = self._makeOne(attr='attr', path_info='path_info')
101         self.assertEqual(inst.__dict__,
102                          {'attr':'attr', 'path_info':'path_info'})
103
104     def test_it_function(self):
105         def view(request): pass
106         decorator = self._makeOne(attr='attr', renderer='renderer')
107         venusian = DummyVenusian()
108         decorator.venusian = venusian
109         wrapped = decorator(view)
110         self.assertTrue(wrapped is view)
111         config = call_venusian(venusian)
112         settings = config.settings
113         self.assertEqual(
114             settings, 
115             [{'attr': 'attr', 'venusian': venusian, 
116               'renderer': 'renderer', '_info': 'codeinfo', 'view': None}]
117             )
118
119     def test_it_class(self):
120         decorator = self._makeOne()
121         venusian = DummyVenusian()
122         decorator.venusian = venusian
123         decorator.venusian.info.scope = 'class'
124         class view(object): pass
125         wrapped = decorator(view)
126         self.assertTrue(wrapped is view)
127         config = call_venusian(venusian)
128         settings = config.settings
129         self.assertEqual(len(settings), 1)
130         self.assertEqual(len(settings[0]), 4)
131         self.assertEqual(settings[0]['venusian'], venusian)
132         self.assertEqual(settings[0]['view'], None) # comes from call_venusian
133         self.assertEqual(settings[0]['attr'], 'view')
134         self.assertEqual(settings[0]['_info'], 'codeinfo')
93c94b 135
AL 136 class Test_exception_view_config(BaseTest, unittest.TestCase):
e8c66a 137     def _makeOne(self, *args, **kw):
93c94b 138         from pyramid.view import exception_view_config
e8c66a 139         return exception_view_config(*args, **kw)
93c94b 140
AL 141     def test_ctor(self):
142         inst = self._makeOne(context=Exception, path_info='path_info')
143         self.assertEqual(inst.__dict__,
144                          {'context':Exception, 'path_info':'path_info'})
145
e8c66a 146     def test_ctor_positional_exception(self):
MM 147         inst = self._makeOne(Exception, path_info='path_info')
148         self.assertEqual(inst.__dict__,
149                          {'context':Exception, 'path_info':'path_info'})
150
151     def test_ctor_positional_extras(self):
152         from pyramid.exceptions import ConfigurationError
153         self.assertRaises(ConfigurationError, lambda: self._makeOne(Exception, True))
154
93c94b 155     def test_it_function(self):
AL 156         def view(request): pass
157         decorator = self._makeOne(context=Exception, renderer='renderer')
158         venusian = DummyVenusian()
159         decorator.venusian = venusian
160         wrapped = decorator(view)
161         self.assertTrue(wrapped is view)
162         config = call_venusian(venusian)
163         settings = config.settings
164         self.assertEqual(
165             settings,
166             [{'venusian': venusian, 'context': Exception,
167               'renderer': 'renderer', '_info': 'codeinfo', 'view': None}]
168             )
169
170     def test_it_class(self):
171         decorator = self._makeOne()
172         venusian = DummyVenusian()
173         decorator.venusian = venusian
174         decorator.venusian.info.scope = 'class'
175         class view(object): pass
176         wrapped = decorator(view)
177         self.assertTrue(wrapped is view)
178         config = call_venusian(venusian)
179         settings = config.settings
180         self.assertEqual(len(settings), 1)
181         self.assertEqual(len(settings[0]), 4)
182         self.assertEqual(settings[0]['venusian'], venusian)
183         self.assertEqual(settings[0]['view'], None) # comes from call_venusian
184         self.assertEqual(settings[0]['attr'], 'view')
185         self.assertEqual(settings[0]['_info'], 'codeinfo')
186
d1c4f0 187 class RenderViewToResponseTests(BaseTest, unittest.TestCase):
b3d74b 188     def _callFUT(self, *arg, **kw):
b60bdb 189         from pyramid.view import render_view_to_response
b3d74b 190         return render_view_to_response(*arg, **kw)
7e2c6c 191     
CM 192     def test_call_no_view_registered(self):
1c0210 193         request = self._makeRequest()
CM 194         context = self._makeContext()
b3d74b 195         result = self._callFUT(context, request, name='notregistered')
7e2c6c 196         self.assertEqual(result, None)
CM 197
45d08c 198     def test_call_no_registry_on_request(self):
CM 199         request = self._makeRequest()
200         del request.registry
201         context = self._makeContext()
202         result = self._callFUT(context, request, name='notregistered')
203         self.assertEqual(result, None)
204
d66bfb 205     def test_call_view_registered_secure(self):
1c0210 206         request = self._makeRequest()
CM 207         context = self._makeContext()
7e2c6c 208         response = DummyResponse()
CM 209         view = make_view(response)
1c0210 210         self._registerView(request.registry, view, 'registered')
b3d74b 211         response = self._callFUT(context, request, name='registered',
CM 212                                  secure=True)
7e2c6c 213         self.assertEqual(response.status, '200 OK')
CM 214
d66bfb 215     def test_call_view_registered_insecure_no_call_permissive(self):
1c0210 216         context = self._makeContext()
CM 217         request = self._makeRequest()
7e2c6c 218         response = DummyResponse()
CM 219         view = make_view(response)
1c0210 220         self._registerView(request.registry, view, 'registered')
b3d74b 221         response = self._callFUT(context, request, name='registered',
CM 222                                  secure=False)
7e2c6c 223         self.assertEqual(response.status, '200 OK')
d66bfb 224
CM 225     def test_call_view_registered_insecure_with_call_permissive(self):
1c0210 226         context = self._makeContext()
CM 227         request = self._makeRequest()
d66bfb 228         response = DummyResponse()
CM 229         view = make_view(response)
230         def anotherview(context, request):
231             return DummyResponse('anotherview')
232         view.__call_permissive__ = anotherview
1c0210 233         self._registerView(request.registry, view, 'registered')
d66bfb 234         response = self._callFUT(context, request, name='registered',
CM 235                                  secure=False)
236         self.assertEqual(response.status, '200 OK')
237         self.assertEqual(response.app_iter, ['anotherview'])
7e2c6c 238
713bc5 239     def test_call_view_with_request_iface_on_request(self):
CM 240         # See https://github.com/Pylons/pyramid/issues/1643
241         from zope.interface import Interface
242         class IWontBeFound(Interface): pass
243         context = self._makeContext()
244         request = self._makeRequest()
245         request.request_iface = IWontBeFound
246         response = DummyResponse('aview')
247         view = make_view(response)
248         self._registerView(request.registry, view, 'aview')
249         response = self._callFUT(context, request, name='aview')
250         self.assertEqual(response.status, '200 OK')
251         self.assertEqual(response.app_iter, ['aview'])
252
d1c4f0 253 class RenderViewToIterableTests(BaseTest, unittest.TestCase):
b3d74b 254     def _callFUT(self, *arg, **kw):
b60bdb 255         from pyramid.view import render_view_to_iterable
b3d74b 256         return render_view_to_iterable(*arg, **kw)
7e2c6c 257     
CM 258     def test_call_no_view_registered(self):
1c0210 259         request = self._makeRequest()
CM 260         context = self._makeContext()
b3d74b 261         result = self._callFUT(context, request, name='notregistered')
7e2c6c 262         self.assertEqual(result, None)
CM 263
d66bfb 264     def test_call_view_registered_secure(self):
1c0210 265         request = self._makeRequest()
CM 266         context = self._makeContext()
7e2c6c 267         response = DummyResponse()
CM 268         view = make_view(response)
1c0210 269         self._registerView(request.registry, view, 'registered')
b3d74b 270         iterable = self._callFUT(context, request, name='registered',
CM 271                                  secure=True)
7e2c6c 272         self.assertEqual(iterable, ())
CM 273
d66bfb 274     def test_call_view_registered_insecure_no_call_permissive(self):
1c0210 275         context = self._makeContext()
CM 276         request = self._makeRequest()
7e2c6c 277         response = DummyResponse()
CM 278         view = make_view(response)
1c0210 279         self._registerView(request.registry, view, 'registered')
b3d74b 280         iterable = self._callFUT(context, request, name='registered',
CM 281                                  secure=False)
7e2c6c 282         self.assertEqual(iterable, ())
d66bfb 283
CM 284     def test_call_view_registered_insecure_with_call_permissive(self):
1c0210 285         context = self._makeContext()
CM 286         request = self._makeRequest()
d66bfb 287         response = DummyResponse()
CM 288         view = make_view(response)
289         def anotherview(context, request):
0a8ea9 290             return DummyResponse(b'anotherview')
d66bfb 291         view.__call_permissive__ = anotherview
1c0210 292         self._registerView(request.registry, view, 'registered')
d66bfb 293         iterable = self._callFUT(context, request, name='registered',
CM 294                                  secure=False)
0a8ea9 295         self.assertEqual(iterable, [b'anotherview'])
MM 296
6ec5a6 297     def test_verify_output_bytestring(self):
AV 298         from pyramid.request import Request
299         from pyramid.config import Configurator
300         from pyramid.view import render_view
301         from webob.compat import text_type
302         config = Configurator(settings={})
303         def view(request):
304             request.response.text = text_type('<body></body>')
305             return request.response
306
307         config.add_view(name='test', view=view)
308         config.commit()
309
310         r = Request({})
311         r.registry = config.registry
312         self.assertEqual(render_view(object(), r, 'test'), b'<body></body>')
7e2c6c 313
08ffc9 314     def test_call_request_has_no_registry(self):
CM 315         request = self._makeRequest()
316         del request.registry
317         registry = self.config.registry
318         context = self._makeContext()
319         response = DummyResponse()
320         view = make_view(response)
321         self._registerView(registry, view, 'registered')
322         iterable = self._callFUT(context, request, name='registered',
323                                  secure=True)
324         self.assertEqual(iterable, ())
325
1c0210 326 class RenderViewTests(BaseTest, unittest.TestCase):
b3d74b 327     def _callFUT(self, *arg, **kw):
b60bdb 328         from pyramid.view import render_view
b3d74b 329         return render_view(*arg, **kw)
885bfb 330     
CM 331     def test_call_no_view_registered(self):
1c0210 332         request = self._makeRequest()
CM 333         context = self._makeContext()
b3d74b 334         result = self._callFUT(context, request, name='notregistered')
885bfb 335         self.assertEqual(result, None)
CM 336
d66bfb 337     def test_call_view_registered_secure(self):
1c0210 338         request = self._makeRequest()
CM 339         context = self._makeContext()
885bfb 340         response = DummyResponse()
CM 341         view = make_view(response)
1c0210 342         self._registerView(request.registry, view, 'registered')
b3d74b 343         s = self._callFUT(context, request, name='registered', secure=True)
6ec5a6 344         self.assertEqual(s, b'')
885bfb 345
d66bfb 346     def test_call_view_registered_insecure_no_call_permissive(self):
1c0210 347         context = self._makeContext()
CM 348         request = self._makeRequest()
885bfb 349         response = DummyResponse()
CM 350         view = make_view(response)
1c0210 351         self._registerView(request.registry, view, 'registered')
b3d74b 352         s = self._callFUT(context, request, name='registered', secure=False)
6ec5a6 353         self.assertEqual(s, b'')
d66bfb 354
CM 355     def test_call_view_registered_insecure_with_call_permissive(self):
1c0210 356         context = self._makeContext()
CM 357         request = self._makeRequest()
d66bfb 358         response = DummyResponse()
CM 359         view = make_view(response)
360         def anotherview(context, request):
0a8ea9 361             return DummyResponse(b'anotherview')
d66bfb 362         view.__call_permissive__ = anotherview
1c0210 363         self._registerView(request.registry, view, 'registered')
d66bfb 364         s = self._callFUT(context, request, name='registered', secure=False)
6ec5a6 365         self.assertEqual(s, b'anotherview')
885bfb 366
197f0c 367 class TestViewConfigDecorator(unittest.TestCase):
5a7f9a 368     def setUp(self):
a00621 369         testing.setUp()
5a7f9a 370
CM 371     def tearDown(self):
a00621 372         testing.tearDown()
5a7f9a 373
CM 374     def _getTargetClass(self):
197f0c 375         from pyramid.view import view_config
CM 376         return view_config
5a7f9a 377
CM 378     def _makeOne(self, *arg, **kw):
379         return self._getTargetClass()(*arg, **kw)
380
381     def test_create_defaults(self):
382         decorator = self._makeOne()
4c29ef 383         self.assertEqual(decorator.__dict__, {})
b04bd5 384
CM 385     def test_create_context_trumps_for(self):
386         decorator = self._makeOne(context='123', for_='456')
387         self.assertEqual(decorator.context, '123')
388
389     def test_create_for_trumps_context_None(self):
390         decorator = self._makeOne(context=None, for_='456')
391         self.assertEqual(decorator.context, '456')
5a7f9a 392         
CM 393     def test_create_nondefaults(self):
4c29ef 394         decorator = self._makeOne(
CM 395             name=None, request_type=None, for_=None,
396             permission='foo', mapper='mapper',
397             decorator='decorator', match_param='match_param'
398             )
5a7f9a 399         self.assertEqual(decorator.name, None)
CM 400         self.assertEqual(decorator.request_type, None)
eecdbc 401         self.assertEqual(decorator.context, None)
5a7f9a 402         self.assertEqual(decorator.permission, 'foo')
5e3d64 403         self.assertEqual(decorator.mapper, 'mapper')
1d9ade 404         self.assertEqual(decorator.decorator, 'decorator')
bf5e0e 405         self.assertEqual(decorator.match_param, 'match_param')
8ec8e2 406
CM 407     def test_create_with_other_predicates(self):
408         decorator = self._makeOne(foo=1)
409         self.assertEqual(decorator.foo, 1)
76c9c2 410
R 411     def test_create_decorator_tuple(self):
412         decorator = self._makeOne(decorator=('decorator1', 'decorator2'))
413         self.assertEqual(decorator.decorator, ('decorator1', 'decorator2'))
5a7f9a 414         
5a11e2 415     def test_call_function(self):
CM 416         decorator = self._makeOne()
e6fa66 417         venusian = DummyVenusian()
CM 418         decorator.venusian = venusian
419         def foo(): pass
5a11e2 420         wrapped = decorator(foo)
a1d395 421         self.assertTrue(wrapped is foo)
b2c4e0 422         config = call_venusian(venusian)
CM 423         settings = config.settings
e6fa66 424         self.assertEqual(len(settings), 1)
4c29ef 425         self.assertEqual(len(settings), 1)
CM 426         self.assertEqual(len(settings[0]), 3)
427         self.assertEqual(settings[0]['venusian'], venusian)
428         self.assertEqual(settings[0]['view'], None) # comes from call_venusian
429         self.assertEqual(settings[0]['_info'], 'codeinfo')
5a11e2 430
e6fa66 431     def test_call_class(self):
5a7f9a 432         decorator = self._makeOne()
e6fa66 433         venusian = DummyVenusian()
CM 434         decorator.venusian = venusian
435         decorator.venusian.info.scope = 'class'
436         class foo(object): pass
5a7f9a 437         wrapped = decorator(foo)
a1d395 438         self.assertTrue(wrapped is foo)
b2c4e0 439         config = call_venusian(venusian)
CM 440         settings = config.settings
e6fa66 441         self.assertEqual(len(settings), 1)
4c29ef 442         self.assertEqual(len(settings[0]), 4)
CM 443         self.assertEqual(settings[0]['venusian'], venusian)
444         self.assertEqual(settings[0]['view'], None) # comes from call_venusian
b04bd5 445         self.assertEqual(settings[0]['attr'], 'foo')
4c29ef 446         self.assertEqual(settings[0]['_info'], 'codeinfo')
b04bd5 447
CM 448     def test_call_class_attr_already_set(self):
449         decorator = self._makeOne(attr='abc')
450         venusian = DummyVenusian()
451         decorator.venusian = venusian
452         decorator.venusian.info.scope = 'class'
453         class foo(object): pass
454         wrapped = decorator(foo)
a1d395 455         self.assertTrue(wrapped is foo)
b2c4e0 456         config = call_venusian(venusian)
CM 457         settings = config.settings
b04bd5 458         self.assertEqual(len(settings), 1)
4c29ef 459         self.assertEqual(len(settings[0]), 4)
CM 460         self.assertEqual(settings[0]['venusian'], venusian)
461         self.assertEqual(settings[0]['view'], None) # comes from call_venusian
b04bd5 462         self.assertEqual(settings[0]['attr'], 'abc')
4c29ef 463         self.assertEqual(settings[0]['_info'], 'codeinfo')
5a7f9a 464
2cce43 465     def test_stacking(self):
CM 466         decorator1 = self._makeOne(name='1')
e6fa66 467         venusian1 = DummyVenusian()
CM 468         decorator1.venusian = venusian1
469         venusian2 = DummyVenusian()
2cce43 470         decorator2 = self._makeOne(name='2')
e6fa66 471         decorator2.venusian = venusian2
CM 472         def foo(): pass
2cce43 473         wrapped1 = decorator1(foo)
CM 474         wrapped2 = decorator2(wrapped1)
a1d395 475         self.assertTrue(wrapped1 is foo)
CM 476         self.assertTrue(wrapped2 is foo)
b2c4e0 477         config1 = call_venusian(venusian1)
CM 478         self.assertEqual(len(config1.settings), 1)
479         self.assertEqual(config1.settings[0]['name'], '1')
480         config2 = call_venusian(venusian2)
481         self.assertEqual(len(config2.settings), 1)
482         self.assertEqual(config2.settings[0]['name'], '2')
2cce43 483
b2f929 484     def test_call_as_method(self):
CM 485         decorator = self._makeOne()
e6fa66 486         venusian = DummyVenusian()
CM 487         decorator.venusian = venusian
488         decorator.venusian.info.scope = 'class'
b2f929 489         def foo(self): pass
CM 490         def bar(self): pass
491         class foo(object):
492             foomethod = decorator(foo)
493             barmethod = decorator(bar)
b2c4e0 494         config = call_venusian(venusian)
CM 495         settings = config.settings
b2f929 496         self.assertEqual(len(settings), 2)
CM 497         self.assertEqual(settings[0]['attr'], 'foo')
498         self.assertEqual(settings[1]['attr'], 'bar')
499
6225a2 500     def test_with_custom_predicates(self):
CM 501         decorator = self._makeOne(custom_predicates=(1,))
e6fa66 502         venusian = DummyVenusian()
CM 503         decorator.venusian = venusian
504         def foo(context, request): pass
6225a2 505         decorated = decorator(foo)
a1d395 506         self.assertTrue(decorated is foo)
b2c4e0 507         config = call_venusian(venusian)
CM 508         settings = config.settings
6225a2 509         self.assertEqual(settings[0]['custom_predicates'], (1,))
CM 510
3d9dd0 511     def test_call_with_renderer_string(self):
CM 512         import pyramid.tests
89968d 513         decorator = self._makeOne(renderer='fixtures/minimal.pt')
e6fa66 514         venusian = DummyVenusian()
CM 515         decorator.venusian = venusian
516         def foo(): pass
89968d 517         wrapped = decorator(foo)
a1d395 518         self.assertTrue(wrapped is foo)
b2c4e0 519         config = call_venusian(venusian)
CM 520         settings = config.settings
e6fa66 521         self.assertEqual(len(settings), 1)
3d9dd0 522         renderer = settings[0]['renderer']
b2c4e0 523         self.assertEqual(renderer, 'fixtures/minimal.pt')
CM 524         self.assertEqual(config.pkg, pyramid.tests)
89968d 525
3d9dd0 526     def test_call_with_renderer_dict(self):
b2c4e0 527         import pyramid.tests
3d9dd0 528         decorator = self._makeOne(renderer={'a':1})
e6fa66 529         venusian = DummyVenusian()
CM 530         decorator.venusian = venusian
531         def foo(): pass
89968d 532         wrapped = decorator(foo)
a1d395 533         self.assertTrue(wrapped is foo)
b2c4e0 534         config = call_venusian(venusian)
CM 535         settings = config.settings
e6fa66 536         self.assertEqual(len(settings), 1)
3d9dd0 537         self.assertEqual(settings[0]['renderer'], {'a':1})
b2c4e0 538         self.assertEqual(config.pkg, pyramid.tests)
89968d 539
2ad827 540     def test_call_with_renderer_IRendererInfo(self):
CM 541         import pyramid.tests
b2c4e0 542         from pyramid.interfaces import IRendererInfo
3b7334 543         @implementer(IRendererInfo)
2ad827 544         class DummyRendererHelper(object):
3b7334 545             pass
2ad827 546         renderer_helper = DummyRendererHelper()
CM 547         decorator = self._makeOne(renderer=renderer_helper)
548         venusian = DummyVenusian()
549         decorator.venusian = venusian
550         def foo(): pass
551         wrapped = decorator(foo)
552         self.assertTrue(wrapped is foo)
553         context = DummyVenusianContext()
b2c4e0 554         config = call_venusian(venusian, context)
CM 555         settings = config.settings
2ad827 556         self.assertEqual(len(settings), 1)
CM 557         renderer = settings[0]['renderer']
73c0ae 558         self.assertTrue(renderer is renderer_helper)
b2c4e0 559         self.assertEqual(config.pkg, pyramid.tests)
2ad827 560
a8d71c 561     def test_call_withdepth(self):
ed1419 562         decorator = self._makeOne(_depth=1)
a8d71c 563         venusian = DummyVenusian()
CM 564         decorator.venusian = venusian
565         def foo(): pass
566         decorator(foo)
567         self.assertEqual(venusian.depth, 2)
568
d96ff9 569 class Test_append_slash_notfound_view(BaseTest, unittest.TestCase):
3a61a3 570     def _callFUT(self, context, request):
b60bdb 571         from pyramid.view import append_slash_notfound_view
3a61a3 572         return append_slash_notfound_view(context, request)
CM 573
1c0210 574     def _registerMapper(self, reg, match=True):
b60bdb 575         from pyramid.interfaces import IRoutesMapper
3a61a3 576         class DummyRoute(object):
CM 577             def __init__(self, val):
578                 self.val = val
579             def match(self, path):
580                 return self.val
581         class DummyMapper(object):
582             def __init__(self):
583                 self.routelist = [ DummyRoute(match) ]
06dad2 584             def get_routes(self):
CM 585                 return self.routelist
3a61a3 586         mapper = DummyMapper()
1c0210 587         reg.registerUtility(mapper, IRoutesMapper)
3a61a3 588         return mapper
CM 589
30e64f 590     def test_context_is_not_exception(self):
CM 591         request = self._makeRequest(PATH_INFO='/abc')
d96ff9 592         request.exception = ExceptionResponse()
30e64f 593         context = DummyContext()
CM 594         response = self._callFUT(context, request)
595         self.assertEqual(response.status, '404 Not Found')
d96ff9 596         self.assertEqual(response.app_iter, ['Not Found'])
30e64f 597
3a61a3 598     def test_no_mapper(self):
1c0210 599         request = self._makeRequest(PATH_INFO='/abc')
d96ff9 600         context = ExceptionResponse()
3a61a3 601         response = self._callFUT(context, request)
CM 602         self.assertEqual(response.status, '404 Not Found')
603
604     def test_no_path(self):
1c0210 605         request = self._makeRequest()
d96ff9 606         context = ExceptionResponse()
1c0210 607         self._registerMapper(request.registry, True)
3a61a3 608         response = self._callFUT(context, request)
CM 609         self.assertEqual(response.status, '404 Not Found')
610
611     def test_mapper_path_already_slash_ending(self):
1c0210 612         request = self._makeRequest(PATH_INFO='/abc/')
d96ff9 613         context = ExceptionResponse()
1c0210 614         self._registerMapper(request.registry, True)
3a61a3 615         response = self._callFUT(context, request)
CM 616         self.assertEqual(response.status, '404 Not Found')
617
d92958 618     def test_no_route_matches(self):
CM 619         request = self._makeRequest(PATH_INFO='/abc')
620         context = ExceptionResponse()
621         mapper = self._registerMapper(request.registry, True)
622         mapper.routelist[0].val = None
623         response = self._callFUT(context, request)
624         self.assertEqual(response.status, '404 Not Found')
625
3a61a3 626     def test_matches(self):
1c0210 627         request = self._makeRequest(PATH_INFO='/abc')
d96ff9 628         context = ExceptionResponse()
1c0210 629         self._registerMapper(request.registry, True)
3a61a3 630         response = self._callFUT(context, request)
CM 631         self.assertEqual(response.status, '302 Found')
632         self.assertEqual(response.location, '/abc/')
633
b596e1 634     def test_matches_with_script_name(self):
CM 635         request = self._makeRequest(PATH_INFO='/abc', SCRIPT_NAME='/foo')
636         context = ExceptionResponse()
637         self._registerMapper(request.registry, True)
638         response = self._callFUT(context, request)
639         self.assertEqual(response.status, '302 Found')
640         self.assertEqual(response.location, '/foo/abc/')
641
6ab71c 642     def test_with_query_string(self):
CM 643         request = self._makeRequest(PATH_INFO='/abc', QUERY_STRING='a=1&b=2')
644         context = ExceptionResponse()
645         self._registerMapper(request.registry, True)
646         response = self._callFUT(context, request)
647         self.assertEqual(response.status, '302 Found')
648         self.assertEqual(response.location, '/abc/?a=1&b=2')
649
d96ff9 650 class TestAppendSlashNotFoundViewFactory(BaseTest, unittest.TestCase):
CM 651     def _makeOne(self, notfound_view):
b60bdb 652         from pyramid.view import AppendSlashNotFoundViewFactory
d96ff9 653         return AppendSlashNotFoundViewFactory(notfound_view)
CM 654     
655     def test_custom_notfound_view(self):
656         request = self._makeRequest(PATH_INFO='/abc')
657         context = ExceptionResponse()
658         def custom_notfound(context, request):
659             return 'OK'
660         view = self._makeOne(custom_notfound)
661         response = view(context, request)
662         self.assertEqual(response, 'OK')
663
664 class Test_default_exceptionresponse_view(unittest.TestCase):
665     def _callFUT(self, context, request):
b60bdb 666         from pyramid.view import default_exceptionresponse_view
d96ff9 667         return default_exceptionresponse_view(context, request)
CM 668
669     def test_is_exception(self):
670         context = Exception()
671         result = self._callFUT(context, None)
a1d395 672         self.assertTrue(result is context)
d96ff9 673
b04bd5 674     def test_is_not_exception_context_is_false_still_chose(self):
d92958 675         request = DummyRequest()
CM 676         request.exception = 0
677         result = self._callFUT(None, request)
a1d395 678         self.assertTrue(result is None)
d92958 679
d96ff9 680     def test_is_not_exception_no_request_exception(self):
CM 681         context = object()
682         request = DummyRequest()
d92958 683         request.exception = None
d96ff9 684         result = self._callFUT(context, request)
a1d395 685         self.assertTrue(result is context)
d96ff9 686
CM 687     def test_is_not_exception_request_exception(self):
688         context = object()
689         request = DummyRequest()
690         request.exception = 'abc'
691         result = self._callFUT(context, request)
692         self.assertEqual(result, 'abc')
693
914abe 694 class Test_view_defaults(unittest.TestCase):
CM 695     def test_it(self):
696         from pyramid.view import view_defaults
697         @view_defaults(route_name='abc', renderer='def')
698         class Foo(object): pass
699         self.assertEqual(Foo.__view_defaults__['route_name'],'abc')
700         self.assertEqual(Foo.__view_defaults__['renderer'],'def')
701
4375cf 702     def test_it_inheritance_not_overridden(self):
914abe 703         from pyramid.view import view_defaults
CM 704         @view_defaults(route_name='abc', renderer='def')
705         class Foo(object): pass
706         class Bar(Foo): pass
707         self.assertEqual(Bar.__view_defaults__['route_name'],'abc')
708         self.assertEqual(Bar.__view_defaults__['renderer'],'def')
709
4375cf 710     def test_it_inheritance_overriden(self):
CM 711         from pyramid.view import view_defaults
712         @view_defaults(route_name='abc', renderer='def')
713         class Foo(object): pass
714         @view_defaults(route_name='ghi')
715         class Bar(Foo): pass
716         self.assertEqual(Bar.__view_defaults__['route_name'],'ghi')
4c29ef 717         self.assertFalse('renderer' in Bar.__view_defaults__)
4375cf 718
CM 719     def test_it_inheritance_overriden_empty(self):
720         from pyramid.view import view_defaults
721         @view_defaults(route_name='abc', renderer='def')
722         class Foo(object): pass
723         @view_defaults()
724         class Bar(Foo): pass
4c29ef 725         self.assertEqual(Bar.__view_defaults__, {})
4375cf 726
d52257 727 class TestViewMethodsMixin(unittest.TestCase):
MM 728     def setUp(self):
729         self.config = testing.setUp()
730
731     def tearDown(self):
732         testing.tearDown()
733
734     def _makeOne(self, environ=None):
735         from pyramid.decorator import reify
736         from pyramid.view import ViewMethodsMixin
737         if environ is None:
738             environ = {}
739         class Request(ViewMethodsMixin):
740             def __init__(self, environ):
741                 self.environ = environ
742
743             @reify
744             def response(self):
745                 return DummyResponse()
746         request = Request(environ)
747         request.registry = self.config.registry
748         return request
749
750     def test_it(self):
751         def exc_view(exc, request):
752             self.assertTrue(exc is dummy_exc)
753             self.assertTrue(request.exception is dummy_exc)
754             return DummyResponse(b'foo')
755         self.config.add_view(exc_view, context=RuntimeError)
756         request = self._makeOne()
757         dummy_exc = RuntimeError()
758         try:
759             raise dummy_exc
760         except RuntimeError:
761             response = request.invoke_exception_view()
762             self.assertEqual(response.app_iter, [b'foo'])
763         else: # pragma: no cover
764             self.fail()
765
766     def test_it_hides_attrs(self):
767         def exc_view(exc, request):
768             self.assertTrue(exc is not orig_exc)
769             self.assertTrue(request.exception is not orig_exc)
770             self.assertTrue(request.exc_info is not orig_exc_info)
771             self.assertTrue(request.response is not orig_response)
772             request.response.app_iter = [b'bar']
773             return request.response
774         self.config.add_view(exc_view, context=RuntimeError)
775         request = self._makeOne()
776         orig_exc = request.exception = DummyContext()
777         orig_exc_info = request.exc_info = DummyContext()
778         orig_response = request.response = DummyResponse(b'foo')
779         try:
780             raise RuntimeError
3b886e 781         except RuntimeError as ex:
d52257 782             response = request.invoke_exception_view()
MM 783             self.assertEqual(response.app_iter, [b'bar'])
3b886e 784             self.assertTrue(request.exception is ex)
MM 785             self.assertTrue(request.exc_info[1] is ex)
d52257 786             self.assertTrue(request.response is orig_response)
MM 787         else: # pragma: no cover
788             self.fail()
789
790     def test_it_supports_alternate_requests(self):
791         def exc_view(exc, request):
792             self.assertTrue(request is other_req)
dda9fa 793             from pyramid.threadlocal import get_current_request
BJR 794             self.assertTrue(get_current_request() is other_req)
d52257 795             return DummyResponse(b'foo')
MM 796         self.config.add_view(exc_view, context=RuntimeError)
797         request = self._makeOne()
798         other_req = self._makeOne()
799         try:
800             raise RuntimeError
801         except RuntimeError:
802             response = request.invoke_exception_view(request=other_req)
803             self.assertEqual(response.app_iter, [b'foo'])
804         else: # pragma: no cover
805             self.fail()
806
807     def test_it_supports_threadlocal_registry(self):
808         def exc_view(exc, request):
809             return DummyResponse(b'foo')
810         self.config.add_view(exc_view, context=RuntimeError)
811         request = self._makeOne()
812         del request.registry
813         try:
814             raise RuntimeError
815         except RuntimeError:
816             response = request.invoke_exception_view()
817             self.assertEqual(response.app_iter, [b'foo'])
818         else: # pragma: no cover
819             self.fail()
820
dda9fa 821     def test_it_raises_if_no_registry(self):
BJR 822         request = self._makeOne()
823         del request.registry
824         from pyramid.threadlocal import manager
825         manager.push({'registry': None, 'request': request})
826         try:
827             raise RuntimeError
828         except RuntimeError:
829             try:
830                 request.invoke_exception_view()
831             except RuntimeError as e:
832                 self.assertEqual(e.args[0], "Unable to retrieve registry")
833         else: # pragma: no cover
834             self.fail()
835         finally:
836             manager.pop()
837
d52257 838     def test_it_supports_alternate_exc_info(self):
MM 839         def exc_view(exc, request):
840             self.assertTrue(request.exc_info is exc_info)
841             return DummyResponse(b'foo')
842         self.config.add_view(exc_view, context=RuntimeError)
843         request = self._makeOne()
844         try:
845             raise RuntimeError
846         except RuntimeError:
847             exc_info = sys.exc_info()
848         response = request.invoke_exception_view(exc_info=exc_info)
849         self.assertEqual(response.app_iter, [b'foo'])
850
851     def test_it_rejects_secured_view(self):
852         from pyramid.exceptions import Forbidden
853         def exc_view(exc, request): pass
854         self.config.testing_securitypolicy(permissive=False)
855         self.config.add_view(exc_view, context=RuntimeError, permission='view')
856         request = self._makeOne()
857         try:
858             raise RuntimeError
859         except RuntimeError:
860             self.assertRaises(Forbidden, request.invoke_exception_view)
861         else: # pragma: no cover
862             self.fail()
863
864     def test_it_allows_secured_view(self):
865         def exc_view(exc, request):
866             return DummyResponse(b'foo')
867         self.config.testing_securitypolicy(permissive=False)
868         self.config.add_view(exc_view, context=RuntimeError, permission='view')
869         request = self._makeOne()
870         try:
871             raise RuntimeError
872         except RuntimeError:
873             response = request.invoke_exception_view(secure=False)
874             self.assertEqual(response.app_iter, [b'foo'])
875         else: # pragma: no cover
876             self.fail()
877
e045cf 878     def test_it_raises_if_not_found(self):
MM 879         from pyramid.httpexceptions import HTTPNotFound
880         request = self._makeOne()
881         dummy_exc = RuntimeError()
882         try:
883             raise dummy_exc
884         except RuntimeError:
885             self.assertRaises(HTTPNotFound, request.invoke_exception_view)
886         else: # pragma: no cover
887             self.fail()
888
6f2f04 889     def test_it_reraises_if_not_found(self):
MM 890         request = self._makeOne()
891         dummy_exc = RuntimeError()
892         try:
893             raise dummy_exc
894         except RuntimeError:
895             self.assertRaises(
896                 RuntimeError,
897                 lambda: request.invoke_exception_view(reraise=True))
898         else: # pragma: no cover
899             self.fail()
900
e045cf 901     def test_it_raises_predicate_mismatch(self):
MM 902         from pyramid.exceptions import PredicateMismatch
903         def exc_view(exc, request): pass
904         self.config.add_view(exc_view, context=Exception, request_method='POST')
905         request = self._makeOne()
906         request.method = 'GET'
907         dummy_exc = RuntimeError()
908         try:
909             raise dummy_exc
910         except RuntimeError:
911             self.assertRaises(PredicateMismatch, request.invoke_exception_view)
912         else: # pragma: no cover
913             self.fail()
914
6f2f04 915     def test_it_reraises_after_predicate_mismatch(self):
MM 916         def exc_view(exc, request): pass
917         self.config.add_view(exc_view, context=Exception, request_method='POST')
918         request = self._makeOne()
919         request.method = 'GET'
920         dummy_exc = RuntimeError()
921         try:
922             raise dummy_exc
923         except RuntimeError:
924             self.assertRaises(
925                 RuntimeError,
926                 lambda: request.invoke_exception_view(reraise=True))
927         else: # pragma: no cover
928             self.fail()
929
d96ff9 930 class ExceptionResponse(Exception):
CM 931     status = '404 Not Found'
932     app_iter = ['Not Found']
933     headerlist = []
e06153 934
7e2c6c 935 class DummyContext:
CM 936     pass
17ce57 937
7e2c6c 938 def make_view(response):
CM 939     def view(context, request):
940         return response
941     return view
942
d96ff9 943 class DummyRequest:
d3e48e 944     exception = None
849196 945     request_iface = IRequest
d96ff9 946
56d0fe 947     def __init__(self, environ=None):
CM 948         if environ is None:
949             environ = {}
950         self.environ = environ
951         
d868ff 952 from pyramid.interfaces import IResponse
CM 953
3b7334 954 @implementer(IResponse)
d868ff 955 class DummyResponse(object):
7e2c6c 956     headerlist = ()
d868ff 957     app_iter = ()
CM 958     status = '200 OK'
959     environ = None
d66bfb 960     def __init__(self, body=None):
CM 961         if body is None:
962             self.app_iter = ()
963         else:
964             self.app_iter = [body]
7df825 965
1c0210 966 from zope.interface import Interface
CM 967 class IContext(Interface):
968     pass
e6fa66 969
CM 970 class DummyVenusianInfo(object):
971     scope = 'notaclass'
b60bdb 972     module = sys.modules['pyramid.tests']
14b78b 973     codeinfo = 'codeinfo'
e6fa66 974
CM 975 class DummyVenusian(object):
976     def __init__(self, info=None):
977         if info is None:
978             info = DummyVenusianInfo()
979         self.info = info
980         self.attachments = []
981
a8d71c 982     def attach(self, wrapped, callback, category=None, depth=1):
e6fa66 983         self.attachments.append((wrapped, callback, category))
a8d71c 984         self.depth = depth
e6fa66 985         return self.info
CM 986
95c9f6 987 class DummyRegistry(object):
CM 988     pass
989
e6fa66 990 class DummyConfig(object):
CM 991     def __init__(self):
992         self.settings = []
95c9f6 993         self.registry = DummyRegistry()
e6fa66 994
CM 995     def add_view(self, **kw):
996         self.settings.append(kw)
997
93c94b 998     add_notfound_view = add_forbidden_view = add_exception_view = add_view
0db4a1 999
b2c4e0 1000     def with_package(self, pkg):
CM 1001         self.pkg = pkg
1002         return self
1003
e6fa66 1004 class DummyVenusianContext(object):
CM 1005     def __init__(self):
1006         self.config = DummyConfig()
1007         
2ad827 1008 def call_venusian(venusian, context=None):
CM 1009     if context is None:
1010         context = DummyVenusianContext()
e6fa66 1011     for wrapped, callback, category in venusian.attachments:
CM 1012         callback(context, None, None)
b2c4e0 1013     return context.config
e6fa66 1014