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
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)
def extract_tender(request): try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(request.environ["PATH_INFO"] or "/") except KeyError: path = "/" except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) tender_id = "" # extract tender id parts = path.split("/") if len(parts) < 4 or parts[3] != "tenders": return tender_id = parts[4] return extract_tender_adapter(request, tender_id)
def extract_doc(request, doc_type): try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(request.environ['PATH_INFO'] or '/') except KeyError: path = '/' except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) doc_id = "" # extract doc id parts = path.split('/') if len(parts) < 4 or parts[3] != '{}s'.format(doc_type.lower()): return doc_id = parts[4] return extract_doc_adapter(request, doc_id, doc_type)
def 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
def extract_doc(request): try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(request.environ["PATH_INFO"] or "/") except KeyError: path = "/" except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) obj_id = "" # extract object id parts = path.split("/") if len(parts) < 4 or parts[3] not in ("frameworks", "submissions", "qualifications"): return obj_type = parts[3][0].upper() + parts[3][1:-1] obj_id = parts[4] return extract_doc_adapter(request, obj_type, obj_id)
def __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}
def _extract_from_request(request): # pragma: no cover """ Extract subpath, vpath and vroot_tuple from the request. The contents of this method is just a copy from the base class' implementation. :param request: Current request :type request: :class:`pyramid.request.Request` :return: (subpath, vpath, vroot_tuple) :rtype: tuple """ environ = request.environ matchdict = request.matchdict if matchdict is not None: path = matchdict.get('traverse', slash) or slash if is_nonstr_iter(path): path = '/' + slash.join(path) or slash subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): subpath = split_path_info(subpath) else: subpath = () try: path = request.path_info or slash except KeyError: path = slash except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if VH_ROOT_KEY in environ: vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) vpath = vroot_path + path else: vroot_tuple = () vpath = path return subpath, vpath, vroot_tuple
def __call__(self, request): environ = request.environ matchdict = request.matchdict if matchdict is not None: path = matchdict.get('traverse', slash) or slash if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them path = '/' + slash.join(path) or slash subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): # this is not a *subpath stararg (just a {subpath}) # routing has already decoded this string, so we just need # to split it subpath = split_path_info(subpath) else: # this request did not match a route subpath = () try: # empty if mounted under a path in mod_wsgi, for example path = request.path_info or slash except KeyError: # if environ['PATH_INFO'] is just not there path = slash except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if VH_ROOT_KEY in environ: # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) vpath = vroot_path + path # both will (must) be unicode or asciistr vroot_idx = len(vroot_tuple) -1 else: vroot_tuple = () vpath = path vroot_idx = -1 root = self.root ob = vroot = root if vpath == slash: # invariant: vpath must not be empty # prevent a call to traversal_path if we know it's going # to return the empty tuple vpath_tuple = () else: # we do dead reckoning here via tuple slicing instead of # pushing and popping temporary lists for speed purposes # and this hurts readability; apologies i = 0 view_selector = self.VIEW_SELECTOR vpath_tuple = split_path_info(vpath) for segment in vpath_tuple: if segment[:2] == view_selector: return {'context':ob, 'view_name':segment[2:], 'subpath':vpath_tuple[i+1:], 'traversed':vpath_tuple[:vroot_idx+i+1], 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root} try: getitem = ob.__getitem__ except AttributeError: return {'context':ob, 'view_name':segment, 'subpath':vpath_tuple[i+1:], 'traversed':vpath_tuple[:vroot_idx+i+1], 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root} try: next = getitem(segment) except KeyError: return {'context':ob, 'view_name':segment, 'subpath':vpath_tuple[i+1:], 'traversed':vpath_tuple[:vroot_idx+i+1], 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root} if i == vroot_idx: vroot = next ob = next i += 1 return {'context':ob, 'view_name':empty, 'subpath':subpath, 'traversed':vpath_tuple, 'virtual_root':vroot, 'virtual_root_path':vroot_tuple, 'root':root}
def traversal_path_info(path): """ Given``path``, return a tuple representing that path which can be used to traverse a resource tree. ``path`` is assumed to be an already-URL-decoded ``str`` type as if it had come to us from an upstream WSGI server as the ``PATH_INFO`` environ variable. The ``path`` is first decoded to from its WSGI representation to Unicode; it is decoded differently depending on platform: - On Python 2, ``path`` is decoded to Unicode from bytes using the UTF-8 decoding directly; a :exc:`pyramid.exc.URLDecodeError` is raised if a the URL cannot be decoded. - On Python 3, as per the PEP 3333 spec, ``path`` is first encoded to bytes using the Latin-1 encoding; the resulting set of bytes is subsequently decoded to text using the UTF-8 encoding; a :exc:`pyramid.exc.URLDecodeError` is raised if a the URL cannot be decoded. The ``path`` is split on slashes, creating a list of segments. If a segment name is empty or if it is ``.``, it is ignored. If a segment name is ``..``, the previous segment is deleted, and the ``..`` is ignored. Examples: ``/`` () ``/foo/bar/baz`` (u'foo', u'bar', u'baz') ``foo/bar/baz`` (u'foo', u'bar', u'baz') ``/foo/bar/baz/`` (u'foo', u'bar', u'baz') ``/foo//bar//baz/`` (u'foo', u'bar', u'baz') ``/foo/bar/baz/..`` (u'foo', u'bar') ``/my%20archives/hello`` (u'my archives', u'hello') ``/archives/La%20Pe%C3%B1a`` (u'archives', u'<unprintable unicode>') .. note:: This function does not generate the same type of tuples that :func:`pyramid.traversal.resource_path_tuple` does. In particular, the leading empty string is not present in the tuple it returns, unlike tuples returned by :func:`pyramid.traversal.resource_path_tuple`. As a result, tuples generated by ``traversal_path`` are not resolveable by the :func:`pyramid.traversal.find_resource` API. ``traversal_path`` is a function mostly used by the internals of :app:`Pyramid` and by people writing their own traversal machinery, as opposed to users writing applications in :app:`Pyramid`. """ try: path = decode_path_info(path) # result will be Unicode except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) return split_path_info(path) # result will be tuple of Unicode
def __call__(self, request): 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 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)
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
def __call__(self, request): # pylint: disable=too-many-locals,too-many-branches,too-many-statements environ = request.environ matchdict = request.matchdict if matchdict is not None: path = matchdict.get('traverse', slash) or slash if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them path = '/' + slash.join(path) or slash subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): # this is not a *subpath stararg (just a {subpath}) # routing has already decoded this string, so we just need # to split it subpath = split_path_info(subpath) else: subpath = () try: # empty if mounted under a path in mod_wsgi, for example path = request.path_info or slash except KeyError: # if environ['PATH_INFO'] is just not there path = slash except UnicodeDecodeError as exc: raise URLDecodeError(exc.encoding, exc.object, exc.start, exc.end, exc.reason) \ from exc if VH_ROOT_KEY in environ: # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) vpath = vroot_path + path vroot_idx = len(vroot_tuple) - 1 else: vroot_tuple = () vpath = path vroot_idx = -1 root = self.root obj = vroot = root request.registry.notify(BeforeTraverseEvent(root, request)) if vpath == slash: # invariant: vpath must not be empty # prevent a call to traversal_path if we know it's going # to return the empty tuple vpath_tuple = () else: # we do dead reckoning here via tuple slicing instead of # pushing and popping temporary lists for speed purposes # and this hurts readability; apologies i = 0 plus_selector = self.PLUS_SELECTOR ns_selector = self.NAMESPACE_SELECTOR view_selector = self.VIEW_SELECTOR vpath_tuple = split_path_info(vpath) for segment in vpath_tuple: if obj is not root: request.registry.notify(BeforeTraverseEvent(obj, request)) if segment == plus_selector: # check for custom namespace called '+' # currently this namespace is used in PyAMS_default_theme package to get # direct access to a given content traverser = queryMultiAdapter((obj, request), ITraversable, '+') if traverser is None: raise NotFound() try: obj = traverser.traverse( vpath_tuple[vroot_idx + i + 2], vpath_tuple[vroot_idx + i + 3:]) except IndexError as exc: # the "+" namespace traverser is waiting for additional elements from # input URL so a "+" URL not followed by something else is just an error! raise NotFound() from exc else: i += 1 return { 'context': obj, 'view_name': ''.join(vpath_tuple[vroot_idx + i + 2:]), 'subpath': vpath_tuple[i + 2:], 'traversed': vpath_tuple[:vroot_idx + i + 2], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } elif segment[:2] == ns_selector: # check for namespace prefixed by '++' # when a namespace is detected, named "ITraversable" multi-adapters are # searched for context and request, or for context, sequentially; a NotFound # exception is raised if traverser can't be found, otherwise it's "traverse" # method is called to get new context nss, name = segment[2:].split(ns_selector, 1) traverser = queryMultiAdapter((obj, request), ITraversable, nss) if traverser is None: traverser = queryAdapter(obj, ITraversable, nss) if traverser is None: raise NotFound() obj = traverser.traverse(name, vpath_tuple[vroot_idx + i + 1:]) i += 1 continue elif segment[:2] == view_selector: # check for view name prefixed by '@@' return { 'context': obj, 'view_name': segment[2:], 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } try: getitem = obj.__getitem__ except AttributeError: return { 'context': obj, 'view_name': segment, 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } try: next_item = getitem(segment) except KeyError: return { 'context': obj, 'view_name': segment, 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } if i == vroot_idx: vroot = next_item obj = next_item i += 1 if obj is not root: request.registry.notify(BeforeTraverseEvent(obj, request)) return { 'context': obj, 'view_name': empty, 'subpath': subpath, 'traversed': vpath_tuple, 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root }
def 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
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
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 }
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