blob: b8417f592255db70fe33df97c6fe5c9b8d9e3c59 [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):
89 rv = self.obj.__lt__(other.obj)
90 if rv is NotImplemented:
91 rv = (str(type(self.obj)), id(self.obj)) < \
92 (str(type(other.obj)), id(other.obj))
93 return rv
94
95def _safe_tuple(t):
96 "Helper function for comparing 2-tuples"
97 return _safe_key(t[0]), _safe_key(t[1])
98
Fred Drakea89fda01997-04-16 16:59:30 +000099class PrettyPrinter:
100 def __init__(self, indent=1, width=80, depth=None, stream=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000101 """Handle pretty printing operations onto a stream using a set of
102 configured parameters.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000103
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000104 indent
105 Number of spaces to indent for each level of nesting.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000106
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000107 width
108 Attempted maximum number of columns in the output.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000109
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000110 depth
111 The maximum depth to print out nested structures.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000112
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000113 stream
114 The desired output stream. If omitted (or false), the standard
115 output stream available at construction will be used.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000116
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000117 """
118 indent = int(indent)
119 width = int(width)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000120 assert indent >= 0, "indent must be >= 0"
Tim Petersa814db52001-05-14 07:05:58 +0000121 assert depth is None or depth > 0, "depth must be > 0"
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000122 assert width, "width must be != 0"
Fred Drakee6691ef2002-07-08 12:28:06 +0000123 self._depth = depth
124 self._indent_per_level = indent
125 self._width = width
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000126 if stream is not None:
Fred Drakee6691ef2002-07-08 12:28:06 +0000127 self._stream = stream
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000128 else:
Fred Drake397b6152002-12-31 07:14:18 +0000129 self._stream = _sys.stdout
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000130
Fred Drakea89fda01997-04-16 16:59:30 +0000131 def pprint(self, object):
Walter Dörwalde62e9362005-11-11 18:18:51 +0000132 self._format(object, self._stream, 0, 0, {}, 0)
133 self._stream.write("\n")
Fred Drakea89fda01997-04-16 16:59:30 +0000134
135 def pformat(self, object):
Fred Drake397b6152002-12-31 07:14:18 +0000136 sio = _StringIO()
Fred Drakee6691ef2002-07-08 12:28:06 +0000137 self._format(object, sio, 0, 0, {}, 0)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000138 return sio.getvalue()
Fred Drakea89fda01997-04-16 16:59:30 +0000139
Fred Drakee0ffabe1997-07-18 20:42:39 +0000140 def isrecursive(self, object):
Fred Drake397b6152002-12-31 07:14:18 +0000141 return self.format(object, {}, 0, 0)[2]
Fred Drakee0ffabe1997-07-18 20:42:39 +0000142
143 def isreadable(self, object):
Fred Drake397b6152002-12-31 07:14:18 +0000144 s, readable, recursive = self.format(object, {}, 0, 0)
Fred Drakeaee113d2002-04-02 05:08:35 +0000145 return readable and not recursive
Fred Drakee0ffabe1997-07-18 20:42:39 +0000146
Fred Drakee6691ef2002-07-08 12:28:06 +0000147 def _format(self, object, stream, indent, allowance, context, level):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000148 level = level + 1
Fred Drake49cc01e2001-11-01 17:50:38 +0000149 objid = _id(object)
150 if objid in context:
151 stream.write(_recursion(object))
Fred Drakee6691ef2002-07-08 12:28:06 +0000152 self._recursive = True
153 self._readable = False
Fred Drake49cc01e2001-11-01 17:50:38 +0000154 return
Fred Drakee6691ef2002-07-08 12:28:06 +0000155 rep = self._repr(object, context, level - 1)
Fred Drake49cc01e2001-11-01 17:50:38 +0000156 typ = _type(object)
Fred Drakee6691ef2002-07-08 12:28:06 +0000157 sepLines = _len(rep) > (self._width - 1 - indent - allowance)
Fred Drake49cc01e2001-11-01 17:50:38 +0000158 write = stream.write
Fred Drakea89fda01997-04-16 16:59:30 +0000159
Alexandre Vassalottieca20b62008-05-16 02:54:33 +0000160 if self._depth and level > self._depth:
161 write(rep)
162 return
163
Fred Drake49cc01e2001-11-01 17:50:38 +0000164 if sepLines:
Walter Dörwald1b626ca2004-11-15 13:51:41 +0000165 r = getattr(typ, "__repr__", None)
Raymond Hettingerbad3c882010-09-09 12:31:00 +0000166 if issubclass(typ, dict):
Fred Drake49cc01e2001-11-01 17:50:38 +0000167 write('{')
Fred Drakee6691ef2002-07-08 12:28:06 +0000168 if self._indent_per_level > 1:
169 write((self._indent_per_level - 1) * ' ')
Fred Drake49cc01e2001-11-01 17:50:38 +0000170 length = _len(object)
171 if length:
172 context[objid] = 1
Fred Drakee6691ef2002-07-08 12:28:06 +0000173 indent = indent + self._indent_per_level
Raymond Hettingerbad3c882010-09-09 12:31:00 +0000174 if issubclass(typ, _OrderedDict):
175 items = list(object.items())
176 else:
177 items = sorted(object.items(), key=_safe_tuple)
Fred Drake49cc01e2001-11-01 17:50:38 +0000178 key, ent = items[0]
Fred Drakee6691ef2002-07-08 12:28:06 +0000179 rep = self._repr(key, context, level)
Fred Drake49cc01e2001-11-01 17:50:38 +0000180 write(rep)
181 write(': ')
Fred Drakee6691ef2002-07-08 12:28:06 +0000182 self._format(ent, stream, indent + _len(rep) + 2,
Fred Drake49cc01e2001-11-01 17:50:38 +0000183 allowance + 1, context, level)
184 if length > 1:
185 for key, ent in items[1:]:
Fred Drakee6691ef2002-07-08 12:28:06 +0000186 rep = self._repr(key, context, level)
Barry Warsaw00859c02001-11-28 05:49:39 +0000187 write(',\n%s%s: ' % (' '*indent, rep))
Fred Drakee6691ef2002-07-08 12:28:06 +0000188 self._format(ent, stream, indent + _len(rep) + 2,
Fred Drake49cc01e2001-11-01 17:50:38 +0000189 allowance + 1, context, level)
Fred Drakee6691ef2002-07-08 12:28:06 +0000190 indent = indent - self._indent_per_level
Fred Drake49cc01e2001-11-01 17:50:38 +0000191 del context[objid]
192 write('}')
193 return
Fred Drakea89fda01997-04-16 16:59:30 +0000194
Christian Heimes1af737c2008-01-23 08:24:23 +0000195 if ((issubclass(typ, list) and r is list.__repr__) or
196 (issubclass(typ, tuple) and r is tuple.__repr__) or
197 (issubclass(typ, set) and r is set.__repr__) or
198 (issubclass(typ, frozenset) and r is frozenset.__repr__)
199 ):
Christian Heimes969fe572008-01-25 11:23:10 +0000200 length = _len(object)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000201 if issubclass(typ, list):
Fred Drake49cc01e2001-11-01 17:50:38 +0000202 write('[')
203 endchar = ']'
Christian Heimes1af737c2008-01-23 08:24:23 +0000204 elif issubclass(typ, set):
Christian Heimes969fe572008-01-25 11:23:10 +0000205 if not length:
206 write('set()')
207 return
Christian Heimes1af737c2008-01-23 08:24:23 +0000208 write('{')
209 endchar = '}'
Raymond Hettingera7da1662009-11-19 01:07:05 +0000210 object = sorted(object, key=_safe_key)
Christian Heimes1af737c2008-01-23 08:24:23 +0000211 elif issubclass(typ, frozenset):
Christian Heimes969fe572008-01-25 11:23:10 +0000212 if not length:
213 write('frozenset()')
214 return
Raymond Hettinger4b8db412008-01-31 01:10:03 +0000215 write('frozenset({')
216 endchar = '})'
Raymond Hettingera7da1662009-11-19 01:07:05 +0000217 object = sorted(object, key=_safe_key)
Christian Heimes969fe572008-01-25 11:23:10 +0000218 indent += 10
Fred Drake49cc01e2001-11-01 17:50:38 +0000219 else:
220 write('(')
221 endchar = ')'
Fred Drakee6691ef2002-07-08 12:28:06 +0000222 if self._indent_per_level > 1:
223 write((self._indent_per_level - 1) * ' ')
Fred Drake49cc01e2001-11-01 17:50:38 +0000224 if length:
225 context[objid] = 1
Fred Drakee6691ef2002-07-08 12:28:06 +0000226 indent = indent + self._indent_per_level
227 self._format(object[0], stream, indent, allowance + 1,
228 context, level)
Fred Drake49cc01e2001-11-01 17:50:38 +0000229 if length > 1:
230 for ent in object[1:]:
231 write(',\n' + ' '*indent)
Fred Drakee6691ef2002-07-08 12:28:06 +0000232 self._format(ent, stream, indent,
Fred Drake49cc01e2001-11-01 17:50:38 +0000233 allowance + 1, context, level)
Fred Drakee6691ef2002-07-08 12:28:06 +0000234 indent = indent - self._indent_per_level
Fred Drake49cc01e2001-11-01 17:50:38 +0000235 del context[objid]
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000236 if issubclass(typ, tuple) and length == 1:
Fred Drake49cc01e2001-11-01 17:50:38 +0000237 write(',')
238 write(endchar)
239 return
Fred Drakea89fda01997-04-16 16:59:30 +0000240
Fred Drake49cc01e2001-11-01 17:50:38 +0000241 write(rep)
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000242
Fred Drakee6691ef2002-07-08 12:28:06 +0000243 def _repr(self, object, context, level):
Fred Drakeaee113d2002-04-02 05:08:35 +0000244 repr, readable, recursive = self.format(object, context.copy(),
Fred Drakee6691ef2002-07-08 12:28:06 +0000245 self._depth, level)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000246 if not readable:
Fred Drakee6691ef2002-07-08 12:28:06 +0000247 self._readable = False
Tim Petersa814db52001-05-14 07:05:58 +0000248 if recursive:
Fred Drakee6691ef2002-07-08 12:28:06 +0000249 self._recursive = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000250 return repr
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000251
Fred Drakeaee113d2002-04-02 05:08:35 +0000252 def format(self, object, context, maxlevels, level):
253 """Format object for a specific context, returning a string
254 and flags indicating whether the representation is 'readable'
255 and whether the object represents a recursive construct.
256 """
257 return _safe_repr(object, context, maxlevels, level)
258
259
Tim Petersa814db52001-05-14 07:05:58 +0000260# Return triple (repr_string, isreadable, isrecursive).
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000261
Fred Drake49cc01e2001-11-01 17:50:38 +0000262def _safe_repr(object, context, maxlevels, level):
263 typ = _type(object)
Martin v. Löwisd02879d2003-06-07 20:47:37 +0000264 if typ is str:
Fred Drake397b6152002-12-31 07:14:18 +0000265 if 'locale' not in _sys.modules:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000266 return repr(object), True, False
Fred Drake1ef106c2001-09-04 19:43:26 +0000267 if "'" in object and '"' not in object:
268 closure = '"'
269 quotes = {'"': '\\"'}
270 else:
271 closure = "'"
272 quotes = {"'": "\\'"}
Fred Drake49cc01e2001-11-01 17:50:38 +0000273 qget = quotes.get
Fred Drake397b6152002-12-31 07:14:18 +0000274 sio = _StringIO()
Fred Drake49cc01e2001-11-01 17:50:38 +0000275 write = sio.write
Fred Drake1ef106c2001-09-04 19:43:26 +0000276 for char in object:
277 if char.isalpha():
Fred Drake49cc01e2001-11-01 17:50:38 +0000278 write(char)
Fred Drake1ef106c2001-09-04 19:43:26 +0000279 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000280 write(qget(char, repr(char)[1:-1]))
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000281 return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False
Tim Peters95b3f782001-05-14 18:39:41 +0000282
Walter Dörwald1b626ca2004-11-15 13:51:41 +0000283 r = getattr(typ, "__repr__", None)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000284 if issubclass(typ, dict) and r is dict.__repr__:
Fred Drake49cc01e2001-11-01 17:50:38 +0000285 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000286 return "{}", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000287 objid = _id(object)
Alexandre Vassalottieca20b62008-05-16 02:54:33 +0000288 if maxlevels and level >= maxlevels:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000289 return "{...}", False, objid in context
Fred Drake49cc01e2001-11-01 17:50:38 +0000290 if objid in context:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000291 return _recursion(object), False, True
Fred Drake49cc01e2001-11-01 17:50:38 +0000292 context[objid] = 1
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000293 readable = True
294 recursive = False
Tim Peters95b3f782001-05-14 18:39:41 +0000295 components = []
Fred Drake49cc01e2001-11-01 17:50:38 +0000296 append = components.append
297 level += 1
298 saferepr = _safe_repr
Raymond Hettingera7da1662009-11-19 01:07:05 +0000299 items = sorted(object.items(), key=_safe_tuple)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000300 for k, v in items:
Fred Drake49cc01e2001-11-01 17:50:38 +0000301 krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
302 vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
303 append("%s: %s" % (krepr, vrepr))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000304 readable = readable and kreadable and vreadable
Fred Drake49cc01e2001-11-01 17:50:38 +0000305 if krecur or vrecur:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000306 recursive = True
Fred Drake49cc01e2001-11-01 17:50:38 +0000307 del context[objid]
308 return "{%s}" % _commajoin(components), readable, recursive
Tim Peters95b3f782001-05-14 18:39:41 +0000309
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000310 if (issubclass(typ, list) and r is list.__repr__) or \
311 (issubclass(typ, tuple) and r is tuple.__repr__):
312 if issubclass(typ, list):
Fred Drake49cc01e2001-11-01 17:50:38 +0000313 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000314 return "[]", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000315 format = "[%s]"
316 elif _len(object) == 1:
317 format = "(%s,)"
318 else:
319 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000320 return "()", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000321 format = "(%s)"
322 objid = _id(object)
Alexandre Vassalottieca20b62008-05-16 02:54:33 +0000323 if maxlevels and level >= maxlevels:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000324 return format % "...", False, objid in context
Fred Drake49cc01e2001-11-01 17:50:38 +0000325 if objid in context:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000326 return _recursion(object), False, True
Fred Drake49cc01e2001-11-01 17:50:38 +0000327 context[objid] = 1
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000328 readable = True
329 recursive = False
Tim Peters95b3f782001-05-14 18:39:41 +0000330 components = []
Fred Drake49cc01e2001-11-01 17:50:38 +0000331 append = components.append
332 level += 1
333 for o in object:
334 orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)
335 append(orepr)
336 if not oreadable:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000337 readable = False
Fred Drake49cc01e2001-11-01 17:50:38 +0000338 if orecur:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000339 recursive = True
Fred Drake49cc01e2001-11-01 17:50:38 +0000340 del context[objid]
341 return format % _commajoin(components), readable, recursive
Tim Peters88768482001-11-13 21:51:26 +0000342
Walter Dörwald70a6b492004-02-12 17:35:32 +0000343 rep = repr(object)
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000344 return rep, (rep and not rep.startswith('<')), False
Tim Peters95b3f782001-05-14 18:39:41 +0000345
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000346
Fred Drake49cc01e2001-11-01 17:50:38 +0000347def _recursion(object):
348 return ("<Recursion on %s with id=%s>"
349 % (_type(object).__name__, _id(object)))
Fred Drakea89fda01997-04-16 16:59:30 +0000350
Fred Drake49cc01e2001-11-01 17:50:38 +0000351
352def _perfcheck(object=None):
353 import time
354 if object is None:
355 object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
356 p = PrettyPrinter()
357 t1 = time.time()
358 _safe_repr(object, {}, None, 0)
359 t2 = time.time()
360 p.pformat(object)
361 t3 = time.time()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000362 print("_safe_repr:", t2 - t1)
363 print("pformat:", t3 - t2)
Fred Drake49cc01e2001-11-01 17:50:38 +0000364
365if __name__ == "__main__":
366 _perfcheck()