tosh
2017-06-27 2c5f77d7776ae9b221d6e5af11c1710335d65bd3
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
2c5f77 569     def test_call_withoutcategory(self):
T 570         decorator = self._makeOne()
571         venusian = DummyVenusian()
572         decorator.venusian = venusian
573         def foo(): pass
574         decorator(foo)
575         attachments = venusian.attachments
576         category = attachments[0][2]
577         self.assertEqual(category, 'pyramid')
578
579     def test_call_withcategory(self):
580         decorator = self._makeOne(_category='not_pyramid')
581         venusian = DummyVenusian()
582         decorator.venusian = venusian
583         def foo(): pass
584         decorator(foo)
585         attachments = venusian.attachments
586         category = attachments[0][2]
587         self.assertEqual(category, 'not_pyramid')
588
d96ff9 589 class Test_append_slash_notfound_view(BaseTest, unittest.TestCase):
3a61a3 590     def _callFUT(self, context, request):
b60bdb 591         from pyramid.view import append_slash_notfound_view
3a61a3 592         return append_slash_notfound_view(context, request)
CM 593
1c0210 594     def _registerMapper(self, reg, match=True):
b60bdb 595         from pyramid.interfaces import IRoutesMapper
3a61a3 596         class DummyRoute(object):
CM 597             def __init__(self, val):
598                 self.val = val
599             def match(self, path):
600                 return self.val
601         class DummyMapper(object):
602             def __init__(self):
603                 self.routelist = [ DummyRoute(match) ]
06dad2 604             def get_routes(self):
CM 605                 return self.routelist
3a61a3 606         mapper = DummyMapper()
1c0210 607         reg.registerUtility(mapper, IRoutesMapper)
3a61a3 608         return mapper
CM 609
30e64f 610     def test_context_is_not_exception(self):
CM 611         request = self._makeRequest(PATH_INFO='/abc')
d96ff9 612         request.exception = ExceptionResponse()
30e64f 613         context = DummyContext()
CM 614         response = self._callFUT(context, request)
615         self.assertEqual(response.status, '404 Not Found')
d96ff9 616         self.assertEqual(response.app_iter, ['Not Found'])
30e64f 617
3a61a3 618     def test_no_mapper(self):
1c0210 619         request = self._makeRequest(PATH_INFO='/abc')
d96ff9 620         context = ExceptionResponse()
3a61a3 621         response = self._callFUT(context, request)
CM 622         self.assertEqual(response.status, '404 Not Found')
623
624     def test_no_path(self):
1c0210 625         request = self._makeRequest()
d96ff9 626         context = ExceptionResponse()
1c0210 627         self._registerMapper(request.registry, True)
3a61a3 628         response = self._callFUT(context, request)
CM 629         self.assertEqual(response.status, '404 Not Found')
630
631     def test_mapper_path_already_slash_ending(self):
1c0210 632         request = self._makeRequest(PATH_INFO='/abc/')
d96ff9 633         context = ExceptionResponse()
1c0210 634         self._registerMapper(request.registry, True)
3a61a3 635         response = self._callFUT(context, request)
CM 636         self.assertEqual(response.status, '404 Not Found')
637
d92958 638     def test_no_route_matches(self):
CM 639         request = self._makeRequest(PATH_INFO='/abc')
640         context = ExceptionResponse()
641         mapper = self._registerMapper(request.registry, True)
642         mapper.routelist[0].val = None
643         response = self._callFUT(context, request)
644         self.assertEqual(response.status, '404 Not Found')
645
3a61a3 646     def test_matches(self):
1c0210 647         request = self._makeRequest(PATH_INFO='/abc')
d96ff9 648         context = ExceptionResponse()
1c0210 649         self._registerMapper(request.registry, True)
3a61a3 650         response = self._callFUT(context, request)
CM 651         self.assertEqual(response.status, '302 Found')
652         self.assertEqual(response.location, '/abc/')
653
b596e1 654     def test_matches_with_script_name(self):
CM 655         request = self._makeRequest(PATH_INFO='/abc', SCRIPT_NAME='/foo')
656         context = ExceptionResponse()
657         self._registerMapper(request.registry, True)
658         response = self._callFUT(context, request)
659         self.assertEqual(response.status, '302 Found')
660         self.assertEqual(response.location, '/foo/abc/')
661
6ab71c 662     def test_with_query_string(self):
CM 663         request = self._makeRequest(PATH_INFO='/abc', QUERY_STRING='a=1&b=2')
664         context = ExceptionResponse()
665         self._registerMapper(request.registry, True)
666         response = self._callFUT(context, request)
667         self.assertEqual(response.status, '302 Found')
668         self.assertEqual(response.location, '/abc/?a=1&b=2')
669
d96ff9 670 class TestAppendSlashNotFoundViewFactory(BaseTest, unittest.TestCase):
CM 671     def _makeOne(self, notfound_view):
b60bdb 672         from pyramid.view import AppendSlashNotFoundViewFactory
d96ff9 673         return AppendSlashNotFoundViewFactory(notfound_view)
CM 674     
675     def test_custom_notfound_view(self):
676         request = self._makeRequest(PATH_INFO='/abc')
677         context = ExceptionResponse()
678         def custom_notfound(context, request):
679             return 'OK'
680         view = self._makeOne(custom_notfound)
681         response = view(context, request)
682         self.assertEqual(response, 'OK')
683
684 class Test_default_exceptionresponse_view(unittest.TestCase):
685     def _callFUT(self, context, request):
b60bdb 686         from pyramid.view import default_exceptionresponse_view
d96ff9 687         return default_exceptionresponse_view(context, request)
CM 688
689     def test_is_exception(self):
690         context = Exception()
691         result = self._callFUT(context, None)
a1d395 692         self.assertTrue(result is context)
d96ff9 693
b04bd5 694     def test_is_not_exception_context_is_false_still_chose(self):
d92958 695         request = DummyRequest()
CM 696         request.exception = 0
697         result = self._callFUT(None, request)
a1d395 698         self.assertTrue(result is None)
d92958 699
d96ff9 700     def test_is_not_exception_no_request_exception(self):
CM 701         context = object()
702         request = DummyRequest()
d92958 703         request.exception = None
d96ff9 704         result = self._callFUT(context, request)
a1d395 705         self.assertTrue(result is context)
d96ff9 706
CM 707     def test_is_not_exception_request_exception(self):
708         context = object()
709         request = DummyRequest()
710         request.exception = 'abc'
711         result = self._callFUT(context, request)
712         self.assertEqual(result, 'abc')
713
914abe 714 class Test_view_defaults(unittest.TestCase):
CM 715     def test_it(self):
716         from pyramid.view import view_defaults
717         @view_defaults(route_name='abc', renderer='def')
718         class Foo(object): pass
719         self.assertEqual(Foo.__view_defaults__['route_name'],'abc')
720         self.assertEqual(Foo.__view_defaults__['renderer'],'def')
721
4375cf 722     def test_it_inheritance_not_overridden(self):
914abe 723         from pyramid.view import view_defaults
CM 724         @view_defaults(route_name='abc', renderer='def')
725         class Foo(object): pass
726         class Bar(Foo): pass
727         self.assertEqual(Bar.__view_defaults__['route_name'],'abc')
728         self.assertEqual(Bar.__view_defaults__['renderer'],'def')
729
4375cf 730     def test_it_inheritance_overriden(self):
CM 731         from pyramid.view import view_defaults
732         @view_defaults(route_name='abc', renderer='def')
733         class Foo(object): pass
734         @view_defaults(route_name='ghi')
735         class Bar(Foo): pass
736         self.assertEqual(Bar.__view_defaults__['route_name'],'ghi')
4c29ef 737         self.assertFalse('renderer' in Bar.__view_defaults__)
4375cf 738
CM 739     def test_it_inheritance_overriden_empty(self):
740         from pyramid.view import view_defaults
741         @view_defaults(route_name='abc', renderer='def')
742         class Foo(object): pass
743         @view_defaults()
744         class Bar(Foo): pass
4c29ef 745         self.assertEqual(Bar.__view_defaults__, {})
4375cf 746
d52257 747 class TestViewMethodsMixin(unittest.TestCase):
MM 748     def setUp(self):
749         self.config = testing.setUp()
750
751     def tearDown(self):
752         testing.tearDown()
753
754     def _makeOne(self, environ=None):
755         from pyramid.decorator import reify
756         from pyramid.view import ViewMethodsMixin
757         if environ is None:
758             environ = {}
759         class Request(ViewMethodsMixin):
760             def __init__(self, environ):
761                 self.environ = environ
762
763             @reify
764             def response(self):
765                 return DummyResponse()
766         request = Request(environ)
767         request.registry = self.config.registry
768         return request
769
770     def test_it(self):
771         def exc_view(exc, request):
772             self.assertTrue(exc is dummy_exc)
773             self.assertTrue(request.exception is dummy_exc)
774             return DummyResponse(b'foo')
775         self.config.add_view(exc_view, context=RuntimeError)
776         request = self._makeOne()
777         dummy_exc = RuntimeError()
778         try:
779             raise dummy_exc
780         except RuntimeError:
781             response = request.invoke_exception_view()
782             self.assertEqual(response.app_iter, [b'foo'])
783         else: # pragma: no cover
784             self.fail()
785
786     def test_it_hides_attrs(self):
787         def exc_view(exc, request):
788             self.assertTrue(exc is not orig_exc)
789             self.assertTrue(request.exception is not orig_exc)
790             self.assertTrue(request.exc_info is not orig_exc_info)
791             self.assertTrue(request.response is not orig_response)
792             request.response.app_iter = [b'bar']
793             return request.response
794         self.config.add_view(exc_view, context=RuntimeError)
795         request = self._makeOne()
796         orig_exc = request.exception = DummyContext()
797         orig_exc_info = request.exc_info = DummyContext()
798         orig_response = request.response = DummyResponse(b'foo')
799         try:
800             raise RuntimeError
3b886e 801         except RuntimeError as ex:
d52257 802             response = request.invoke_exception_view()
MM 803             self.assertEqual(response.app_iter, [b'bar'])
3b886e 804             self.assertTrue(request.exception is ex)
MM 805             self.assertTrue(request.exc_info[1] is ex)
d52257 806             self.assertTrue(request.response is orig_response)
MM 807         else: # pragma: no cover
808             self.fail()
809
810     def test_it_supports_alternate_requests(self):
811         def exc_view(exc, request):
812             self.assertTrue(request is other_req)
dda9fa 813             from pyramid.threadlocal import get_current_request
BJR 814             self.assertTrue(get_current_request() is other_req)
d52257 815             return DummyResponse(b'foo')
MM 816         self.config.add_view(exc_view, context=RuntimeError)
817         request = self._makeOne()
818         other_req = self._makeOne()
819         try:
820             raise RuntimeError
821         except RuntimeError:
822             response = request.invoke_exception_view(request=other_req)
823             self.assertEqual(response.app_iter, [b'foo'])
824         else: # pragma: no cover
825             self.fail()
826
827     def test_it_supports_threadlocal_registry(self):
828         def exc_view(exc, request):
829             return DummyResponse(b'foo')
830         self.config.add_view(exc_view, context=RuntimeError)
831         request = self._makeOne()
832         del request.registry
833         try:
834             raise RuntimeError
835         except RuntimeError:
836             response = request.invoke_exception_view()
837             self.assertEqual(response.app_iter, [b'foo'])
838         else: # pragma: no cover
839             self.fail()
840
dda9fa 841     def test_it_raises_if_no_registry(self):
BJR 842         request = self._makeOne()
843         del request.registry
844         from pyramid.threadlocal import manager
845         manager.push({'registry': None, 'request': request})
846         try:
847             raise RuntimeError
848         except RuntimeError:
849             try:
850                 request.invoke_exception_view()
851             except RuntimeError as e:
852                 self.assertEqual(e.args[0], "Unable to retrieve registry")
853         else: # pragma: no cover
854             self.fail()
855         finally:
856             manager.pop()
857
d52257 858     def test_it_supports_alternate_exc_info(self):
MM 859         def exc_view(exc, request):
860             self.assertTrue(request.exc_info is exc_info)
861             return DummyResponse(b'foo')
862         self.config.add_view(exc_view, context=RuntimeError)
863         request = self._makeOne()
864         try:
865             raise RuntimeError
866         except RuntimeError:
867             exc_info = sys.exc_info()
868         response = request.invoke_exception_view(exc_info=exc_info)
869         self.assertEqual(response.app_iter, [b'foo'])
870
871     def test_it_rejects_secured_view(self):
872         from pyramid.exceptions import Forbidden
873         def exc_view(exc, request): pass
874         self.config.testing_securitypolicy(permissive=False)
875         self.config.add_view(exc_view, context=RuntimeError, permission='view')
876         request = self._makeOne()
877         try:
878             raise RuntimeError
879         except RuntimeError:
880             self.assertRaises(Forbidden, request.invoke_exception_view)
881         else: # pragma: no cover
882             self.fail()
883
884     def test_it_allows_secured_view(self):
885         def exc_view(exc, request):
886             return DummyResponse(b'foo')
887         self.config.testing_securitypolicy(permissive=False)
888         self.config.add_view(exc_view, context=RuntimeError, permission='view')
889         request = self._makeOne()
890         try:
891             raise RuntimeError
892         except RuntimeError:
893             response = request.invoke_exception_view(secure=False)
894             self.assertEqual(response.app_iter, [b'foo'])
895         else: # pragma: no cover
896             self.fail()
897
e045cf 898     def test_it_raises_if_not_found(self):
MM 899         from pyramid.httpexceptions import HTTPNotFound
900         request = self._makeOne()
901         dummy_exc = RuntimeError()
902         try:
903             raise dummy_exc
904         except RuntimeError:
905             self.assertRaises(HTTPNotFound, request.invoke_exception_view)
906         else: # pragma: no cover
907             self.fail()
908
6f2f04 909     def test_it_reraises_if_not_found(self):
MM 910         request = self._makeOne()
911         dummy_exc = RuntimeError()
912         try:
913             raise dummy_exc
914         except RuntimeError:
915             self.assertRaises(
916                 RuntimeError,
917                 lambda: request.invoke_exception_view(reraise=True))
918         else: # pragma: no cover
919             self.fail()
920
e045cf 921     def test_it_raises_predicate_mismatch(self):
MM 922         from pyramid.exceptions import PredicateMismatch
923         def exc_view(exc, request): pass
924         self.config.add_view(exc_view, context=Exception, request_method='POST')
925         request = self._makeOne()
926         request.method = 'GET'
927         dummy_exc = RuntimeError()
928         try:
929             raise dummy_exc
930         except RuntimeError:
931             self.assertRaises(PredicateMismatch, request.invoke_exception_view)
932         else: # pragma: no cover
933             self.fail()
934
6f2f04 935     def test_it_reraises_after_predicate_mismatch(self):
MM 936         def exc_view(exc, request): pass
937         self.config.add_view(exc_view, context=Exception, request_method='POST')
938         request = self._makeOne()
939         request.method = 'GET'
940         dummy_exc = RuntimeError()
941         try:
942             raise dummy_exc
943         except RuntimeError:
944             self.assertRaises(
945                 RuntimeError,
946                 lambda: request.invoke_exception_view(reraise=True))
947         else: # pragma: no cover
948             self.fail()
949
d96ff9 950 class ExceptionResponse(Exception):
CM 951     status = '404 Not Found'
952     app_iter = ['Not Found']
953     headerlist = []
e06153 954
7e2c6c 955 class DummyContext:
CM 956     pass
17ce57 957
7e2c6c 958 def make_view(response):
CM 959     def view(context, request):
960         return response
961     return view
962
d96ff9 963 class DummyRequest:
d3e48e 964     exception = None
849196 965     request_iface = IRequest
d96ff9 966
56d0fe 967     def __init__(self, environ=None):
CM 968         if environ is None:
969             environ = {}
970         self.environ = environ
971         
d868ff 972 from pyramid.interfaces import IResponse
CM 973
3b7334 974 @implementer(IResponse)
d868ff 975 class DummyResponse(object):
7e2c6c 976     headerlist = ()
d868ff 977     app_iter = ()
CM 978     status = '200 OK'
979     environ = None
d66bfb 980     def __init__(self, body=None):
CM 981         if body is None:
982             self.app_iter = ()
983         else:
984             self.app_iter = [body]
7df825 985
1c0210 986 from zope.interface import Interface
CM 987 class IContext(Interface):
988     pass
e6fa66 989
CM 990 class DummyVenusianInfo(object):
991     scope = 'notaclass'
b60bdb 992     module = sys.modules['pyramid.tests']
14b78b 993     codeinfo = 'codeinfo'
e6fa66 994
CM 995 class DummyVenusian(object):
996     def __init__(self, info=None):
997         if info is None:
998             info = DummyVenusianInfo()
999         self.info = info
1000         self.attachments = []
1001
a8d71c 1002     def attach(self, wrapped, callback, category=None, depth=1):
e6fa66 1003         self.attachments.append((wrapped, callback, category))
a8d71c 1004         self.depth = depth
e6fa66 1005         return self.info
CM 1006
95c9f6 1007 class DummyRegistry(object):
CM 1008     pass
1009
e6fa66 1010 class DummyConfig(object):
CM 1011     def __init__(self):
1012         self.settings = []
95c9f6 1013         self.registry = DummyRegistry()
e6fa66 1014
CM 1015     def add_view(self, **kw):
1016         self.settings.append(kw)
1017
93c94b 1018     add_notfound_view = add_forbidden_view = add_exception_view = add_view
0db4a1 1019
b2c4e0 1020     def with_package(self, pkg):
CM 1021         self.pkg = pkg
1022         return self
1023
e6fa66 1024 class DummyVenusianContext(object):
CM 1025     def __init__(self):
1026         self.config = DummyConfig()
1027         
2ad827 1028 def call_venusian(venusian, context=None):
CM 1029     if context is None:
1030         context = DummyVenusianContext()
e6fa66 1031     for wrapped, callback, category in venusian.attachments:
CM 1032         callback(context, None, None)
b2c4e0 1033     return context.config
e6fa66 1034