blob: b3a644649e5ae88d1d3fd1dcca918d159c0c3385 [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
Guido van Rossum5e92aff1997-04-16 00:49:59 +000038
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)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000166 if issubclass(typ, dict) and r is dict.__repr__:
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 Hettingera7da1662009-11-19 01:07:05 +0000174 items = sorted(object.items(), key=_safe_tuple)
Fred Drake49cc01e2001-11-01 17:50:38 +0000175 key, ent = items[0]
Fred Drakee6691ef2002-07-08 12:28:06 +0000176 rep = self._repr(key, context, level)
Fred Drake49cc01e2001-11-01 17:50:38 +0000177 write(rep)
178 write(': ')
Fred Drakee6691ef2002-07-08 12:28:06 +0000179 self._format(ent, stream, indent + _len(rep) + 2,
Fred Drake49cc01e2001-11-01 17:50:38 +0000180 allowance + 1, context, level)
181 if length > 1:
182 for key, ent in items[1:]:
Fred Drakee6691ef2002-07-08 12:28:06 +0000183 rep = self._repr(key, context, level)
Barry Warsaw00859c02001-11-28 05:49:39 +0000184 write(',\n%s%s: ' % (' '*indent, rep))
Fred Drakee6691ef2002-07-08 12:28:06 +0000185 self._format(ent, stream, indent + _len(rep) + 2,
Fred Drake49cc01e2001-11-01 17:50:38 +0000186 allowance + 1, context, level)
Fred Drakee6691ef2002-07-08 12:28:06 +0000187 indent = indent - self._indent_per_level
Fred Drake49cc01e2001-11-01 17:50:38 +0000188 del context[objid]
189 write('}')
190 return
Fred Drakea89fda01997-04-16 16:59:30 +0000191
Christian Heimes1af737c2008-01-23 08:24:23 +0000192 if ((issubclass(typ, list) and r is list.__repr__) or
193 (issubclass(typ, tuple) and r is tuple.__repr__) or
194 (issubclass(typ, set) and r is set.__repr__) or
195 (issubclass(typ, frozenset) and r is frozenset.__repr__)
196 ):
Christian Heimes969fe572008-01-25 11:23:10 +0000197 length = _len(object)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000198 if issubclass(typ, list):
Fred Drake49cc01e2001-11-01 17:50:38 +0000199 write('[')
200 endchar = ']'
Christian Heimes1af737c2008-01-23 08:24:23 +0000201 elif issubclass(typ, set):
Christian Heimes969fe572008-01-25 11:23:10 +0000202 if not length:
203 write('set()')
204 return
Christian Heimes1af737c2008-01-23 08:24:23 +0000205 write('{')
206 endchar = '}'
Raymond Hettingera7da1662009-11-19 01:07:05 +0000207 object = sorted(object, key=_safe_key)
Christian Heimes1af737c2008-01-23 08:24:23 +0000208 elif issubclass(typ, frozenset):
Christian Heimes969fe572008-01-25 11:23:10 +0000209 if not length:
210 write('frozenset()')
211 return
Raymond Hettinger4b8db412008-01-31 01:10:03 +0000212 write('frozenset({')
213 endchar = '})'
Raymond Hettingera7da1662009-11-19 01:07:05 +0000214 object = sorted(object, key=_safe_key)
Christian Heimes969fe572008-01-25 11:23:10 +0000215 indent += 10
Fred Drake49cc01e2001-11-01 17:50:38 +0000216 else:
217 write('(')
218 endchar = ')'
Fred Drakee6691ef2002-07-08 12:28:06 +0000219 if self._indent_per_level > 1:
220 write((self._indent_per_level - 1) * ' ')
Fred Drake49cc01e2001-11-01 17:50:38 +0000221 if length:
222 context[objid] = 1
Fred Drakee6691ef2002-07-08 12:28:06 +0000223 indent = indent + self._indent_per_level
224 self._format(object[0], stream, indent, allowance + 1,
225 context, level)
Fred Drake49cc01e2001-11-01 17:50:38 +0000226 if length > 1:
227 for ent in object[1:]:
228 write(',\n' + ' '*indent)
Fred Drakee6691ef2002-07-08 12:28:06 +0000229 self._format(ent, stream, indent,
Fred Drake49cc01e2001-11-01 17:50:38 +0000230 allowance + 1, context, level)
Fred Drakee6691ef2002-07-08 12:28:06 +0000231 indent = indent - self._indent_per_level
Fred Drake49cc01e2001-11-01 17:50:38 +0000232 del context[objid]
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000233 if issubclass(typ, tuple) and length == 1:
Fred Drake49cc01e2001-11-01 17:50:38 +0000234 write(',')
235 write(endchar)
236 return
Fred Drakea89fda01997-04-16 16:59:30 +0000237
Fred Drake49cc01e2001-11-01 17:50:38 +0000238 write(rep)
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000239
Fred Drakee6691ef2002-07-08 12:28:06 +0000240 def _repr(self, object, context, level):
Fred Drakeaee113d2002-04-02 05:08:35 +0000241 repr, readable, recursive = self.format(object, context.copy(),
Fred Drakee6691ef2002-07-08 12:28:06 +0000242 self._depth, level)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000243 if not readable:
Fred Drakee6691ef2002-07-08 12:28:06 +0000244 self._readable = False
Tim Petersa814db52001-05-14 07:05:58 +0000245 if recursive:
Fred Drakee6691ef2002-07-08 12:28:06 +0000246 self._recursive = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000247 return repr
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000248
Fred Drakeaee113d2002-04-02 05:08:35 +0000249 def format(self, object, context, maxlevels, level):
250 """Format object for a specific context, returning a string
251 and flags indicating whether the representation is 'readable'
252 and whether the object represents a recursive construct.
253 """
254 return _safe_repr(object, context, maxlevels, level)
255
256
Tim Petersa814db52001-05-14 07:05:58 +0000257# Return triple (repr_string, isreadable, isrecursive).
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000258
Fred Drake49cc01e2001-11-01 17:50:38 +0000259def _safe_repr(object, context, maxlevels, level):
260 typ = _type(object)
Martin v. Löwisd02879d2003-06-07 20:47:37 +0000261 if typ is str:
Fred Drake397b6152002-12-31 07:14:18 +0000262 if 'locale' not in _sys.modules:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000263 return repr(object), True, False
Fred Drake1ef106c2001-09-04 19:43:26 +0000264 if "'" in object and '"' not in object:
265 closure = '"'
266 quotes = {'"': '\\"'}
267 else:
268 closure = "'"
269 quotes = {"'": "\\'"}
Fred Drake49cc01e2001-11-01 17:50:38 +0000270 qget = quotes.get
Fred Drake397b6152002-12-31 07:14:18 +0000271 sio = _StringIO()
Fred Drake49cc01e2001-11-01 17:50:38 +0000272 write = sio.write
Fred Drake1ef106c2001-09-04 19:43:26 +0000273 for char in object:
274 if char.isalpha():
Fred Drake49cc01e2001-11-01 17:50:38 +0000275 write(char)
Fred Drake1ef106c2001-09-04 19:43:26 +0000276 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000277 write(qget(char, repr(char)[1:-1]))
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000278 return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False
Tim Peters95b3f782001-05-14 18:39:41 +0000279
Walter Dörwald1b626ca2004-11-15 13:51:41 +0000280 r = getattr(typ, "__repr__", None)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000281 if issubclass(typ, dict) and r is dict.__repr__:
Fred Drake49cc01e2001-11-01 17:50:38 +0000282 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000283 return "{}", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000284 objid = _id(object)
Alexandre Vassalottieca20b62008-05-16 02:54:33 +0000285 if maxlevels and level >= maxlevels:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000286 return "{...}", False, objid in context
Fred Drake49cc01e2001-11-01 17:50:38 +0000287 if objid in context:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000288 return _recursion(object), False, True
Fred Drake49cc01e2001-11-01 17:50:38 +0000289 context[objid] = 1
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000290 readable = True
291 recursive = False
Tim Peters95b3f782001-05-14 18:39:41 +0000292 components = []
Fred Drake49cc01e2001-11-01 17:50:38 +0000293 append = components.append
294 level += 1
295 saferepr = _safe_repr
Raymond Hettingera7da1662009-11-19 01:07:05 +0000296 items = sorted(object.items(), key=_safe_tuple)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000297 for k, v in items:
Fred Drake49cc01e2001-11-01 17:50:38 +0000298 krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
299 vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
300 append("%s: %s" % (krepr, vrepr))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000301 readable = readable and kreadable and vreadable
Fred Drake49cc01e2001-11-01 17:50:38 +0000302 if krecur or vrecur:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000303 recursive = True
Fred Drake49cc01e2001-11-01 17:50:38 +0000304 del context[objid]
305 return "{%s}" % _commajoin(components), readable, recursive
Tim Peters95b3f782001-05-14 18:39:41 +0000306
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000307 if (issubclass(typ, list) and r is list.__repr__) or \
308 (issubclass(typ, tuple) and r is tuple.__repr__):
309 if issubclass(typ, list):
Fred Drake49cc01e2001-11-01 17:50:38 +0000310 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000311 return "[]", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000312 format = "[%s]"
313 elif _len(object) == 1:
314 format = "(%s,)"
315 else:
316 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000317 return "()", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000318 format = "(%s)"
319 objid = _id(object)
Alexandre Vassalottieca20b62008-05-16 02:54:33 +0000320 if maxlevels and level >= maxlevels:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000321 return format % "...", False, objid in context
Fred Drake49cc01e2001-11-01 17:50:38 +0000322 if objid in context:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000323 return _recursion(object), False, True
Fred Drake49cc01e2001-11-01 17:50:38 +0000324 context[objid] = 1
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000325 readable = True
326 recursive = False
Tim Peters95b3f782001-05-14 18:39:41 +0000327 components = []
Fred Drake49cc01e2001-11-01 17:50:38 +0000328 append = components.append
329 level += 1
330 for o in object:
331 orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)
332 append(orepr)
333 if not oreadable:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000334 readable = False
Fred Drake49cc01e2001-11-01 17:50:38 +0000335 if orecur:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000336 recursive = True
Fred Drake49cc01e2001-11-01 17:50:38 +0000337 del context[objid]
338 return format % _commajoin(components), readable, recursive
Tim Peters88768482001-11-13 21:51:26 +0000339
Walter Dörwald70a6b492004-02-12 17:35:32 +0000340 rep = repr(object)
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000341 return rep, (rep and not rep.startswith('<')), False
Tim Peters95b3f782001-05-14 18:39:41 +0000342
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000343
Fred Drake49cc01e2001-11-01 17:50:38 +0000344def _recursion(object):
345 return ("<Recursion on %s with id=%s>"
346 % (_type(object).__name__, _id(object)))
Fred Drakea89fda01997-04-16 16:59:30 +0000347
Fred Drake49cc01e2001-11-01 17:50:38 +0000348
349def _perfcheck(object=None):
350 import time
351 if object is None:
352 object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
353 p = PrettyPrinter()
354 t1 = time.time()
355 _safe_repr(object, {}, None, 0)
356 t2 = time.time()
357 p.pformat(object)
358 t3 = time.time()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000359 print("_safe_repr:", t2 - t1)
360 print("pformat:", t3 - t2)
Fred Drake49cc01e2001-11-01 17:50:38 +0000361
362if __name__ == "__main__":
363 _perfcheck()