blob: 1f98f5c5a8e1d3f2c3811d9c968492ad243ffa30 [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
Antoine Pitrou64c16c32013-03-23 20:30:39 +010037import re
Fred Drake397b6152002-12-31 07:14:18 +000038import sys as _sys
Raymond Hettingerbad3c882010-09-09 12:31:00 +000039from collections import OrderedDict as _OrderedDict
Guido van Rossum34d19282007-08-09 01:03:29 +000040from io import StringIO as _StringIO
Guido van Rossum5e92aff1997-04-16 00:49:59 +000041
Skip Montanaroc62c81e2001-02-12 02:00:42 +000042__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr",
43 "PrettyPrinter"]
Guido van Rossum5e92aff1997-04-16 00:49:59 +000044
Fred Drake49cc01e2001-11-01 17:50:38 +000045# cache these for faster access:
46_commajoin = ", ".join
Fred Drake49cc01e2001-11-01 17:50:38 +000047_id = id
48_len = len
49_type = type
50
51
Walter Dörwaldc8de4582003-12-03 20:26:05 +000052def pprint(object, stream=None, indent=1, width=80, depth=None):
Skip Montanaro2dc0c132004-05-14 16:31:56 +000053 """Pretty-print a Python object to a stream [default is sys.stdout]."""
Walter Dörwaldc8de4582003-12-03 20:26:05 +000054 printer = PrettyPrinter(
55 stream=stream, indent=indent, width=width, depth=depth)
Fred Drakea89fda01997-04-16 16:59:30 +000056 printer.pprint(object)
Guido van Rossum5e92aff1997-04-16 00:49:59 +000057
Walter Dörwaldc8de4582003-12-03 20:26:05 +000058def pformat(object, indent=1, width=80, depth=None):
Fred Drakea89fda01997-04-16 16:59:30 +000059 """Format a Python object into a pretty-printed representation."""
Walter Dörwaldc8de4582003-12-03 20:26:05 +000060 return PrettyPrinter(indent=indent, width=width, depth=depth).pformat(object)
Guido van Rossum5e92aff1997-04-16 00:49:59 +000061
Fred Drakea89fda01997-04-16 16:59:30 +000062def saferepr(object):
63 """Version of repr() which can handle recursive data structures."""
Fred Drake49cc01e2001-11-01 17:50:38 +000064 return _safe_repr(object, {}, None, 0)[0]
Guido van Rossum5e92aff1997-04-16 00:49:59 +000065
Tim Petersa814db52001-05-14 07:05:58 +000066def isreadable(object):
67 """Determine if saferepr(object) is readable by eval()."""
Fred Drake49cc01e2001-11-01 17:50:38 +000068 return _safe_repr(object, {}, None, 0)[1]
Tim Petersa814db52001-05-14 07:05:58 +000069
70def isrecursive(object):
71 """Determine if object requires a recursive representation."""
Fred Drake49cc01e2001-11-01 17:50:38 +000072 return _safe_repr(object, {}, None, 0)[2]
Guido van Rossum5e92aff1997-04-16 00:49:59 +000073
Raymond Hettingera7da1662009-11-19 01:07:05 +000074class _safe_key:
75 """Helper function for key functions when sorting unorderable objects.
76
77 The wrapped-object will fallback to an Py2.x style comparison for
78 unorderable types (sorting first comparing the type name and then by
79 the obj ids). Does not work recursively, so dict.items() must have
80 _safe_key applied to both the key and the value.
81
82 """
83
84 __slots__ = ['obj']
85
86 def __init__(self, obj):
87 self.obj = obj
88
89 def __lt__(self, other):
Florent Xiclunad6da90f2012-07-21 11:17:38 +020090 try:
91 rv = self.obj.__lt__(other.obj)
92 except TypeError:
93 rv = NotImplemented
94
Raymond Hettingera7da1662009-11-19 01:07:05 +000095 if rv is NotImplemented:
96 rv = (str(type(self.obj)), id(self.obj)) < \
97 (str(type(other.obj)), id(other.obj))
98 return rv
99
100def _safe_tuple(t):
101 "Helper function for comparing 2-tuples"
102 return _safe_key(t[0]), _safe_key(t[1])
103
Fred Drakea89fda01997-04-16 16:59:30 +0000104class PrettyPrinter:
105 def __init__(self, indent=1, width=80, depth=None, stream=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000106 """Handle pretty printing operations onto a stream using a set of
107 configured parameters.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000108
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000109 indent
110 Number of spaces to indent for each level of nesting.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000111
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000112 width
113 Attempted maximum number of columns in the output.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000114
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000115 depth
116 The maximum depth to print out nested structures.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000117
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000118 stream
119 The desired output stream. If omitted (or false), the standard
120 output stream available at construction will be used.
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000121
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000122 """
123 indent = int(indent)
124 width = int(width)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000125 assert indent >= 0, "indent must be >= 0"
Tim Petersa814db52001-05-14 07:05:58 +0000126 assert depth is None or depth > 0, "depth must be > 0"
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000127 assert width, "width must be != 0"
Fred Drakee6691ef2002-07-08 12:28:06 +0000128 self._depth = depth
129 self._indent_per_level = indent
130 self._width = width
Raymond Hettinger16e3c422002-06-01 16:07:16 +0000131 if stream is not None:
Fred Drakee6691ef2002-07-08 12:28:06 +0000132 self._stream = stream
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000133 else:
Fred Drake397b6152002-12-31 07:14:18 +0000134 self._stream = _sys.stdout
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000135
Fred Drakea89fda01997-04-16 16:59:30 +0000136 def pprint(self, object):
Walter Dörwalde62e9362005-11-11 18:18:51 +0000137 self._format(object, self._stream, 0, 0, {}, 0)
138 self._stream.write("\n")
Fred Drakea89fda01997-04-16 16:59:30 +0000139
140 def pformat(self, object):
Fred Drake397b6152002-12-31 07:14:18 +0000141 sio = _StringIO()
Fred Drakee6691ef2002-07-08 12:28:06 +0000142 self._format(object, sio, 0, 0, {}, 0)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000143 return sio.getvalue()
Fred Drakea89fda01997-04-16 16:59:30 +0000144
Fred Drakee0ffabe1997-07-18 20:42:39 +0000145 def isrecursive(self, object):
Fred Drake397b6152002-12-31 07:14:18 +0000146 return self.format(object, {}, 0, 0)[2]
Fred Drakee0ffabe1997-07-18 20:42:39 +0000147
148 def isreadable(self, object):
Fred Drake397b6152002-12-31 07:14:18 +0000149 s, readable, recursive = self.format(object, {}, 0, 0)
Fred Drakeaee113d2002-04-02 05:08:35 +0000150 return readable and not recursive
Fred Drakee0ffabe1997-07-18 20:42:39 +0000151
Fred Drakee6691ef2002-07-08 12:28:06 +0000152 def _format(self, object, stream, indent, allowance, context, level):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000153 level = level + 1
Fred Drake49cc01e2001-11-01 17:50:38 +0000154 objid = _id(object)
155 if objid in context:
156 stream.write(_recursion(object))
Fred Drakee6691ef2002-07-08 12:28:06 +0000157 self._recursive = True
158 self._readable = False
Fred Drake49cc01e2001-11-01 17:50:38 +0000159 return
Fred Drakee6691ef2002-07-08 12:28:06 +0000160 rep = self._repr(object, context, level - 1)
Fred Drake49cc01e2001-11-01 17:50:38 +0000161 typ = _type(object)
Antoine Pitrou64c16c32013-03-23 20:30:39 +0100162 max_width = self._width - 1 - indent - allowance
163 sepLines = _len(rep) > max_width
Fred Drake49cc01e2001-11-01 17:50:38 +0000164 write = stream.write
Fred Drakea89fda01997-04-16 16:59:30 +0000165
Fred Drake49cc01e2001-11-01 17:50:38 +0000166 if sepLines:
Walter Dörwald1b626ca2004-11-15 13:51:41 +0000167 r = getattr(typ, "__repr__", None)
Raymond Hettingerbad3c882010-09-09 12:31:00 +0000168 if issubclass(typ, dict):
Fred Drake49cc01e2001-11-01 17:50:38 +0000169 write('{')
Fred Drakee6691ef2002-07-08 12:28:06 +0000170 if self._indent_per_level > 1:
171 write((self._indent_per_level - 1) * ' ')
Fred Drake49cc01e2001-11-01 17:50:38 +0000172 length = _len(object)
173 if length:
174 context[objid] = 1
Fred Drakee6691ef2002-07-08 12:28:06 +0000175 indent = indent + self._indent_per_level
Raymond Hettingerbad3c882010-09-09 12:31:00 +0000176 if issubclass(typ, _OrderedDict):
177 items = list(object.items())
178 else:
179 items = sorted(object.items(), key=_safe_tuple)
Fred Drake49cc01e2001-11-01 17:50:38 +0000180 key, ent = items[0]
Fred Drakee6691ef2002-07-08 12:28:06 +0000181 rep = self._repr(key, context, level)
Fred Drake49cc01e2001-11-01 17:50:38 +0000182 write(rep)
183 write(': ')
Fred Drakee6691ef2002-07-08 12:28:06 +0000184 self._format(ent, stream, indent + _len(rep) + 2,
Fred Drake49cc01e2001-11-01 17:50:38 +0000185 allowance + 1, context, level)
186 if length > 1:
187 for key, ent in items[1:]:
Fred Drakee6691ef2002-07-08 12:28:06 +0000188 rep = self._repr(key, context, level)
Barry Warsaw00859c02001-11-28 05:49:39 +0000189 write(',\n%s%s: ' % (' '*indent, rep))
Fred Drakee6691ef2002-07-08 12:28:06 +0000190 self._format(ent, stream, indent + _len(rep) + 2,
Fred Drake49cc01e2001-11-01 17:50:38 +0000191 allowance + 1, context, level)
Fred Drakee6691ef2002-07-08 12:28:06 +0000192 indent = indent - self._indent_per_level
Fred Drake49cc01e2001-11-01 17:50:38 +0000193 del context[objid]
194 write('}')
195 return
Fred Drakea89fda01997-04-16 16:59:30 +0000196
Christian Heimes1af737c2008-01-23 08:24:23 +0000197 if ((issubclass(typ, list) and r is list.__repr__) or
198 (issubclass(typ, tuple) and r is tuple.__repr__) or
199 (issubclass(typ, set) and r is set.__repr__) or
200 (issubclass(typ, frozenset) and r is frozenset.__repr__)
201 ):
Christian Heimes969fe572008-01-25 11:23:10 +0000202 length = _len(object)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000203 if issubclass(typ, list):
Fred Drake49cc01e2001-11-01 17:50:38 +0000204 write('[')
205 endchar = ']'
Christian Heimes1af737c2008-01-23 08:24:23 +0000206 elif issubclass(typ, set):
Christian Heimes969fe572008-01-25 11:23:10 +0000207 if not length:
208 write('set()')
209 return
Christian Heimes1af737c2008-01-23 08:24:23 +0000210 write('{')
211 endchar = '}'
Raymond Hettingera7da1662009-11-19 01:07:05 +0000212 object = sorted(object, key=_safe_key)
Christian Heimes1af737c2008-01-23 08:24:23 +0000213 elif issubclass(typ, frozenset):
Christian Heimes969fe572008-01-25 11:23:10 +0000214 if not length:
215 write('frozenset()')
216 return
Raymond Hettinger4b8db412008-01-31 01:10:03 +0000217 write('frozenset({')
218 endchar = '})'
Raymond Hettingera7da1662009-11-19 01:07:05 +0000219 object = sorted(object, key=_safe_key)
Christian Heimes969fe572008-01-25 11:23:10 +0000220 indent += 10
Fred Drake49cc01e2001-11-01 17:50:38 +0000221 else:
222 write('(')
223 endchar = ')'
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
Antoine Pitrou64c16c32013-03-23 20:30:39 +0100243 if issubclass(typ, str) and len(object) > 0 and r is str.__repr__:
244 def _str_parts(s):
245 """
246 Return a list of string literals comprising the repr()
247 of the given string using literal concatenation.
248 """
249 lines = s.splitlines(True)
250 for i, line in enumerate(lines):
251 rep = repr(line)
252 if _len(rep) <= max_width:
253 yield rep
254 else:
255 # A list of alternating (non-space, space) strings
256 parts = re.split(r'(\s+)', line) + ['']
257 current = ''
258 for i in range(0, len(parts), 2):
259 part = parts[i] + parts[i+1]
260 candidate = current + part
261 if len(repr(candidate)) > max_width:
262 if current:
263 yield repr(current)
264 current = part
265 else:
266 current = candidate
267 if current:
268 yield repr(current)
269 for i, rep in enumerate(_str_parts(object)):
270 if i > 0:
271 write('\n' + ' '*indent)
272 write(rep)
273 return
Fred Drake49cc01e2001-11-01 17:50:38 +0000274 write(rep)
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000275
Fred Drakee6691ef2002-07-08 12:28:06 +0000276 def _repr(self, object, context, level):
Fred Drakeaee113d2002-04-02 05:08:35 +0000277 repr, readable, recursive = self.format(object, context.copy(),
Fred Drakee6691ef2002-07-08 12:28:06 +0000278 self._depth, level)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000279 if not readable:
Fred Drakee6691ef2002-07-08 12:28:06 +0000280 self._readable = False
Tim Petersa814db52001-05-14 07:05:58 +0000281 if recursive:
Fred Drakee6691ef2002-07-08 12:28:06 +0000282 self._recursive = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000283 return repr
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000284
Fred Drakeaee113d2002-04-02 05:08:35 +0000285 def format(self, object, context, maxlevels, level):
286 """Format object for a specific context, returning a string
287 and flags indicating whether the representation is 'readable'
288 and whether the object represents a recursive construct.
289 """
290 return _safe_repr(object, context, maxlevels, level)
291
292
Tim Petersa814db52001-05-14 07:05:58 +0000293# Return triple (repr_string, isreadable, isrecursive).
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000294
Fred Drake49cc01e2001-11-01 17:50:38 +0000295def _safe_repr(object, context, maxlevels, level):
296 typ = _type(object)
Martin v. Löwisd02879d2003-06-07 20:47:37 +0000297 if typ is str:
Fred Drake397b6152002-12-31 07:14:18 +0000298 if 'locale' not in _sys.modules:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000299 return repr(object), True, False
Fred Drake1ef106c2001-09-04 19:43:26 +0000300 if "'" in object and '"' not in object:
301 closure = '"'
302 quotes = {'"': '\\"'}
303 else:
304 closure = "'"
305 quotes = {"'": "\\'"}
Fred Drake49cc01e2001-11-01 17:50:38 +0000306 qget = quotes.get
Fred Drake397b6152002-12-31 07:14:18 +0000307 sio = _StringIO()
Fred Drake49cc01e2001-11-01 17:50:38 +0000308 write = sio.write
Fred Drake1ef106c2001-09-04 19:43:26 +0000309 for char in object:
310 if char.isalpha():
Fred Drake49cc01e2001-11-01 17:50:38 +0000311 write(char)
Fred Drake1ef106c2001-09-04 19:43:26 +0000312 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000313 write(qget(char, repr(char)[1:-1]))
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000314 return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False
Tim Peters95b3f782001-05-14 18:39:41 +0000315
Walter Dörwald1b626ca2004-11-15 13:51:41 +0000316 r = getattr(typ, "__repr__", None)
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000317 if issubclass(typ, dict) and r is dict.__repr__:
Fred Drake49cc01e2001-11-01 17:50:38 +0000318 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000319 return "{}", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000320 objid = _id(object)
Alexandre Vassalottieca20b62008-05-16 02:54:33 +0000321 if maxlevels and level >= maxlevels:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000322 return "{...}", False, objid in context
Fred Drake49cc01e2001-11-01 17:50:38 +0000323 if objid in context:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000324 return _recursion(object), False, True
Fred Drake49cc01e2001-11-01 17:50:38 +0000325 context[objid] = 1
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000326 readable = True
327 recursive = False
Tim Peters95b3f782001-05-14 18:39:41 +0000328 components = []
Fred Drake49cc01e2001-11-01 17:50:38 +0000329 append = components.append
330 level += 1
331 saferepr = _safe_repr
Raymond Hettingera7da1662009-11-19 01:07:05 +0000332 items = sorted(object.items(), key=_safe_tuple)
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000333 for k, v in items:
Fred Drake49cc01e2001-11-01 17:50:38 +0000334 krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
335 vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
336 append("%s: %s" % (krepr, vrepr))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000337 readable = readable and kreadable and vreadable
Fred Drake49cc01e2001-11-01 17:50:38 +0000338 if krecur or vrecur:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000339 recursive = True
Fred Drake49cc01e2001-11-01 17:50:38 +0000340 del context[objid]
341 return "{%s}" % _commajoin(components), readable, recursive
Tim Peters95b3f782001-05-14 18:39:41 +0000342
Walter Dörwald7a7ede52003-12-03 20:15:28 +0000343 if (issubclass(typ, list) and r is list.__repr__) or \
344 (issubclass(typ, tuple) and r is tuple.__repr__):
345 if issubclass(typ, list):
Fred Drake49cc01e2001-11-01 17:50:38 +0000346 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000347 return "[]", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000348 format = "[%s]"
349 elif _len(object) == 1:
350 format = "(%s,)"
351 else:
352 if not object:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000353 return "()", True, False
Fred Drake49cc01e2001-11-01 17:50:38 +0000354 format = "(%s)"
355 objid = _id(object)
Alexandre Vassalottieca20b62008-05-16 02:54:33 +0000356 if maxlevels and level >= maxlevels:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000357 return format % "...", False, objid in context
Fred Drake49cc01e2001-11-01 17:50:38 +0000358 if objid in context:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000359 return _recursion(object), False, True
Fred Drake49cc01e2001-11-01 17:50:38 +0000360 context[objid] = 1
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000361 readable = True
362 recursive = False
Tim Peters95b3f782001-05-14 18:39:41 +0000363 components = []
Fred Drake49cc01e2001-11-01 17:50:38 +0000364 append = components.append
365 level += 1
366 for o in object:
367 orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)
368 append(orepr)
369 if not oreadable:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000370 readable = False
Fred Drake49cc01e2001-11-01 17:50:38 +0000371 if orecur:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000372 recursive = True
Fred Drake49cc01e2001-11-01 17:50:38 +0000373 del context[objid]
374 return format % _commajoin(components), readable, recursive
Tim Peters88768482001-11-13 21:51:26 +0000375
Walter Dörwald70a6b492004-02-12 17:35:32 +0000376 rep = repr(object)
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000377 return rep, (rep and not rep.startswith('<')), False
Tim Peters95b3f782001-05-14 18:39:41 +0000378
Guido van Rossum5e92aff1997-04-16 00:49:59 +0000379
Fred Drake49cc01e2001-11-01 17:50:38 +0000380def _recursion(object):
381 return ("<Recursion on %s with id=%s>"
382 % (_type(object).__name__, _id(object)))
Fred Drakea89fda01997-04-16 16:59:30 +0000383
Fred Drake49cc01e2001-11-01 17:50:38 +0000384
385def _perfcheck(object=None):
386 import time
387 if object is None:
388 object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
389 p = PrettyPrinter()
390 t1 = time.time()
391 _safe_repr(object, {}, None, 0)
392 t2 = time.time()
393 p.pformat(object)
394 t3 = time.time()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000395 print("_safe_repr:", t2 - t1)
396 print("pformat:", t3 - t2)
Fred Drake49cc01e2001-11-01 17:50:38 +0000397
398if __name__ == "__main__":
399 _perfcheck()