~malept/ubuntu/lucid/python2.6/dev-dependency-fix

« back to all changes in this revision

Viewing changes to Lib/pprint.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-13 12:51:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090213125100-uufgcb9yeqzujpqw
Tags: upstream-2.6.1
ImportĀ upstreamĀ versionĀ 2.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#  Author:      Fred L. Drake, Jr.
 
2
#               fdrake@acm.org
 
3
#
 
4
#  This is a simple little module I wrote to make life easier.  I didn't
 
5
#  see anything quite like it in the library, though I may have overlooked
 
6
#  something.  I wrote this when I was trying to read some heavily nested
 
7
#  tuples with fairly non-descriptive content.  This is modeled very much
 
8
#  after Lisp/Scheme - style pretty-printing of lists.  If you find it
 
9
#  useful, thank small children who sleep at night.
 
10
 
 
11
"""Support to pretty-print lists, tuples, & dictionaries recursively.
 
12
 
 
13
Very simple, but useful, especially in debugging data structures.
 
14
 
 
15
Classes
 
16
-------
 
17
 
 
18
PrettyPrinter()
 
19
    Handle pretty-printing operations onto a stream using a configured
 
20
    set of formatting parameters.
 
21
 
 
22
Functions
 
23
---------
 
24
 
 
25
pformat()
 
26
    Format a Python object into a pretty-printed representation.
 
27
 
 
28
pprint()
 
29
    Pretty-print a Python object to a stream [default is sys.stdout].
 
30
 
 
31
saferepr()
 
32
    Generate a 'standard' repr()-like value, but protect against recursive
 
33
    data structures.
 
34
 
 
35
"""
 
36
 
 
37
import sys as _sys
 
38
 
 
39
from cStringIO import StringIO as _StringIO
 
40
 
 
41
__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr",
 
42
           "PrettyPrinter"]
 
43
 
 
44
# cache these for faster access:
 
45
_commajoin = ", ".join
 
46
_id = id
 
47
_len = len
 
48
_type = type
 
49
 
 
50
 
 
51
def pprint(object, stream=None, indent=1, width=80, depth=None):
 
52
    """Pretty-print a Python object to a stream [default is sys.stdout]."""
 
53
    printer = PrettyPrinter(
 
54
        stream=stream, indent=indent, width=width, depth=depth)
 
55
    printer.pprint(object)
 
56
 
 
57
def pformat(object, indent=1, width=80, depth=None):
 
58
    """Format a Python object into a pretty-printed representation."""
 
59
    return PrettyPrinter(indent=indent, width=width, depth=depth).pformat(object)
 
60
 
 
61
def saferepr(object):
 
62
    """Version of repr() which can handle recursive data structures."""
 
63
    return _safe_repr(object, {}, None, 0)[0]
 
64
 
 
65
def isreadable(object):
 
66
    """Determine if saferepr(object) is readable by eval()."""
 
67
    return _safe_repr(object, {}, None, 0)[1]
 
68
 
 
69
def isrecursive(object):
 
70
    """Determine if object requires a recursive representation."""
 
71
    return _safe_repr(object, {}, None, 0)[2]
 
72
 
 
73
class PrettyPrinter:
 
74
    def __init__(self, indent=1, width=80, depth=None, stream=None):
 
75
        """Handle pretty printing operations onto a stream using a set of
 
76
        configured parameters.
 
77
 
 
78
        indent
 
79
            Number of spaces to indent for each level of nesting.
 
80
 
 
81
        width
 
82
            Attempted maximum number of columns in the output.
 
83
 
 
84
        depth
 
85
            The maximum depth to print out nested structures.
 
86
 
 
87
        stream
 
88
            The desired output stream.  If omitted (or false), the standard
 
89
            output stream available at construction will be used.
 
90
 
 
91
        """
 
92
        indent = int(indent)
 
93
        width = int(width)
 
94
        assert indent >= 0, "indent must be >= 0"
 
95
        assert depth is None or depth > 0, "depth must be > 0"
 
96
        assert width, "width must be != 0"
 
97
        self._depth = depth
 
98
        self._indent_per_level = indent
 
99
        self._width = width
 
100
        if stream is not None:
 
101
            self._stream = stream
 
102
        else:
 
103
            self._stream = _sys.stdout
 
104
 
 
105
    def pprint(self, object):
 
106
        self._format(object, self._stream, 0, 0, {}, 0)
 
107
        self._stream.write("\n")
 
