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.sydout].
32 Generate a 'standard' repr()-like value, but protect against recursive
37 from types
import DictType
, ListType
, TupleType
, StringType
41 from cStringIO
import StringIO
43 from StringIO
import StringIO
45 __all__
= ["pprint","pformat","isreadable","isrecursive","saferepr",
48 # cache these for faster access:
49 _commajoin
= ", ".join
50 _sys_modules
= sys
.modules
56 def pprint(object, stream
=None):
57 """Pretty-print a Python object to a stream [default is sys.sydout]."""
58 printer
= PrettyPrinter(stream
=stream
)
59 printer
.pprint(object)
62 """Format a Python object into a pretty-printed representation."""
63 return PrettyPrinter().pformat(object)
66 """Version of repr() which can handle recursive data structures."""
67 return _safe_repr(object, {}, None, 0)[0]
69 def isreadable(object):
70 """Determine if saferepr(object) is readable by eval()."""
71 return _safe_repr(object, {}, None, 0)[1]
73 def isrecursive(object):
74 """Determine if object requires a recursive representation."""
75 return _safe_repr(object, {}, None, 0)[2]
78 def __init__(self
, indent
=1, width
=80, depth
=None, stream
=None):
79 """Handle pretty printing operations onto a stream using a set of
80 configured parameters.
83 Number of spaces to indent for each level of nesting.
86 Attempted maximum number of columns in the output.
89 The maximum depth to print out nested structures.
92 The desired output stream. If omitted (or false), the standard
93 output stream available at construction will be used.
99 assert depth
is None or depth
> 0, "depth must be > 0"
102 self
.__indent
_per
_level
= indent
105 self
.__stream
= stream
107 self
.__stream
= sys
.stdout
109 def pprint(self
, object):
110 self
.__stream
.write(self
.pformat(object) + "\n")
112 def pformat(self
, object):
114 self
.__format
(object, sio
, 0, 0, {}, 0)
115 return sio
.getvalue()
117 def isrecursive(self
, object):
119 self
.__repr
(object, {}, 0)
120 return self
.__recursive
122 def isreadable(self
, object):
125 self
.__repr
(object, {}, 0)
126 return self
.__readable
and not self
.__recursive
128 def __format(self
, object, stream
, indent
, allowance
, context
, level
):
132 stream
.write(_recursion(object))
136 rep
= self
.__repr
(object, context
, level
- 1)
138 sepLines
= _len(rep
) > (self
.__width
- 1 - indent
- allowance
)
144 if self
.__indent
_per
_level
> 1:
145 write((self
.__indent
_per
_level
- 1) * ' ')
146 length
= _len(object)
149 indent
= indent
+ self
.__indent
_per
_level
150 items
= object.items()
153 rep
= self
.__repr
(key
, context
, level
)
156 self
.__format
(ent
, stream
, indent
+ _len(rep
) + 2,
157 allowance
+ 1, context
, level
)
159 for key
, ent
in items
[1:]:
160 rep
= self
.__repr
(key
, context
, level
)
161 write(',\n%s%s: ' % (' '*indent
, rep
))
162 self
.__format
(ent
, stream
, indent
+ _len(rep
) + 2,
163 allowance
+ 1, context
, level
)
164 indent
= indent
- self
.__indent
_per
_level
169 if typ
is ListType
or typ
is TupleType
:
176 if self
.__indent
_per
_level
> 1:
177 write((self
.__indent
_per
_level
- 1) * ' ')
178 length
= _len(object)
181 indent
= indent
+ self
.__indent
_per
_level
182 self
.__format
(object[0], stream
, indent
, allowance
+ 1,
185 for ent
in object[1:]:
186 write(',\n' + ' '*indent
)
187 self
.__format
(ent
, stream
, indent
,
188 allowance
+ 1, context
, level
)
189 indent
= indent
- self
.__indent
_per
_level
191 if typ
is TupleType
and length
== 1:
198 def __repr(self
, object, context
, level
):
199 repr, readable
, recursive
= _safe_repr(object, context
,
207 # Return triple (repr_string, isreadable, isrecursive).
209 def _safe_repr(object, context
, maxlevels
, level
):
211 if typ
is StringType
:
212 if 'locale' not in _sys_modules
:
213 return `
object`
, 1, 0
214 if "'" in object and '"' not in object:
216 quotes
= {'"': '\\"'}
219 quotes
= {"'": "\\'"}
227 write(qget(char
, `char`
[1:-1]))
228 return ("%s%s%s" % (closure
, sio
.getvalue(), closure
)), 1, 0
234 if maxlevels
and level
> maxlevels
:
235 return "{...}", 0, objid
in context
237 return _recursion(object), 0, 1
242 append
= components
.append
244 saferepr
= _safe_repr
245 for k
, v
in object.iteritems():
246 krepr
, kreadable
, krecur
= saferepr(k
, context
, maxlevels
, level
)
247 vrepr
, vreadable
, vrecur
= saferepr(v
, context
, maxlevels
, level
)
248 append("%s: %s" % (krepr
, vrepr
))
249 readable
= readable
and kreadable
and vreadable
253 return "{%s}" % _commajoin(components
), readable
, recursive
255 if typ
is ListType
or typ
is TupleType
:
260 elif _len(object) == 1:
267 if maxlevels
and level
> maxlevels
:
268 return format
% "...", 0, objid
in context
270 return _recursion(object), 0, 1
275 append
= components
.append
278 orepr
, oreadable
, orecur
= _safe_repr(o
, context
, maxlevels
, level
)
285 return format
% _commajoin(components
), readable
, recursive
288 return rep
, (rep
and not rep
.startswith('<')), 0
291 def _recursion(object):
292 return ("<Recursion on %s with id=%s>"
293 % (_type(object).__name
__, _id(object)))
296 def _perfcheck(object=None):
299 object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
302 _safe_repr(object, {}, None, 0)
306 print "_safe_repr:", t2
- t1
307 print "pformat:", t3
- t2
309 if __name__
== "__main__":