Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/websdk/werkzeug/debug/repr.py
diff options
context:
space:
mode:
Diffstat (limited to 'websdk/werkzeug/debug/repr.py')
-rw-r--r--websdk/werkzeug/debug/repr.py267
1 files changed, 267 insertions, 0 deletions
diff --git a/websdk/werkzeug/debug/repr.py b/websdk/werkzeug/debug/repr.py
new file mode 100644
index 0000000..a6a54a9
--- /dev/null
+++ b/websdk/werkzeug/debug/repr.py
@@ -0,0 +1,267 @@
+# -*- coding: utf-8 -*-
+"""
+ werkzeug.debug.repr
+ ~~~~~~~~~~~~~~~~~~~
+
+ This module implements object representations for debugging purposes.
+ Unlike the default repr these reprs expose a lot more information and
+ produce HTML instead of ASCII.
+
+ Together with the CSS and JavaScript files of the debugger this gives
+ a colorful and more compact output.
+
+ :copyright: (c) 2011 by the Werkzeug Team, see AUTHORS for more details.
+ :license: BSD.
+"""
+import sys
+import re
+from traceback import format_exception_only
+try:
+ from collections import deque
+except ImportError: # pragma: no cover
+ deque = None
+from werkzeug.utils import escape
+
+
+missing = object()
+_paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')
+RegexType = type(_paragraph_re)
+
+
+HELP_HTML = '''\
+<div class=box>
+ <h3>%(title)s</h3>
+ <pre class=help>%(text)s</pre>
+</div>\
+'''
+OBJECT_DUMP_HTML = '''\
+<div class=box>
+ <h3>%(title)s</h3>
+ %(repr)s
+ <table>%(items)s</table>
+</div>\
+'''
+
+
+def debug_repr(obj):
+ """Creates a debug repr of an object as HTML unicode string."""
+ return DebugReprGenerator().repr(obj)
+
+
+def dump(obj=missing):
+ """Print the object details to stdout._write (for the interactive
+ console of the web debugger.
+ """
+ gen = DebugReprGenerator()
+ if obj is missing:
+ rv = gen.dump_locals(sys._getframe(1).f_locals)
+ else:
+ rv = gen.dump_object(obj)
+ sys.stdout._write(rv)
+
+
+class _Helper(object):
+ """Displays an HTML version of the normal help, for the interactive
+ debugger only because it requires a patched sys.stdout.
+ """
+
+ def __repr__(self):
+ return 'Type help(object) for help about object.'
+
+ 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 = sys.stdout.reset().decode('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})
+
+
+helper = _Helper()
+
+
+def _add_subclass_info(inner, obj, base):
+ if isinstance(base, tuple):
+ for base in base:
+ if type(obj) is base:
+ return inner
+ elif type(obj) is base:
+ return inner
+ module = ''
+ if obj.__class__.__module__ not in ('__builtin__', 'exceptions'):
+ module = '<span class="module">%s.</span>' % obj.__class__.__module__
+ return '%s%s(%s)' % (module, obj.__class__.__name__, inner)
+
+
+class DebugReprGenerator(object):
+
+ def __init__(self):
+ self._stack = []
+
+ def _sequence_repr_maker(left, right, base=object(), limit=8):
+ 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(u''.join(buf), obj, base)
+ return proxy
+
+ list_repr = _sequence_repr_maker('[', ']', list)
+ tuple_repr = _sequence_repr_maker('(', ')', tuple)
+ set_repr = _sequence_repr_maker('set([', '])', set)
+ frozenset_repr = _sequence_repr_maker('frozenset([', '])', frozenset)
+ if deque is not None:
+ deque_repr = _sequence_repr_maker('<span class="module">collections.'
+ '</span>deque([', '])', deque)
+ del _sequence_repr_maker
+
+ def regex_repr(self, obj):
+ pattern = repr(obj.pattern).decode('string-escape', 'ignore')
+ if pattern[:1] == 'u':
+ pattern = 'ur' + pattern[1:]
+ else:
+ pattern = 'r' + pattern
+ return u're.compile(<span class="string regex">%s</span>)' % pattern
+
+ def string_repr(self, obj, limit=70):
+ buf = ['<span class="string">']
+ escaped = escape(obj)
+ a = repr(escaped[:limit])
+ b = repr(escaped[limit:])
+ if isinstance(obj, unicode):
+ 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(u''.join(buf), obj, (str, unicode))
+
+ def dict_repr(self, d, recursive, limit=5):
+ if recursive:
+ return _add_subclass_info(u'{...}', d, dict)
+ buf = ['{']
+ have_extended_section = False
+ for idx, (key, value) in enumerate(d.iteritems()):
+ 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(u''.join(buf), d, dict)
+
+ def object_repr(self, obj):
+ return u'<span class="object">%s</span>' % \
+ escape(repr(obj).decode('utf-8', 'replace'))
+
+ def dispatch_repr(self, obj, recursive):
+ if obj is helper:
+ return u'<span class="help">%r</span>' % helper
+ if isinstance(obj, (int, long, float, complex)):
+ return u'<span class="number">%r</span>' % obj
+ if isinstance(obj, basestring):
+ return self.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 fallback_repr(self):
+ try:
+ info = ''.join(format_exception_only(*sys.exc_info()[:2]))
+ except Exception: # pragma: no cover
+ info = '?'
+ return u'<span class="brokenrepr">&lt;broken repr (%s)&gt;' \
+ u'</span>' % escape(info.decode('utf-8', 'ignore').strip())
+
+ def repr(self, obj):
+ recursive = False
+ for item in self._stack:
+ if item is obj:
+ recursive = True
+ break
+ self._stack.append(obj)
+ try:
+ try:
+ return self.dispatch_repr(obj, recursive)
+ except Exception:
+ return self.fallback_repr()
+ finally:
+ self._stack.pop()
+
+ def dump_object(self, obj):
+ repr = items = None
+ if isinstance(obj, dict):
+ title = 'Contents of'
+ items = []
+ for key, value in obj.iteritems():
+ if not isinstance(key, basestring):
+ items = None
+ break
+ items.append((key, self.repr(value)))
+ if items is None:
+ items = []
+ repr = self.repr(obj)
+ for key in dir(obj):
+ try:
+ items.append((key, self.repr(getattr(obj, key))))
+ except Exception:
+ pass
+ title = 'Details for'
+ title += ' ' + object.__repr__(obj)[1:-1]
+ return self.render_object_dump(items, title, repr)
+
+ def dump_locals(self, d):
+ items = [(key, self.repr(value)) for key, value in d.items()]
+ return self.render_object_dump(items, 'Local variables in frame')
+
+ def render_object_dump(self, items, title, repr=None):
+ html_items = []
+ for key, value in items:
+ html_items.append('<tr><th>%s<td><pre class=repr>%s</pre>' %
+ (escape(key), value))
+ if not html_items:
+ html_items.append('<tr><td><em>Nothing</em>')
+ return OBJECT_DUMP_HTML % {
+ 'title': escape(title),
+ 'repr': repr and '<pre class=repr>%s</pre>' % repr or '',
+ 'items': '\n'.join(html_items)
+ }