108
 
 
109
    def pformat(self, object):
 
110
        sio = _StringIO()
 
111
        self._format(object, sio, 0, 0, {}, 0)
 
112
        return sio.getvalue()
 
113
 
 
114
    def isrecursive(self, object):
 
115
        return self.format(object, {}, 0, 0)[2]
 
116
 
 
117
    def isreadable(self, object):
 
118
        s, readable, recursive = self.format(object, {}, 0, 0)
 
119
        return readable and not recursive
 
120
 
 
121
    def _format(self, object, stream, indent, allowance, context, level):
 
122
        level = level + 1
 
123
        objid = _id(object)
 
124
        if objid in context:
 
125
            stream.write(_recursion(object))
 
126
            self._recursive = True
 
127
            self._readable = False
 
128
            return
 
129
        rep = self._repr(object, context, level - 1)
 
130
        typ = _type(object)
 
131
        sepLines = _len(rep) > (self._width - 1 - indent - allowance)
 
132
        write = stream.write
 
133
 
 
134
        if self._depth and level > self._depth:
 
135
            write(rep)
 
136
            return
 
137
 
 
138
        r = getattr(typ, "__repr__", None)
 
139
        if issubclass(typ, dict) and r is dict.__repr__:
 
140
            write('{')
 
141
            if self._indent_per_level > 1:
 
142
                write((self._indent_per_level - 1) * ' ')
 
143
            length = _len(object)
 
144
            if length:
 
145
                context[objid] = 1
 
146
                indent = indent + self._indent_per_level
 
147
                items  = object.items()
 
148
                items.sort()
 
149
                key, ent = items[0]
 
150
                rep = self._repr(key, context, level)
 
151
                write(rep)
 
152
                write(': ')
 
153
                self._format(ent, stream, indent + _len(rep) + 2,
 
154
                              allowance + 1, context, level)
 
155
                if length > 1:
 
156
                    for key, ent in items[1:]:
 
157
                        rep = self._repr(key, context, level)
 
158
                        if sepLines:
 
159
                            write(',\n%s%s: ' % (' '*indent, rep))
 
160
                        else:
 
161
                            write(', %s: ' % rep)
 
162
                        self._format(ent, stream, indent + _len(rep) + 2,
 
163
                                      allowance + 1, context, level)
 
164
                indent = indent - self._indent_per_level
 
165
                del context[objid]
 
166
            write('}')
 
167
            return
 
168
 
 
169
        if ((issubclass(typ, list) and r is list.__repr__) or
 
170
            (issubclass(typ, tuple) and r is tuple.__repr__) or
 
171
            (issubclass(typ, set) and r is set.__repr__) or
 
172
            (issubclass(typ, frozenset) and r is frozenset.__repr__)
 
173
           ):
 
174
            length = _len(object)
 
175
            if issubclass(typ, list):
 
176
                write('[')
 
177
                endchar = ']'
 
178
            elif issubclass(typ, set):
 
179
                if not length:
 
180
                    write('set()')
 
181
                    return
 
182
                write('set([')
 
183
                endchar = '])'
 
184
                object = sorted(object)
 
185
                indent += 4
 
186
            elif issubclass(typ, frozenset):
 
187
                if not length:
 
188
                    write('frozenset()')
 
189
                    return
 
190
                write('frozenset([')
 
191
                endchar = '])'
 
192
                object = sorted(object)
 
193
                indent += 10
 
194
            else:
 
195
                write('(')
 
196
                endchar = ')'
 
197
            if self._indent_per_level > 1 and sepLines:
 
198
                write((self._indent_per_level - 1) * ' ')
 
199
            if length:
 
200
                context[objid] = 1
 
201
                indent = indent + self._indent_per_level
 
202
                self._format(object[0], stream, indent, allowance + 1,
 
203
                             context, level)
 
204
                if length > 1:
 
205
                    for ent in object[1:]:
 
206
                        if sepLines:
 
207
                            write(',\n' + ' '*indent)
 
208
                        else:
 
209
                            write(', ')
 
210
                        self._format(ent, stream, indent,
 
211
                                      allowance + 1, context, level)
 
212
                indent = indent - self._indent_per_level
 
213
                del context[objid]
 
214
            if issubclass(typ, tuple) and length == 1:
 
215
                write(',')
 
216
            write(endchar)
 
217
            return
 
218
 
 
219
        write(rep)
 
220
 
 
221
    def _repr(self, object, context, level):
 
