def get_traverse_endpoint_context(self, router: Router, route: Route) -> Resource: """Get root object for a traversable route. E.g. resolve /container/* to a SampleContainer context. """ # chop off last part /container/*traverse' start_path = "/".join(route.pattern.split("/")[0:-2]) + "/" # create a new request to traverse based on detected route pattern # dbsession must be passed here to prevent creating new dbsession sample_request = make_routable_request( dbsession=self.request.dbsession, registry=self.request.registry, path=start_path) root = route.factory(sample_request) traverser = self.request.registry.queryAdapter(root, ITraverser) # We are about to traverse and find a context if traverser is None: traverser = ResourceTreeTraverser(root) # {'virtual_root': <websauna.tests.sitemapsamples.SampleContainer object at 0x104656f98>, 'traversed': (), 'root': <websauna.tests.sitemapsamples.SampleContainer object at 0x104656f98>, 'virtual_root_path': (), 'view_name': 'container', 'subpath': (), 'context': <websauna.tests.sitemapsamples.SampleContainer object at 0x104656f98>} tdict = traverser(sample_request) context = tdict["context"] return context
def __init__(self, infos, context_iface, root_factory, request): self.views = [] for info in infos: match, route = info['match'], info['route'] if route is not None: request_iface = registry.queryUtility( IRouteRequest, name=route.name, default=IRequest ) views = _find_views( request.registry, request_iface, context_iface, '' ) if not views: continue view = views[0] view.__request_attrs__ = {} view.__request_attrs__['matchdict'] = match view.__request_attrs__['matched_route'] = route root_factory = route.factory or root_factory root = root_factory(request) traverser = adapters.queryAdapter(root, ITraverser) if traverser is None: traverser = ResourceTreeTraverser(root) tdict = traverser(request) view.__request_attrs__.update(tdict) if not hasattr(view, '__view_attr__'): view.__view_attr__ = '' self.views.append((None, view, None))
def __call__(self, request): system = ResourceTreeTraverser.__call__(self, request) context = system['context'] view_name = system['view_name'] if IResource.providedBy(context) and '.' in view_name: # pylint: disable=E1101 rc_name, repr_name = view_name.split('.') try: child_rc = context[rc_name] except KeyError: pass else: if IResource.providedBy(child_rc): # pylint: disable=E1101 system['context'] = child_rc system['view_name'] = repr_name return system
def __call__(self, request, queries=_path_queries): environ = request.environ context = root = self.root if root.__default_root__ and 'bfg.routes.route' in environ: return ResourceTreeTraverser(root)(request) path = '/%s/' % '/'.join(traversal_path(environ.get('PATH_INFO', '/'))) vroot_tuple = () l_path = len(root.__root_path__) # build paths for all parents in content hierarchy idx = 0 paths = {} current = root.__path__ for sec in path[l_path:].split('/'): if sec: current = '%s%s/' % (current, sec) paths[str(idx)] = current idx += 1 if idx: if idx not in queries: bindparams = [sql.bindparam(str(p)) for p in range(idx)] queries[idx] = ptah.QueryFreezer( lambda: ptah.get_session().query(BaseContent)\ .filter(BaseContent.__path__.in_(bindparams))) parents = sorted(queries[idx].all(**paths), reverse=True, key=lambda item: item.__path__) else: parents = [] if parents: # set __parent__ parents[-1].__parent__ = root for idx in range(len(parents) - 1): parents[idx].__parent__ = parents[idx + 1] context = parents[0] node = context.__path__[len(root.__path__):] leaf = path[l_path + len(node):].split('/') leaf, subpath = leaf[0], leaf[1:] return { 'context': context, 'view_name': leaf, 'subpath': subpath, 'traversed': traversal_path(node), 'virtual_root': root, 'virtual_root_path': vroot_tuple, 'root': root } else: vpath_tuple = () leaf = path[l_path:].split('/') leaf, subpath = leaf[0], leaf[1:] return { 'context': context, 'view_name': leaf, 'subpath': subpath, 'traversed': vpath_tuple, 'virtual_root': root, 'virtual_root_path': (), 'root': root }
def handle_request(self, request): attrs = request.__dict__ registry = attrs['registry'] request.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 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: 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, ', '.join( [p.text() for p in route.predicates]))) logger and logger.debug(msg) request.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.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: try: response = view_callable(context, request) except PredicateMismatch: # look for other views that meet the predicate # criteria for iface in context_iface.__sro__[1:]: previous_view_callable = view_callable view_callable = adapters.lookup( (IViewClassifier, request.request_iface, iface), IView, name=view_name, default=None) # intermediate bases may lookup same view_callable if view_callable is previous_view_callable: continue if view_callable is not None: try: response = view_callable(context, request) break except PredicateMismatch: pass else: raise return response
def _find_view(self, request): """ Accept ``url`` and ``registry``; create a :term:`request` and find a :app:`Pyramid` view based on introspection of :term:`view configuration` within the application registry; return the view. """ from zope.interface import providedBy from zope.interface import implementer from pyramid.interfaces import IRequest from pyramid.interfaces import IRootFactory from pyramid.interfaces import IRouteRequest from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import ITraverser from pyramid.traversal import DefaultRootFactory from pyramid.traversal import ResourceTreeTraverser registry = request.registry q = registry.queryUtility root_factory = q(IRootFactory, default=DefaultRootFactory) routes_mapper = q(IRoutesMapper) adapters = registry.adapters @implementer(IMultiView) class RoutesMultiView(object): def __init__(self, infos, context_iface, root_factory, request): self.views = [] for info in infos: match, route = info['match'], info['route'] if route is not None: request_iface = registry.queryUtility( IRouteRequest, name=route.name, default=IRequest ) views = _find_views( request.registry, request_iface, context_iface, '' ) if not views: continue view = views[0] view.__request_attrs__ = {} view.__request_attrs__['matchdict'] = match view.__request_attrs__['matched_route'] = route root_factory = route.factory or root_factory root = root_factory(request) traverser = adapters.queryAdapter(root, ITraverser) if traverser is None: traverser = ResourceTreeTraverser(root) tdict = traverser(request) view.__request_attrs__.update(tdict) if not hasattr(view, '__view_attr__'): view.__view_attr__ = '' self.views.append((None, view, None)) context = None routes_multiview = None attrs = request.__dict__ request_iface = IRequest # find the root object if routes_mapper is not None: infos = self._find_multi_routes(routes_mapper, request) if len(infos) == 1: info = infos[0] match, route = info['match'], info['route'] if route is not None: attrs['matchdict'] = match attrs['matched_route'] = route request.environ['bfg.routes.matchdict'] = match request_iface = registry.queryUtility( IRouteRequest, name=route.name, default=IRequest ) root_factory = route.factory or root_factory if len(infos) > 1: routes_multiview = infos 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 = (tdict['context'], tdict['view_name']) attrs.update(tdict) # find a view callable context_iface = providedBy(context) if routes_multiview is None: views = _find_views( request.registry, request_iface, context_iface, view_name ) if views: view = views[0] else: view = None else: view = RoutesMultiView(infos, context_iface, root_factory, request) # routes are not registered with a view name if view is None: views = _find_views( request.registry, request_iface, context_iface, '' ) if views: view = views[0] else: view = None # we don't want a multiview here if IMultiView.providedBy(view): view = None if view is not None: view.__request_attrs__ = attrs return view
def handle_request(self, request): attrs = request.__dict__ registry = attrs['registry'] request.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 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: 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, ', '.join([p.text() for p in route.predicates]), )) logger and logger.debug(msg) request.request_iface = registry.queryUtility(IRouteRequest, name=route.name, default=IRequest) root_factory = route.factory or self.root_factory # Notify anyone listening that we are about to start traversal # # Notify before creating root_factory in case we want to do something # special on a route we may have matched. See # https://github.com/Pylons/pyramid/pull/1876 for ideas of what is # possible. has_listeners and notify(BeforeTraversal(request)) # Create the root factory root = root_factory(request) attrs['root'] = root # We are about to traverse and 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) # Notify anyone listening that we have a context and traversal is # complete has_listeners and notify(ContextFound(request)) # find a view callable context_iface = providedBy(context) response = _call_view(registry, request, context, context_iface, view_name) if response 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) return response
def _find_view(self, url, registry): """ Accept ``url`` and ``registry``; create a :term:`request` and find a :app:`Pyramid` view based on introspection of :term:`view configuration` within the application registry; return the view. """ from zope.interface import providedBy from zope.interface import implementer from pyramid.interfaces import IRequest from pyramid.interfaces import IRootFactory from pyramid.interfaces import IRouteRequest from pyramid.interfaces import IRequestFactory from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import ITraverser from pyramid.request import Request from pyramid.traversal import DefaultRootFactory from pyramid.traversal import ResourceTreeTraverser q = registry.queryUtility root_factory = q(IRootFactory, default=DefaultRootFactory) routes_mapper = q(IRoutesMapper) request_factory = q(IRequestFactory, default=Request) adapters = registry.adapters request = None @implementer(IMultiView) class RoutesMultiView(object): def __init__(self, infos, context_iface, root_factory, request): self.views = [] for info in infos: match, route = info['match'], info['route'] if route is not None: request_iface = registry.queryUtility(IRouteRequest, name=route.name, default=IRequest) view = adapters.lookup( (IViewClassifier, request_iface, context_iface), IView, name='', default=None) if view is None: continue view.__request_attrs__ = {} view.__request_attrs__['matchdict'] = match view.__request_attrs__['matched_route'] = route root_factory = route.factory or root_factory root = root_factory(request) traverser = adapters.queryAdapter(root, ITraverser) if traverser is None: traverser = ResourceTreeTraverser(root) tdict = traverser(request) view.__request_attrs__.update(tdict) if not hasattr(view, '__view_attr__'): view.__view_attr__ = '' self.views.append((None, view, None)) # create the request environ = { 'wsgi.url_scheme': 'http', 'SERVER_NAME': 'localhost', 'SERVER_PORT': '8080', 'REQUEST_METHOD': 'GET', 'PATH_INFO': url, } request = request_factory(environ) context = None routes_multiview = None attrs = request.__dict__ attrs['registry'] = registry request_iface = IRequest # find the root object if routes_mapper is not None: infos = self._find_multi_routes(routes_mapper, request) if len(infos) == 1: info = infos[0] match, route = info['match'], info['route'] if route is not None: attrs['matchdict'] = match attrs['matched_route'] = route request.environ['bfg.routes.matchdict'] = match request_iface = registry.queryUtility(IRouteRequest, name=route.name, default=IRequest) root_factory = route.factory or root_factory if len(infos) > 1: routes_multiview = infos 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) # find a view callable context_iface = providedBy(context) if routes_multiview is None: view = adapters.lookup( (IViewClassifier, request_iface, context_iface), IView, name=view_name, default=None) else: view = RoutesMultiView(infos, context_iface, root_factory, request) # routes are not registered with a view name if view is None: view = adapters.lookup( (IViewClassifier, request_iface, context_iface), IView, name='', default=None) # we don't want a multiview here if IMultiView.providedBy(view): view = None if view is not None: view.__request_attrs__ = attrs return view
def handle_request(self, request): attrs = request.__dict__ registry = attrs['registry'] request.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 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, ', '.join( [p.__text__ for p in route.predicates]))) logger and logger.debug(msg) request.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.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: response = view_callable(context, request) return response
def _traverser(self): from pyramid.traversal import ResourceTreeTraverser ctx_root = self._pyramid_app.root_factory(self) return ResourceTreeTraverser(ctx_root)
def __call__(self, environ, start_response): """ Accept ``environ`` and ``start_response``; create a :term:`request` and route the request to a :app:`Pyramid` view based on introspection of :term:`view configuration` within the application registry; call ``start_response`` and return an iterable. """ registry = self.registry adapters = registry.adapters has_listeners = registry.has_listeners logger = self.logger manager = self.threadlocal_manager request = None threadlocals = {'registry': registry, 'request': request} manager.push(threadlocals) try: # matches finally: manager.pop() try: # matches finally: ... call request finished callbacks ... # create the request request = self.request_factory(environ) context = None threadlocals['request'] = request attrs = request.__dict__ attrs['registry'] = registry request_iface = IRequest try: # matches except Exception (exception view execution) has_listeners and registry.notify(NewRequest(request)) # find the root object root_factory = self.root_factory if self.routes_mapper is not None: info = self.routes_mapper(request) match, route = info['match'], info['route'] if route is None: if self.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['bfg.routes.route'] = route environ['bfg.routes.matchdict'] = match attrs['matchdict'] = match attrs['matched_route'] = route if self.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 registry.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 NotFound(msg) else: response = view_callable(context, request) # handle exceptions raised during root finding and view-exec except Exception, why: attrs['exception'] = why for_ = (IExceptionViewClassifier, request_iface.combined, providedBy(why)) view_callable = adapters.lookup(for_, IView, default=None) if view_callable is None: raise try: msg = why[0] except: msg = '' # repoze.bfg.message docs-deprecated in Pyramid 1.0 environ['repoze.bfg.message'] = msg response = view_callable(why, request) # process the response has_listeners and registry.notify( NewResponse(request, response)) if request.response_callbacks: request._process_response_callbacks(response) try: headers = response.headerlist app_iter = response.app_iter status = response.status except AttributeError: raise ValueError( 'Non-response object returned from view named %s ' '(and no renderer): %r' % (view_name, response)) finally: if request is not None and request.finished_callbacks: request._process_finished_callbacks() start_response(status, headers) return app_iter
def handle_request(self, request): attrs = request.__dict__ registry = attrs['registry'] request.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 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: 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, ', '.join( [p.text() for p in route.predicates]))) logger and logger.debug(msg) request.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) response = _call_view(registry, request, context, context_iface, view_name) if response 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) return response