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
._format
(object, self
._stream
, 0, 0, {}, 0)
107 self
._stream
.write("\n")
109 def pformat(self
, object):
111 self
._format
(object, sio
, 0, 0, {}, 0)
112 return sio
.getvalue()
114 def isrecursive(self
, object):
115 return self
.format(object, {}, 0, 0)[2]
117 def isreadable(self
, object):
118 s
, readable
, recursive
= self
.format(object, {}, 0, 0)
119 return readable
and not recursive
121 def _format(self
, object, stream
, indent
, allowance
, context
, level
):
125 stream
.write(_recursion(object))
126 self
._recursive
= True
127 self
._readable
= False
129 rep
= self
._repr
(object, context
, level
- 1)
131 sepLines
= _len(rep
) > (self
._width
- 1 - indent
- allowance
)
135 r
= getattr(typ
, "__repr__", None)
136 if issubclass(typ
, dict) and r
is dict.__repr
__:
138 if self
._indent
_per
_level
> 1:
139 write((self
._indent
_per
_level
- 1) * ' ')
140 length
= _len(object)
143 indent
= indent
+ self
._indent
_per
_level
144 items
= object.items()
147 rep
= self
._repr
(key
, context
, level
)
150 self
._format
(ent
, stream
, indent
+ _len(rep
) + 2,
151 allowance
+ 1, context
, level
)
153 for key
, ent
in items
[1:]:
154 rep
= self
._repr
(key
, context
, level
)
155 write(',\n%s%s: ' % (' '*indent
, rep
))
156 self
._format
(ent
, stream
, indent
+ _len(rep
) + 2,
157 allowance
+ 1, context
, level
)
158 indent
= indent
- self
._indent
_per
_level
163 if (issubclass(typ
, list) and r
is list.__repr
__) or \
164 (issubclass(typ
, tuple) and r
is tuple.__repr
__):
165 if issubclass(typ
, list):
171 if self
._indent
_per
_level
> 1:
172 write((self
._indent
_per
_level
- 1) * ' ')
173 length
= _len(object)
176 indent
= indent
+ self
._indent
_per
_level
177 self
._format
(object[0], stream
, indent
, allowance
+ 1,
180 for ent
in object[1:]:
181 write(',\n' + ' '*indent
)
182 self
._format
(ent
, stream
, indent
,
183 allowance
+ 1, context
, level
)
184 indent
= indent
- self
._indent
_per
_level
186 if issubclass(typ
, tuple) and length
== 1:
193 def _repr(self
, object, context
, level
):
194 repr, readable
, recursive
= self
.format(object, context
.copy(),
197 self
._readable
= False
199 self
._recursive
= True
202 def format(self
, object, context
, maxlevels
, level
):
203 """Format object for a specific context, returning a string
204 and flags indicating whether the representation is 'readable'
205 and whether the object represents a recursive construct.
207 return _safe_repr(object, context
, maxlevels
, level
)
210 # Return triple (repr_string, isreadable, isrecursive).
212 def _safe_repr(object, context
, maxlevels
, level
):
215 if 'locale' not in _sys
.modules
:
216 return repr(object), True, False
217 if "'" in object and '"' not in object:
219 quotes
= {'"': '\\"'}
222 quotes
= {"'": "\\'"}
230 write(qget(char
, repr(char
)[1:-1]))
231 return ("%s%s%s" % (closure
, sio
.getvalue(), closure
)), True, False
233 r
= getattr(typ
, "__repr__", None)
234 if issubclass(typ
, dict) and r
is dict.__repr
__:
236 return "{}", True, False
238 if maxlevels
and level
> maxlevels
:
239 return "{...}", False, objid
in context
241 return _recursion(object), False, True
246 append
= components
.append
248 saferepr
= _safe_repr
249 for k
, v
in sorted(object.items()):
250 krepr
, kreadable
, krecur
= saferepr(k
, context
, maxlevels
, level
)
251 vrepr
, vreadable
, vrecur
= saferepr(v
, context
, maxlevels
, level
)
252 append("%s: %s" % (krepr
, vrepr
))
253 readable
= readable
and kreadable
and vreadable
257 return "{%s}" % _commajoin(components
), readable
, recursive
259 if (issubclass(typ
, list) and r
is list.__repr
__) or \
260 (issubclass(typ
, tuple) and r
is tuple.__repr
__):
261 if issubclass(typ
, list):
263 return "[]", True, False
265 elif _len(object) == 1:
269 return "()", True, False
272 if maxlevels
and level
> maxlevels
:
273 return format
% "...", False, objid
in context
275 return _recursion(object), False, True
280 append
= components
.append
283 orepr
, oreadable
, orecur
= _safe_repr(o
, context
, maxlevels
, level
)
290 return format
% _commajoin(components
), readable
, recursive
293 return rep
, (rep
and not rep
.startswith('<')), False
296 def _recursion(object):
297 return ("<Recursion on %s with id=%s>"
298 % (_type(object).__name
__, _id(object)))
301 def _perfcheck(object=None):
304 object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
307 _safe_repr(object, {}, None, 0)
311 print "_safe_repr:", t2
- t1
312 print "pformat:", t3
- t2
314 if __name__
== "__main__":