示例#1
0
 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)
示例#2
0
 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)
示例#3
0
文件: view.py 项目: rob0t7/pyramid
 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)
示例#5
0
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)
示例#6
0
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)
示例#7
0
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)
示例#9
0
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)
示例#10
0
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)
示例#11
0
文件: views.py 项目: t-8ch/devpi
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)
示例#12
0
    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}
示例#13
0
    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
示例#14
0
    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
示例#15
0
    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,
        }
示例#16
0
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
示例#17
0
    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}
示例#19
0
    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}
示例#20
0
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
示例#21
0
    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
        }
示例#22
0
    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
        }
示例#23
0
    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
        }