1 # Author: Fred L. Drake, Jr.
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.
11 """Support to pretty-print lists, tuples, & dictionaries recursively.
13 Very simple, but useful, especially in debugging data structures.
19 Handle pretty-printing operations onto a stream using a configured
20 set of formatting parameters.
26 Format a Python object into a pretty-printed representation.
29 Pretty-print a Python object to a stream [default is sys.stdout].
32 Generate a 'standard' repr()-like value, but protect against recursive
39 from cStringIO
import StringIO
as _StringIO
41 __all__
= ["pprint","pformat","isreadable","isrecursive","saferepr",
44 # cache these for faster access:
45 _commajoin
= ", ".join
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)
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)
62 """Version of repr() which can handle recursive data structures."""
63 return _safe_repr(object, {}, None, 0)[0]
65 def isreadable(object):
66 """Determine if saferepr(object) is readable by eval()."""
67 return _safe_repr(object, {}, None, 0)[1]
69 def isrecursive(object):
70 """Determine if object requires a recursive representation."""
71 return _safe_repr(object, {}, None, 0)[2]
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.
79 Number of spaces to indent for each level of nesting.
82 Attempted maximum number of columns in the output.
85 The maximum depth to print out nested structures.
88 The desired output stream. If omitted (or false), the standard
89 output stream available at construction will be used.
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"
98 self
._indent
_per
_level
= indent
100 if stream
is not None:
101 self
._stream
= stream
103 self
._stream
= _sys
.stdout
105 def pprint(self
, object):
106 self
._stream
.write(self
.pformat(object) + "\n")
108 def pformat(self
, object):
110 self
._format
(object, sio
, 0, 0, {}, 0)
111 return sio
.getvalue()
113 def isrecursive(self
, object):
114 return self
.format(object, {}, 0, 0)[2]
116 def isreadable(self
, object):
117 s
, readable
, recursive
= self
.format(object, {}, 0, 0)
118 return readable
and not recursive
120 def _format(self
, object, stream
, indent
, allowance
, context
, level
):
124 stream
.write(_recursion(object))
125 self
._recursive
= True
126 self
._readable
= False
128 rep
= self
._repr
(object, context
, level
- 1)
130 sepLines
= _len(rep
) > (self
._width
- 1 - indent
- allowance
)
134 r
= getattr(typ
, "__repr__", None)
135 if issubclass(typ
, dict) and r
is dict.__repr
__:
137 if self
._indent
_per
_level
> 1:
138 write((self
._indent
_per
_level
- 1) * ' ')
139 length
= _len(object)
142 indent
= indent
+ self
._indent
_per
_level
143 items
= object.items()
146 rep
= self
._repr
(key
, context
, level
)
149 self
._format
(ent
, stream
, indent
+ _len(rep
) + 2,
150 allowance
+ 1, context
, level
)
152 for key
, ent
in items
[1:]:
153 rep
= self
._repr
(key
, context
, level
)
154 write(',\n%s%s: ' % (' '*indent
, rep
))
155 self
._format
(ent
, stream
, indent
+ _len(rep
) + 2,
156 allowance
+ 1, context
, level
)
157 indent
= indent
- self
._indent
_per
_level
162 if (issubclass(typ
, list) and r
is list.__repr
__) or \
163 (issubclass(typ
, tuple) and r
is tuple.__repr
__):
164 if issubclass(typ
, list):
170 if self
._indent
_per
_level
> 1:
171 write((self
._indent
_per
_level
- 1) * ' ')
172 length
= _len(object)
175 indent
= indent
+ self
._indent
_per
_level
176 self
._format
(object[0], stream
, indent
, allowance
+ 1,
179 for ent
in object[1:]:
180 write(',\n' + ' '*indent
)
181 self
._format
(ent
, stream
, indent
,
182 allowance
+ 1, context
, level
)
183 indent
= indent
- self
._indent
_per
_level
185 if issubclass(typ
, tuple) and length
== 1:
192 def _repr(self
, object, context
, level
):
193 repr, readable
, recursive
= self
.format(object, context
.copy(),
196 self
._readable
= False
198 self
._recursive
= True
201 def format(self
, object, context
, maxlevels
, level
):
202 """Format object for a specific context, returning a string
203 and flags indicating whether the representation is 'readable'
204 and whether the object represents a recursive construct.
206 return _safe_repr(object, context
, maxlevels
, level
)
209 # Return triple (repr_string, isreadable, isrecursive).
211 def _safe_repr(object, context
, maxlevels
, level
):
214 if 'locale' not in _sys
.modules
:
215 return repr(object), True, False
216 if "'" in object and '"' not in object:
218 quotes
= {'"': '\\"'}
221 quotes
= {"'": "\\'"}
229 write(qget(char
, repr(char
)[1:-1]))
230 return ("%s%s%s" % (closure
, sio
.getvalue(), closure
)), True, False
232 r
= getattr(typ
, "__repr__", None)
233 if issubclass(typ
, dict) and r
is dict.__repr
__:
235 return "{}", True, False
237 if maxlevels
and level
> maxlevels
:
238 return "{...}", False, objid
in context
240 return _recursion(object), False, True
245 append
= components
.append
247 saferepr
= _safe_repr
248 for k
, v
in object.iteritems():
249 krepr
, kreadable
, krecur
= saferepr(k
, context
, maxlevels
, level
)
250 vrepr
, vreadable
, vrecur
= saferepr(v
, context
, maxlevels
, level
)
251 append("%s: %s" % (krepr
, vrepr
))
252 readable
= readable
and kreadable
and vreadable
256 return "{%s}" % _commajoin(components
), readable
, recursive
258 if (issubclass(typ
, list) and r
is list.__repr
__) or \
259 (issubclass(typ
, tuple) and r
is tuple.__repr
__):
260 if issubclass(typ
, list):
262 return "[]", True, False
264 elif _len(object) == 1:
268 return "()", True, False
271 if maxlevels
and level
> maxlevels
:
272 return format
% "...", False, objid
in context
274 return _recursion(object), False, True
279 append
= components
.append
282 orepr
, oreadable
, orecur
= _safe_repr(o
, context
, maxlevels
, level
)
289 return format
% _commajoin(components
), readable
, recursive
292 return rep
, (rep
and not rep
.startswith('<')), False
295 def _recursion(object):
296 return ("<Recursion on %s with id=%s>"
297 % (_type(object).__name
__, _id(object)))
300 def _perfcheck(object=None):
303 object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
306 _safe_repr(object, {}, None, 0)
310 print "_safe_repr:", t2
- t1
311 print "pformat:", t3
- t2
313 if __name__
== "__main__":