1import unittest 2 3from pyramid import testing 4 5class TestRouter(unittest.TestCase): 6 def setUp(self): 7 self.config = testing.setUp() 8 self.registry = self.config.registry 9 10 def tearDown(self): 11 testing.tearDown() 12 13 def _registerRouteRequest(self, name): 14 from pyramid.interfaces import IRouteRequest 15 from pyramid.request import route_request_iface 16 iface = route_request_iface(name) 17 self.registry.registerUtility(iface, IRouteRequest, name=name) 18 return iface 19 20 def _connectRoute(self, name, path, factory=None): 21 from pyramid.interfaces import IRoutesMapper 22 from pyramid.urldispatch import RoutesMapper 23 mapper = self.registry.queryUtility(IRoutesMapper) 24 if mapper is None: 25 mapper = RoutesMapper() 26 self.registry.registerUtility(mapper, IRoutesMapper) 27 return mapper.connect(name, path, factory) 28 29 def _registerLogger(self): 30 from pyramid.interfaces import IDebugLogger 31 logger = DummyLogger() 32 self.registry.registerUtility(logger, IDebugLogger) 33 return logger 34 35 def _registerSettings(self, **kw): 36 settings = {'debug_authorization':False, 37 'debug_notfound':False, 38 'debug_routematch':False} 39 settings.update(kw) 40 self.registry.settings = settings 41 42 def _registerTraverserFactory(self, context, view_name='', subpath=None, 43 traversed=None, virtual_root=None, 44 virtual_root_path=None, raise_error=None, 45 **kw): 46 from pyramid.interfaces import ITraverser 47 48 if virtual_root is None: 49 virtual_root = context 50 if subpath is None: 51 subpath = [] 52 if traversed is None: 53 traversed = [] 54 if virtual_root_path is None: 55 virtual_root_path = [] 56 57 class DummyTraverserFactory: 58 def __init__(self, root): 59 self.root = root 60 61 def __call__(self, request): 62 if raise_error: 63 raise raise_error 64 values = {'root':self.root, 65 'context':context, 66 'view_name':view_name, 67 'subpath':subpath, 68 'traversed':traversed, 69 'virtual_root':virtual_root, 70 'virtual_root_path':virtual_root_path} 71 kw.update(values) 72 return kw 73 74 self.registry.registerAdapter(DummyTraverserFactory, (None,), 75 ITraverser, name='') 76 77 def _registerView(self, app, name, classifier, req_iface, ctx_iface): 78 from pyramid.interfaces import IView 79 self.registry.registerAdapter( 80 app, (classifier, req_iface, ctx_iface), IView, name) 81 82 def _registerEventListener(self, iface): 83 L = [] 84 def listener(event): 85 L.append(event) 86 self.registry.registerHandler(listener, (iface,)) 87 return L 88 89 def _registerRootFactory(self, val): 90 rootfactory = DummyRootFactory(val) 91 from pyramid.interfaces import IRootFactory 92 self.registry.registerUtility(rootfactory, IRootFactory) 93 return rootfactory 94 95 def _getTargetClass(self): 96 from pyramid.router import Router 97 return Router 98 99 def _makeOne(self): 100 klass = self._getTargetClass() 101 return klass(self.registry) 102 103 def _makeEnviron(self, **extras): 104 environ = { 105 'wsgi.url_scheme':'http', 106 'SERVER_NAME':'localhost', 107 'SERVER_PORT':'8080', 108 'REQUEST_METHOD':'GET', 109 'PATH_INFO':'/', 110 } 111 environ.update(extras) 112 return environ 113 114 def test_ctor_registry_has_no_settings(self): 115 self.registry.settings = None 116 router = self._makeOne() 117 self.assertEqual(router.debug_notfound, False) 118 self.assertEqual(router.debug_routematch, False) 119 self.assertFalse('debug_notfound' in router.__dict__) 120 self.assertFalse('debug_routematch' in router.__dict__) 121 122 def test_root_policy(self): 123 context = DummyContext() 124 self._registerTraverserFactory(context) 125 rootfactory = self._registerRootFactory('abc') 126 router = self._makeOne() 127 self.assertEqual(router.root_policy, rootfactory) 128 129 def test_request_factory(self): 130 from pyramid.interfaces import IRequestFactory 131 class DummyRequestFactory(object): 132 pass 133 self.registry.registerUtility(DummyRequestFactory, IRequestFactory) 134 router = self._makeOne() 135 self.assertEqual(router.request_factory, DummyRequestFactory) 136 137 def test_tween_factories(self): 138 from pyramid.interfaces import ITweens 139 from pyramid.config.tweens import Tweens 140 from pyramid.response import Response 141 from pyramid.interfaces import IViewClassifier 142 from pyramid.interfaces import IResponse 143 tweens = Tweens() 144 self.registry.registerUtility(tweens, ITweens) 145 L = [] 146 def tween_factory1(handler, registry): 147 L.append((handler, registry)) 148 def wrapper(request): 149 request.environ['handled'].append('one') 150 return handler(request) 151 wrapper.name = 'one' 152 wrapper.child = handler 153 return wrapper 154 def tween_factory2(handler, registry): 155 L.append((handler, registry)) 156 def wrapper(request): 157 request.environ['handled'] = ['two'] 158 return handler(request) 159 wrapper.name = 'two' 160 wrapper.child = handler 161 return wrapper 162 tweens.add_implicit('one', tween_factory1) 163 tweens.add_implicit('two', tween_factory2) 164 router = self._makeOne() 165 self.assertEqual(router.handle_request.name, 'two') 166 self.assertEqual(router.handle_request.child.name, 'one') 167 self.assertEqual(router.handle_request.child.child.__name__, 168 'handle_request') 169 context = DummyContext() 170 self._registerTraverserFactory(context) 171 environ = self._makeEnviron() 172 view = DummyView('abc') 173 self._registerView(self.config.derive_view(view), '', 174 IViewClassifier, None, None) 175 start_response = DummyStartResponse() 176 def make_response(s): 177 return Response(s) 178 router.registry.registerAdapter(make_response, (str,), IResponse) 179 app_iter = router(environ, start_response) 180 self.assertEqual(app_iter, [b'abc']) 181 self.assertEqual(start_response.status, '200 OK') 182 self.assertEqual(environ['handled'], ['two', 'one']) 183 184 def test_call_traverser_default(self): 185 from pyramid.httpexceptions import HTTPNotFound 186 environ = self._makeEnviron() 187 logger = self._registerLogger() 188 router = self._makeOne() 189 start_response = DummyStartResponse() 190 why = exc_raised(HTTPNotFound, router, environ, start_response) 191 self.assertTrue('/' in why.args[0], why) 192 self.assertFalse('debug_notfound' in why.args[0]) 193 self.assertEqual(len(logger.messages), 0) 194 195 def test_traverser_raises_notfound_class(self): 196 from pyramid.httpexceptions import HTTPNotFound 197 environ = self._makeEnviron() 198 context = DummyContext() 199 self._registerTraverserFactory(context, raise_error=HTTPNotFound) 200 router = self._makeOne() 201 start_response = DummyStartResponse() 202 self.assertRaises(HTTPNotFound, router, environ, start_response) 203 204 def test_traverser_raises_notfound_instance(self): 205 from pyramid.httpexceptions import HTTPNotFound 206 environ = self._makeEnviron() 207 context = DummyContext() 208 self._registerTraverserFactory(context, raise_error=HTTPNotFound('foo')) 209 router = self._makeOne() 210 start_response = DummyStartResponse() 211 why = exc_raised(HTTPNotFound, router, environ, start_response) 212 self.assertTrue('foo' in why.args[0], why) 213 214 def test_traverser_raises_forbidden_class(self): 215 from pyramid.httpexceptions import HTTPForbidden 216 environ = self._makeEnviron() 217 context = DummyContext() 218 self._registerTraverserFactory(context, raise_error=HTTPForbidden) 219 router = self._makeOne() 220 start_response = DummyStartResponse() 221 self.assertRaises(HTTPForbidden, router, environ, start_response) 222 223 def test_traverser_raises_forbidden_instance(self): 224 from pyramid.httpexceptions import HTTPForbidden 225 environ = self._makeEnviron() 226 context = DummyContext() 227 self._registerTraverserFactory(context, 228 raise_error=HTTPForbidden('foo')) 229 router = self._makeOne() 230 start_response = DummyStartResponse() 231 why = exc_raised(HTTPForbidden, router, environ, start_response) 232 self.assertTrue('foo' in why.args[0], why) 233 234 def test_call_no_view_registered_no_isettings(self): 235 from pyramid.httpexceptions import HTTPNotFound 236 environ = self._makeEnviron() 237 context = DummyContext() 238 self._registerTraverserFactory(context) 239 logger = self._registerLogger() 240 router = self._makeOne() 241 start_response = DummyStartResponse() 242 why = exc_raised(HTTPNotFound, router, environ, start_response) 243 self.assertTrue('/' in why.args[0], why) 244 self.assertFalse('debug_notfound' in why.args[0]) 245 self.assertEqual(len(logger.messages), 0) 246 247 def test_call_no_view_registered_debug_notfound_false(self): 248 from pyramid.httpexceptions import HTTPNotFound 249 environ = self._makeEnviron() 250 context = DummyContext() 251 self._registerTraverserFactory(context) 252 logger = self._registerLogger() 253 self._registerSettings(debug_notfound=False) 254 router = self._makeOne() 255 start_response = DummyStartResponse() 256 why = exc_raised(HTTPNotFound, router, environ, start_response) 257 self.assertTrue('/' in why.args[0], why) 258 self.assertFalse('debug_notfound' in why.args[0]) 259 self.assertEqual(len(logger.messages), 0) 260 261 def test_call_no_view_registered_debug_notfound_true(self): 262 from pyramid.httpexceptions import HTTPNotFound 263 environ = self._makeEnviron() 264 context = DummyContext() 265 self._registerTraverserFactory(context) 266 self._registerSettings(debug_notfound=True) 267 logger = self._registerLogger() 268 router = self._makeOne() 269 start_response = DummyStartResponse() 270 why = exc_raised(HTTPNotFound, router, environ, start_response) 271 self.assertTrue( 272 "debug_notfound of url http://localhost:8080/; " in why.args[0]) 273 self.assertTrue("view_name: '', subpath: []" in why.args[0]) 274 self.assertTrue('http://localhost:8080' in why.args[0], why) 275 276 self.assertEqual(len(logger.messages), 1) 277 message = logger.messages[0] 278 self.assertTrue('of url http://localhost:8080' in message) 279 self.assertTrue("path_info: " in message) 280 self.assertTrue('DummyContext' in message) 281 self.assertTrue("view_name: ''" in message) 282 self.assertTrue("subpath: []" in message) 283 284 def test_call_view_returns_non_iresponse(self): 285 from pyramid.interfaces import IViewClassifier 286 context = DummyContext() 287 self._registerTraverserFactory(context) 288 environ = self._makeEnviron() 289 view = DummyView('abc') 290 self._registerView(self.config.derive_view(view), '', IViewClassifier, 291 None, None) 292 router = self._makeOne() 293 start_response = DummyStartResponse() 294 self.assertRaises(ValueError, router, environ, start_response) 295 296 def test_call_view_returns_adapted_response(self): 297 from pyramid.response import Response 298 from pyramid.interfaces import IViewClassifier 299 from pyramid.interfaces import IResponse 300 context = DummyContext() 301 self._registerTraverserFactory(context) 302 environ = self._makeEnviron() 303 view = DummyView('abc') 304 self._registerView(self.config.derive_view(view), '', 305 IViewClassifier, None, None) 306 router = self._makeOne() 307 start_response = DummyStartResponse() 308 def make_response(s): 309 return Response(s) 310 router.registry.registerAdapter(make_response, (str,), IResponse) 311 app_iter = router(environ, start_response) 312 self.assertEqual(app_iter, [b'abc']) 313 self.assertEqual(start_response.status, '200 OK') 314 315 def test_call_with_request_extensions(self): 316 from pyramid.interfaces import IViewClassifier 317 from pyramid.interfaces import IRequestExtensions 318 from pyramid.interfaces import IRequest 319 from pyramid.request import Request 320 from pyramid.util import InstancePropertyHelper 321 context = DummyContext() 322 self._registerTraverserFactory(context) 323 class Extensions(object): 324 def __init__(self): 325 self.methods = {} 326 self.descriptors = {} 327 extensions = Extensions() 328 ext_method = lambda r: 'bar' 329 name, fn = InstancePropertyHelper.make_property(ext_method, name='foo') 330 extensions.descriptors[name] = fn 331 request = Request.blank('/') 332 request.request_iface = IRequest 333 request.registry = self.registry 334 def request_factory(environ): 335 return request 336 self.registry.registerUtility(extensions, IRequestExtensions) 337 environ = self._makeEnviron() 338 response = DummyResponse() 339 response.app_iter = ['Hello world'] 340 view = DummyView(response) 341 self._registerView(self.config.derive_view(view), '', 342 IViewClassifier, None, None) 343 router = self._makeOne() 344 router.request_factory = request_factory 345 start_response = DummyStartResponse() 346 router(environ, start_response) 347 self.assertEqual(view.request.foo, 'bar') 348 349 def test_call_view_registered_nonspecific_default_path(self): 350 from pyramid.interfaces import IViewClassifier 351 context = DummyContext() 352 self._registerTraverserFactory(context) 353 response = DummyResponse() 354 response.app_iter = ['Hello world'] 355 view = DummyView(response) 356 environ = self._makeEnviron() 357 self._registerView(self.config.derive_view(view), '', 358 IViewClassifier, None, None) 359 self._registerRootFactory(context) 360 router = self._makeOne() 361 start_response = DummyStartResponse() 362 result = router(environ, start_response) 363 self.assertEqual(result, ['Hello world']) 364 self.assertEqual(start_response.headers, ()) 365 self.assertEqual(start_response.status, '200 OK') 366 request = view.request 367 self.assertEqual(request.view_name, '') 368 self.assertEqual(request.subpath, []) 369 self.assertEqual(request.context, context) 370 self.assertEqual(request.root, context) 371 372 def test_call_view_registered_nonspecific_nondefault_path_and_subpath(self): 373 from pyramid.interfaces import IViewClassifier 374 context = DummyContext() 375 self._registerTraverserFactory(context, view_name='foo', 376 subpath=['bar'], 377 traversed=['context']) 378 self._registerRootFactory(context) 379 response = DummyResponse() 380 response.app_iter = ['Hello world'] 381 view = DummyView(response) 382 environ = self._makeEnviron() 383 self._registerView(view, 'foo', IViewClassifier, None, None) 384 router = self._makeOne() 385 start_response = DummyStartResponse() 386 result = router(environ, start_response) 387 self.assertEqual(result, ['Hello world']) 388 self.assertEqual(start_response.headers, ()) 389 self.assertEqual(start_response.status, '200 OK') 390 request = view.request 391 self.assertEqual(request.view_name, 'foo') 392 self.assertEqual(request.subpath, ['bar']) 393 self.assertEqual(request.context, context) 394 self.assertEqual(request.root, context) 395 396 def test_call_view_registered_specific_success(self): 397 from zope.interface import Interface 398 from zope.interface import directlyProvides 399 class IContext(Interface): 400 pass 401 from pyramid.interfaces import IRequest 402 from pyramid.interfaces import IViewClassifier 403 context = DummyContext() 404 directlyProvides(context, IContext) 405 self._registerTraverserFactory(context) 406 self._registerRootFactory(context) 407 response = DummyResponse() 408 response.app_iter = ['Hello world'] 409 view = DummyView(response) 410 environ = self._makeEnviron() 411 self._registerView(view, '', IViewClassifier, IRequest, IContext) 412 router = self._makeOne() 413 start_response = DummyStartResponse() 414 result = router(environ, start_response) 415 self.assertEqual(result, ['Hello world']) 416 self.assertEqual(start_response.headers, ()) 417 self.assertEqual(start_response.status, '200 OK') 418 request = view.request 419 self.assertEqual(request.view_name, '') 420 self.assertEqual(request.subpath, []) 421 self.assertEqual(request.context, context) 422 self.assertEqual(request.root, context) 423 424 def test_call_view_registered_specific_fail(self): 425 from zope.interface import Interface 426 from zope.interface import directlyProvides 427 from pyramid.httpexceptions import HTTPNotFound 428 from pyramid.interfaces import IViewClassifier 429 class IContext(Interface): 430 pass 431 class INotContext(Interface): 432 pass 433 from pyramid.interfaces import IRequest 434 context = DummyContext() 435 directlyProvides(context, INotContext) 436 self._registerTraverserFactory(context, subpath=['']) 437 response = DummyResponse() 438 view = DummyView(response) 439 environ = self._makeEnviron() 440 self._registerView(view, '', IViewClassifier, IRequest, IContext) 441 router = self._makeOne() 442 start_response = DummyStartResponse() 443 self.assertRaises(HTTPNotFound, router, environ, start_response) 444 445 def test_call_view_raises_forbidden(self): 446 from zope.interface import Interface 447 from zope.interface import directlyProvides 448 from pyramid.httpexceptions import HTTPForbidden 449 class IContext(Interface): 450 pass 451 from pyramid.interfaces import IRequest 452 from pyramid.interfaces import IViewClassifier 453 context = DummyContext() 454 directlyProvides(context, IContext) 455 self._registerTraverserFactory(context, subpath=['']) 456 response = DummyResponse() 457 view = DummyView(response, 458 raise_exception=HTTPForbidden("unauthorized")) 459 environ = self._makeEnviron() 460 self._registerView(view, '', IViewClassifier, IRequest, IContext) 461 router = self._makeOne() 462 start_response = DummyStartResponse() 463 why = exc_raised(HTTPForbidden, router, environ, start_response) 464 self.assertEqual(why.args[0], 'unauthorized') 465 466 def test_call_view_raises_notfound(self): 467 from zope.interface import Interface 468 from zope.interface import directlyProvides 469 class IContext(Interface): 470 pass 471 from pyramid.interfaces import IRequest 472 from pyramid.interfaces import IViewClassifier 473 from pyramid.httpexceptions import HTTPNotFound 474 context = DummyContext() 475 directlyProvides(context, IContext) 476 self._registerTraverserFactory(context, subpath=['']) 477 response = DummyResponse() 478 view = DummyView(response, raise_exception=HTTPNotFound("notfound")) 479 environ = self._makeEnviron() 480 self._registerView(view, '', IViewClassifier, IRequest, IContext) 481 router = self._makeOne() 482 start_response = DummyStartResponse() 483 why = exc_raised(HTTPNotFound, router, environ, start_response) 484 self.assertEqual(why.args[0], 'notfound') 485 486 def test_call_view_raises_response_cleared(self): 487 from zope.interface import Interface 488 from zope.interface import directlyProvides 489 from pyramid.interfaces import IExceptionViewClassifier 490 class IContext(Interface): 491 pass 492 from pyramid.interfaces import IRequest 493 from pyramid.interfaces import IViewClassifier 494 context = DummyContext() 495 directlyProvides(context, IContext) 496 self._registerTraverserFactory(context, subpath=['']) 497 def view(context, request): 498 request.response.a = 1 499 raise KeyError 500 def exc_view(context, request): 501 self.assertFalse(hasattr(request.response, 'a')) 502 request.response.body = b'OK' 503 return request.response 504 environ = self._makeEnviron() 505 self._registerView(view, '', IViewClassifier, IRequest, IContext) 506 self._registerView(exc_view, '', IExceptionViewClassifier, 507 IRequest, KeyError) 508 router = self._makeOne() 509 start_response = DummyStartResponse() 510 itera = router(environ, start_response) 511 self.assertEqual(itera, [b'OK']) 512 513 def test_call_request_has_response_callbacks(self): 514 from zope.interface import Interface 515 from zope.interface import directlyProvides 516 class IContext(Interface): 517 pass 518 from pyramid.interfaces import IRequest 519 from pyramid.interfaces import IViewClassifier 520 context = DummyContext() 521 directlyProvides(context, IContext) 522 self._registerTraverserFactory(context, subpath=['']) 523 response = DummyResponse('200 OK') 524 def view(context, request): 525 def callback(request, response): 526 response.called_back = True 527 request.add_response_callback(callback) 528 return response 529 environ = self._makeEnviron() 530 self._registerView(view, '', IViewClassifier, IRequest, IContext) 531 router = self._makeOne() 532 start_response = DummyStartResponse() 533 router(environ, start_response) 534 self.assertEqual(response.called_back, True) 535 536 def test_call_request_has_finished_callbacks_when_view_succeeds(self): 537 from zope.interface import Interface 538 from zope.interface import directlyProvides 539 class IContext(Interface): 540 pass 541 from pyramid.interfaces import IRequest 542 from pyramid.interfaces import IViewClassifier 543 context = DummyContext() 544 directlyProvides(context, IContext) 545 self._registerTraverserFactory(context, subpath=['']) 546 response = DummyResponse('200 OK') 547 def view(context, request): 548 def callback(request): 549 request.environ['called_back'] = True 550 request.add_finished_callback(callback) 551 return response 552 environ = self._makeEnviron() 553 self._registerView(view, '', IViewClassifier, IRequest, IContext) 554 router = self._makeOne() 555 start_response = DummyStartResponse() 556 router(environ, start_response) 557 self.assertEqual(environ['called_back'], True) 558 559 def test_call_request_has_finished_callbacks_when_view_raises(self): 560 from zope.interface import Interface 561 from zope.interface import directlyProvides 562 class IContext(Interface): 563 pass 564 from pyramid.interfaces import IRequest 565 from pyramid.interfaces import IViewClassifier 566 context = DummyContext() 567 directlyProvides(context, IContext) 568 self._registerTraverserFactory(context, subpath=['']) 569 def view(context, request): 570 def callback(request): 571 request.environ['called_back'] = True 572 request.add_finished_callback(callback) 573 raise NotImplementedError 574 environ = self._makeEnviron() 575 self._registerView(view, '', IViewClassifier, IRequest, IContext) 576 router = self._makeOne() 577 start_response = DummyStartResponse() 578 exc_raised(NotImplementedError, router, environ, start_response) 579 self.assertEqual(environ['called_back'], True) 580 581 def test_call_request_factory_raises(self): 582 # making sure finally doesnt barf when a request cannot be created 583 environ = self._makeEnviron() 584 router = self._makeOne() 585 def dummy_request_factory(environ): 586 raise NotImplementedError 587 router.request_factory = dummy_request_factory 588 start_response = DummyStartResponse() 589 exc_raised(NotImplementedError, router, environ, start_response) 590 591 def test_call_eventsends(self): 592 from pyramid.interfaces import INewRequest 593 from pyramid.interfaces import INewResponse 594 from pyramid.interfaces import IBeforeTraversal 595 from pyramid.interfaces import IContextFound 596 from pyramid.interfaces import IViewClassifier 597 context = DummyContext() 598 self._registerTraverserFactory(context) 599 response = DummyResponse() 600 response.app_iter = ['Hello world'] 601 view = DummyView(response) 602 environ = self._makeEnviron() 603 self._registerView(view, '', IViewClassifier, None, None) 604 request_events = self._registerEventListener(INewRequest) 605 beforetraversal_events = self._registerEventListener(IBeforeTraversal) 606 context_found_events = self._registerEventListener(IContextFound) 607 response_events = self._registerEventListener(INewResponse) 608 router = self._makeOne() 609 start_response = DummyStartResponse() 610 result = router(environ, start_response) 611 self.assertEqual(len(request_events), 1) 612 self.assertEqual(request_events[0].request.environ, environ) 613 self.assertEqual(len(beforetraversal_events), 1) 614 self.assertEqual(beforetraversal_events[0].request.environ, environ) 615 self.assertEqual(len(context_found_events), 1) 616 self.assertEqual(context_found_events[0].request.environ, environ) 617 self.assertEqual(context_found_events[0].request.context, context) 618 self.assertEqual(len(response_events), 1) 619 self.assertEqual(response_events[0].response, response) 620 self.assertEqual(response_events[0].request.context, context) 621 self.assertEqual(result, response.app_iter) 622 623 def test_call_newrequest_evllist_exc_can_be_caught_by_exceptionview(self): 624 from pyramid.interfaces import INewRequest 625 from pyramid.interfaces import IExceptionViewClassifier 626 from pyramid.interfaces import IRequest 627 context = DummyContext() 628 self._registerTraverserFactory(context) 629 environ = self._makeEnviron() 630 def listener(event): 631 raise KeyError 632 self.registry.registerHandler(listener, (INewRequest,)) 633 exception_response = DummyResponse() 634 exception_response.app_iter = ["Hello, world"] 635 exception_view = DummyView(exception_response) 636 environ = self._makeEnviron() 637 self._registerView(exception_view, '', IExceptionViewClassifier, 638 IRequest, KeyError) 639 router = self._makeOne() 640 start_response = DummyStartResponse() 641 result = router(environ, start_response) 642 self.assertEqual(result, exception_response.app_iter) 643 644 def test_call_pushes_and_pops_threadlocal_manager(self): 645 from pyramid.interfaces import IViewClassifier 646 context = DummyContext() 647 self._registerTraverserFactory(context) 648 response = DummyResponse() 649 response.app_iter = ['Hello world'] 650 view = DummyView(response) 651 environ = self._makeEnviron() 652 self._registerView(view, '', IViewClassifier, None, None) 653 router = self._makeOne() 654 start_response = DummyStartResponse() 655 router.threadlocal_manager = DummyThreadLocalManager() 656 router(environ, start_response) 657 self.assertEqual(len(router.threadlocal_manager.pushed), 1) 658 self.assertEqual(len(router.threadlocal_manager.popped), 1) 659 660 def test_call_route_matches_and_has_factory(self): 661 from pyramid.interfaces import IViewClassifier 662 logger = self._registerLogger() 663 self._registerSettings(debug_routematch=True) 664 self._registerRouteRequest('foo') 665 root = object() 666 def factory(request): 667 return root 668 route = self._connectRoute('foo', 'archives/:action/:article', factory) 669 route.predicates = [DummyPredicate()] 670 context = DummyContext() 671 self._registerTraverserFactory(context) 672 response = DummyResponse() 673 response.app_iter = ['Hello world'] 674 view = DummyView(response) 675 environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') 676 self._registerView(view, '', IViewClassifier, None, None) 677 self._registerRootFactory(context) 678 router = self._makeOne() 679 start_response = DummyStartResponse() 680 result = router(environ, start_response) 681 self.assertEqual(result, ['Hello world']) 682 self.assertEqual(start_response.headers, ()) 683 self.assertEqual(start_response.status, '200 OK') 684 request = view.request 685 self.assertEqual(request.view_name, '') 686 self.assertEqual(request.subpath, []) 687 self.assertEqual(request.context, context) 688 self.assertEqual(request.root, root) 689 matchdict = {'action':'action1', 'article':'article1'} 690 self.assertEqual(request.matchdict, matchdict) 691 self.assertEqual(request.matched_route.name, 'foo') 692 self.assertEqual(len(logger.messages), 1) 693 self.assertTrue( 694 logger.messages[0].startswith( 695 "route matched for url http://localhost:8080" 696 "/archives/action1/article1; " 697 "route_name: 'foo', " 698 "path_info: ") 699 ) 700 self.assertTrue( 701 "predicates: 'predicate'" in logger.messages[0] 702 ) 703 704 def test_call_route_match_miss_debug_routematch(self): 705 from pyramid.httpexceptions import HTTPNotFound 706 logger = self._registerLogger() 707 self._registerSettings(debug_routematch=True) 708 self._registerRouteRequest('foo') 709 self._connectRoute('foo', 'archives/:action/:article') 710 context = DummyContext() 711 self._registerTraverserFactory(context) 712 environ = self._makeEnviron(PATH_INFO='/wontmatch') 713 self._registerRootFactory(context) 714 router = self._makeOne() 715 start_response = DummyStartResponse() 716 self.assertRaises(HTTPNotFound, router, environ, start_response) 717 718 self.assertEqual(len(logger.messages), 1) 719 self.assertEqual( 720 logger.messages[0], 721 'no route matched for url http://localhost:8080/wontmatch') 722 723 def test_call_route_matches_doesnt_overwrite_subscriber_iface(self): 724 from pyramid.interfaces import INewRequest 725 from pyramid.interfaces import IViewClassifier 726 from zope.interface import alsoProvides 727 from zope.interface import Interface 728 self._registerRouteRequest('foo') 729 class IFoo(Interface): 730 pass 731 def listener(event): 732 alsoProvides(event.request, IFoo) 733 self.registry.registerHandler(listener, (INewRequest,)) 734 root = object() 735 def factory(request): 736 return root 737 self._connectRoute('foo', 'archives/:action/:article', factory) 738 context = DummyContext() 739 self._registerTraverserFactory(context) 740 response = DummyResponse() 741 response.app_iter = ['Hello world'] 742 view = DummyView(response) 743 environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') 744 self._registerView(view, '', IViewClassifier, None, None) 745 self._registerRootFactory(context) 746 router = self._makeOne() 747 start_response = DummyStartResponse() 748 result = router(environ, start_response) 749 self.assertEqual(result, ['Hello world']) 750 self.assertEqual(start_response.headers, ()) 751 self.assertEqual(start_response.status, '200 OK') 752 request = view.request 753 self.assertEqual(request.view_name, '') 754 self.assertEqual(request.subpath, []) 755 self.assertEqual(request.context, context) 756 self.assertEqual(request.root, root) 757 matchdict = {'action':'action1', 'article':'article1'} 758 self.assertEqual(request.matchdict, matchdict) 759 self.assertEqual(request.matched_route.name, 'foo') 760 self.assertTrue(IFoo.providedBy(request)) 761 762 def test_root_factory_raises_notfound(self): 763 from pyramid.interfaces import IRootFactory 764 from pyramid.httpexceptions import HTTPNotFound 765 from zope.interface import Interface 766 from zope.interface import directlyProvides 767 def rootfactory(request): 768 raise HTTPNotFound('from root factory') 769 self.registry.registerUtility(rootfactory, IRootFactory) 770 class IContext(Interface): 771 pass 772 context = DummyContext() 773 directlyProvides(context, IContext) 774 environ = self._makeEnviron() 775 router = self._makeOne() 776 start_response = DummyStartResponse() 777 why = exc_raised(HTTPNotFound, router, environ, start_response) 778 self.assertTrue('from root factory' in why.args[0]) 779 780 def test_root_factory_raises_forbidden(self): 781 from pyramid.interfaces import IRootFactory 782 from pyramid.httpexceptions import HTTPForbidden 783 from zope.interface import Interface 784 from zope.interface import directlyProvides 785 def rootfactory(request): 786 raise HTTPForbidden('from root factory') 787 self.registry.registerUtility(rootfactory, IRootFactory) 788 class IContext(Interface): 789 pass 790 context = DummyContext() 791 directlyProvides(context, IContext) 792 environ = self._makeEnviron() 793 router = self._makeOne() 794 start_response = DummyStartResponse() 795 why = exc_raised(HTTPForbidden, router, environ, start_response) 796 self.assertTrue('from root factory' in why.args[0]) 797 798 def test_root_factory_exception_propagating(self): 799 from pyramid.interfaces import IRootFactory 800 from zope.interface import Interface 801 from zope.interface import directlyProvides 802 def rootfactory(request): 803 raise RuntimeError() 804 self.registry.registerUtility(rootfactory, IRootFactory) 805 class IContext(Interface): 806 pass 807 context = DummyContext() 808 directlyProvides(context, IContext) 809 environ = self._makeEnviron() 810 router = self._makeOne() 811 start_response = DummyStartResponse() 812 self.assertRaises(RuntimeError, router, environ, start_response) 813 814 def test_traverser_exception_propagating(self): 815 environ = self._makeEnviron() 816 context = DummyContext() 817 self._registerTraverserFactory(context, raise_error=RuntimeError()) 818 router = self._makeOne() 819 start_response = DummyStartResponse() 820 self.assertRaises(RuntimeError, router, environ, start_response) 821 822 def test_call_view_exception_propagating(self): 823 from zope.interface import Interface 824 from zope.interface import directlyProvides 825 class IContext(Interface): 826 pass 827 from pyramid.interfaces import IRequest 828 from pyramid.interfaces import IViewClassifier 829 from pyramid.interfaces import IRequestFactory 830 from pyramid.interfaces import IExceptionViewClassifier 831 def rfactory(environ): 832 return request 833 self.registry.registerUtility(rfactory, IRequestFactory) 834 from pyramid.request import Request 835 request = Request.blank('/') 836 context = DummyContext() 837 directlyProvides(context, IContext) 838 self._registerTraverserFactory(context, subpath=['']) 839 response = DummyResponse() 840 response.app_iter = ['OK'] 841 error = RuntimeError() 842 view = DummyView(response, raise_exception=error) 843 environ = self._makeEnviron() 844 def exception_view(context, request): 845 self.assertEqual(request.exc_info[0], RuntimeError) 846 return response 847 self._registerView(view, '', IViewClassifier, IRequest, IContext) 848 self._registerView(exception_view, '', IExceptionViewClassifier, 849 IRequest, RuntimeError) 850 router = self._makeOne() 851 start_response = DummyStartResponse() 852 result = router(environ, start_response) 853 self.assertEqual(result, ['OK']) 854 # exc_info and exception should still be around on the request after 855 # the excview tween has run (see 856 # https://github.com/Pylons/pyramid/issues/1223) 857 self.assertEqual(request.exception, error) 858 self.assertEqual(request.exc_info[:2], (RuntimeError, error,)) 859 860 def test_call_view_raises_exception_view(self): 861 from pyramid.interfaces import IViewClassifier 862 from pyramid.interfaces import IExceptionViewClassifier 863 from pyramid.interfaces import IRequest 864 response = DummyResponse() 865 exception_response = DummyResponse() 866 exception_response.app_iter = ["Hello, world"] 867 view = DummyView(response, raise_exception=RuntimeError) 868 def exception_view(context, request): 869 self.assertEqual(request.exception.__class__, RuntimeError) 870 return exception_response 871 environ = self._makeEnviron() 872 self._registerView(view, '', IViewClassifier, IRequest, None) 873 self._registerView(exception_view, '', IExceptionViewClassifier, 874 IRequest, RuntimeError) 875 router = self._makeOne() 876 start_response = DummyStartResponse() 877 result = router(environ, start_response) 878 self.assertEqual(result, ["Hello, world"]) 879 880 def test_call_view_raises_super_exception_sub_exception_view(self): 881 from pyramid.interfaces import IViewClassifier 882 from pyramid.interfaces import IExceptionViewClassifier 883 from pyramid.interfaces import IRequest 884 class SuperException(Exception): 885 pass 886 class SubException(SuperException): 887 pass 888 response = DummyResponse() 889 exception_response = DummyResponse() 890 exception_response.app_iter = ["Hello, world"] 891 view = DummyView(response, raise_exception=SuperException) 892 exception_view = DummyView(exception_response) 893 environ = self._makeEnviron() 894 self._registerView(view, '', IViewClassifier, IRequest, None) 895 self._registerView(exception_view, '', IExceptionViewClassifier, 896 IRequest, SubException) 897 router = self._makeOne() 898 start_response = DummyStartResponse() 899 self.assertRaises(SuperException, router, environ, start_response) 900 901 def test_call_view_raises_sub_exception_super_exception_view(self): 902 from pyramid.interfaces import IViewClassifier 903 from pyramid.interfaces import IExceptionViewClassifier 904 from pyramid.interfaces import IRequest 905 class SuperException(Exception): 906 pass 907 class SubException(SuperException): 908 pass 909 response = DummyResponse() 910 exception_response = DummyResponse() 911 exception_response.app_iter = ["Hello, world"] 912 view = DummyView(response, raise_exception=SubException) 913 exception_view = DummyView(exception_response) 914 environ = self._makeEnviron() 915 self._registerView(view, '', IViewClassifier, IRequest, None) 916 self._registerView(exception_view, '', IExceptionViewClassifier, 917 IRequest, SuperException) 918 router = self._makeOne() 919 start_response = DummyStartResponse() 920 result = router(environ, start_response) 921 self.assertEqual(result, ["Hello, world"]) 922 923 def test_call_view_raises_exception_another_exception_view(self): 924 from pyramid.interfaces import IViewClassifier 925 from pyramid.interfaces import IExceptionViewClassifier 926 from pyramid.interfaces import IRequest 927 class MyException(Exception): 928 pass 929 class AnotherException(Exception): 930 pass 931 response = DummyResponse() 932 exception_response = DummyResponse() 933 exception_response.app_iter = ["Hello, world"] 934 view = DummyView(response, raise_exception=MyException) 935 exception_view = DummyView(exception_response) 936 environ = self._makeEnviron() 937 self._registerView(view, '', IViewClassifier, IRequest, None) 938 self._registerView(exception_view, '', IExceptionViewClassifier, 939 IRequest, AnotherException) 940 router = self._makeOne() 941 start_response = DummyStartResponse() 942 self.assertRaises(MyException, router, environ, start_response) 943 944 def test_root_factory_raises_exception_view(self): 945 from pyramid.interfaces import IRootFactory 946 from pyramid.interfaces import IRequest 947 from pyramid.interfaces import IExceptionViewClassifier 948 def rootfactory(request): 949 raise RuntimeError() 950 self.registry.registerUtility(rootfactory, IRootFactory) 951 exception_response = DummyResponse() 952 exception_response.app_iter = ["Hello, world"] 953 exception_view = DummyView(exception_response) 954 self._registerView(exception_view, '', IExceptionViewClassifier, 955 IRequest, RuntimeError) 956 environ = self._makeEnviron() 957 router = self._makeOne() 958 start_response = DummyStartResponse() 959 app_iter = router(environ, start_response) 960 self.assertEqual(app_iter, ["Hello, world"]) 961 962 def test_traverser_raises_exception_view(self): 963 from pyramid.interfaces import IRequest 964 from pyramid.interfaces import IExceptionViewClassifier 965 environ = self._makeEnviron() 966 context = DummyContext() 967 self._registerTraverserFactory(context, raise_error=RuntimeError()) 968 exception_response = DummyResponse() 969 exception_response.app_iter = ["Hello, world"] 970 exception_view = DummyView(exception_response) 971 self._registerView(exception_view, '', IExceptionViewClassifier, 972 IRequest, RuntimeError) 973 router = self._makeOne() 974 start_response = DummyStartResponse() 975 result = router(environ, start_response) 976 self.assertEqual(result, ["Hello, world"]) 977 978 def test_exception_view_returns_non_iresponse(self): 979 from pyramid.interfaces import IRequest 980 from pyramid.interfaces import IViewClassifier 981 from pyramid.interfaces import IExceptionViewClassifier 982 environ = self._makeEnviron() 983 response = DummyResponse() 984 view = DummyView(response, raise_exception=RuntimeError) 985 986 self._registerView(self.config.derive_view(view), '', 987 IViewClassifier, IRequest, None) 988 exception_view = DummyView(None) 989 self._registerView(self.config.derive_view(exception_view), '', 990 IExceptionViewClassifier, 991 IRequest, RuntimeError) 992 router = self._makeOne() 993 start_response = DummyStartResponse() 994 self.assertRaises(ValueError, router, environ, start_response) 995 996 def test_call_route_raises_route_exception_view(self): 997 from pyramid.interfaces import IViewClassifier 998 from pyramid.interfaces import IExceptionViewClassifier 999 req_iface = self._registerRouteRequest('foo') 1000 self._connectRoute('foo', 'archives/:action/:article', None) 1001 view = DummyView(DummyResponse(), raise_exception=RuntimeError) 1002 self._registerView(view, '', IViewClassifier, req_iface, None) 1003 response = DummyResponse() 1004 response.app_iter = ["Hello, world"] 1005 exception_view = DummyView(response) 1006 self._registerView(exception_view, '', IExceptionViewClassifier, 1007 req_iface, RuntimeError) 1008 environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') 1009 start_response = DummyStartResponse() 1010 router = self._makeOne() 1011 result = router(environ, start_response) 1012 self.assertEqual(result, ["Hello, world"]) 1013 1014 def test_call_view_raises_exception_route_view(self): 1015 from pyramid.interfaces import IViewClassifier 1016 from pyramid.interfaces import IExceptionViewClassifier 1017 from pyramid.interfaces import IRequest 1018 req_iface = self._registerRouteRequest('foo') 1019 self._connectRoute('foo', 'archives/:action/:article', None) 1020 view = DummyView(DummyResponse(), raise_exception=RuntimeError) 1021 self._registerView(view, '', IViewClassifier, IRequest, None) 1022 response = DummyResponse() 1023 response.app_iter = ["Hello, world"] 1024 exception_view = DummyView(response) 1025 self._registerView(exception_view, '', IExceptionViewClassifier, 1026 req_iface, RuntimeError) 1027 environ = self._makeEnviron() 1028 start_response = DummyStartResponse() 1029 router = self._makeOne() 1030 self.assertRaises(RuntimeError, router, environ, start_response) 1031 1032 def test_call_route_raises_exception_view(self): 1033 from pyramid.interfaces import IViewClassifier 1034 from pyramid.interfaces import IExceptionViewClassifier 1035 from pyramid.interfaces import IRequest 1036 req_iface = self._registerRouteRequest('foo') 1037 self._connectRoute('foo', 'archives/:action/:article', None) 1038 view = DummyView(DummyResponse(), raise_exception=RuntimeError) 1039 self._registerView(view, '', IViewClassifier, req_iface, None) 1040 response = DummyResponse() 1041 response.app_iter = ["Hello, world"] 1042 exception_view = DummyView(response) 1043 self._registerView(exception_view, '', IExceptionViewClassifier, 1044 IRequest, RuntimeError) 1045 environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') 1046 start_response = DummyStartResponse() 1047 router = self._makeOne() 1048 result = router(environ, start_response) 1049 self.assertEqual(result, ["Hello, world"]) 1050 1051 def test_call_route_raises_super_exception_sub_exception_view(self): 1052 from pyramid.interfaces import IViewClassifier 1053 from pyramid.interfaces import IExceptionViewClassifier 1054 from pyramid.interfaces import IRequest 1055 class SuperException(Exception): 1056 pass 1057 class SubException(SuperException): 1058 pass 1059 req_iface = self._registerRouteRequest('foo') 1060 self._connectRoute('foo', 'archives/:action/:article', None) 1061 view = DummyView(DummyResponse(), raise_exception=SuperException) 1062 self._registerView(view, '', IViewClassifier, req_iface, None) 1063 response = DummyResponse() 1064 response.app_iter = ["Hello, world"] 1065 exception_view = DummyView(response) 1066 self._registerView(exception_view, '', IExceptionViewClassifier, 1067 IRequest, SubException) 1068 environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') 1069 start_response = DummyStartResponse() 1070 router = self._makeOne() 1071 self.assertRaises(SuperException, router, environ, start_response) 1072 1073 def test_call_route_raises_sub_exception_super_exception_view(self): 1074 from pyramid.interfaces import IViewClassifier 1075 from pyramid.interfaces import IExceptionViewClassifier 1076 from pyramid.interfaces import IRequest 1077 class SuperException(Exception): 1078 pass 1079 class SubException(SuperException): 1080 pass 1081 req_iface = self._registerRouteRequest('foo') 1082 self._connectRoute('foo', 'archives/:action/:article', None) 1083 view = DummyView(DummyResponse(), raise_exception=SubException) 1084 self._registerView(view, '', IViewClassifier, req_iface, None) 1085 response = DummyResponse() 1086 response.app_iter = ["Hello, world"] 1087 exception_view = DummyView(response) 1088 self._registerView(exception_view, '', IExceptionViewClassifier, 1089 IRequest, SuperException) 1090 environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') 1091 start_response = DummyStartResponse() 1092 router = self._makeOne() 1093 result = router(environ, start_response) 1094 self.assertEqual(result, ["Hello, world"]) 1095 1096 def test_call_route_raises_exception_another_exception_view(self): 1097 from pyramid.interfaces import IViewClassifier 1098 from pyramid.interfaces import IExceptionViewClassifier 1099 from pyramid.interfaces import IRequest 1100 class MyException(Exception): 1101 pass 1102 class AnotherException(Exception): 1103 pass 1104 req_iface = self._registerRouteRequest('foo') 1105 self._connectRoute('foo', 'archives/:action/:article', None) 1106 view = DummyView(DummyResponse(), raise_exception=MyException) 1107 self._registerView(view, '', IViewClassifier, req_iface, None) 1108 response = DummyResponse() 1109 response.app_iter = ["Hello, world"] 1110 exception_view = DummyView(response) 1111 self._registerView(exception_view, '', IExceptionViewClassifier, 1112 IRequest, AnotherException) 1113 environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') 1114 start_response = DummyStartResponse() 1115 router = self._makeOne() 1116 self.assertRaises(MyException, router, environ, start_response) 1117 1118 def test_call_route_raises_exception_view_specializing(self): 1119 from pyramid.interfaces import IViewClassifier 1120 from pyramid.interfaces import IExceptionViewClassifier 1121 from pyramid.interfaces import IRequest 1122 req_iface = self._registerRouteRequest('foo') 1123 self._connectRoute('foo', 'archives/:action/:article', None) 1124 view = DummyView(DummyResponse(), raise_exception=RuntimeError) 1125 self._registerView(view, '', IViewClassifier, req_iface, None) 1126 response = DummyResponse() 1127 response.app_iter = ["Hello, world"] 1128 exception_view = DummyView(response) 1129 self._registerView(exception_view, '', IExceptionViewClassifier, 1130 IRequest, RuntimeError) 1131 response_spec = DummyResponse() 1132 response_spec.app_iter = ["Hello, special world"] 1133 exception_view_spec = DummyView(response_spec) 1134 self._registerView(exception_view_spec, '', IExceptionViewClassifier, 1135 req_iface, RuntimeError) 1136 environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') 1137 start_response = DummyStartResponse() 1138 router = self._makeOne() 1139 result = router(environ, start_response) 1140 self.assertEqual(result, ["Hello, special world"]) 1141 1142 def test_call_route_raises_exception_view_another_route(self): 1143 from pyramid.interfaces import IViewClassifier 1144 from pyramid.interfaces import IExceptionViewClassifier 1145 req_iface = self._registerRouteRequest('foo') 1146 another_req_iface = self._registerRouteRequest('bar') 1147 self._connectRoute('foo', 'archives/:action/:article', None) 1148 view = DummyView(DummyResponse(), raise_exception=RuntimeError) 1149 self._registerView(view, '', IViewClassifier, req_iface, None) 1150 response = DummyResponse() 1151 response.app_iter = ["Hello, world"] 1152 exception_view = DummyView(response) 1153 self._registerView(exception_view, '', IExceptionViewClassifier, 1154 another_req_iface, RuntimeError) 1155 environ = self._makeEnviron(PATH_INFO='/archives/action1/article1') 1156 start_response = DummyStartResponse() 1157 router = self._makeOne() 1158 self.assertRaises(RuntimeError, router, environ, start_response) 1159 1160 def test_call_view_raises_exception_view_route(self): 1161 from pyramid.interfaces import IRequest 1162 from pyramid.interfaces import IViewClassifier 1163 from pyramid.interfaces import IExceptionViewClassifier 1164 req_iface = self._registerRouteRequest('foo') 1165 response = DummyResponse() 1166 exception_response = DummyResponse() 1167 exception_response.app_iter = ["Hello, world"] 1168 view = DummyView(response, raise_exception=RuntimeError) 1169 exception_view = DummyView(exception_response) 1170 environ = self._makeEnviron() 1171 self._registerView(view, '', IViewClassifier, IRequest, None) 1172 self._registerView(exception_view, '', IExceptionViewClassifier, 1173 req_iface, RuntimeError) 1174 router = self._makeOne() 1175 start_response = DummyStartResponse() 1176 self.assertRaises(RuntimeError, router, environ, start_response) 1177 1178 def test_call_view_raises_predicate_mismatch(self): 1179 from pyramid.exceptions import PredicateMismatch 1180 from pyramid.interfaces import IViewClassifier 1181 from pyramid.interfaces import IRequest 1182 view = DummyView(DummyResponse(), raise_exception=PredicateMismatch) 1183 self._registerView(view, '', IViewClassifier, IRequest, None) 1184 environ = self._makeEnviron() 1185 router = self._makeOne() 1186 start_response = DummyStartResponse() 1187 self.assertRaises(PredicateMismatch, router, environ, start_response) 1188 1189 def test_call_view_predicate_mismatch_doesnt_hide_views(self): 1190 from pyramid.exceptions import PredicateMismatch 1191 from pyramid.interfaces import IViewClassifier 1192 from pyramid.interfaces import IRequest, IResponse 1193 from pyramid.response import Response 1194 class BaseContext: 1195 pass 1196 class DummyContext(BaseContext): 1197 pass 1198 context = DummyContext() 1199 self._registerTraverserFactory(context) 1200 view = DummyView(DummyResponse(), raise_exception=PredicateMismatch) 1201 self._registerView(view, '', IViewClassifier, IRequest, 1202 DummyContext) 1203 good_view = DummyView('abc') 1204 self._registerView(self.config.derive_view(good_view), 1205 '', IViewClassifier, IRequest, BaseContext) 1206 router = self._makeOne() 1207 def make_response(s): 1208 return Response(s) 1209 router.registry.registerAdapter(make_response, (str,), IResponse) 1210 environ = self._makeEnviron() 1211 start_response = DummyStartResponse() 1212 app_iter = router(environ, start_response) 1213 self.assertEqual(app_iter, [b'abc']) 1214 1215 def test_call_view_multiple_predicate_mismatches_dont_hide_views(self): 1216 from pyramid.exceptions import PredicateMismatch 1217 from pyramid.interfaces import IViewClassifier 1218 from pyramid.interfaces import IRequest, IResponse 1219 from pyramid.response import Response 1220 from zope.interface import Interface, implementer 1221 class IBaseContext(Interface): 1222 pass 1223 class IContext(IBaseContext): 1224 pass 1225 @implementer(IContext) 1226 class DummyContext: 1227 pass 1228 context = DummyContext() 1229 self._registerTraverserFactory(context) 1230 view1 = DummyView(DummyResponse(), raise_exception=PredicateMismatch) 1231 self._registerView(view1, '', IViewClassifier, IRequest, 1232 DummyContext) 1233 view2 = DummyView(DummyResponse(), raise_exception=PredicateMismatch) 1234 self._registerView(view2, '', IViewClassifier, IRequest, 1235 IContext) 1236 good_view = DummyView('abc') 1237 self._registerView(self.config.derive_view(good_view), 1238 '', IViewClassifier, IRequest, IBaseContext) 1239 router = self._makeOne() 1240 def make_response(s): 1241 return Response(s) 1242 router.registry.registerAdapter(make_response, (str,), IResponse) 1243 environ = self._makeEnviron() 1244 start_response = DummyStartResponse() 1245 app_iter = router(environ, start_response) 1246 self.assertEqual(app_iter, [b'abc']) 1247 1248 def test_call_view_predicate_mismatch_doesnt_find_unrelated_views(self): 1249 from pyramid.exceptions import PredicateMismatch 1250 from pyramid.interfaces import IViewClassifier 1251 from pyramid.interfaces import IRequest 1252 from zope.interface import Interface, implementer 1253 class IContext(Interface): 1254 pass 1255 class IOtherContext(Interface): 1256 pass 1257 @implementer(IContext) 1258 class DummyContext: 1259 pass 1260 context = DummyContext() 1261 self._registerTraverserFactory(context) 1262 view = DummyView(DummyResponse(), raise_exception=PredicateMismatch) 1263 self._registerView(view, '', IViewClassifier, IRequest, 1264 DummyContext) 1265 please_dont_call_me_view = DummyView('abc') 1266 self._registerView(self.config.derive_view(please_dont_call_me_view), 1267 '', IViewClassifier, IRequest, IOtherContext) 1268 router = self._makeOne() 1269 environ = self._makeEnviron() 1270 router = self._makeOne() 1271 start_response = DummyStartResponse() 1272 self.assertRaises(PredicateMismatch, router, environ, start_response) 1273 1274class DummyPredicate(object): 1275 def __call__(self, info, request): 1276 return True 1277 def text(self): 1278 return 'predicate' 1279 1280class DummyContext: 1281 pass 1282 1283class DummyView: 1284 def __init__(self, response, raise_exception=None): 1285 self.response = response 1286 self.raise_exception = raise_exception 1287 1288 def __call__(self, context, request): 1289 self.context = context 1290 self.request = request 1291 if self.raise_exception is not None: 1292 raise self.raise_exception 1293 return self.response 1294 1295class DummyRootFactory: 1296 def __init__(self, root): 1297 self.root = root 1298 1299 def __call__(self, environ): 1300 return self.root 1301 1302class DummyStartResponse: 1303 status = () 1304 headers = () 1305 def __call__(self, status, headers): 1306 self.status = status 1307 self.headers = headers 1308 1309from pyramid.interfaces import IResponse 1310from zope.interface import implementer 1311 1312@implementer(IResponse) 1313class DummyResponse(object): 1314 headerlist = () 1315 app_iter = () 1316 environ = None 1317 def __init__(self, status='200 OK'): 1318 self.status = status 1319 1320 def __call__(self, environ, start_response): 1321 self.environ = environ 1322 start_response(self.status, self.headerlist) 1323 return self.app_iter 1324 1325class DummyThreadLocalManager: 1326 def __init__(self): 1327 self.pushed = [] 1328 self.popped = [] 1329 1330 def push(self, val): 1331 self.pushed.append(val) 1332 1333 def pop(self): 1334 self.popped.append(True) 1335 1336class DummyAuthenticationPolicy: 1337 pass 1338 1339class DummyLogger: 1340 def __init__(self): 1341 self.messages = [] 1342 def info(self, msg): 1343 self.messages.append(msg) 1344 warn = info 1345 debug = info 1346 1347def exc_raised(exc, func, *arg, **kw): 1348 try: 1349 func(*arg, **kw) 1350 except exc as e: 1351 return e 1352 else: 1353 raise AssertionError('%s not raised' % exc) # pragma: no cover 1354 1355 1356