~ubuntu-branches/ubuntu/natty/moin/natty-updates

« back to all changes in this revision

Viewing changes to MoinMoin/support/werkzeug/debug/repr.py

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2008-06-22 21:17:13 UTC
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20080622211713-inlv5k4eifxckelr
ImportĀ upstreamĀ versionĀ 1.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
"""
3
 
    werkzeug.debug.repr
4
 
    ~~~~~~~~~~~~~~~~~~~
5
 
 
6
 
    This module implements object representations for debugging purposes.
7
 
    Unlike the default repr these reprs expose a lot more information and
8
 
    produce HTML instead of ASCII.
9
 
 
10
 
    Together with the CSS and JavaScript files of the debugger this gives
11
 
    a colorful and more compact output.
12
 
 
13
 
    :copyright: (c) 2009 by the Werkzeug Team, see AUTHORS for more details.
14
 
    :license: BSD.
15
 
"""
16
 
import sys
17
 
import re
18
 
from traceback import format_exception_only
19
 
try:
20
 
    from collections import deque
21
 
except ImportError:
22
 
    deque = None
23
 
from werkzeug.utils import escape
24
 
from werkzeug.debug.utils import render_template
25
 
 
26
 
 
27
 
missing = object()
28
 
_paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')
29
 
RegexType = type(_paragraph_re)
30
 
 
31
 
 
32
 
def debug_repr(obj):
33
 
    """Creates a debug repr of an object as HTML unicode string."""
34
 
    return DebugReprGenerator().repr(obj)
35
 
 
36
 
 
37
 
def dump(obj=missing):
38
 
    """Print the object details to stdout._write (for the interactive
39
 
    console of the web debugger.
40
 
    """
41
 
    gen = DebugReprGenerator()
42
 
    if obj is missing:
43
 
        rv = gen.dump_locals(sys._getframe(1).f_locals)
44
 
    else:
45
 
        rv = gen.dump_object(obj)
46
 
    sys.stdout._write(rv)
47
 
 
48
 
 
49
 
class _Helper(object):
50
 
    """Displays an HTML version of the normal help, for the interactive
51
 
    debugger only because it requires a patched sys.stdout.
52
 
    """
53
 
 
54
 
    def __call__(self, topic=None):
55
 
        sys.stdout._write(self.get_help(topic))
56
 
 
57
 
    def get_help(self, topic):
58
 
        title = text = None
59
 
        if topic is not None:
60
 
            import pydoc
61
 
            pydoc.help(topic)
62
 
            rv = sys.stdout.reset().decode('utf-8', 'ignore')
63
 
            paragraphs = _paragraph_re.split(rv)
64
 
            if len(paragraphs) > 1:
65
 
                title = paragraphs[0]
66
 
                text = '\n\n'.join(paragraphs[1:])
67
 
            else:
68
 
                title = 'Help'
69
 
                text = paragraphs[0]
70
 
        return render_template('help_command.html', title=title, text=text)
71
 
 
72
 
helper = _Helper()
73
 
 
74
 
 
75
 
def _add_subclass_info(inner, obj, base):
76
 
    if isinstance(base, tuple):
77
 
        for base in base:
78
 
            if type(obj) is base:
79
 
                return inner
80
 
    elif type(obj) is base:
81
 
        return inner
82
 
    module = ''
83
 
    if obj.__class__.__module__ not in ('__builtin__', 'exceptions'):
84
 
        module = '<span class="module">%s.</span>' % obj.__class__.__module__
85
 
    return '%s%s(%s)' % (module, obj.__class__.__name__, inner)
86
 
 
87
 
 
88
 
class DebugReprGenerator(object):
89
 
 
90
 
    def __init__(self):
91
 
        self._stack = []
92
 
 
93
 
    def _sequence_repr_maker(left, right, base=object(), limit=8):
94
 
        def proxy(self, obj, recursive):
95
 
            if recursive:
96
 
                return _add_subclass_info(left + '...' + right, obj, base)
97
 
            buf = [left]
98
 
            have_extended_section = False
99
 
            for idx, item in enumerate(obj):
100
 
                if idx:
101
 
                    buf.append(', ')
102
 
                if idx == limit:
103
 
                    buf.append('<span class="extended">')
104
 
                    have_extended_section = True
105
 
                buf.append(self.repr(item))
106
 
            if have_extended_section:
107
 
                buf.append('</span>')
108
 
            buf.append(right)
109
 
            return _add_subclass_info(u''.join(buf), obj, base)
110
 
        return proxy
111
 
 
112
 
    list_repr = _sequence_repr_maker('[', ']', list)
113
 
    tuple_repr = _sequence_repr_maker('(', ')', tuple)
114
 
    set_repr = _sequence_repr_maker('set([', '])', set)
115
 
    frozenset_repr = _sequence_repr_maker('frozenset([', '])', frozenset)
116
 
    if deque is not None:
117
 
        deque_repr = _sequence_repr_maker('<span class="module">collections.'
118
 
                                          '</span>deque([', '])', deque)
119
 
    del _sequence_repr_maker
120
 
 
121
 
    def regex_repr(self, obj):
