1edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# Author: Fred L. Drake, Jr. 2edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# fdrake@acm.org 3edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# 4edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# This is a simple little module I wrote to make life easier. I didn't 5edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# see anything quite like it in the library, though I may have overlooked 6edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# something. I wrote this when I was trying to read some heavily nested 7edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# tuples with fairly non-descriptive content. This is modeled very much 8edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# after Lisp/Scheme - style pretty-printing of lists. If you find it 9edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# useful, thank small children who sleep at night. 10edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 11edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep"""Support to pretty-print lists, tuples, & dictionaries recursively. 12edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 13edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepVery simple, but useful, especially in debugging data structures. 14edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 15edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepClasses 16edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep------- 17edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 18edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepPrettyPrinter() 19edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep Handle pretty-printing operations onto a stream using a configured 20edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep set of formatting parameters. 21edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 22edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepFunctions 23edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep--------- 24edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 25edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoeppformat() 26edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep Format a Python object into a pretty-printed representation. 27edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 28edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoeppprint() 29edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep Pretty-print a Python object to a stream [default is sys.stdout]. 30edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 31edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepsaferepr() 32edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep Generate a 'standard' repr()-like value, but protect against recursive 33edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep data structures. 34edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 35edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep""" 36edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 37edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport sys as _sys 38edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport warnings 39edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 40edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoeptry: 41edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep from cStringIO import StringIO as _StringIO 42edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepexcept ImportError: 43edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep from StringIO import StringIO as _StringIO 44edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 45edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr", 46edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep "PrettyPrinter"] 47edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 48edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# cache these for faster access: 49edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep_commajoin = ", ".join 50edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep_id = id 51edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep_len = len 52edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep_type = type 53edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 54edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 55edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef pprint(object, stream=None, indent=1, width=80, depth=None): 56edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Pretty-print a Python object to a stream [default is sys.stdout].""" 57edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep printer = PrettyPrinter( 58edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep stream=stream, indent=indent, width=width, depth=depth) 59edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep printer.pprint(object) 60edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 61edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef pformat(object, indent=1, width=80, depth=None): 62edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Format a Python object into a pretty-printed representation.""" 63edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return PrettyPrinter(indent=indent, width=width, depth=depth).pformat(object) 64edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 65edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef saferepr(object): 66edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Version of repr() which can handle recursive data structures.""" 67edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return _safe_repr(object, {}, None, 0)[0] 68edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 69edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef isreadable(object): 70edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Determine if saferepr(object) is readable by eval().""" 71edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return _safe_repr(object, {}, None, 0)[1] 72edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 73edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef isrecursive(object): 74edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Determine if object requires a recursive representation.""" 75edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return _safe_repr(object, {}, None, 0)[2] 76edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 77edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef _sorted(iterable): 78edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep with warnings.catch_warnings(): 79edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if _sys.py3kwarning: 80edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep warnings.filterwarnings("ignore", "comparing unequal types " 81edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep "not supported", DeprecationWarning) 82edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return sorted(iterable) 83edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 84edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass PrettyPrinter: 85edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __init__(self, indent=1, width=80, depth=None, stream=None): 86edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Handle pretty printing operations onto a stream using a set of 87edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep configured parameters. 88edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 89edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep indent 90edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep Number of spaces to indent for each level of nesting. 91edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 92edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep width 93edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep Attempted maximum number of columns in the output. 94edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 95edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep depth 96edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep The maximum depth to print out nested structures. 97edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 98edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep stream 99edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep The desired output stream. If omitted (or false), the standard 100edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep output stream available at construction will be used. 101edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 102edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """ 103edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep indent = int(indent) 104edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep width = int(width) 105edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep assert indent >= 0, "indent must be >= 0" 106edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep assert depth is None or depth > 0, "depth must be > 0" 107edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep assert width, "width must be != 0" 108edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._depth = depth 109edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._indent_per_level = indent 110edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._width = width 111edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if stream is not None: 112edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._stream = stream 113edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 114edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._stream = _sys.stdout 115edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 116edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def pprint(self, object): 117edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._format(object, self._stream, 0, 0, {}, 0) 118edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._stream.write("\n") 119edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 120edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def pformat(self, object): 121edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep sio = _StringIO() 122edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._format(object, sio, 0, 0, {}, 0) 123edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return sio.getvalue() 124edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 125edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def isrecursive(self, object): 126edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self.format(object, {}, 0, 0)[2] 127edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 128edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def isreadable(self, object): 129edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep s, readable, recursive = self.format(object, {}, 0, 0) 130edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return readable and not recursive 131edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 132edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def _format(self, object, stream, indent, allowance, context, level): 133edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep level = level + 1 134edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep objid = _id(object) 135edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if objid in context: 136edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep stream.write(_recursion(object)) 137edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._recursive = True 138edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._readable = False 139edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return 140edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep rep = self._repr(object, context, level - 1) 141edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep typ = _type(object) 142edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep sepLines = _len(rep) > (self._width - 1 - indent - allowance) 143edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write = stream.write 144edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 145edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._depth and level > self._depth: 146edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(rep) 147edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return 148edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 149edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep r = getattr(typ, "__repr__", None) 150edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if issubclass(typ, dict) and r is dict.__repr__: 151edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write('{') 152edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._indent_per_level > 1: 153edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write((self._indent_per_level - 1) * ' ') 154edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep length = _len(object) 155edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if length: 156edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context[objid] = 1 157edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep indent = indent + self._indent_per_level 158edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep items = _sorted(object.items()) 159edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep key, ent = items[0] 160edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep rep = self._repr(key, context, level) 161edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(rep) 162edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(': ') 163edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._format(ent, stream, indent + _len(rep) + 2, 164edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep allowance + 1, context, level) 165edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if length > 1: 166edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for key, ent in items[1:]: 167edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep rep = self._repr(key, context, level) 168edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if sepLines: 169edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(',\n%s%s: ' % (' '*indent, rep)) 170edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 171edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(', %s: ' % rep) 172edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._format(ent, stream, indent + _len(rep) + 2, 173edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep allowance + 1, context, level) 174edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep indent = indent - self._indent_per_level 175edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep del context[objid] 176edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write('}') 177edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return 178edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 179edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if ((issubclass(typ, list) and r is list.__repr__) or 180edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep (issubclass(typ, tuple) and r is tuple.__repr__) or 181edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep (issubclass(typ, set) and r is set.__repr__) or 182edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep (issubclass(typ, frozenset) and r is frozenset.__repr__) 183edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ): 184edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep length = _len(object) 185edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if issubclass(typ, list): 186edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write('[') 187edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep endchar = ']' 188edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep elif issubclass(typ, set): 189edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if not length: 190edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write('set()') 191edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return 192edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write('set([') 193edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep endchar = '])' 194edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep object = _sorted(object) 195edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep indent += 4 196edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep elif issubclass(typ, frozenset): 197edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if not length: 198edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write('frozenset()') 199edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return 200edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write('frozenset([') 201edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep endchar = '])' 202edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep object = _sorted(object) 203edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep indent += 10 204edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 205edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write('(') 206edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep endchar = ')' 207edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._indent_per_level > 1 and sepLines: 208edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write((self._indent_per_level - 1) * ' ') 209edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if length: 210edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context[objid] = 1 211edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep indent = indent + self._indent_per_level 212edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._format(object[0], stream, indent, allowance + 1, 213edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context, level) 214edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if length > 1: 215edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for ent in object[1:]: 216edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if sepLines: 217edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(',\n' + ' '*indent) 218edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 219edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(', ') 220edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._format(ent, stream, indent, 221edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep allowance + 1, context, level) 222edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep indent = indent - self._indent_per_level 223edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep del context[objid] 224edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if issubclass(typ, tuple) and length == 1: 225edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(',') 226edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(endchar) 227edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return 228edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 229edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(rep) 230edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 231edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def _repr(self, object, context, level): 232edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep repr, readable, recursive = self.format(object, context.copy(), 233edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._depth, level) 234edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if not readable: 235edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._readable = False 236edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if recursive: 237edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._recursive = True 238edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return repr 239edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 240edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def format(self, object, context, maxlevels, level): 241edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Format object for a specific context, returning a string 242edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep and flags indicating whether the representation is 'readable' 243edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep and whether the object represents a recursive construct. 244edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """ 245edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return _safe_repr(object, context, maxlevels, level) 246edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 247edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 248edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# Return triple (repr_string, isreadable, isrecursive). 249edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 250edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef _safe_repr(object, context, maxlevels, level): 251edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep typ = _type(object) 252edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if typ is str: 253edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if 'locale' not in _sys.modules: 254edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return repr(object), True, False 255edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if "'" in object and '"' not in object: 256edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep closure = '"' 257edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep quotes = {'"': '\\"'} 258edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 259edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep closure = "'" 260edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep quotes = {"'": "\\'"} 261edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep qget = quotes.get 262edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep sio = _StringIO() 263edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write = sio.write 264edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for char in object: 265edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if char.isalpha(): 266edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(char) 267edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 268edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep write(qget(char, repr(char)[1:-1])) 269edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return ("%s%s%s" % (closure, sio.getvalue(), closure)), True, False 270edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 271edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep r = getattr(typ, "__repr__", None) 272edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if issubclass(typ, dict) and r is dict.__repr__: 273edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if not object: 274edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return "{}", True, False 275edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep objid = _id(object) 276edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if maxlevels and level >= maxlevels: 277edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return "{...}", False, objid in context 278edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if objid in context: 279edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return _recursion(object), False, True 280edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context[objid] = 1 281edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep readable = True 282edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep recursive = False 283edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep components = [] 284edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep append = components.append 285edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep level += 1 286edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep saferepr = _safe_repr 287edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for k, v in _sorted(object.items()): 288edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep krepr, kreadable, krecur = saferepr(k, context, maxlevels, level) 289edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level) 290edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep append("%s: %s" % (krepr, vrepr)) 291edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep readable = readable and kreadable and vreadable 292edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if krecur or vrecur: 293edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep recursive = True 294edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep del context[objid] 295edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return "{%s}" % _commajoin(components), readable, recursive 296edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 297edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if (issubclass(typ, list) and r is list.__repr__) or \ 298edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep (issubclass(typ, tuple) and r is tuple.__repr__): 299edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if issubclass(typ, list): 300edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if not object: 301edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return "[]", True, False 302edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep format = "[%s]" 303edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep elif _len(object) == 1: 304edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep format = "(%s,)" 305edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 306edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if not object: 307edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return "()", True, False 308edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep format = "(%s)" 309edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep objid = _id(object) 310edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if maxlevels and level >= maxlevels: 311edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return format % "...", False, objid in context 312edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if objid in context: 313edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return _recursion(object), False, True 314edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep context[objid] = 1 315edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep readable = True 316edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep recursive = False 317edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep components = [] 318edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep append = components.append 319edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep level += 1 320edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for o in object: 321edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level) 322edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep append(orepr) 323edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if not oreadable: 324edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep readable = False 325edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if orecur: 326edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep recursive = True 327edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep del context[objid] 328edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return format % _commajoin(components), readable, recursive 329edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 330edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep rep = repr(object) 331edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return rep, (rep and not rep.startswith('<')), False 332edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 333edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 334edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef _recursion(object): 335edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return ("<Recursion on %s with id=%s>" 336edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep % (_type(object).__name__, _id(object))) 337edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 338edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 339edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef _perfcheck(object=None): 340edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep import time 341edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if object is None: 342edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000 343edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep p = PrettyPrinter() 344edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep t1 = time.time() 345edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep _safe_repr(object, {}, None, 0) 346edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep t2 = time.time() 347edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep p.pformat(object) 348edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep t3 = time.time() 349edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep print "_safe_repr:", t2 - t1 350edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep print "pformat:", t3 - t2 351edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 352edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepif __name__ == "__main__": 353edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep _perfcheck() 354