blob: 22be0b4bdb6fb73c4c4ac09e6cb67c1e4dea1ea3 [file] [log] [blame]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001# Author: Fred L. Drake, Jr.
Fred Drake3e5e6612001-10-09 20:53:48 +00002# fdrake@acm.org
Guido van Rossum5e92aff1997-04-16 00:49:59 +00003#
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
Thomas Wouters7e474022000-07-16 12:04:32 +00007# tuples with fairly non-descriptive content. This is modeled very much
Guido van Rossum5e92aff1997-04-16 00:49:59 +00008# 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
13Very simple, but useful, especially in debugging data structures.
14
Fred Drakea89fda01997-04-16 16:59:30 +000015Classes
16-------
17
18PrettyPrinter()
19 Handle pretty-printing operations onto a stream using a configured
20 set of formatting parameters.
21
Guido van Rossum5e92aff1997-04-16 00:49:59 +000022Functions
23---------
24
25pformat()
26 Format a Python object into a pretty-printed representation.
27
28pprint()
Skip Montanaro2dc0c132004-05-14 16:31:56 +000029 Pretty-print a Python object to a stream [default is sys.stdout].
Guido van Rossum5e92aff1997-04-16 00:49:59 +000030
Fred Drakea89fda01997-04-16 16:59:30 +000031saferepr()
32 Generate a 'standard' repr()-like value, but protect against recursive
33 data structures.
Guido van Rossum5e92aff1997-04-16 00:49:59 +000034
35"""
36
Fred Drake397b6152002-12-31 07:14:18 +000037import sys as _sys
Raymond Hettingerbad3c882010-09-09 12:31:00 +000038from collections import OrderedDict as _OrderedDict
Guido van Rossum34d19282007-08-09 01:03:29 +000039from io import StringIO as _StringIO
Guido van Rossum5e92aff1997-04-16 00:49:59 +000040
Skip Montanaroc62c81e2001-02-12 02:00:42 +000041__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr",
42 "PrettyPrinter"]
Guido van Rossum5e92aff1997-04-16 00:49:59 +000043
Fred Drake49cc01e2001-11-01 17:50:38 +000044# cache these for faster access:
45_commajoin = ", ".join
Fred Drake49cc01e2001-11-01 17:50:38 +000046_id = id
47_len = len
48_type = type
49
50
Walter Dörwaldc8de4582003-12-03 20:26:05 +000051def pprint(object, stream=None, indent=1, width=80, depth=None):
Skip Montanaro2dc0c132004-05-14 16:31:56 +000052 """Pretty-print a Python object to a stream [default is sys.stdout]."""
Walter Dörwaldc8de4582003-12-03 20:26:05 +000053 printer = PrettyPrinter(
54 stream=stream, indent=indent, width=width, depth=depth)
Fred Drakea89fda01997-04-16 16:59:30 +000055 printer.pprint(object)
Guido van Rossum5e92aff1997-04-16 00:49:59 +000056
Walter Dörwaldc8de4582003-12-03 20:26:05 +000057def pformat(object, indent=1, width=80, depth=None):
Fred Drakea89fda01997-04-16 16:59:30 +000058 """Format a Python object into a pretty-printed representation."""
Walter Dörwaldc8de4582003-12-03 20:26:05 +000059 return PrettyPrinter(indent=indent, width=width, depth=depth).pformat(object)
Guido van Rossum5e92aff1997-04-16 00:49:59 +000060
Fred Drakea89fda01997-04-16 16:59:30 +000061def saferepr(object):
62 """Version of repr() which can handle recursive data structures."""
Fred Drake49cc01e2001-11-01 17:50:38 +000063 return _safe_repr(object, {}, None, 0)[0]
Guido van Rossum5e92aff1997-04-16 00:49:59 +000064
Tim Petersa814db52001-05-14 07:05:58 +000065def isreadable(object):
66 """Determine if saferepr(object) is readable by eval()."""
Fred Drake49cc01e2001-11-01 17:50:38 +000067 return _safe_repr(object, {}, None, 0)[1]
Tim Petersa814db52001-05-14 07:05:58 +000068
69def isrecursive(object):
70 """Determine if object requires a recursive representation."""
Fred Drake49cc01e2001-11-01 17:50:38 +000071 return _safe_repr(object, {}, None, 0)[2]
Guido van Rossum5e92aff1997-04-16 00:49:59 +000072
Raymond Hettingera7da1662009-11-19 01:07:05 +000073class _safe_key:
74 """Helper function for key functions when sorting unorderable objects.
75
76 The wrapped-object will fallback to an Py2.x style comparison for
77 unorderable types (sorting first comparing the type name and then by
78 the obj ids). Does not work recursively, so dict.items() must have
79 _safe_key applied to both the key and the value.
80
81 """
82
83 __slots__ = ['obj']
84
85 def __init__(self, obj):
86 self.obj = obj
87
88 def __lt__(self, other):
Florent Xiclunad6da90f2012-07-21 11:17:38 +020089 try:
90 rv = self.obj.__lt__(other.obj)
91 except TypeError:
92 rv = NotImplemented
93
Raymond Hettingera7da1662009-11-19 01:07:05 +000094 if rv is NotImplemented:
95 rv = (str(type(self.obj)), id(self.obj)) < \
96 (str(type(other.obj)), id(other.obj))
97 return rv
98
99def _safe_tuple(t):
100 "Helper function for comparing 2-tuples"
101 return _safe_key(t[0]), _safe_key(t[1])
102
Fred Drakea89fda01997-04-16 16:59:30 +0000103class PrettyPrinter:
104 def __init__(self, indent=1, width=80, depth=None, stream=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000105 """Handle pretty printing operations onto a stream using a set of
106 configured parameters.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000107
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000108 indent
109 Number of spaces to indent for each level of nesting.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000110
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000111 width
112 Attempted maximum number of columns in the output.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000113
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000114 depth
115 The maximum depth to print out nested structures.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000116
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000117 stream
118 The desired output stream. If omitted (or false), the standard
119 output stream available at construction will be used.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000120
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000121 """
122 indent = int(indent)
123 width = int(width)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000124 assert indent >= 0, "indent must be >= 0"
Tim Petersa814db52001-05-14 07:05:58 +0000125 assert depth is None or depth > 0, "depth must be > 0"
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000126 assert width, "width must be != 0"
Fred Drakee6691ef2002-07-08 12:28:06 +0000127 self._depth = depth
128 self._indent_per_level = indent
129 self._width = width
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000130 if stream is not None:
Fred Drakee6691ef2002-07-08 12:28:06 +0000131 self._stream = stream
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000132 else:
Fred Drake397b6152002-12-31 07:14:18 +0000133 self._stream = _sys.stdout
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000134
Fred Drakea89fda01997-04-16 16:59:30 +0000135 def pprint(self, object):
Walter Dörwalde62e9362005-11-11 18:18:51 +0000136 self._format(object, self._stream, 0, 0, {}, 0)
137 self._stream.write("\n")
Fred Drakea89fda01997-04-16 16:59:30 +0000138
139 def pformat(self, object):
Fred Drake397b6152002-12-31 07:14:18 +0000140 sio = _StringIO()
Fred Drakee6691ef2002-07-08 12:28:06 +0000141 self._format(object, sio, 0, 0, {}, 0)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000142 return sio.getvalue()
Fred Drakea89fda01997-04-16 16:59:30 +0000143
Fred Drakee0ffabe1997-07-18 20:42:39 +0000144 def isrecursive(self, object):
Fred Drake397b6152002-12-31 07:14:18 +0000145 return self.format(object, {}, 0, 0)[2]
Fred Drakee0ffabe1997-07-18 20:42:39 +0000146
147 def isreadable(self, object):
Fred Drake397b6152002-12-31 07:14:18 +0000148 s, readable, recursive = self.format(object, {}, 0, 0)
Fred Drakeaee113d2002-04-02 05:08:35 +0000149 return readable and not recursive
Fred Drakee0ffabe1997-07-18 20:42:39 +0000150
Fred Drakee6691ef2002-07-08 12:28:06 +0000151 def _format(self, object, stream, indent, allowance, context, level):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000152 level = level + 1
Fred Drake49cc01e2001-11-01 17:50:38 +0000153 objid = _id(object)
154 if objid in context:
155 stream.write(_recursion(object))
Fred Drakee6691ef2002-07-08 12:28:06 +0000156 self._recursive = True
157 self._readable = False
Fred Drake49cc01e2001-11-01 17:50:38 +0000158 return
Fred Drakee6691ef2002-07-08 12:28:06 +0000159 rep = self._repr(object, context, level - 1)
Fred Drake49cc01e2001-11-01 17:50:38 +0000160 typ = _type(object)
Fred Drakee6691ef2002-07-08 12:28:06 +0000161 sepLines = _len(rep) > (self._width - 1 - indent - allowance)
Fred Drake49cc01e2001-11-01 17:50:38 +0000162 write = stream.write
Fred Drakea89fda01997-04-16 16:59:30 +0000163
Alexandre Vassalottieca20b62008-05-16 02:54:33 +0000164 if self._depth and level > self._depth:
165 write(rep)
166 return
167
Fred Drake49cc01e2001-11-01 17:50:38 +0000168 if sepLines:
Walter Dörwald1b626ca2004-11-15 13:51:41 +0000169 r = getattr(typ, "__repr__", None)
Raymond Hettingerbad3c882010-09-09 12:31:00 +0000170 if issubclass(typ, dict):
Fred Drake49cc01e2001-11-01 17:50:38 +0000171 write('{')
Fred Drakee6691ef2002-07-08 12:28:06 +0000172 if self._indent_per_level > 1:
173 write((self._indent_per_level - 1) * ' ')
Fred Drake49cc01e2001-11-01 17:50:38 +0000174 length = _len(object)
175 if length:
176 context[objid] = 1
Fred Drakee6691ef2002-07-08 12:28:06 +0000177 indent = indent + self._indent_per_level
Raymond Hettingerbad3c882010-09-09 12:31:00 +0000178 if issubclass(typ, _OrderedDict):
179 items = list(object.items())
180 else:
181 items = sorted(object.items(), key=_safe_tuple)
Fred Drake49cc01e2001-11-01 17:50:38 +0000182 key, ent = items[0]
Fred Drakee6691ef2002-07-08 12:28:06 +0000183 rep = self._repr(key, context, level)
Fred Drake49cc01e2001-11-01 17:50:38 +0000184 write(rep)
185 write(': ')
Fred Drakee6691ef2002-07-08 12:28:06 +0000186 self._format(ent, stream, indent + _len(rep) + 2,
Fred Drake49cc01e2001-11-01 17:50:38 +0000187 allowance + 1, context, level)
188 if length > 1:
189 for key, ent in items[1:]:
Fred Drakee6691ef2002-07-08 12:28:06 +0000190 rep = self._repr(key, context, level)
Barry Warsaw00859c02001-11-28 05:49:39 +0000191 write(',\n%s%s: ' % (' '*indent, rep))
Fred Drakee6691ef2002-07-08 12:28:06 +0000192 self._format(ent, stream, indent + _len(rep) + 2,
Fred Drake49cc01e2001-11-01 17:50:38 +0000193 allowance + 1, context, level)
Fred Drakee6691ef2002-07-08 12:28:06 +0000194 indent = indent - self._indent_per_level
Fred Drake49cc01e2001-11-01 17:50:38 +0000195 del context[objid]
196 write('}')
197 return
Fred Drakea89fda01997-04-16 16:59:30 +0000198
Christian Heimes1af737c2008-01-23 08:24:23 +0000199 if ((issubclass(typ, list) and r is list.__repr__) or
200 (issubclass(typ, tuple) and r is tuple.__repr__) or
201 (issubclass(typ, set) and r is set.__repr__) or
202 (issubclass(typ, frozenset) and r is frozenset.__repr__)
203 ):
Christian Heimes969fe572008-01-25 11:23:10 +0000204 length = _len(object)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000205 if issubclass(typ, list):
Fred Drake49cc01e2001-11-01 17:50:38 +0000206 write('[')
207 endchar = ']'
Serhiy Storchaka51844382013-10-02 11:40:49 +0300208 elif issubclass(typ, tuple):
Fred Drake49cc01e2001-11-01 17:50:38 +0000209 write('(')
210 endchar = ')'
Serhiy Storchaka51844382013-10-02 11:40:49 +0300211 else:
212 if not length:
213 write(rep)
214 return
215 if typ is set:
216 write('{')
217 endchar = '}'
218 else:
219 write(typ.__name__)
220 write('({')
221 endchar = '})'
222 indent += len(typ.__name__) + 1
223 object = sorted(object, key=_safe_key)
Fred Drakee6691ef2002-07-08 12:28:06 +0000224 if self._indent_per_level > 1:
225 write((self._indent_per_level - 1) * ' ')
Fred Drake49cc01e2001-11-01 17:50:38 +0000226 if length:
227 context[objid] = 1
Fred Drakee6691ef2002-07-08 12:28:06 +0000228 indent = indent + self._indent_per_level
229 self._format(object[0], stream, indent, allowance + 1,
230 context, level)
Fred Drake49cc01e2001-11-01 17:50:38 +0000231 if length > 1:
232 for ent in object[1:]:
233 write(',\n' + ' '*indent)
Fred Drakee6691ef2002-07-08 12:28:06 +0000234 self._format(ent, stream, indent,
Fred Drake49cc01e2001-11-01 17:50:38 +0000235 allowance + 1, context, level)
Fred Drakee6691ef2002-07-08 12:28:06 +0000236 indent = indent - self._indent_per_level
Fred Drake49cc01e2001-11-01 17:50:38 +0000237 del context[objid]
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000238 if issubclass(typ, tuple) and length == 1:
Fred Drake49cc01e2001-11-01 17:50:38 +0000239 write(',')
240 write(endchar)
241 return
Fred Drakea89fda01997-04-16 16:59:30 +0000242
Fred Drake49cc01e2001-11-01 17:50:38 +0000243 write(rep)
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000244
Fred Drakee6691ef2002-07-08 12:28:06 +0000245 def _repr(self, object, context, level):
Fred Drakeaee113d2002-04-02 05:08:35 +0000246 repr, readable, recursive = self.format(object, context.copy(),
Fred Drakee6691ef2002-07-08 12:28:06 +0000247 self._depth, level)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000248 if not readable:
Fred Drakee6691ef2002-07-08 12:28:06 +0000249 self._readable = False
Tim Petersa814db52001-05-14 07:05:58 +0000250 if recursive:
Fred Drakee6691ef2002-07-08 12:28:06 +0000251 self._recursive = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000252 return repr
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000253
Fred Drakeaee113d2002-04-02 05:08:35 +0000254 def format(self, object, context, maxlevels, level):
255 """Format object for a specific context, returning a string
256 and flags indicating whether the representation is 'readable'
257 and whether the object represents a recursive construct.
258 """
259 return _safe_repr(object, context, maxlevels, level)
260
261
Tim Petersa814db52001-05-14 07:05:58 +0000262# Return triple (repr_string, isreadable, isrecursive).
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000263
Fred Drake49cc01e2001-11-01 17:50:38 +0000264def _safe_repr(object, context, maxlevels, level):
265 typ = _type(object)
Martin v. Löwisd02879d2003-06-07 20:47:37 +0000266 if typ is str:
Fred Drake397b6152002-12-31 07:14:18 +0000267 if 'locale' not in _sys.modules:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000268 return repr(object), True, False
Fred Drake1ef106c2001-09-04 19:43:26 +0000269 if "'" in object and '"' not in object:
270 closure = '"'
271 quotes = {'"': '\\"'}
272 else:
273 closure = "'"
274 quotes = {"'": "\\'"}
Fred Drake49cc01e2001-11-01 17:50:38 +0000275 qget = quotes.get
Fred Drake397b6152002-12-31 07:14:18 +0000276 sio = _StringIO()
Fred Drake49cc01e2001-11-01 17:50:38 +0000277 write = sio.write
Fred Drake1ef106c2001-09-04 19:43:26 +0000278 for char in object:
279 if char.isalpha():
Fred Drake49cc01e2001-11-01 17:50:38 +0000280 write(char)
Fred Drake1ef106c2001-09-04 19:43:26 +0000281 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000282 write(qget(char, repr(char)[1:-1]))
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000283 return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False
Tim Peters95b3f782001-05-14 18:39:41 +0000284
Walter Dörwald1b626ca2004-11-15 13:51:41 +0000285 r = getattr(typ, "__repr__", None)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000286 if issubclass(typ, dict) and r is dict.__repr__:
Fred Drake49cc01e2001-11-01 17:50:38 +0000287 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000288 return "{}", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000289 objid = _id(object)
Alexandre Vassalottieca20b62008-05-16 02:54:33 +0000290 if maxlevels and level >= maxlevels:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000291 return "{...}", False, objid in context
Fred Drake49cc01e2001-11-01 17:50:38 +0000292 if objid in context:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000293 return _recursion(object), False, True
Fred Drake49cc01e2001-11-01 17:50:38 +0000294 context[objid] = 1
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000295 readable = True
296 recursive = False
Tim Peters95b3f782001-05-14 18:39:41 +0000297 components = []
Fred Drake49cc01e2001-11-01 17:50:38 +0000298 append = components.append
299 level += 1
300 saferepr = _safe_repr
Raymond Hettingera7da1662009-11-19 01:07:05 +0000301 items = sorted(object.items(), key=_safe_tuple)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000302 for k, v in items:
Fred Drake49cc01e2001-11-01 17:50:38 +0000303 krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
304 vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
305 append("%s: %s" % (krepr, vrepr))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000306 readable = readable and kreadable and vreadable
Fred Drake49cc01e2001-11-01 17:50:38 +0000307 if krecur or vrecur:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000308 recursive = True
Fred Drake49cc01e2001-11-01 17:50:38 +0000309 del context[objid]
310 return "{%s}" % _commajoin(components), readable, recursive
Tim Peters95b3f782001-05-14 18:39:41 +0000311
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000312 if (issubclass(typ, list) and r is list.__repr__) or \
313 (issubclass(typ, tuple) and r is tuple.__repr__):
314 if issubclass(typ, list):
Fred Drake49cc01e2001-11-01 17:50:38 +0000315 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000316 return "[]", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000317 format = "[%s]"
318 elif _len(object) == 1:
319 format = "(%s,)"
320 else:
321 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000322 return "()", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000323 format = "(%s)"
324 objid = _id(object)
Alexandre Vassalottieca20b62008-05-16 02:54:33 +0000325 if maxlevels and level >= maxlevels:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000326 return format % "...", False, objid in context
Fred Drake49cc01e2001-11-01 17:50:38 +0000327 if objid in context:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000328 return _recursion(object), False, True
Fred Drake49cc01e2001-11-01 17:50:38 +0000329 context[objid] = 1
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000330 readable = True
331 recursive = False
Tim Peters95b3f782001-05-14 18:39:41 +0000332 components = []
Fred Drake49cc01e2001-11-01 17:50:38 +0000333 append = components.append
334 level += 1
335 for o in object:
336 orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)
337 append(orepr)
338 if not oreadable:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000339 readable = False
Fred Drake49cc01e2001-11-01 17:50:38 +0000340 if orecur:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000341 recursive = True
Fred Drake49cc01e2001-11-01 17:50:38 +0000342 del context[objid]
343 return format % _commajoin(components), readable, recursive
Tim Peters88768482001-11-13 21:51:26 +0000344
Walter Dörwald70a6b492004-02-12 17:35:32 +0000345 rep = repr(object)
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000346 return rep, (rep and not rep.startswith('<')), False
Tim Peters95b3f782001-05-14 18:39:41 +0000347
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000348
Fred Drake49cc01e2001-11-01 17:50:38 +0000349def _recursion(object):
350 return ("<Recursion on %s with id=%s>"
351 % (_type(object).__name__, _id(object)))
Fred Drakea89fda01997-04-16 16:59:30 +0000352
Fred Drake49cc01e2001-11-01 17:50:38 +0000353
354def _perfcheck(object=None):
355 import time
356 if object is None:
357 object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
358 p = PrettyPrinter()
359 t1 = time.time()
360 _safe_repr(object, {}, None, 0)
361 t2 = time.time()
362 p.pformat(object)
363 t3 = time.time()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000364 print("_safe_repr:", t2 - t1)
365 print("pformat:", t3 - t2)
Fred Drake49cc01e2001-11-01 17:50:38 +0000366
367if __name__ == "__main__":
368 _perfcheck()