122
 
        pattern = repr(obj.pattern).decode('string-escape', 'ignore')
123
 
        if pattern[:1] == 'u':
124
 
            pattern = 'ur' + pattern[1:]
125
 
        else:
126
 
            pattern = 'r' + pattern
127
 
        return u're.compile(<span class="string regex">%s</span>)' % pattern
128
 
 
129
 
    def string_repr(self, obj, limit=70):
130
 
        buf = ['<span class="string">']
131
 
        escaped = escape(obj)
132
 
        a = repr(escaped[:limit])
133
 
        b = repr(escaped[limit:])
134
 
        if isinstance(obj, unicode):
135
 
            buf.append('u')
136
 
            a = a[1:]
137
 
            b = b[1:]
138
 
        if b != "''":
139
 
            buf.extend((a[:-1], '<span class="extended">', b[1:], '</span>'))
140
 
        else:
141
 
            buf.append(a)
142
 
        buf.append('</span>')
143
 
        return _add_subclass_info(u''.join(buf), obj, (str, unicode))
144
 
 
145
 
    def dict_repr(self, d, recursive, limit=5):
146
 
        if recursive:
147
 
            return _add_subclass_info(u'{...}', d, dict)
148
 
        buf = ['{']
149
 
        have_extended_section = False
150
 
        for idx, (key, value) in enumerate(d.iteritems()):
151
 
            if idx:
152
 
                buf.append(', ')
153
 
            if idx == limit - 1:
154
 
                buf.append('<span class="extended">')
155
 
                have_extended_section = True
156
 
            buf.append('<span class="pair"><span class="key">%s</span>: '
157
 
                       '<span class="value">%s</span></span>' %
158
 
                       (self.repr(key), self.repr(value)))
159
 
        if have_extended_section:
160
 
            buf.append('</span>')
161
 
        buf.append('}')
162
 
        return _add_subclass_info(u''.join(buf), d, dict)
163
 
 
164
 
    def object_repr(self, obj):
165
 
        return u'<span class="object">%s</span>' % \
166
 
               escape(repr(obj).decode('utf-8', 'replace'))
167
 
 
168
 
    def dispatch_repr(self, obj, recursive):
169
 
        if obj is helper:
170
 
            return helper.get_help(None)
171
 
        if isinstance(obj, (int, long, float, complex)):
172
 
            return u'<span class="number">%r</span>' % obj
173
 
        if isinstance(obj, basestring):
174
 
            return self.string_repr(obj)
175
 
        if isinstance(obj, RegexType):
176
 
            return self.regex_repr(obj)
177
 
        if isinstance(obj, list):
178
 
            return self.list_repr(obj, recursive)
179
 
        if isinstance(obj, tuple):
180
 
            return self.tuple_repr(obj, recursive)
181
 
        if isinstance(obj, set):
182
 
            return self.set_repr(obj, recursive)
183
 
        if isinstance(obj, frozenset):
184
 
            return self.frozenset_repr(obj, recursive)
185
 
        if isinstance(obj, dict):
186
 
            return self.dict_repr(obj, recursive)
187
 
        if deque is not None and isinstance(obj, deque):
188
 
            return self.deque_repr(obj, recursive)
189
 
        return self.object_repr(obj)
190
 
 
191
 
    def fallback_repr(self):
192
 
        try:
193
 
            info = ''.join(format_exception_only(*sys.exc_info()[:2]))
194
 
        except:
195
 
            info = '?'
196
 
        return u'<span class="brokenrepr">&lt;broken repr (%s)&gt;' \
197
 
               u'</span>' % escape(info.decode('utf-8', 'ignore').strip())
198
 
 
199
 
    def repr(self, obj):
200
 
        recursive = False
201
 
        for item in self._stack:
202
 
            if item is obj:
203
 
                recursive = True
204
 
                break
205
 
        self._stack.append(obj)
206
 
        try:
207
 
            try:
208
 
                return self.dispatch_repr(obj, recursive)
209
 
            except:
210
 
                return self.fallback_repr()
211
 
        finally:
212
 
            self._stack.pop()
213
 
 
214
 
    def dump_object(self, obj):
215
 
        repr = items = None
216
 
        if isinstance(obj, dict):
217
 
            title = 'Contents of'
218
 
            items = []
219
 
            for key, value in obj.iteritems():
220
 
                if not isinstance(key, basestring):
221
 
                    items = None
222
 
                    break
223
 
                items.append((key, self.repr(value)))
224
 
        if items is None:
225
 
            items = []
226
 
            repr = self.repr(obj)
227
 
            for key in dir(obj):
228
 
                try:
229
 
                    items.append((key, self.repr(getattr(obj, key))))
230
 
                except:
231
 
                    pass
232
 
            title = 'Details for'
233
 
        title += ' ' + object.__repr__(obj)[1:-1]
234
 
        return render_template('dump_object.html', items=items,
235
 
                               title=title, repr=repr)
236
 
 
237
 
    def dump_locals(self, d):
238
 
        items = [(key, self.repr(value)) for key, value in d.items()]
239
 
        return render_template('dump_object.html', items=items,
240
 
                               title='Local variables in frame', repr=None)