def process_response(self, response): response_headers = [(text_(k), text_(v)) for k, v in sorted(response.headerlist)] self.data = { 'request_headers': self.request_headers, 'response_headers': response_headers }
def __init__(self, request): def finished_callback(request): self.process_response_deferred() request.add_finished_callback(finished_callback) self.request_headers = [(text_(k), text_(v)) for k, v in sorted(request.headers.items())]
def render_summary(self, include_title=True, request=None): """Render the traceback for the interactive console.""" title = '' frames = [] classes = ['traceback'] if not self.frames: classes.append('noframe-traceback') if include_title: if self.is_syntax_error: title = text_('Syntax Error') else: title = text_('Traceback <em>(most recent call last)</em>:') for frame in self.frames: frames.append( text_('<li%s>%s') % ( frame.info and text_(' title="%s"' % escape(frame.info)) or text_(''), frame.render() )) if self.is_syntax_error: description_wrapper = '<pre class=syntaxerror>%s</pre>' else: description_wrapper = '<blockquote>%s</blockquote>' vars = { 'classes': text_(' '.join(classes)), 'title': title and text_('<h3>%s</h3>' % title) or text_(''), 'frames': text_('\n'.join(frames)), 'description': text_(description_wrapper % escape(self.exception)), } return render('pyramid_debugtoolbar:templates/exception_summary.mako', vars, request=request)
def dispatch_repr(self, obj, recursive): if obj is helper: return text_('<span class="help">%r</span>' % helper) if isinstance(obj, (int, long, float, complex)): return text_('<span class="number">%r</span>' % obj) if PY3: if isinstance(obj, text_type): return self.py3_text_repr(obj) if isinstance(obj, binary_type): return self.py3_binary_repr(obj) else: if isinstance(obj, basestring): return self.py2_string_repr(obj) if isinstance(obj, RegexType): return self.regex_repr(obj) if isinstance(obj, list): return self.list_repr(obj, recursive) if isinstance(obj, tuple): return self.tuple_repr(obj, recursive) if isinstance(obj, set): return self.set_repr(obj, recursive) if isinstance(obj, frozenset): return self.frozenset_repr(obj, recursive) if isinstance(obj, dict): return self.dict_repr(obj, recursive) if deque is not None and isinstance(obj, deque): return self.deque_repr(obj, recursive) return self.object_repr(obj)
def sse(request): response = request.response response.content_type = 'text/event-stream' history = request.pdtb_history response.text = U_BLANK active_request_id = text_(request.GET.get('request_id')) client_last_request_id = text_(request.headers.get('Last-Event-Id', 0)) max_visible_requests = get_setting(request.registry.settings, 'max_visible_requests') if history: last_request_pair = history.last(1)[0] last_request_id = last_request_pair[0] if not last_request_id == client_last_request_id: data = [ [ _id, toolbar.json, 'active' if active_request_id == _id else '' ] for _id, toolbar in history.last(max_visible_requests) if toolbar.visible ] if data: response.text = U_SSE_PAYLOAD.format(last_request_id, json.dumps(data)) return response
def generate_plaintext_traceback(self): """Like the plaintext attribute but returns a generator""" yield text_('Traceback (most recent call last):') for frame in self.frames: yield text_(' File "%s", line %s, in %s' % (frame.filename, frame.lineno, frame.function_name)) yield text_(' ' + frame.current_line.strip()) yield text_(self.exception, 'utf-8')
def fallback_repr(self): try: info = ''.join(format_exception_only(*sys.exc_info()[:2])) except Exception: # pragma: no cover info = '?' return text_('<span class="brokenrepr"><broken repr (%s)>' '</span>' % escape(text_(info, 'utf-8', 'ignore').strip()))
def format_sql(query): if not HAVE_PYGMENTS: # pragma: no cover return text_(query) return text_( highlight( query, SqlLexer(encoding="utf-8"), HtmlFormatter(encoding="utf-8", noclasses=True, style=PYGMENT_STYLE) ) )
def fallback_repr(self): try: info = ''.join(format_exception_only(*sys.exc_info()[:2])) except Exception: # pragma: no cover info = '?' return text_( '<span class="brokenrepr"><broken repr (%s)>' '</span>' % escape(text_(info, 'utf-8', 'ignore').strip()) )
def format_sql(query): if not HAVE_PYGMENTS: # pragma: no cover return text_(query) return text_( highlight( query, SqlLexer(encoding='utf-8'), HtmlFormatter(encoding='utf-8', noclasses=True, style=PYGMENT_STYLE)))
def generate_plaintext_traceback(self): """Like the plaintext attribute but returns a generator""" yield text_('Traceback (most recent call last):') for frame in self.frames: yield text_(' File "%s", line %s, in %s' % ( frame.filename, frame.lineno, frame.function_name )) yield text_(' ' + frame.current_line.strip()) yield text_(self.exception, 'utf-8')
def dict_repr(self, d, recursive): if recursive: return _add_subclass_info(text_('{...}'), d, dict) buf = ['{'] for idx, (key, value) in enumerate(iteritems_(d)): if idx: buf.append(', ') buf.append('<span class="pair"><span class="key">%s</span>: ' '<span class="value">%s</span></span>' % (self.repr(key), self.repr(value))) buf.append('}') return _add_subclass_info(text_(''.join(buf)), d, dict)
def py3_binary_repr(self, obj, limit=70): buf = ['<span class="string">'] escaped = escape(text_(obj, 'utf-8', 'replace')) a = repr(escaped[:limit]) b = repr(escaped[limit:]) buf.append('b') if b != "''": buf.extend((a[:-1], '<span class="extended">', b[1:], '</span>')) else: buf.append(a) buf.append('</span>') return _add_subclass_info(text_(''.join(buf)), obj, binary_type)
def regex_repr(self, obj): if PY3: pattern = text_("'%s'" % str(obj.pattern), 'string-escape', 'ignore') pattern = 'r' + pattern else: pattern = text_(repr(obj.pattern), 'string-escape', 'ignore') if pattern[:1] == 'u': pattern = 'ur' + pattern[1:] else: pattern = 'r' + pattern return text_( 're.compile(<span class="string regex">%s</span>)' % pattern)
def regex_repr(self, obj): if PY3: pattern = text_("'%s'" % str(obj.pattern), 'string-escape', 'ignore') pattern = 'r' + pattern else: pattern = text_(repr(obj.pattern), 'string-escape', 'ignore') if pattern[:1] == 'u': pattern = 'ur' + pattern[1:] else: pattern = 'r' + pattern return text_('re.compile(<span class="string regex">%s</span>)' % pattern)
def render_full(self, request, lodgeit_url=None): """Render the Full HTML page with the traceback info.""" static_path = request.static_url(STATIC_PATH) root_path = request.route_url(ROOT_ROUTE_NAME) exc = text_(escape(self.exception)) summary = self.render_summary(include_title=False, request=request) qs = {'token':request.exc_history.token, 'tb':str(self.id)} url = request.route_url(EXC_ROUTE_NAME, _query=qs) evalex = request.exc_history.eval_exc vars = { 'evalex': evalex and 'true' or 'false', 'console': 'false', 'lodgeit_url': escape(lodgeit_url), 'title': exc, 'exception': exc, 'exception_type': escape(self.exception_type), 'summary': summary, 'plaintext': self.plaintext, 'plaintext_cs': re.sub('-{2,}', '-', self.plaintext), 'traceback_id': self.id, 'static_path': static_path, 'token': request.exc_history.token, 'root_path': root_path, 'url': url, } return render('pyramid_debugtoolbar:templates/exception.mako', vars, request=request)
def dict_repr(self, d, recursive, limit=5): if recursive: return _add_subclass_info(text_('{...}'), d, dict) buf = ['{'] have_extended_section = False for idx, (key, value) in enumerate(iteritems_(d)): if idx: buf.append(', ') if idx == limit - 1: buf.append('<span class="extended">') have_extended_section = True buf.append('<span class="pair"><span class="key">%s</span>: ' '<span class="value">%s</span></span>' % (self.repr(key), self.repr(value))) if have_extended_section: buf.append('</span>') buf.append('}') return _add_subclass_info(text_(''.join(buf)), d, dict)
def proxy(self, obj, recursive): if recursive: return _add_subclass_info(left + '...' + right, obj, base) buf = [left] for idx, item in enumerate(obj): if idx: buf.append(', ') buf.append(self.repr(item)) buf.append(right) return _add_subclass_info(text_(''.join(buf)), obj, base)
def sse(request): response = request.response response.content_type = 'text/event-stream' history = find_request_history(request) response.text = U_BLANK active_request_id = text_(request.GET.get('request_id')) client_last_request_id = text_(request.headers.get('Last-Event-Id', 0)) if history: last_request_pair = history.last(1)[0] last_request_id = last_request_pair[0] if not last_request_id == client_last_request_id: data = [[_id, toolbar.json, 'active' if active_request_id == _id else ''] for _id,toolbar in history.last(10)] if data: response.text = U_SSE_PAYLOAD.format(last_request_id, json.dumps(data)) return response
def sse(request): response = request.response response.content_type = 'text/event-stream' history = find_request_history(request) response.text = U_BLANK active_request_id = text_(request.GET.get('request_id')) client_last_request_id = text_(request.headers.get('Last-Event-Id', 0)) if history: last_request_pair = history.last(1)[0] last_request_id = last_request_pair[0] if not last_request_id == client_last_request_id: data = [[ _id, toolbar.json, 'active' if active_request_id == _id else '' ] for _id, toolbar in history.last(10)] if data: response.text = U_SSE_PAYLOAD.format(last_request_id, json.dumps(data)) return response
def process_beforerender(self, event): if not self.renderings: self.renderings = [] name = event["renderer_info"].name if name and name.startswith("pyramid_debugtoolbar"): return val = getattr(event, "rendering_val", "<unknown>") try: val = repr(val) except: # crazyass code raises an exception during __repr__ (formish) val = "<unknown>" self.renderings.append(dict(name=name, system=dictrepr(event), val=text_(val, "utf-8")))
def process_beforerender(self, event): if not self.renderings: self.renderings = [] name = event['renderer_info'].name if name and name.startswith('pyramid_debugtoolbar'): return val = getattr(event, 'rendering_val', '<unknown>') try: val = repr(val) except: # crazyass code raises an exception during __repr__ (formish) val = '<unknown>' self.renderings.append( dict(name=name, system=dictrepr(event), val=text_(val, 'utf-8')))
def process_beforerender(self, event): if not self.renderings: self.renderings = [] name = event['renderer_info'].name if name and name.startswith('pyramid_debugtoolbar'): return val = getattr(event, 'rendering_val', '<unknown>') try: val = repr(val) except: # crazyass code raises an exception during __repr__ (formish) val = '<unknown>' self.renderings.append( dict(name=name, system=dictrepr(event), val=text_(val, 'utf-8')) )
def __call__(self, topic=None): if topic is None: sys.stdout._write('<span class=help>%s</span>' % repr(self)) return import pydoc pydoc.help(topic) rv = text_(sys.stdout.reset(), 'utf-8', 'ignore') paragraphs = _paragraph_re.split(rv) if len(paragraphs) > 1: title = paragraphs[0] text = '\n\n'.join(paragraphs[1:]) else: # pragma: no cover title = 'Help' text = paragraphs[0] sys.stdout._write(HELP_HTML % {'title': title, 'text': text})
def py2_string_repr(self, obj, limit=70): buf = ['<span class="string">'] escaped = escape(obj) a = repr(escaped[:limit]) b = repr(escaped[limit:]) if isinstance(obj, text_type): buf.append('u') a = a[1:] b = b[1:] if b != "''": buf.extend((a[:-1], '<span class="extended">', b[1:], '</span>')) else: buf.append(a) buf.append('</span>') return _add_subclass_info(text_('').join(buf), obj, (str, unicode))
def proxy(self, obj, recursive): if recursive: return _add_subclass_info(left + '...' + right, obj, base) buf = [left] have_extended_section = False for idx, item in enumerate(obj): if idx: buf.append(', ') if idx == limit: buf.append('<span class="extended">') have_extended_section = True buf.append(self.repr(item)) if have_extended_section: buf.append('</span>') buf.append(right) return _add_subclass_info(text_(''.join(buf)), obj, base)
def test_exception_summary(self): from pyramid.renderers import render self.config.include("pyramid_jinja2") request = self._makeRequest() request.static_url = lambda *arg, **kw: "http://static" vars = { "classes": text_("classfoo class&bar"), "title": text_("<h3>TEH TITLE</h3>"), "frames": text_("<pre>Frame1</pre><pre>Frame2</pre>"), } html = render("pyramid_debugtoolbar:templates/exception_summary.jinja2", vars, request=request) self.assertTrue(text_('<div class="classfoo class&bar">') in html, html) self.assertTrue(text_("<h3>TEH TITLE</h3>") in html, html) self.assertTrue(text_("<pre>Frame1</pre><pre>Frame2</pre>") in html, html)
def test_exception_summary(self): from pyramid.renderers import render request = self._makeRequest() request.static_url = lambda *arg, **kw: 'http://static' vars = { 'classes': text_('classfoo class&bar'), 'title': text_('<h3>TEH TITLE</h3>'), 'frames': text_('<pre>Frame1</pre><pre>Frame2</pre>'), } html = render('pyramid_debugtoolbar:templates/exception_summary.mako', vars, request=request) self.assertTrue( text_('<div class="classfoo class&bar">') in html, html) self.assertTrue(text_('<h3>TEH TITLE</h3>') in html, html) self.assertTrue( text_('<pre>Frame1</pre><pre>Frame2</pre>') in html, html)
def __init__(self, exc_type, exc_value, tb): self.lineno = tb.tb_lineno self.function_name = tb.tb_frame.f_code.co_name self.locals = tb.tb_frame.f_locals self.globals = tb.tb_frame.f_globals fn = inspect.getsourcefile(tb) or inspect.getfile(tb) if fn[-4:] in ('.pyo', '.pyc'): fn = fn[:-1] # if it's a file on the file system resolve the real filename. if os.path.isfile(fn): fn = os.path.realpath(fn) self.filename = fn self.module = self.globals.get('__name__') self.loader = self.globals.get('__loader__') self.code = tb.tb_frame.f_code # support for paste's traceback extensions self.hide = self.locals.get('__traceback_hide__', False) info = self.locals.get('__traceback_info__') if info is not None: info = text_(info, errors='replace') self.info = info
def test_exception_summary(self): from pyramid.renderers import render request = self._makeRequest() request.static_url = lambda *arg, **kw: 'http://static' vars = { 'classes': text_('classfoo class&bar'), 'title': text_('<h3>TEH TITLE</h3>'), 'frames': text_('<pre>Frame1</pre><pre>Frame2</pre>'), } html = render( 'pyramid_debugtoolbar:templates/exception_summary.dbtmako', vars, request=request) self.assertTrue( text_('<div class="classfoo class&bar">') in html,html) self.assertTrue( text_('<h3>TEH TITLE</h3>') in html, html) self.assertTrue( text_('<pre>Frame1</pre><pre>Frame2</pre>') in html, html)
def __init__(self): self.token = text_(binascii.hexlify(os.urandom(10))) self.frames = {} self.tracebacks = {}
def render_source(self): """Render the sourcecode.""" return SOURCE_TABLE_HTML % text_('\n'.join( line.render() for line in self.get_annotated_lines()))
def render_source(self): """Render the sourcecode.""" return SOURCE_TABLE_HTML % text_('\n'.join(line.render() for line in self.get_annotated_lines()))
def current_line(self): try: return self.sourcelines[self.lineno - 1] except IndexError: return text_('')
def plaintext(self): return text_('\n'.join(self.generate_plaintext_traceback()))
_coding_re = re.compile(r'coding[:=]\s*([-\w.]+)') _line_re = re.compile(r'^(.*?)$(?m)') _funcdef_re = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)') UTF8_COOKIE = '\xef\xbb\xbf' system_exceptions = (SystemExit, KeyboardInterrupt) try: system_exceptions += (GeneratorExit,) except NameError: pass FRAME_HTML = text_('''\ <div class="frame" id="frame-%(id)d"> <h4>File <cite class="filename">"%(filename)s"</cite>, line <em class="line">%(lineno)s</em>, in <code class="function">%(function_name)s</code></h4> <pre>%(current_line)s</pre> </div> ''') SOURCE_TABLE_HTML = text_('<table class=source>%s</table>') SOURCE_LINE_HTML = text_('''\ <tr class="%(classes)s"> <td class=lineno>%(lineno)s</td> <td>%(code)s</td> </tr> ''') def get_current_traceback(ignore_system_exceptions=False,
def get_platform(self): return 'Python %s on %s' % (sys.version, text_(self._get_platform_name(), 'utf8'))
def render_summary(self, include_title=True, request=None): """Render the traceback for the interactive console.""" title = '' frames = [] classes = ['traceback'] if not self.frames: classes.append('noframe-traceback') if include_title: if self.is_syntax_error: title = text_('Syntax Error') else: title = text_('Traceback <em>(most recent call last)</em>:') for frame in self.frames: frames.append( text_('<li%s>%s') % (frame.info and text_(' title="%s"' % escape(frame.info)) or text_(''), frame.render())) if self.is_syntax_error: description_wrapper = text_('<pre class=syntaxerror>%s</pre>') else: description_wrapper = text_('<blockquote>%s</blockquote>') vars = { 'classes': text_(' '.join(classes)), 'title': title and text_('<h3>%s</h3>' % title) or text_(''), 'frames': text_('\n'.join(frames)), 'description': description_wrapper % escape(self.exception), } return render( 'pyramid_debugtoolbar:templates/exception_summary.dbtmako', vars, request=request)
def test_debug_repr(self): assert debug_repr([]) == '[]' assert debug_repr([1, 2]) == \ '[<span class="number">1</span>, <span class="number">2</span>]' assert debug_repr([1, 'test']) == \ '[<span class="number">1</span>, <span class="string">\'test\'</span>]' assert debug_repr([None]) == \ '[<span class="object">None</span>]' assert debug_repr(list(range(20))) == ( '[<span class="number">0</span>, <span class="number">1</span>, ' '<span class="number">2</span>, <span class="number">3</span>, ' '<span class="number">4</span>, <span class="number">5</span>, ' '<span class="number">6</span>, <span class="number">7</span>, ' '<span class="number">8</span>, <span class="number">9</span>, ' '<span class="number">10</span>, <span class="number">11</span>, ' '<span class="number">12</span>, <span class="number">13</span>, ' '<span class="number">14</span>, <span class="number">15</span>, ' '<span class="number">16</span>, <span class="number">17</span>, ' '<span class="number">18</span>, <span class="number">19</span>]' ) assert debug_repr({}) == '{}' assert debug_repr({'foo': 42}) == \ '{<span class="pair"><span class="key"><span class="string">\'foo\''\ '</span></span>: <span class="value"><span class="number">42' \ '</span></span></span>}' result = debug_repr((1, bytes_('zwei'), text_('drei'))) if PY3: # pragma: no cover expected = ( '(<span class="number">1</span>, <span class="string">b\'' 'zwei\'</span>, <span class="string">\'drei\'</span>)') else: expected = ( '(<span class="number">1</span>, <span class="string">\'' 'zwei\'</span>, <span class="string">u\'drei\'</span>)') assert result == expected class Foo(object): def __repr__(self): return '<Foo 42>' assert debug_repr(Foo()) == '<span class="object"><Foo 42></span>' class MyList(list): pass tmp = debug_repr(MyList([1, 2])) assert tmp == \ '<span class="module">pyramid_debugtoolbar.tests.test_debug.</span>MyList([' \ '<span class="number">1</span>, <span class="number">2</span>])' result = debug_repr(re.compile(r'foo\d')) assert result == \ 're.compile(<span class="string regex">r\'foo\\d\'</span>)' result = debug_repr(re.compile(text_(r'foo\d'))) if PY3: # pragma: no cover assert result == \ 're.compile(<span class="string regex">r\'foo\\d\'</span>)' else: assert result == \ 're.compile(<span class="string regex">ur\'foo\\d\'</span>)' assert debug_repr(frozenset('x')) == \ 'frozenset([<span class="string">\'x\'</span>])' assert debug_repr(set('x')) == \ 'set([<span class="string">\'x\'</span>])' a = [1] a.append(a) assert debug_repr(a) == '[<span class="number">1</span>, [...]]' class Foo(object): def __repr__(self): 1/0 result = debug_repr(Foo()) assert 'division' in result
def object_repr(self, obj): return text_('<span class="object">%s</span>' % escape(text_(repr(obj), 'utf-8', 'replace')))
def hexlify(value): """Hexlify int, str then returns native str type.""" # If integer str_ = str(value) hexified = text_(binascii.hexlify(bytes_(str_))) return hexified
max_visible_requests = get_setting(request.registry.settings, 'max_visible_requests') hist_toolbars = history.last(max_visible_requests) return {'panels': toolbar.panels if toolbar else [], 'static_path': static_path, 'root_path': root_path, 'button_style': button_style, 'history': hist_toolbars, 'default_active_panels': ( toolbar.default_active_panels if toolbar else []), 'global_panels': toolbar.global_panels if toolbar else [], 'request_id': request_id } U_BLANK = text_("") U_SSE_PAYLOAD = text_("id:{0}\nevent: new_request\ndata:{1}\n\n") @view_config(route_name='debugtoolbar.sse') def sse(request): response = request.response response.content_type = 'text/event-stream' history = request.pdtb_history response.text = U_BLANK active_request_id = text_(request.GET.get('request_id')) client_last_request_id = text_(request.headers.get('Last-Event-Id', 0)) max_visible_requests = get_setting(request.registry.settings, 'max_visible_requests')
def render(self): return SOURCE_LINE_HTML % { 'classes': text_(' '.join(self.classes)), 'lineno': self.lineno, 'code': escape(self.code) }
def process_response_deferred(self): if self.response: response = self.response response_headers = [(text_(k), text_(v)) for k, v in sorted(response.headerlist)] self.data['response_headers'] = response_headers