def __call__(self, context, request): path = decode_path_info(request.environ['PATH_INFO'] or '/') registry = request.registry mapper = registry.queryUtility(IRoutesMapper) if mapper is not None and not path.endswith('/'): slashpath = path + '/' for route in mapper.get_routes(): if route.match(slashpath) is not None: qs = request.query_string if qs: qs = '?' + qs return self.redirect_class(location=request.path + '/' + qs) return self.notfound_view(context, request)
def __call__(self, context, request): path = decode_path_info(request.environ['PATH_INFO'] or '/') registry = request.registry mapper = registry.queryUtility(IRoutesMapper) if mapper is not None and not path.endswith('/'): slashpath = path + '/' for route in mapper.get_routes(): if route.match(slashpath) is not None: qs = request.query_string if qs: qs = '?' + qs return HTTPFound(location=request.path + '/' + qs) return self.notfound_view(context, request)
def __call__(self, context, request): path = decode_path_info(request.environ["PATH_INFO"] or "/") registry = request.registry mapper = registry.queryUtility(IRoutesMapper) if mapper is not None and not path.endswith("/"): slashpath = path + "/" for route in mapper.get_routes(): if route.match(slashpath) is not None: qs = request.query_string if qs: qs = "?" + qs return HTTPFound(location=request.path + "/" + qs) return self.notfound_view(context, request)
def extract_agreement(request): try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(request.environ["PATH_INFO"] or "/") except KeyError: path = "/" except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) # extract agreement id parts = path.split("/") if len(parts) < 4 or parts[3] != "agreements": return agreement_id = parts[4] return extract_agreement_by_id(request, agreement_id)
def extract_tender(request): try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(request.environ['PATH_INFO'] or '/') except KeyError: path = '/' except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) tender_id = "" # extract tender id parts = path.split('/') if len(parts) < 4 or parts[3] != 'tenders': return tender_id = parts[4] return extract_tender_adapter(request, tender_id)
def extract_doc(request, doc_type): try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(request.environ['PATH_INFO'] or '/') except KeyError: path = '/' except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) doc_id = "" # extract doc id parts = path.split('/') if len(parts) < 4 or parts[3] != '{}s'.format(doc_type.lower()): return doc_id = parts[4] return extract_doc_adapter(request, doc_id, doc_type)
def extract_tender(request): try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(request.environ["PATH_INFO"] or "/") except KeyError: path = "/" except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) tender_id = "" # extract tender id parts = path.split("/") if len(parts) < 4 or parts[3] != "tenders": return tender_id = parts[4] return extract_tender_adapter(request, tender_id)
def extract_auction(request): try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(request.environ['PATH_INFO'] or '/') except KeyError: path = '/' except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) auction_id = "" # extract auction id parts = path.split('/') if len(parts) < 4 or parts[3] != 'auctions': return auction_id = parts[4] return extract_auction_adapter(request, auction_id)
def extract_doc(request): try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(request.environ["PATH_INFO"] or "/") except KeyError: path = "/" except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) obj_id = "" # extract object id parts = path.split("/") if len(parts) < 4 or parts[3] not in ("frameworks", "submissions", "qualifications"): return obj_type = parts[3][0].upper() + parts[3][1:-1] obj_id = parts[4] return extract_doc_adapter(request, obj_type, obj_id)
def notfound(request): if request.method == 'POST': request.response.status = 404 return dict(msg=request.exception) path = decode_path_info(request.environ['PATH_INFO'] or '/') registry = request.registry mapper = registry.queryUtility(IRoutesMapper) if mapper is not None and path.endswith('/') and '+simple' not in path: # redirect URLs with a trailing slash to URLs without one, if there # is a matching route nonslashpath = path.rstrip('/') for route in mapper.get_routes(): if route.match(nonslashpath) is not None: qs = request.query_string if qs: qs = '?' + qs return HTTPFound(location=request.application_url + nonslashpath + qs) request.response.status = 404 return dict(msg=request.exception)
def notfound(request): if request.method == 'POST': request.response.status = 404 return dict(msg=request.exception) path = decode_path_info(request.environ['PATH_INFO'] or '/') registry = request.registry mapper = registry.queryUtility(IRoutesMapper) if mapper is not None and path.endswith('/'): # redirect URLs with a trailing slash to URLs without one, if there # is a matching route nonslashpath = path.rstrip('/') for route in mapper.get_routes(): if route.match(nonslashpath) is not None: qs = request.query_string if qs: qs = '?' + qs return HTTPFound(location=nonslashpath + qs) request.response.status = 404 return dict(msg=request.exception)
def __call__(self, request): environ = request.environ try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(environ['PATH_INFO'] or '/') except KeyError: path = '/' except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) for route in self.routelist: match = route.match(path) if match is not None: preds = route.predicates info = {'match':match, 'route':route} if preds and not all((p(info, request) for p in preds)): continue return info return {'route':None, 'match':None}
def _extract_from_request(request): # pragma: no cover """ Extract subpath, vpath and vroot_tuple from the request. The contents of this method is just a copy from the base class' implementation. :param request: Current request :type request: :class:`pyramid.request.Request` :return: (subpath, vpath, vroot_tuple) :rtype: tuple """ environ = request.environ matchdict = request.matchdict if matchdict is not None: path = matchdict.get('traverse', slash) or slash if is_nonstr_iter(path): path = '/' + slash.join(path) or slash subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): subpath = split_path_info(subpath) else: subpath = () try: path = request.path_info or slash except KeyError: path = slash except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if VH_ROOT_KEY in environ: vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) vpath = vroot_path + path else: vroot_tuple = () vpath = path return subpath, vpath, vroot_tuple
def __call__(self, request): environ = request.environ matchdict = request.matchdict if matchdict is not None: path = matchdict.get("traverse", slash) or slash if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them path = "/" + slash.join(path) or slash subpath = matchdict.get("subpath", ()) if not is_nonstr_iter(subpath): # this is not a *subpath stararg (just a {subpath}) # routing has already decoded this string, so we just need # to split it subpath = split_path_info(subpath) else: # this request did not match a route subpath = () try: # empty if mounted under a path in mod_wsgi, for example path = request.path_info or slash except KeyError: # if environ['PATH_INFO'] is just not there path = slash except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if VH_ROOT_KEY in environ: # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) vpath = vroot_path + path # both will (must) be unicode or asciistr vroot_idx = len(vroot_tuple) - 1 else: vroot_tuple = () vpath = path vroot_idx = -1 root = self.root ob = vroot = root if vpath == slash: # invariant: vpath must not be empty # prevent a call to traversal_path if we know it's going # to return the empty tuple vpath_tuple = () else: # we do dead reckoning here via tuple slicing instead of # pushing and popping temporary lists for speed purposes # and this hurts readability; apologies i = 0 view_selector = self.VIEW_SELECTOR vpath_tuple = split_path_info(vpath) for segment in vpath_tuple: if segment[:2] == view_selector: return { "context": ob, "view_name": segment[2:], "subpath": vpath_tuple[i + 1 :], "traversed": vpath_tuple[: vroot_idx + i + 1], "virtual_root": vroot, "virtual_root_path": vroot_tuple, "root": root, } try: getitem = ob.__getitem__ except AttributeError: return { "context": ob, "view_name": segment, "subpath": vpath_tuple[i + 1 :], "traversed": vpath_tuple[: vroot_idx + i + 1], "virtual_root": vroot, "virtual_root_path": vroot_tuple, "root": root, } try: next = getitem(segment) except KeyError: return { "context": ob, "view_name": segment, "subpath": vpath_tuple[i + 1 :], "traversed": vpath_tuple[: vroot_idx + i + 1], "virtual_root": vroot, "virtual_root_path": vroot_tuple, "root": root, } if i == vroot_idx: vroot = next ob = next i += 1 return { "context": ob, "view_name": empty, "subpath": subpath, "traversed": vpath_tuple, "virtual_root": vroot, "virtual_root_path": vroot_tuple, "root": root, }
def traversal_path_info(path): """ Given``path``, return a tuple representing that path which can be used to traverse a resource tree. ``path`` is assumed to be an already-URL-decoded ``str`` type as if it had come to us from an upstream WSGI server as the ``PATH_INFO`` environ variable. The ``path`` is first decoded to from its WSGI representation to Unicode; it is decoded differently depending on platform: - On Python 2, ``path`` is decoded to Unicode from bytes using the UTF-8 decoding directly; a :exc:`pyramid.exc.URLDecodeError` is raised if a the URL cannot be decoded. - On Python 3, as per the PEP 3333 spec, ``path`` is first encoded to bytes using the Latin-1 encoding; the resulting set of bytes is subsequently decoded to text using the UTF-8 encoding; a :exc:`pyramid.exc.URLDecodeError` is raised if a the URL cannot be decoded. The ``path`` is split on slashes, creating a list of segments. If a segment name is empty or if it is ``.``, it is ignored. If a segment name is ``..``, the previous segment is deleted, and the ``..`` is ignored. Examples: ``/`` () ``/foo/bar/baz`` (u'foo', u'bar', u'baz') ``foo/bar/baz`` (u'foo', u'bar', u'baz') ``/foo/bar/baz/`` (u'foo', u'bar', u'baz') ``/foo//bar//baz/`` (u'foo', u'bar', u'baz') ``/foo/bar/baz/..`` (u'foo', u'bar') ``/my%20archives/hello`` (u'my archives', u'hello') ``/archives/La%20Pe%C3%B1a`` (u'archives', u'<unprintable unicode>') .. note:: This function does not generate the same type of tuples that :func:`pyramid.traversal.resource_path_tuple` does. In particular, the leading empty string is not present in the tuple it returns, unlike tuples returned by :func:`pyramid.traversal.resource_path_tuple`. As a result, tuples generated by ``traversal_path`` are not resolveable by the :func:`pyramid.traversal.find_resource` API. ``traversal_path`` is a function mostly used by the internals of :app:`Pyramid` and by people writing their own traversal machinery, as opposed to users writing applications in :app:`Pyramid`. """ try: path = decode_path_info(path) # result will be Unicode except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) return split_path_info(path) # result will be tuple of Unicode
def __call__(self, request): environ = request.environ matchdict = request.matchdict if matchdict is not None: path = matchdict.get('traverse', SLASH) or SLASH if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them path = '/' + SLASH.join(path) or SLASH subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): # this is not a *subpath stararg (just a {subpath}) # routing has already decoded this string, so we just need # to split it subpath = split_path_info(subpath) else: # this request did not match a route subpath = () try: # empty if mounted under a path in mod_wsgi, for example path = request.path_info or SLASH except KeyError: # if environ['PATH_INFO'] is just not there path = SLASH except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if VH_ROOT_KEY in environ: # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) vpath = vroot_path + path vroot_idx = len(vroot_tuple) - 1 else: vroot_tuple = () vpath = path vroot_idx = - 1 root = self.root ob = vroot = root if vpath == SLASH: vpath_tuple = () else: i = 0 view_selector = self.VIEW_SELECTOR vpath_tuple = split_path_info(vpath) return traverse( i, ob, view_selector, vpath_tuple, vroot_idx, vroot, vroot_tuple, root, subpath, ) return { 'context': ob, 'view_name': "", 'subpath': subpath, 'traversed': vpath_tuple, 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root }
def __call__(self, request): try: environ = request.environ except AttributeError: # In BFG 1.0 and before, this API expected an environ # rather than a request; some bit of code may still be # passing us an environ. If so, deal. environ = request depwarn = ('Passing an environ dictionary directly to a traverser ' 'is deprecated in Pyramid 1.1. Pass a request object ' 'instead.') warnings.warn(depwarn, DeprecationWarning, 2) if 'bfg.routes.matchdict' in environ: matchdict = environ['bfg.routes.matchdict'] path = matchdict.get('traverse', '/') or '/' if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them path = '/'.join(path) or '/' subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): # this is not a *subpath stararg (just a {subpath}) # routing has already decoded this string, so we just need # to split it subpath = split_path_info(subpath) else: # this request did not match a route subpath = () try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(environ['PATH_INFO'] or '/') except KeyError: path = '/' except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if VH_ROOT_KEY in environ: # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) vpath = vroot_path + path # both will (must) be unicode or asciistr vroot_idx = len(vroot_tuple) -1 else: vroot_tuple = () vpath = path vroot_idx = -1 root = self.root ob = vroot = root if vpath == '/': # invariant: vpath must not be empty # prevent a call to traversal_path if we know it's going # to return the empty tuple vpath_tuple = () else: # we do dead reckoning here via tuple slicing instead of # pushing and popping temporary lists for speed purposes # and this hurts readability; apologies i = 0 view_selector = self.VIEW_SELECTOR vpath_tuple = split_path_info(vpath) for segment in vpath_tuple: if segment[:2] == view_selector: return {'context':ob, 'view_name':segment[2:], 'subpath':vpath_tuple[i+1:], 'traversed':vpath_tuple[:vroot_idx+i+1], 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root} try: getitem = ob.__getitem__ except AttributeError: return {'context':ob, 'view_name':segment, 'subpath':vpath_tuple[i+1:], 'traversed':vpath_tuple[:vroot_idx+i+1], 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root} try: next = getitem(segment) except KeyError: return {'context':ob, 'view_name':segment, 'subpath':vpath_tuple[i+1:], 'traversed':vpath_tuple[:vroot_idx+i+1], 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root} if i == vroot_idx: vroot = next ob = next i += 1 return {'context':ob, 'view_name':empty, 'subpath':subpath, 'traversed':vpath_tuple, 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root}
def __call__(self, request): environ = request.environ matchdict = request.matchdict if matchdict is not None: path = matchdict.get('traverse', slash) or slash if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them path = '/' + slash.join(path) or slash subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): # this is not a *subpath stararg (just a {subpath}) # routing has already decoded this string, so we just need # to split it subpath = split_path_info(subpath) else: # this request did not match a route subpath = () try: # empty if mounted under a path in mod_wsgi, for example path = request.path_info or slash except KeyError: # if environ['PATH_INFO'] is just not there path = slash except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if VH_ROOT_KEY in environ: # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) vpath = vroot_path + path # both will (must) be unicode or asciistr vroot_idx = len(vroot_tuple) -1 else: vroot_tuple = () vpath = path vroot_idx = -1 root = self.root ob = vroot = root if vpath == slash: # invariant: vpath must not be empty # prevent a call to traversal_path if we know it's going # to return the empty tuple vpath_tuple = () else: # we do dead reckoning here via tuple slicing instead of # pushing and popping temporary lists for speed purposes # and this hurts readability; apologies i = 0 view_selector = self.VIEW_SELECTOR vpath_tuple = split_path_info(vpath) for segment in vpath_tuple: if segment[:2] == view_selector: return {'context':ob, 'view_name':segment[2:], 'subpath':vpath_tuple[i+1:], 'traversed':vpath_tuple[:vroot_idx+i+1], 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root} try: getitem = ob.__getitem__ except AttributeError: return {'context':ob, 'view_name':segment, 'subpath':vpath_tuple[i+1:], 'traversed':vpath_tuple[:vroot_idx+i+1], 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root} try: next = getitem(segment) except KeyError: return {'context':ob, 'view_name':segment, 'subpath':vpath_tuple[i+1:], 'traversed':vpath_tuple[:vroot_idx+i+1], 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root} if i == vroot_idx: vroot = next ob = next i += 1 return {'context':ob, 'view_name':empty, 'subpath':subpath, 'traversed':vpath_tuple, 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root}
def __call__(self, request): environ = request.environ matchdict = request.matchdict if matchdict is not None: path = matchdict.get('traverse', SLASH) or SLASH if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them path = '/' + SLASH.join(path) or SLASH subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): # this is not a *subpath stararg (just a {subpath}) # routing has already decoded this string, so we just need # to split it subpath = split_path_info(subpath) else: # this request did not match a route subpath = () try: # empty if mounted under a path in mod_wsgi, for example path = request.path_info or SLASH except KeyError: # if environ['PATH_INFO'] is just not there path = SLASH except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if VH_ROOT_KEY in environ: # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) vpath = vroot_path + path vroot_idx = len(vroot_tuple) - 1 else: vroot_tuple = () vpath = path vroot_idx = -1 root = self.root ob = vroot = root if vpath == SLASH: vpath_tuple = () else: i = 0 view_selector = self.VIEW_SELECTOR vpath_tuple = split_path_info(vpath) return traverse( i, ob, view_selector, vpath_tuple, vroot_idx, vroot, vroot_tuple, root, subpath, ) return { 'context': ob, 'view_name': "", 'subpath': subpath, 'traversed': vpath_tuple, 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root }
def __call__(self, request): # pylint: disable=too-many-locals,too-many-branches,too-many-statements environ = request.environ matchdict = request.matchdict if matchdict is not None: path = matchdict.get('traverse', slash) or slash if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them path = '/' + slash.join(path) or slash subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): # this is not a *subpath stararg (just a {subpath}) # routing has already decoded this string, so we just need # to split it subpath = split_path_info(subpath) else: subpath = () try: # empty if mounted under a path in mod_wsgi, for example path = request.path_info or slash except KeyError: # if environ['PATH_INFO'] is just not there path = slash except UnicodeDecodeError as exc: raise URLDecodeError(exc.encoding, exc.object, exc.start, exc.end, exc.reason) \ from exc if VH_ROOT_KEY in environ: # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) vpath = vroot_path + path vroot_idx = len(vroot_tuple) - 1 else: vroot_tuple = () vpath = path vroot_idx = -1 root = self.root obj = vroot = root request.registry.notify(BeforeTraverseEvent(root, request)) if vpath == slash: # invariant: vpath must not be empty # prevent a call to traversal_path if we know it's going # to return the empty tuple vpath_tuple = () else: # we do dead reckoning here via tuple slicing instead of # pushing and popping temporary lists for speed purposes # and this hurts readability; apologies i = 0 plus_selector = self.PLUS_SELECTOR ns_selector = self.NAMESPACE_SELECTOR view_selector = self.VIEW_SELECTOR vpath_tuple = split_path_info(vpath) for segment in vpath_tuple: if obj is not root: request.registry.notify(BeforeTraverseEvent(obj, request)) if segment == plus_selector: # check for custom namespace called '+' # currently this namespace is used in PyAMS_default_theme package to get # direct access to a given content traverser = queryMultiAdapter((obj, request), ITraversable, '+') if traverser is None: raise NotFound() try: obj = traverser.traverse( vpath_tuple[vroot_idx + i + 2], vpath_tuple[vroot_idx + i + 3:]) except IndexError as exc: # the "+" namespace traverser is waiting for additional elements from # input URL so a "+" URL not followed by something else is just an error! raise NotFound() from exc else: i += 1 return { 'context': obj, 'view_name': ''.join(vpath_tuple[vroot_idx + i + 2:]), 'subpath': vpath_tuple[i + 2:], 'traversed': vpath_tuple[:vroot_idx + i + 2], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } elif segment[:2] == ns_selector: # check for namespace prefixed by '++' # when a namespace is detected, named "ITraversable" multi-adapters are # searched for context and request, or for context, sequentially; a NotFound # exception is raised if traverser can't be found, otherwise it's "traverse" # method is called to get new context nss, name = segment[2:].split(ns_selector, 1) traverser = queryMultiAdapter((obj, request), ITraversable, nss) if traverser is None: traverser = queryAdapter(obj, ITraversable, nss) if traverser is None: raise NotFound() obj = traverser.traverse(name, vpath_tuple[vroot_idx + i + 1:]) i += 1 continue elif segment[:2] == view_selector: # check for view name prefixed by '@@' return { 'context': obj, 'view_name': segment[2:], 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } try: getitem = obj.__getitem__ except AttributeError: return { 'context': obj, 'view_name': segment, 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } try: next_item = getitem(segment) except KeyError: return { 'context': obj, 'view_name': segment, 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } if i == vroot_idx: vroot = next_item obj = next_item i += 1 if obj is not root: request.registry.notify(BeforeTraverseEvent(obj, request)) return { 'context': obj, 'view_name': empty, 'subpath': subpath, 'traversed': vpath_tuple, 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root }
def __call__(self, request): try: environ = request.environ except AttributeError: # In BFG 1.0 and before, this API expected an environ # rather than a request; some bit of code may still be # passing us an environ. If so, deal. environ = request depwarn = ('Passing an environ dictionary directly to a traverser ' 'is deprecated in Pyramid 1.1. Pass a request object ' 'instead.') warnings.warn(depwarn, DeprecationWarning, 2) if 'bfg.routes.matchdict' in environ: matchdict = environ['bfg.routes.matchdict'] path = matchdict.get('traverse', '/') or '/' if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them path = '/'.join(path) or '/' subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): # this is not a *subpath stararg (just a {subpath}) # routing has already decoded this string, so we just need # to split it subpath = split_path_info(subpath) else: # this request did not match a route subpath = () try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(environ['PATH_INFO'] or '/') except KeyError: path = '/' except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if VH_ROOT_KEY in environ: # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) vpath = vroot_path + path # both will be unicode or asciistr vroot_idx = len(vroot_tuple) - 1 else: vroot_tuple = () vpath = path vroot_idx = -1 root = self.root ob = vroot = root if vpath == '/': # invariant: vpath must not be empty # prevent a call to traversal_path if we know it's going # to return the empty tuple vpath_tuple = () else: # we do dead reckoning here via tuple slicing instead of # pushing and popping temporary lists for speed purposes # and this hurts readability; apologies i = 0 view_selector = self.VIEW_SELECTOR vpath_tuple = split_path_info(vpath) for segment in vpath_tuple: if segment[:2] == view_selector: return { 'context': ob, 'view_name': segment[2:], 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } try: # CHANGED: try to use adaper to get the __getitem__ method #try local registry registry = get_current_registry() adapter = registry.queryAdapter(ob, IChildsDictLike) #try global registry if not adapter: adapter = zope.component.queryAdapter(ob,\ IChildsDictLike) #else use the object directly if not adapter: adapter = ob getitem = adapter.__getitem__ except AttributeError: return { 'context': ob, 'view_name': segment, 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } try: next = getitem(segment) except KeyError: return { 'context': ob, 'view_name': segment, 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } if i == vroot_idx: vroot = next ob = next i += 1 return { 'context': ob, 'view_name': empty, 'subpath': subpath, 'traversed': vpath_tuple, 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root }
def __call__(self, request): # pylint:disable=too-many-locals,too-many-branches,too-many-statements """ See :meth:`pyramid.interfaces.ITraversar.__call__`. """ # JAM: Unfortunately, the superclass implementation is entirely monolithic # and we so we cannot reuse any part of it. Instead, # we copy-and-paste it. Unless otherwise noted, comments below are # original. # JAM: Note the abundance of no covers. These are for features we are # not currently using and the code is lifted directly from pyramid. environ = request.environ if request.matchdict is not None: matchdict = request.matchdict path = matchdict.get('traverse', '/') or '/' if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them path = '/'.join(path) or '/' subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): # pragma: no cover # this is not a *subpath stararg (just a {subpath}) # routing has already decoded this string, so we just need # to split it subpath = split_path_info(subpath) else: # pragma: no cover # this request did not match a route subpath = () try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(environ['PATH_INFO'] or '/') except KeyError: path = '/' except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if VH_ROOT_KEY in environ: # pragma: no cover # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) # both will (must) be unicode or asciistr vpath = vroot_path + path vroot_idx = len(vroot_tuple) - 1 else: vroot_tuple = () vpath = path vroot_idx = -1 root = self.root ob = vroot = root if vpath == '/': # invariant: vpath must not be empty # prevent a call to traversal_path if we know it's going # to return the empty tuple vpath_tuple = () else: i = 0 view_selector = self.VIEW_SELECTOR # A list so that remaining_path can be modified vpath_tuple = list(split_path_info(vpath)) for segment in vpath_tuple: # JAM: Fire traversal events, mainly so sites get installed. See # zope.publisher.base. _notify_before_traverse_event(ob, request) # JAM: Notice that checking for '@@' is special cased, and # doesn't go through the normal namespace lookup as it would in # plain zope traversal. (XXX: Why not?) if segment.startswith(view_selector): # pragma: no cover return { 'context': ob, 'view_name': segment[2:], 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } try: # JAM: This is where we differ. instead of using __getitem__, # we use the traversing machinery. # The zope app would use IPublishTraverser, which # would install security proxies along the way. We probably don't need to # do that? TODO: # NOTE: By passing the request here, we require all traversers # (including the namespace traversers) to be registered as multi-adapters. # None of the default namespaces are. See our # configure.zcml for what is. # JAM: Damn stupid implementation of traversePathElement ignores # the request argument to find a traversable /except/ when a namespace is found. # therefore, we explicitly query for the multi adapter ourself in the non-namespace case # (In the namespace case, we let traversing handle it, because it needs a named adapter # after parsing) traversable = None if segment and segment[0] not in '+@' \ and not ITraversable.providedBy(ob): try: # Use the installed component registry # instead of the request registry (which # is the global component registry if # pyramid was configured that way, or a # standalone registry) in case the act of # traversing has changed the site manager; # zope.site.site.threadSiteSubscriber will # do this for each BeforeTraverseEvent # that's fired (though that's not # registered by default). traversable = queryMultiAdapter((ob, request), ITraversable) except TypeError: # Some things are registered for "*" (DefaultTraversable) # which means they get called here. If they can't take # two arguments, then we bail. Sucks. pass remaining_path = vpath_tuple[i + 1:] next_ob = ztraversing.traversePathElement( ob, segment, remaining_path, traversable=traversable, request=request) if remaining_path != vpath_tuple[i + 1:]: # Is this if check necessary? It would be faster to # always assign vpath_tuple[i + 1:] = remaining_path except LocationError: # LocationError is a type of KeyError. The DefaultTraversable turns # plain KeyError and TypeErrors into LocationError. return { 'context': ob, 'view_name': segment, 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } if i == vroot_idx: # pragma: no cover vroot = next_ob ob = next_ob i += 1 # JAM: Also fire before traversal for the actual context item, since we # won't actually traverse into it. Be sure not to fire multiple times # for this (E.g., the root). This logic is complicated by the # multi-returns above. _notify_before_traverse_event(ob, request) return { 'context': ob, 'view_name': empty, 'subpath': subpath, 'traversed': vpath_tuple, 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root }