示例#1
0
    def test_render_exception_error(self, request_):
        from pyramid.exceptions import URLDecodeError
        import json
        try:
            b'\222'.decode()
            assert False
        except UnicodeDecodeError as err:
            error = URLDecodeError(err.encoding, err.object, err.start,
                                   err.end, err.reason)
            inst = self.make_one(error, request_)

            assert inst.status == '400 Bad Request'
            wanted = {
                'status':
                'error',
                'errors': [{
                    'location':
                    'url',
                    'name':
                    '',
                    'description':
                    "400 Bad Request 'utf-8' codec can't decode byte 0x92 in position 0: invalid start byte"
                }]
            }
            assert json.loads(inst.body.decode()) == wanted
示例#2
0
 def matcher(path):
     m = match(path)
     if m is None:
         return m
     d = {}
     for k, v in m.groupdict().iteritems():
         if k == star:
             d[k] = traversal_path(v)
         else:
             encoded = unquote(v)
             try:
                 d[k] = encoded.decode('utf-8')
             except UnicodeDecodeError, e:
                 raise URLDecodeError(e.encoding, e.object, e.start, e.end,
                                      e.reason)
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_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)
示例#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 matcher(path):
        m = match(path)
        if m is None:
            return m
        d = {}
        for k, v in m.groupdict().items():
            if k == star:
                d[k] = traversal_path_info(v)
            else:
                try:
                    val = bytes_(v).decode('utf-8', 'strict')
                    d[k] = val
                except UnicodeDecodeError as e:
                    raise URLDecodeError(e.encoding, e.object, e.start, e.end,
                                         e.reason)

        return d
示例#8
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)
示例#9
0
    def __call__(self, request):
        try:
            # empty if mounted under a path in mod_wsgi, for example
            path = request.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}
示例#10
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
示例#11
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}
示例#12
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
示例#13
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
        }
示例#14
0
def traversal_path(path):
    """ Given a ``PATH_INFO`` string (slash-separated path segments),
    return a tuple representing that path which can be used to
    traverse a resource tree.

    The ``PATH_INFO`` is split on slashes, creating a list of
    segments.  Each segment is URL-unquoted, and subsequently decoded
    into Unicode. Each segment is assumed to be encoded using the
    UTF-8 encoding (or a subset, such as ASCII); a
    :exc:`pyramid.exceptions.URLDecodeError` is raised if a segment
    cannot be decoded.  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.

    If this function is passed a Unicode object instead of a string,
    that Unicode object *must* directly encodeable to ASCII.  For
    example, u'/foo' will work but u'/<unprintable unicode>' (a
    Unicode object with characters that cannot be encoded to ascii)
    will not.

    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`.
    """
    if isinstance(path, unicode):
        path = path.encode('ascii')
    path = path.strip('/')
    clean = []
    for segment in path.split('/'):
        segment = urllib.unquote(segment)  # deal with spaces in path segment
        if not segment or segment == '.':
            continue
        elif segment == '..':
            del clean[-1]
        else:
            try:
                segment = segment.decode('utf-8')
            except UnicodeDecodeError, e:
                raise URLDecodeError(e.encoding, e.object, e.start, e.end,
                                     e.reason)
            clean.append(segment)
