diff options
| author | Chris McDonough <chrism@plope.com> | 2011-08-02 21:10:32 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-08-02 21:10:32 -0400 |
| commit | d15920e8e4ebf90e0213ad79017f621ea0e9781e (patch) | |
| tree | 71ce2a8a014249bf41de2deca7101d528e13d548 | |
| parent | 1e04ba77eb69bca09fa0e8e212fa02454194f401 (diff) | |
| download | pyramid-d15920e8e4ebf90e0213ad79017f621ea0e9781e.tar.gz pyramid-d15920e8e4ebf90e0213ad79017f621ea0e9781e.tar.bz2 pyramid-d15920e8e4ebf90e0213ad79017f621ea0e9781e.zip | |
first cut
| -rw-r--r-- | pyramid/router.py | 286 |
1 files changed, 143 insertions, 143 deletions
diff --git a/pyramid/router.py b/pyramid/router.py index ddec23cdb..73e97a94b 100644 --- a/pyramid/router.py +++ b/pyramid/router.py @@ -57,143 +57,160 @@ class Router(object): self.debug_routematch = settings['debug_routematch'] def handle_request(self, request): + exc = None attrs = request.__dict__ registry = attrs['registry'] - request_iface = IRequest - context = None - routes_mapper = self.routes_mapper - debug_routematch = self.debug_routematch - adapters = registry.adapters - has_listeners = registry.has_listeners - notify = registry.notify - logger = self.logger - - try: # matches except Exception (exception view execution) - has_listeners and notify(NewRequest(request)) - # find the root object - root_factory = self.root_factory - if routes_mapper is not None: - info = routes_mapper(request) - match, route = info['match'], info['route'] - if route is None: - if debug_routematch: - msg = ('no route matched for url %s' % - request.url) - logger and logger.debug(msg) - else: - # TODO: kill off bfg.routes.* environ keys - # when traverser requires request arg, and - # cant cope with environ anymore (they are - # docs-deprecated as of BFG 1.3) - environ = request.environ - environ['bfg.routes.route'] = route - environ['bfg.routes.matchdict'] = match - attrs['matchdict'] = match - attrs['matched_route'] = route - - if debug_routematch: + + try: # matches finally: manager.pop() + manager = self.threadlocal_manager + threadlocals = { 'registry':registry, 'request':request} + manager.push(threadlocals) + request_iface = IRequest + context = None + routes_mapper = self.routes_mapper + debug_routematch = self.debug_routematch + adapters = registry.adapters + has_listeners = registry.has_listeners + notify = registry.notify + logger = self.logger + + try: # matches except Exception (exception view execution) + has_listeners and notify(NewRequest(request)) + # find the root object + root_factory = self.root_factory + if routes_mapper is not None: + info = routes_mapper(request) + match, route = info['match'], info['route'] + if route is None: + if debug_routematch: + msg = ('no route matched for url %s' % + request.url) + logger and logger.debug(msg) + else: + # TODO: kill off bfg.routes.* environ keys + # when traverser requires request arg, and + # cant cope with environ anymore (they are + # docs-deprecated as of BFG 1.3) + environ = request.environ + environ['bfg.routes.route'] = route + environ['bfg.routes.matchdict'] = match + attrs['matchdict'] = match + attrs['matched_route'] = route + + if debug_routematch: + msg = ( + 'route matched for url %s; ' + 'route_name: %r, ' + 'path_info: %r, ' + 'pattern: %r, ' + 'matchdict: %r, ' + 'predicates: %r' % ( + request.url, + route.name, + request.path_info, + route.pattern, match, + route.predicates) + ) + logger and logger.debug(msg) + + request_iface = registry.queryUtility( + IRouteRequest, + name=route.name, + default=IRequest) + + root_factory = route.factory or \ + self.root_factory + + root = root_factory(request) + attrs['root'] = root + + # find a context + traverser = adapters.queryAdapter(root, ITraverser) + if traverser is None: + traverser = ResourceTreeTraverser(root) + tdict = traverser(request) + + context, view_name, subpath, traversed, vroot, \ + vroot_path = ( + tdict['context'], + tdict['view_name'], + tdict['subpath'], + tdict['traversed'], + tdict['virtual_root'], + tdict['virtual_root_path'] + ) + + attrs.update(tdict) + has_listeners and notify(ContextFound(request)) + + # find a view callable + context_iface = providedBy(context) + view_callable = adapters.lookup( + (IViewClassifier, request_iface, context_iface), + IView, name=view_name, default=None) + + # invoke the view callable + if view_callable is None: + if self.debug_notfound: msg = ( - 'route matched for url %s; ' - 'route_name: %r, ' - 'path_info: %r, ' - 'pattern: %r, ' - 'matchdict: %r, ' - 'predicates: %r' % ( - request.url, - route.name, - request.path_info, - route.pattern, match, - route.predicates) + 'debug_notfound of url %s; path_info: %r, ' + 'context: %r, view_name: %r, subpath: %r, ' + 'traversed: %r, root: %r, vroot: %r, ' + 'vroot_path: %r' % ( + request.url, request.path_info, context, + view_name, + subpath, traversed, root, vroot, + vroot_path) ) logger and logger.debug(msg) - - request_iface = registry.queryUtility( - IRouteRequest, - name=route.name, - default=IRequest) - - root_factory = route.factory or \ - self.root_factory - - root = root_factory(request) - attrs['root'] = root - - # find a context - traverser = adapters.queryAdapter(root, ITraverser) - if traverser is None: - traverser = ResourceTreeTraverser(root) - tdict = traverser(request) - - context, view_name, subpath, traversed, vroot, \ - vroot_path = ( - tdict['context'], - tdict['view_name'], - tdict['subpath'], - tdict['traversed'], - tdict['virtual_root'], - tdict['virtual_root_path'] - ) - - attrs.update(tdict) - has_listeners and notify(ContextFound(request)) - - # find a view callable - context_iface = providedBy(context) - view_callable = adapters.lookup( - (IViewClassifier, request_iface, context_iface), - IView, name=view_name, default=None) - - # invoke the view callable - if view_callable is None: - if self.debug_notfound: - msg = ( - 'debug_notfound of url %s; path_info: %r, ' - 'context: %r, view_name: %r, subpath: %r, ' - 'traversed: %r, root: %r, vroot: %r, ' - 'vroot_path: %r' % ( - request.url, request.path_info, context, - view_name, - subpath, traversed, root, vroot, - vroot_path) - ) - logger and logger.debug(msg) + else: + msg = request.path_info + raise HTTPNotFound(msg) else: - msg = request.path_info - raise HTTPNotFound(msg) - else: - # if there were any view wrappers for the current - # request, use them to wrap the view + # if there were any view wrappers for the current + # request, use them to wrap the view - response = view_callable(context, request) + response = view_callable(context, request) - # handle exceptions raised during root finding and view-exec - except Exception, why: - # clear old generated request.response, if any; it may - # have been mutated by the view, and its state is not - # sane (e.g. caching headers) - if 'response' in attrs: - del attrs['response'] + # handle exceptions raised during root finding and view-exec + except Exception, exc: + # WARNING: do not assign the result of sys.exc_info() to a + # local var here, doing so will cause a leak + attrs['exc_info'] = sys.exc_info() + attrs['exception'] = exc - attrs['exception'] = why - attrs['exc_info'] = sys.exc_info() + # clear old generated request.response, if any; it may + # have been mutated by the view, and its state is not + # sane (e.g. caching headers) + if 'response' in attrs: + del attrs['response'] - for_ = (IExceptionViewClassifier, - request_iface.combined, - providedBy(why)) - view_callable = adapters.lookup(for_, IView, - default=None) + for_ = (IExceptionViewClassifier, + request_iface.combined, + providedBy(exc)) + view_callable = adapters.lookup(for_, IView, + default=None) - if view_callable is None: - raise + if view_callable is None: + raise - response = view_callable(why, request) + response = view_callable(exc, request) - has_listeners and notify(NewResponse(request, response)) + has_listeners and notify(NewResponse(request, response)) - if request.response_callbacks: - request._process_response_callbacks(response) + if request.response_callbacks: + request._process_response_callbacks(response) - return response + return request, response, attrs.get('exc_info') + + finally: + manager.pop() + if request is not None: + try: + if request.finished_callbacks: + request._process_finished_callbacks() + finally: + request.exc_info = None def __call__(self, environ, start_response): """ @@ -203,25 +220,8 @@ class Router(object): within the application registry; call ``start_response`` and return an iterable. """ - registry = self.registry - manager = self.threadlocal_manager - request = None - threadlocals = {'registry':registry, 'request':request} - manager.push(threadlocals) - - try: - try: - request = self.request_factory(environ) - threadlocals['request'] = request - request.registry = registry - response = self.handle_request(request) - finally: - if request is not None: - if request.finished_callbacks: - request._process_finished_callbacks() - request.exc_info = None # avoid leak - - return response(request.environ, start_response) - finally: - manager.pop() + request = self.request_factory(environ) + request.registry = self.registry + request, response = self.handle_request(request)[:2] + return response(request.environ, start_response) |
