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 __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