示例#15
0
    def toolbar_tween(request):
        try:
            p = request.path_info
        except UnicodeDecodeError as e:
            raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason)

        last_proxy_addr = None
        if request.remote_addr:
            last_proxy_addr = last_proxy(request.remote_addr)

        if (
            last_proxy_addr is None
            or any(p.startswith(e) for e in exclude_prefixes)
            or not addr_in(last_proxy_addr, hosts)
            or auth_check and not auth_check(request)
        ):
            return handler(request)

        if request.environ.get('wsgi.multiprocess', False):
            warnings.warn(
                'pyramid_debugtoolbar has detected that the application is '
                'being served by a forking / multiprocess web server. The '
                'toolbar relies on global state to work and is not compatible '
                'with this environment. The toolbar will be disabled.')
            return handler(request)

        root_path = debug_toolbar_url(request, '', _app_url='')
        if p.startswith(root_path):
            # we know root_path will always have a trailing slash
            # but script_name doesn't want it
            try:
                old_script_name = request.script_name
                old_path_info = request.path_info
                request.script_name += root_path[:-1]
                request.path_info = request.path_info[len(root_path) - 1:]
                return dispatch(request)
            finally:
                request.script_name = old_script_name
                request.path_info = old_path_info

        request.pdtb_id = hexlify(id(request))
        toolbar = DebugToolbar(request, panel_classes, global_panel_classes,
                               default_active_panels)
        request.debug_toolbar = toolbar
        request_history.put(request.pdtb_id, toolbar)

        _handler = handler
        for panel in toolbar.panels:
            _handler = panel.wrap_handler(_handler)

        try:
            response = _handler(request)
            toolbar.status_int = response.status_int

            if request.exc_info and intercept_exc:
                toolbar.traceback = process_traceback(request.exc_info)

                msg = 'Squashed %s at %s\ntraceback url: %s'
                exc_name = get_exc_name(request.exc_info[1])
                subrequest = make_subrequest(
                    request, root_path, request.pdtb_id + '/exception')
                exc_msg = msg % (exc_name, request.url, subrequest.url)
                _logger.info(exc_msg)

        except Exception as exc:
            exc_name = get_exc_name(exc)
            if intercept_exc:
                toolbar.traceback = process_traceback(sys.exc_info())

                msg = 'Uncaught %s at %s\ntraceback url: %s'
                subrequest = make_subrequest(
                    request, root_path, request.pdtb_id + '/exception')
                exc_msg = msg % (exc_name, request.url, subrequest.url)
                _logger.exception(exc_msg)

                response = dispatch(subrequest)
                toolbar.status_int = response.status_int

                # The original request must be processed so that the panel
                # data exists if the request is later examined in the full
                # toolbar view.
                toolbar.process_response(request, response)

                # Inject the button to activate the full toolbar view.
                toolbar.inject(request, response)
                return response

            else:
                msg = 'Uncaught %s at %s'
                _logger.exception(msg % (exc_name, request.url))
            raise

        else:
            if intercept_redirects:
                # Intercept http redirect codes and display an html page with a
                # link to the target.
                if response.status_int in redirect_codes:
                    redirect_to = response.location
                    redirect_code = response.status_int
                    if redirect_to:
                        qs = {
                            'redirect_to': redirect_to,
                            'redirect_code': str(redirect_code),
                        }
                        subrequest = make_subrequest(
                            request, root_path, 'redirect', qs)
                        content = dispatch(subrequest).text
                        response.location = None
                        response.text = content
                        response.status_int = 200

            toolbar.process_response(request, response)

            if not show_on_exc_only and response.content_type in html_types:
                toolbar.inject(request, response)
            return response

        finally:
            # break circref
            del request.debug_toolbar
示例#16
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
        }