222
        repr, readable, recursive = self.format(object, context.copy(),
 
223
                                                self._depth, level)
 
224
        if not readable:
 
225
            self._readable = False
 
226
        if recursive:
 
227
            self._recursive = True
 
228
        return repr
 
229
 
 
230
    def format(self, object, context, maxlevels, level):
 
231
        """Format object for a specific context, returning a string
 
232
        and flags indicating whether the representation is 'readable'
 
233
        and whether the object represents a recursive construct.
 
234
        """
 
235
        return _safe_repr(object, context, maxlevels, level)
 
236
 
 
237
 
 
238
# Return triple (repr_string, isreadable, isrecursive).
 
239
 
 
240
def _safe_repr(object, context, maxlevels, level):
 
241
    typ = _type(object)
 
242
    if typ is str:
 
243
        if 'locale' not in _sys.modules:
 
244
            return repr(object), True, False
 
245
        if "'" in object and '"' not in object:
 
246
            closure = '"'
 
247
            quotes = {'"': '\\"'}
 
248
        else:
 
249
            closure = "'"
 
250
            quotes = {"'": "\\'"}
 
251
        qget = quotes.get
 
252
        sio = _StringIO()
 
253
        write = sio.write
 
254
        for char in object:
 
255
            if char.isalpha():
 
256
                write(char)
 
257
            else:
 
258
                write(qget(char, repr(char)[1:-1]))
 
259
        return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False
 
260
 
 
261
    r = getattr(typ, "__repr__", None)
 
262
    if issubclass(typ, dict) and r is dict.__repr__:
 
263
        if not object:
 
264
            return "{}", True, False
 
265
        objid = _id(object)
 
266
        if maxlevels and level >= maxlevels:
 
267
            return "{...}", False, objid in context
 
268
        if objid in context:
 
269
            return _recursion(object), False, True
 
270
        context[objid] = 1
 
271
        readable = True
 
272
        recursive = False
 
273
        components = []
 
274
        append = components.append
 
275
        level += 1
 
276
        saferepr = _safe_repr
 
277
        for k, v in sorted(object.items()):
 
278
            krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
 
279
            vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
 
280
            append("%s: %s" % (krepr, vrepr))
 
281
            readable = readable and kreadable and vreadable
 
282
            if krecur or vrecur:
 
283
                recursive = True
 
284
        del context[objid]
 
285
        return "{%s}" % _commajoin(components), readable, recursive
 
286
 
 
287
    if (issubclass(typ, list) and r is list.__repr__) or \
 
288
       (issubclass(typ, tuple) and r is tuple.__repr__):
 
289
        if issubclass(typ, list):
 
290
            if not object:
 
291
                return "[]", True, False
 
292
            format = "[%s]"
 
293
        elif _len(object) == 1:
 
294
            format = "(%s,)"
 
295
        else:
 
296
            if not object:
 
297
                return "()", True, False
 
298
            format = "(%s)"
 
299
        objid = _id(object)
 
300
        if maxlevels and level >= maxlevels:
 
301
            return format % "...", False, objid in context
 
302
        if objid in context:
 
303
            return _recursion(object), False, True
 
304
        context[objid] = 1
 
305
        readable = True
 
306
        recursive = False
 
307
        components = []
 
308
        append = components.append
 
309
        level += 1
 
310
        for o in object:
 
311
            orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)
 
312
            append(orepr)
 
313
            if not oreadable:
 
314
                readable = False
 
315
            if orecur:
 
316
                recursive = True
 
317
        del context[objid]
 
318
        return format % _commajoin(components), readable, recursive
 
319
 
 
320
    rep = repr(object)
 
321
    return rep, (rep and not rep.startswith('<')), False
 
322
 
 
323
 
 
324
def _recursion(object):
 
325
    return ("<Recursion on %s with id=%s>"
 
326
            % (_type(object).__name__, _id(object)))
 
327
 
 
328
 
 
329
def _perfcheck(object=None):
 
330
    import time
 
331
    if object is None:
 
332
        object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
 
333
    p = PrettyPrinter()
 
334
    t1 = time.time()
 
335
    _safe_repr(object, {}, None, 0)
 
336
    t2 = time.time()
 
337
    p.pformat(object)
 
338
    t3 = time.time()
 
339
    print "_safe_repr:", t2 - t1
 
340
    print "pformat:", t3 - t2
 
341
 
 
342
if __name__ == "__main__":
 
343
    _perfcheck()