示例#17
0
    def toolbar_tween(request):
        request.exc_history = exc_history
        request.history = request_history
        root_url = request.route_path('debugtoolbar', subpath='')
        exclude = [root_url] + exclude_prefixes
        last_proxy_addr = None

        try:
            p = request.path
        except UnicodeDecodeError as e:
            raise URLDecodeError(e.encoding, e.object, e.start, e.end,
                                 e.reason)
        starts_with_excluded = list(filter(None, map(p.startswith, exclude)))

        if request.remote_addr:
            last_proxy_addr = last_proxy(request.remote_addr)

        if last_proxy_addr is None \
            or starts_with_excluded \
            or not addr_in(last_proxy_addr, hosts) \
            or auth_check and not auth_check(request):
            return handler(request)

        toolbar = DebugToolbar(request, panel_classes, global_panel_classes)
        request.debug_toolbar = toolbar

        _handler = handler

        # XXX
        for panel in toolbar.panels:
            _handler = panel.wrap_handler(_handler)

        try:
            response = _handler(request)
            toolbar.status_int = response.status_int
        except Exception:
            if exc_history is not None:
                tb = get_traceback(info=sys.exc_info(),
                                   skip=1,
                                   show_hidden_frames=False,
                                   ignore_system_exceptions=True)
                for frame in tb.frames:
                    exc_history.frames[frame.id] = frame
                exc_history.tracebacks[tb.id] = tb
                request.pdbt_tb = tb

                qs = {'token': registry.pdtb_token, 'tb': str(tb.id)}
                msg = 'Exception at %s\ntraceback url: %s'
                exc_url = debug_toolbar_url(request, 'exception', _query=qs)
                exc_msg = msg % (request.url, exc_url)
                _logger.exception(exc_msg)

                subenviron = request.environ.copy()
                del subenviron['PATH_INFO']
                del subenviron['QUERY_STRING']
                subrequest = type(request).blank(exc_url, subenviron)
                subrequest.script_name = request.script_name
                subrequest.path_info = \
                    subrequest.path_info[len(request.script_name):]
                response = request.invoke_subrequest(subrequest)

                toolbar.process_response(request, response)

                request.id = hexlify(id(request))
                toolbar.response = response
                toolbar.status_int = response.status_int

                request_history.put(request.id, toolbar)
                toolbar.inject(request, response)
                return response
            else:
                _logger.exception('Exception at %s' % request.url)
            raise

        else:
            if intercept_redirects:
                # Intercept http redirect codes and display an html page with a
                # link to the target.
                if response.status_int in redirect_codes:
                    redirect_to = response.location
                    redirect_code = response.status_int
                    if redirect_to:
                        content = render(
                            'pyramid_debugtoolbar:templates/redirect.dbtmako',
                            {
                                'redirect_to': redirect_to,
                                'redirect_code': redirect_code,
                            },
                            request=request)
                        content = content.encode(response.charset)
                        response.content_length = len(content)
                        response.location = None
                        response.app_iter = [content]
                        response.status_int = 200

            toolbar.process_response(request, response)
            request.id = hexlify(id(request))
            # Don't store the favicon.ico request
            # it's requested by the browser automatically
            if not "/favicon.ico" == request.path:
                toolbar.response = response
                request_history.put(request.id, toolbar)

            if not show_on_exc_only and response.content_type in html_types:
                toolbar.inject(request, response)
            return response

        finally:
            # break circref
            del request.debug_toolbar
示例#18
0
    def toolbar_tween(request):
        try:
            p = request.path_info
        except UnicodeDecodeError as e:
            raise URLDecodeError(e.encoding, e.object, e.start, e.end,
                                 e.reason)

        last_proxy_addr = None
        if request.remote_addr:
            last_proxy_addr = last_proxy(request.remote_addr)

        if (last_proxy_addr is None
                or any(p.startswith(e) for e in exclude_prefixes)
                or not addr_in(last_proxy_addr, hosts)
                or auth_check and not auth_check(request)):
            return handler(request)

        if request.environ.get('wsgi.multiprocess', False):
            warnings.warn(
                'pyramid_debugtoolbar has detected that the application is '
                'being served by a forking / multiprocess web server. The '
                'toolbar relies on global state to work and is not compatible '
                'with this environment. The toolbar will be disabled.')
            return handler(request)

        root_path = debug_toolbar_url(request, '', _app_url='')
        if p.startswith(root_path):
            # we know root_path will always have a trailing slash
            # but script_name doesn't want it
            try:
                old_script_name = request.script_name
                old_path_info = request.path_info
                request.script_name += root_path[:-1]
                request.path_info = request.path_info[len(root_path) - 1:]
                return dispatch(request)
            finally:
                request.script_name = old_script_name
                request.path_info = old_path_info

        request.exc_history = exc_history
        request.history = request_history
        request.pdtb_id = hexlify(id(request))
        toolbar = DebugToolbar(request, panel_classes, global_panel_classes,
                               default_active_panels)
        request.debug_toolbar = toolbar

        _handler = handler
        for panel in toolbar.panels:
            _handler = panel.wrap_handler(_handler)

        try:
            response = _handler(request)
            toolbar.status_int = response.status_int
        except Exception:
            if exc_history is not None:
                tb = get_traceback(info=sys.exc_info(),
                                   skip=1,
                                   show_hidden_frames=False,
                                   ignore_system_exceptions=True)
                for frame in tb.frames:
                    exc_history.frames[frame.id] = frame
                exc_history.tracebacks[tb.id] = tb
                request.pdbt_tb = tb

                msg = 'Exception at %s\ntraceback url: %s'
                qs = {'token': registry.pdtb_token, 'tb': str(tb.id)}
                subrequest = make_subrequest(request, root_path, 'exception',
                                             qs)
                exc_msg = msg % (request.url, subrequest.url)
                _logger.exception(exc_msg)

                response = dispatch(subrequest)

                # The original request must be processed so that the panel data exists
                # if the request is later examined in the full toolbar view.
                toolbar.process_response(request, response)

                toolbar.response = response
                toolbar.status_int = response.status_int

                request_history.put(request.pdtb_id, toolbar)
                # Inject the button to activate the full toolbar view.
                toolbar.inject(request, response)
                return response
            else:
                _logger.exception('Exception at %s' % request.url)
            raise

        else:
            if intercept_redirects:
                # Intercept http redirect codes and display an html page with a
                # link to the target.
                if response.status_int in redirect_codes:
                    redirect_to = response.location
                    redirect_code = response.status_int
                    if redirect_to:
                        qs = {
                            'token': registry.pdtb_token,
                            'redirect_to': redirect_to,
                            'redirect_code': str(redirect_code),
                        }
                        subrequest = make_subrequest(request, root_path,
                                                     'redirect', qs)
                        content = dispatch(subrequest).text
                        response.location = None
                        response.text = content
                        response.status_int = 200

            toolbar.process_response(request, response)
            # Don't store the favicon.ico request
            # it's requested by the browser automatically
            if not "/favicon.ico" == request.path:
                toolbar.response = response
                request_history.put(request.pdtb_id, toolbar)

            if not show_on_exc_only and response.content_type in html_types:
                toolbar.inject(request, response)
            return response

        finally:
            # break circref
            del request.debug_toolbar
示例#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
            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
        """
        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
        }
示例#21
0
    def toolbar_tween(request):
        root_path = request.route_path(ROOT_ROUTE_NAME)
        exclude = [root_path] + exclude_prefixes
        request.exc_history = exc_history
        last_proxy_addr = None

        try:
            p = request.path
        except UnicodeDecodeError as e:
            raise URLDecodeError(e.encoding, e.object, e.start, e.end,
                                 e.reason)

        starts_with_excluded = list(filter(None, map(p.startswith, exclude)))

        if request.remote_addr:
            last_proxy_addr = last_proxy(request.remote_addr)

        if last_proxy_addr is None \
            or starts_with_excluded \
            or not addr_in(last_proxy_addr, hosts) \
            or auth_check and not auth_check(request):
            return handler(request)

        toolbar = DebugToolbar(request, panel_classes)
        request.debug_toolbar = toolbar

        _handler = handler

        for panel in toolbar.panels:
            _handler = panel.wrap_handler(_handler)

        try:
            response = _handler(request)
        except Exception:
            if exc_history is not None:
                tb = get_traceback(info=sys.exc_info(),
                                   skip=1,
                                   show_hidden_frames=False,
                                   ignore_system_exceptions=True)
                for frame in tb.frames:
                    exc_history.frames[frame.id] = frame

                exc_history.tracebacks[tb.id] = tb
                body = tb.render_full(request).encode('utf-8', 'replace')
                response = Response(body, status=500)
                toolbar.process_response(response)
                qs = {'token': exc_history.token, 'tb': str(tb.id)}
                msg = 'Exception at %s\ntraceback url: %s'
                exc_url = request.route_url(EXC_ROUTE_NAME, _query=qs)
                exc_msg = msg % (request.url, exc_url)
                _logger.exception(exc_msg)
                return response
            else:
                _logger.exception('Exception at %s' % request.url)
            raise

        else:
            if intercept_redirects:
                # Intercept http redirect codes and display an html page with a
                # link to the target.
                if response.status_int in redirect_codes:
                    redirect_to = response.location
                    redirect_code = response.status_int
                    if redirect_to:
                        content = render(
                            'pyramid_debugtoolbar:templates/redirect.dbtmako',
                            {
                                'redirect_to': redirect_to,
                                'redirect_code': redirect_code
                            },
                            request=request)
                        content = content.encode(response.charset)
                        response.content_length = len(content)
                        response.location = None
                        response.app_iter = [content]
                        response.status_int = 200

            if not show_on_exc_only:
                toolbar.process_response(response)
            return response

        finally:
            # break circref
            del request.debug_toolbar