1*cda5da8dSAndroid Build Coastguard Worker# Author: Fred L. Drake, Jr. 2*cda5da8dSAndroid Build Coastguard Worker# [email protected] 3*cda5da8dSAndroid Build Coastguard Worker# 4*cda5da8dSAndroid Build Coastguard Worker# This is a simple little module I wrote to make life easier. I didn't 5*cda5da8dSAndroid Build Coastguard Worker# see anything quite like it in the library, though I may have overlooked 6*cda5da8dSAndroid Build Coastguard Worker# something. I wrote this when I was trying to read some heavily nested 7*cda5da8dSAndroid Build Coastguard Worker# tuples with fairly non-descriptive content. This is modeled very much 8*cda5da8dSAndroid Build Coastguard Worker# after Lisp/Scheme - style pretty-printing of lists. If you find it 9*cda5da8dSAndroid Build Coastguard Worker# useful, thank small children who sleep at night. 10*cda5da8dSAndroid Build Coastguard Worker 11*cda5da8dSAndroid Build Coastguard Worker"""Support to pretty-print lists, tuples, & dictionaries recursively. 12*cda5da8dSAndroid Build Coastguard Worker 13*cda5da8dSAndroid Build Coastguard WorkerVery simple, but useful, especially in debugging data structures. 14*cda5da8dSAndroid Build Coastguard Worker 15*cda5da8dSAndroid Build Coastguard WorkerClasses 16*cda5da8dSAndroid Build Coastguard Worker------- 17*cda5da8dSAndroid Build Coastguard Worker 18*cda5da8dSAndroid Build Coastguard WorkerPrettyPrinter() 19*cda5da8dSAndroid Build Coastguard Worker Handle pretty-printing operations onto a stream using a configured 20*cda5da8dSAndroid Build Coastguard Worker set of formatting parameters. 21*cda5da8dSAndroid Build Coastguard Worker 22*cda5da8dSAndroid Build Coastguard WorkerFunctions 23*cda5da8dSAndroid Build Coastguard Worker--------- 24*cda5da8dSAndroid Build Coastguard Worker 25*cda5da8dSAndroid Build Coastguard Workerpformat() 26*cda5da8dSAndroid Build Coastguard Worker Format a Python object into a pretty-printed representation. 27*cda5da8dSAndroid Build Coastguard Worker 28*cda5da8dSAndroid Build Coastguard Workerpprint() 29*cda5da8dSAndroid Build Coastguard Worker Pretty-print a Python object to a stream [default is sys.stdout]. 30*cda5da8dSAndroid Build Coastguard Worker 31*cda5da8dSAndroid Build Coastguard Workersaferepr() 32*cda5da8dSAndroid Build Coastguard Worker Generate a 'standard' repr()-like value, but protect against recursive 33*cda5da8dSAndroid Build Coastguard Worker data structures. 34*cda5da8dSAndroid Build Coastguard Worker 35*cda5da8dSAndroid Build Coastguard Worker""" 36*cda5da8dSAndroid Build Coastguard Worker 37*cda5da8dSAndroid Build Coastguard Workerimport collections as _collections 38*cda5da8dSAndroid Build Coastguard Workerimport dataclasses as _dataclasses 39*cda5da8dSAndroid Build Coastguard Workerimport re 40*cda5da8dSAndroid Build Coastguard Workerimport sys as _sys 41*cda5da8dSAndroid Build Coastguard Workerimport types as _types 42*cda5da8dSAndroid Build Coastguard Workerfrom io import StringIO as _StringIO 43*cda5da8dSAndroid Build Coastguard Worker 44*cda5da8dSAndroid Build Coastguard Worker__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr", 45*cda5da8dSAndroid Build Coastguard Worker "PrettyPrinter", "pp"] 46*cda5da8dSAndroid Build Coastguard Worker 47*cda5da8dSAndroid Build Coastguard Worker 48*cda5da8dSAndroid Build Coastguard Workerdef pprint(object, stream=None, indent=1, width=80, depth=None, *, 49*cda5da8dSAndroid Build Coastguard Worker compact=False, sort_dicts=True, underscore_numbers=False): 50*cda5da8dSAndroid Build Coastguard Worker """Pretty-print a Python object to a stream [default is sys.stdout].""" 51*cda5da8dSAndroid Build Coastguard Worker printer = PrettyPrinter( 52*cda5da8dSAndroid Build Coastguard Worker stream=stream, indent=indent, width=width, depth=depth, 53*cda5da8dSAndroid Build Coastguard Worker compact=compact, sort_dicts=sort_dicts, 54*cda5da8dSAndroid Build Coastguard Worker underscore_numbers=underscore_numbers) 55*cda5da8dSAndroid Build Coastguard Worker printer.pprint(object) 56*cda5da8dSAndroid Build Coastguard Worker 57*cda5da8dSAndroid Build Coastguard Workerdef pformat(object, indent=1, width=80, depth=None, *, 58*cda5da8dSAndroid Build Coastguard Worker compact=False, sort_dicts=True, underscore_numbers=False): 59*cda5da8dSAndroid Build Coastguard Worker """Format a Python object into a pretty-printed representation.""" 60*cda5da8dSAndroid Build Coastguard Worker return PrettyPrinter(indent=indent, width=width, depth=depth, 61*cda5da8dSAndroid Build Coastguard Worker compact=compact, sort_dicts=sort_dicts, 62*cda5da8dSAndroid Build Coastguard Worker underscore_numbers=underscore_numbers).pformat(object) 63*cda5da8dSAndroid Build Coastguard Worker 64*cda5da8dSAndroid Build Coastguard Workerdef pp(object, *args, sort_dicts=False, **kwargs): 65*cda5da8dSAndroid Build Coastguard Worker """Pretty-print a Python object""" 66*cda5da8dSAndroid Build Coastguard Worker pprint(object, *args, sort_dicts=sort_dicts, **kwargs) 67*cda5da8dSAndroid Build Coastguard Worker 68*cda5da8dSAndroid Build Coastguard Workerdef saferepr(object): 69*cda5da8dSAndroid Build Coastguard Worker """Version of repr() which can handle recursive data structures.""" 70*cda5da8dSAndroid Build Coastguard Worker return PrettyPrinter()._safe_repr(object, {}, None, 0)[0] 71*cda5da8dSAndroid Build Coastguard Worker 72*cda5da8dSAndroid Build Coastguard Workerdef isreadable(object): 73*cda5da8dSAndroid Build Coastguard Worker """Determine if saferepr(object) is readable by eval().""" 74*cda5da8dSAndroid Build Coastguard Worker return PrettyPrinter()._safe_repr(object, {}, None, 0)[1] 75*cda5da8dSAndroid Build Coastguard Worker 76*cda5da8dSAndroid Build Coastguard Workerdef isrecursive(object): 77*cda5da8dSAndroid Build Coastguard Worker """Determine if object requires a recursive representation.""" 78*cda5da8dSAndroid Build Coastguard Worker return PrettyPrinter()._safe_repr(object, {}, None, 0)[2] 79*cda5da8dSAndroid Build Coastguard Worker 80*cda5da8dSAndroid Build Coastguard Workerclass _safe_key: 81*cda5da8dSAndroid Build Coastguard Worker """Helper function for key functions when sorting unorderable objects. 82*cda5da8dSAndroid Build Coastguard Worker 83*cda5da8dSAndroid Build Coastguard Worker The wrapped-object will fallback to a Py2.x style comparison for 84*cda5da8dSAndroid Build Coastguard Worker unorderable types (sorting first comparing the type name and then by 85*cda5da8dSAndroid Build Coastguard Worker the obj ids). Does not work recursively, so dict.items() must have 86*cda5da8dSAndroid Build Coastguard Worker _safe_key applied to both the key and the value. 87*cda5da8dSAndroid Build Coastguard Worker 88*cda5da8dSAndroid Build Coastguard Worker """ 89*cda5da8dSAndroid Build Coastguard Worker 90*cda5da8dSAndroid Build Coastguard Worker __slots__ = ['obj'] 91*cda5da8dSAndroid Build Coastguard Worker 92*cda5da8dSAndroid Build Coastguard Worker def __init__(self, obj): 93*cda5da8dSAndroid Build Coastguard Worker self.obj = obj 94*cda5da8dSAndroid Build Coastguard Worker 95*cda5da8dSAndroid Build Coastguard Worker def __lt__(self, other): 96*cda5da8dSAndroid Build Coastguard Worker try: 97*cda5da8dSAndroid Build Coastguard Worker return self.obj < other.obj 98*cda5da8dSAndroid Build Coastguard Worker except TypeError: 99*cda5da8dSAndroid Build Coastguard Worker return ((str(type(self.obj)), id(self.obj)) < \ 100*cda5da8dSAndroid Build Coastguard Worker (str(type(other.obj)), id(other.obj))) 101*cda5da8dSAndroid Build Coastguard Worker 102*cda5da8dSAndroid Build Coastguard Workerdef _safe_tuple(t): 103*cda5da8dSAndroid Build Coastguard Worker "Helper function for comparing 2-tuples" 104*cda5da8dSAndroid Build Coastguard Worker return _safe_key(t[0]), _safe_key(t[1]) 105*cda5da8dSAndroid Build Coastguard Worker 106*cda5da8dSAndroid Build Coastguard Workerclass PrettyPrinter: 107*cda5da8dSAndroid Build Coastguard Worker def __init__(self, indent=1, width=80, depth=None, stream=None, *, 108*cda5da8dSAndroid Build Coastguard Worker compact=False, sort_dicts=True, underscore_numbers=False): 109*cda5da8dSAndroid Build Coastguard Worker """Handle pretty printing operations onto a stream using a set of 110*cda5da8dSAndroid Build Coastguard Worker configured parameters. 111*cda5da8dSAndroid Build Coastguard Worker 112*cda5da8dSAndroid Build Coastguard Worker indent 113*cda5da8dSAndroid Build Coastguard Worker Number of spaces to indent for each level of nesting. 114*cda5da8dSAndroid Build Coastguard Worker 115*cda5da8dSAndroid Build Coastguard Worker width 116*cda5da8dSAndroid Build Coastguard Worker Attempted maximum number of columns in the output. 117*cda5da8dSAndroid Build Coastguard Worker 118*cda5da8dSAndroid Build Coastguard Worker depth 119*cda5da8dSAndroid Build Coastguard Worker The maximum depth to print out nested structures. 120*cda5da8dSAndroid Build Coastguard Worker 121*cda5da8dSAndroid Build Coastguard Worker stream 122*cda5da8dSAndroid Build Coastguard Worker The desired output stream. If omitted (or false), the standard 123*cda5da8dSAndroid Build Coastguard Worker output stream available at construction will be used. 124*cda5da8dSAndroid Build Coastguard Worker 125*cda5da8dSAndroid Build Coastguard Worker compact 126*cda5da8dSAndroid Build Coastguard Worker If true, several items will be combined in one line. 127*cda5da8dSAndroid Build Coastguard Worker 128*cda5da8dSAndroid Build Coastguard Worker sort_dicts 129*cda5da8dSAndroid Build Coastguard Worker If true, dict keys are sorted. 130*cda5da8dSAndroid Build Coastguard Worker 131*cda5da8dSAndroid Build Coastguard Worker """ 132*cda5da8dSAndroid Build Coastguard Worker indent = int(indent) 133*cda5da8dSAndroid Build Coastguard Worker width = int(width) 134*cda5da8dSAndroid Build Coastguard Worker if indent < 0: 135*cda5da8dSAndroid Build Coastguard Worker raise ValueError('indent must be >= 0') 136*cda5da8dSAndroid Build Coastguard Worker if depth is not None and depth <= 0: 137*cda5da8dSAndroid Build Coastguard Worker raise ValueError('depth must be > 0') 138*cda5da8dSAndroid Build Coastguard Worker if not width: 139*cda5da8dSAndroid Build Coastguard Worker raise ValueError('width must be != 0') 140*cda5da8dSAndroid Build Coastguard Worker self._depth = depth 141*cda5da8dSAndroid Build Coastguard Worker self._indent_per_level = indent 142*cda5da8dSAndroid Build Coastguard Worker self._width = width 143*cda5da8dSAndroid Build Coastguard Worker if stream is not None: 144*cda5da8dSAndroid Build Coastguard Worker self._stream = stream 145*cda5da8dSAndroid Build Coastguard Worker else: 146*cda5da8dSAndroid Build Coastguard Worker self._stream = _sys.stdout 147*cda5da8dSAndroid Build Coastguard Worker self._compact = bool(compact) 148*cda5da8dSAndroid Build Coastguard Worker self._sort_dicts = sort_dicts 149*cda5da8dSAndroid Build Coastguard Worker self._underscore_numbers = underscore_numbers 150*cda5da8dSAndroid Build Coastguard Worker 151*cda5da8dSAndroid Build Coastguard Worker def pprint(self, object): 152*cda5da8dSAndroid Build Coastguard Worker if self._stream is not None: 153*cda5da8dSAndroid Build Coastguard Worker self._format(object, self._stream, 0, 0, {}, 0) 154*cda5da8dSAndroid Build Coastguard Worker self._stream.write("\n") 155*cda5da8dSAndroid Build Coastguard Worker 156*cda5da8dSAndroid Build Coastguard Worker def pformat(self, object): 157*cda5da8dSAndroid Build Coastguard Worker sio = _StringIO() 158*cda5da8dSAndroid Build Coastguard Worker self._format(object, sio, 0, 0, {}, 0) 159*cda5da8dSAndroid Build Coastguard Worker return sio.getvalue() 160*cda5da8dSAndroid Build Coastguard Worker 161*cda5da8dSAndroid Build Coastguard Worker def isrecursive(self, object): 162*cda5da8dSAndroid Build Coastguard Worker return self.format(object, {}, 0, 0)[2] 163*cda5da8dSAndroid Build Coastguard Worker 164*cda5da8dSAndroid Build Coastguard Worker def isreadable(self, object): 165*cda5da8dSAndroid Build Coastguard Worker s, readable, recursive = self.format(object, {}, 0, 0) 166*cda5da8dSAndroid Build Coastguard Worker return readable and not recursive 167*cda5da8dSAndroid Build Coastguard Worker 168*cda5da8dSAndroid Build Coastguard Worker def _format(self, object, stream, indent, allowance, context, level): 169*cda5da8dSAndroid Build Coastguard Worker objid = id(object) 170*cda5da8dSAndroid Build Coastguard Worker if objid in context: 171*cda5da8dSAndroid Build Coastguard Worker stream.write(_recursion(object)) 172*cda5da8dSAndroid Build Coastguard Worker self._recursive = True 173*cda5da8dSAndroid Build Coastguard Worker self._readable = False 174*cda5da8dSAndroid Build Coastguard Worker return 175*cda5da8dSAndroid Build Coastguard Worker rep = self._repr(object, context, level) 176*cda5da8dSAndroid Build Coastguard Worker max_width = self._width - indent - allowance 177*cda5da8dSAndroid Build Coastguard Worker if len(rep) > max_width: 178*cda5da8dSAndroid Build Coastguard Worker p = self._dispatch.get(type(object).__repr__, None) 179*cda5da8dSAndroid Build Coastguard Worker if p is not None: 180*cda5da8dSAndroid Build Coastguard Worker context[objid] = 1 181*cda5da8dSAndroid Build Coastguard Worker p(self, object, stream, indent, allowance, context, level + 1) 182*cda5da8dSAndroid Build Coastguard Worker del context[objid] 183*cda5da8dSAndroid Build Coastguard Worker return 184*cda5da8dSAndroid Build Coastguard Worker elif (_dataclasses.is_dataclass(object) and 185*cda5da8dSAndroid Build Coastguard Worker not isinstance(object, type) and 186*cda5da8dSAndroid Build Coastguard Worker object.__dataclass_params__.repr and 187*cda5da8dSAndroid Build Coastguard Worker # Check dataclass has generated repr method. 188*cda5da8dSAndroid Build Coastguard Worker hasattr(object.__repr__, "__wrapped__") and 189*cda5da8dSAndroid Build Coastguard Worker "__create_fn__" in object.__repr__.__wrapped__.__qualname__): 190*cda5da8dSAndroid Build Coastguard Worker context[objid] = 1 191*cda5da8dSAndroid Build Coastguard Worker self._pprint_dataclass(object, stream, indent, allowance, context, level + 1) 192*cda5da8dSAndroid Build Coastguard Worker del context[objid] 193*cda5da8dSAndroid Build Coastguard Worker return 194*cda5da8dSAndroid Build Coastguard Worker stream.write(rep) 195*cda5da8dSAndroid Build Coastguard Worker 196*cda5da8dSAndroid Build Coastguard Worker def _pprint_dataclass(self, object, stream, indent, allowance, context, level): 197*cda5da8dSAndroid Build Coastguard Worker cls_name = object.__class__.__name__ 198*cda5da8dSAndroid Build Coastguard Worker indent += len(cls_name) + 1 199*cda5da8dSAndroid Build Coastguard Worker items = [(f.name, getattr(object, f.name)) for f in _dataclasses.fields(object) if f.repr] 200*cda5da8dSAndroid Build Coastguard Worker stream.write(cls_name + '(') 201*cda5da8dSAndroid Build Coastguard Worker self._format_namespace_items(items, stream, indent, allowance, context, level) 202*cda5da8dSAndroid Build Coastguard Worker stream.write(')') 203*cda5da8dSAndroid Build Coastguard Worker 204*cda5da8dSAndroid Build Coastguard Worker _dispatch = {} 205*cda5da8dSAndroid Build Coastguard Worker 206*cda5da8dSAndroid Build Coastguard Worker def _pprint_dict(self, object, stream, indent, allowance, context, level): 207*cda5da8dSAndroid Build Coastguard Worker write = stream.write 208*cda5da8dSAndroid Build Coastguard Worker write('{') 209*cda5da8dSAndroid Build Coastguard Worker if self._indent_per_level > 1: 210*cda5da8dSAndroid Build Coastguard Worker write((self._indent_per_level - 1) * ' ') 211*cda5da8dSAndroid Build Coastguard Worker length = len(object) 212*cda5da8dSAndroid Build Coastguard Worker if length: 213*cda5da8dSAndroid Build Coastguard Worker if self._sort_dicts: 214*cda5da8dSAndroid Build Coastguard Worker items = sorted(object.items(), key=_safe_tuple) 215*cda5da8dSAndroid Build Coastguard Worker else: 216*cda5da8dSAndroid Build Coastguard Worker items = object.items() 217*cda5da8dSAndroid Build Coastguard Worker self._format_dict_items(items, stream, indent, allowance + 1, 218*cda5da8dSAndroid Build Coastguard Worker context, level) 219*cda5da8dSAndroid Build Coastguard Worker write('}') 220*cda5da8dSAndroid Build Coastguard Worker 221*cda5da8dSAndroid Build Coastguard Worker _dispatch[dict.__repr__] = _pprint_dict 222*cda5da8dSAndroid Build Coastguard Worker 223*cda5da8dSAndroid Build Coastguard Worker def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level): 224*cda5da8dSAndroid Build Coastguard Worker if not len(object): 225*cda5da8dSAndroid Build Coastguard Worker stream.write(repr(object)) 226*cda5da8dSAndroid Build Coastguard Worker return 227*cda5da8dSAndroid Build Coastguard Worker cls = object.__class__ 228*cda5da8dSAndroid Build Coastguard Worker stream.write(cls.__name__ + '(') 229*cda5da8dSAndroid Build Coastguard Worker self._format(list(object.items()), stream, 230*cda5da8dSAndroid Build Coastguard Worker indent + len(cls.__name__) + 1, allowance + 1, 231*cda5da8dSAndroid Build Coastguard Worker context, level) 232*cda5da8dSAndroid Build Coastguard Worker stream.write(')') 233*cda5da8dSAndroid Build Coastguard Worker 234*cda5da8dSAndroid Build Coastguard Worker _dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict 235*cda5da8dSAndroid Build Coastguard Worker 236*cda5da8dSAndroid Build Coastguard Worker def _pprint_list(self, object, stream, indent, allowance, context, level): 237*cda5da8dSAndroid Build Coastguard Worker stream.write('[') 238*cda5da8dSAndroid Build Coastguard Worker self._format_items(object, stream, indent, allowance + 1, 239*cda5da8dSAndroid Build Coastguard Worker context, level) 240*cda5da8dSAndroid Build Coastguard Worker stream.write(']') 241*cda5da8dSAndroid Build Coastguard Worker 242*cda5da8dSAndroid Build Coastguard Worker _dispatch[list.__repr__] = _pprint_list 243*cda5da8dSAndroid Build Coastguard Worker 244*cda5da8dSAndroid Build Coastguard Worker def _pprint_tuple(self, object, stream, indent, allowance, context, level): 245*cda5da8dSAndroid Build Coastguard Worker stream.write('(') 246*cda5da8dSAndroid Build Coastguard Worker endchar = ',)' if len(object) == 1 else ')' 247*cda5da8dSAndroid Build Coastguard Worker self._format_items(object, stream, indent, allowance + len(endchar), 248*cda5da8dSAndroid Build Coastguard Worker context, level) 249*cda5da8dSAndroid Build Coastguard Worker stream.write(endchar) 250*cda5da8dSAndroid Build Coastguard Worker 251*cda5da8dSAndroid Build Coastguard Worker _dispatch[tuple.__repr__] = _pprint_tuple 252*cda5da8dSAndroid Build Coastguard Worker 253*cda5da8dSAndroid Build Coastguard Worker def _pprint_set(self, object, stream, indent, allowance, context, level): 254*cda5da8dSAndroid Build Coastguard Worker if not len(object): 255*cda5da8dSAndroid Build Coastguard Worker stream.write(repr(object)) 256*cda5da8dSAndroid Build Coastguard Worker return 257*cda5da8dSAndroid Build Coastguard Worker typ = object.__class__ 258*cda5da8dSAndroid Build Coastguard Worker if typ is set: 259*cda5da8dSAndroid Build Coastguard Worker stream.write('{') 260*cda5da8dSAndroid Build Coastguard Worker endchar = '}' 261*cda5da8dSAndroid Build Coastguard Worker else: 262*cda5da8dSAndroid Build Coastguard Worker stream.write(typ.__name__ + '({') 263*cda5da8dSAndroid Build Coastguard Worker endchar = '})' 264*cda5da8dSAndroid Build Coastguard Worker indent += len(typ.__name__) + 1 265*cda5da8dSAndroid Build Coastguard Worker object = sorted(object, key=_safe_key) 266*cda5da8dSAndroid Build Coastguard Worker self._format_items(object, stream, indent, allowance + len(endchar), 267*cda5da8dSAndroid Build Coastguard Worker context, level) 268*cda5da8dSAndroid Build Coastguard Worker stream.write(endchar) 269*cda5da8dSAndroid Build Coastguard Worker 270*cda5da8dSAndroid Build Coastguard Worker _dispatch[set.__repr__] = _pprint_set 271*cda5da8dSAndroid Build Coastguard Worker _dispatch[frozenset.__repr__] = _pprint_set 272*cda5da8dSAndroid Build Coastguard Worker 273*cda5da8dSAndroid Build Coastguard Worker def _pprint_str(self, object, stream, indent, allowance, context, level): 274*cda5da8dSAndroid Build Coastguard Worker write = stream.write 275*cda5da8dSAndroid Build Coastguard Worker if not len(object): 276*cda5da8dSAndroid Build Coastguard Worker write(repr(object)) 277*cda5da8dSAndroid Build Coastguard Worker return 278*cda5da8dSAndroid Build Coastguard Worker chunks = [] 279*cda5da8dSAndroid Build Coastguard Worker lines = object.splitlines(True) 280*cda5da8dSAndroid Build Coastguard Worker if level == 1: 281*cda5da8dSAndroid Build Coastguard Worker indent += 1 282*cda5da8dSAndroid Build Coastguard Worker allowance += 1 283*cda5da8dSAndroid Build Coastguard Worker max_width1 = max_width = self._width - indent 284*cda5da8dSAndroid Build Coastguard Worker for i, line in enumerate(lines): 285*cda5da8dSAndroid Build Coastguard Worker rep = repr(line) 286*cda5da8dSAndroid Build Coastguard Worker if i == len(lines) - 1: 287*cda5da8dSAndroid Build Coastguard Worker max_width1 -= allowance 288*cda5da8dSAndroid Build Coastguard Worker if len(rep) <= max_width1: 289*cda5da8dSAndroid Build Coastguard Worker chunks.append(rep) 290*cda5da8dSAndroid Build Coastguard Worker else: 291*cda5da8dSAndroid Build Coastguard Worker # A list of alternating (non-space, space) strings 292*cda5da8dSAndroid Build Coastguard Worker parts = re.findall(r'\S*\s*', line) 293*cda5da8dSAndroid Build Coastguard Worker assert parts 294*cda5da8dSAndroid Build Coastguard Worker assert not parts[-1] 295*cda5da8dSAndroid Build Coastguard Worker parts.pop() # drop empty last part 296*cda5da8dSAndroid Build Coastguard Worker max_width2 = max_width 297*cda5da8dSAndroid Build Coastguard Worker current = '' 298*cda5da8dSAndroid Build Coastguard Worker for j, part in enumerate(parts): 299*cda5da8dSAndroid Build Coastguard Worker candidate = current + part 300*cda5da8dSAndroid Build Coastguard Worker if j == len(parts) - 1 and i == len(lines) - 1: 301*cda5da8dSAndroid Build Coastguard Worker max_width2 -= allowance 302*cda5da8dSAndroid Build Coastguard Worker if len(repr(candidate)) > max_width2: 303*cda5da8dSAndroid Build Coastguard Worker if current: 304*cda5da8dSAndroid Build Coastguard Worker chunks.append(repr(current)) 305*cda5da8dSAndroid Build Coastguard Worker current = part 306*cda5da8dSAndroid Build Coastguard Worker else: 307*cda5da8dSAndroid Build Coastguard Worker current = candidate 308*cda5da8dSAndroid Build Coastguard Worker if current: 309*cda5da8dSAndroid Build Coastguard Worker chunks.append(repr(current)) 310*cda5da8dSAndroid Build Coastguard Worker if len(chunks) == 1: 311*cda5da8dSAndroid Build Coastguard Worker write(rep) 312*cda5da8dSAndroid Build Coastguard Worker return 313*cda5da8dSAndroid Build Coastguard Worker if level == 1: 314*cda5da8dSAndroid Build Coastguard Worker write('(') 315*cda5da8dSAndroid Build Coastguard Worker for i, rep in enumerate(chunks): 316*cda5da8dSAndroid Build Coastguard Worker if i > 0: 317*cda5da8dSAndroid Build Coastguard Worker write('\n' + ' '*indent) 318*cda5da8dSAndroid Build Coastguard Worker write(rep) 319*cda5da8dSAndroid Build Coastguard Worker if level == 1: 320*cda5da8dSAndroid Build Coastguard Worker write(')') 321*cda5da8dSAndroid Build Coastguard Worker 322*cda5da8dSAndroid Build Coastguard Worker _dispatch[str.__repr__] = _pprint_str 323*cda5da8dSAndroid Build Coastguard Worker 324*cda5da8dSAndroid Build Coastguard Worker def _pprint_bytes(self, object, stream, indent, allowance, context, level): 325*cda5da8dSAndroid Build Coastguard Worker write = stream.write 326*cda5da8dSAndroid Build Coastguard Worker if len(object) <= 4: 327*cda5da8dSAndroid Build Coastguard Worker write(repr(object)) 328*cda5da8dSAndroid Build Coastguard Worker return 329*cda5da8dSAndroid Build Coastguard Worker parens = level == 1 330*cda5da8dSAndroid Build Coastguard Worker if parens: 331*cda5da8dSAndroid Build Coastguard Worker indent += 1 332*cda5da8dSAndroid Build Coastguard Worker allowance += 1 333*cda5da8dSAndroid Build Coastguard Worker write('(') 334*cda5da8dSAndroid Build Coastguard Worker delim = '' 335*cda5da8dSAndroid Build Coastguard Worker for rep in _wrap_bytes_repr(object, self._width - indent, allowance): 336*cda5da8dSAndroid Build Coastguard Worker write(delim) 337*cda5da8dSAndroid Build Coastguard Worker write(rep) 338*cda5da8dSAndroid Build Coastguard Worker if not delim: 339*cda5da8dSAndroid Build Coastguard Worker delim = '\n' + ' '*indent 340*cda5da8dSAndroid Build Coastguard Worker if parens: 341*cda5da8dSAndroid Build Coastguard Worker write(')') 342*cda5da8dSAndroid Build Coastguard Worker 343*cda5da8dSAndroid Build Coastguard Worker _dispatch[bytes.__repr__] = _pprint_bytes 344*cda5da8dSAndroid Build Coastguard Worker 345*cda5da8dSAndroid Build Coastguard Worker def _pprint_bytearray(self, object, stream, indent, allowance, context, level): 346*cda5da8dSAndroid Build Coastguard Worker write = stream.write 347*cda5da8dSAndroid Build Coastguard Worker write('bytearray(') 348*cda5da8dSAndroid Build Coastguard Worker self._pprint_bytes(bytes(object), stream, indent + 10, 349*cda5da8dSAndroid Build Coastguard Worker allowance + 1, context, level + 1) 350*cda5da8dSAndroid Build Coastguard Worker write(')') 351*cda5da8dSAndroid Build Coastguard Worker 352*cda5da8dSAndroid Build Coastguard Worker _dispatch[bytearray.__repr__] = _pprint_bytearray 353*cda5da8dSAndroid Build Coastguard Worker 354*cda5da8dSAndroid Build Coastguard Worker def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level): 355*cda5da8dSAndroid Build Coastguard Worker stream.write('mappingproxy(') 356*cda5da8dSAndroid Build Coastguard Worker self._format(object.copy(), stream, indent + 13, allowance + 1, 357*cda5da8dSAndroid Build Coastguard Worker context, level) 358*cda5da8dSAndroid Build Coastguard Worker stream.write(')') 359*cda5da8dSAndroid Build Coastguard Worker 360*cda5da8dSAndroid Build Coastguard Worker _dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy 361*cda5da8dSAndroid Build Coastguard Worker 362*cda5da8dSAndroid Build Coastguard Worker def _pprint_simplenamespace(self, object, stream, indent, allowance, context, level): 363*cda5da8dSAndroid Build Coastguard Worker if type(object) is _types.SimpleNamespace: 364*cda5da8dSAndroid Build Coastguard Worker # The SimpleNamespace repr is "namespace" instead of the class 365*cda5da8dSAndroid Build Coastguard Worker # name, so we do the same here. For subclasses; use the class name. 366*cda5da8dSAndroid Build Coastguard Worker cls_name = 'namespace' 367*cda5da8dSAndroid Build Coastguard Worker else: 368*cda5da8dSAndroid Build Coastguard Worker cls_name = object.__class__.__name__ 369*cda5da8dSAndroid Build Coastguard Worker indent += len(cls_name) + 1 370*cda5da8dSAndroid Build Coastguard Worker items = object.__dict__.items() 371*cda5da8dSAndroid Build Coastguard Worker stream.write(cls_name + '(') 372*cda5da8dSAndroid Build Coastguard Worker self._format_namespace_items(items, stream, indent, allowance, context, level) 373*cda5da8dSAndroid Build Coastguard Worker stream.write(')') 374*cda5da8dSAndroid Build Coastguard Worker 375*cda5da8dSAndroid Build Coastguard Worker _dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace 376*cda5da8dSAndroid Build Coastguard Worker 377*cda5da8dSAndroid Build Coastguard Worker def _format_dict_items(self, items, stream, indent, allowance, context, 378*cda5da8dSAndroid Build Coastguard Worker level): 379*cda5da8dSAndroid Build Coastguard Worker write = stream.write 380*cda5da8dSAndroid Build Coastguard Worker indent += self._indent_per_level 381*cda5da8dSAndroid Build Coastguard Worker delimnl = ',\n' + ' ' * indent 382*cda5da8dSAndroid Build Coastguard Worker last_index = len(items) - 1 383*cda5da8dSAndroid Build Coastguard Worker for i, (key, ent) in enumerate(items): 384*cda5da8dSAndroid Build Coastguard Worker last = i == last_index 385*cda5da8dSAndroid Build Coastguard Worker rep = self._repr(key, context, level) 386*cda5da8dSAndroid Build Coastguard Worker write(rep) 387*cda5da8dSAndroid Build Coastguard Worker write(': ') 388*cda5da8dSAndroid Build Coastguard Worker self._format(ent, stream, indent + len(rep) + 2, 389*cda5da8dSAndroid Build Coastguard Worker allowance if last else 1, 390*cda5da8dSAndroid Build Coastguard Worker context, level) 391*cda5da8dSAndroid Build Coastguard Worker if not last: 392*cda5da8dSAndroid Build Coastguard Worker write(delimnl) 393*cda5da8dSAndroid Build Coastguard Worker 394*cda5da8dSAndroid Build Coastguard Worker def _format_namespace_items(self, items, stream, indent, allowance, context, level): 395*cda5da8dSAndroid Build Coastguard Worker write = stream.write 396*cda5da8dSAndroid Build Coastguard Worker delimnl = ',\n' + ' ' * indent 397*cda5da8dSAndroid Build Coastguard Worker last_index = len(items) - 1 398*cda5da8dSAndroid Build Coastguard Worker for i, (key, ent) in enumerate(items): 399*cda5da8dSAndroid Build Coastguard Worker last = i == last_index 400*cda5da8dSAndroid Build Coastguard Worker write(key) 401*cda5da8dSAndroid Build Coastguard Worker write('=') 402*cda5da8dSAndroid Build Coastguard Worker if id(ent) in context: 403*cda5da8dSAndroid Build Coastguard Worker # Special-case representation of recursion to match standard 404*cda5da8dSAndroid Build Coastguard Worker # recursive dataclass repr. 405*cda5da8dSAndroid Build Coastguard Worker write("...") 406*cda5da8dSAndroid Build Coastguard Worker else: 407*cda5da8dSAndroid Build Coastguard Worker self._format(ent, stream, indent + len(key) + 1, 408*cda5da8dSAndroid Build Coastguard Worker allowance if last else 1, 409*cda5da8dSAndroid Build Coastguard Worker context, level) 410*cda5da8dSAndroid Build Coastguard Worker if not last: 411*cda5da8dSAndroid Build Coastguard Worker write(delimnl) 412*cda5da8dSAndroid Build Coastguard Worker 413*cda5da8dSAndroid Build Coastguard Worker def _format_items(self, items, stream, indent, allowance, context, level): 414*cda5da8dSAndroid Build Coastguard Worker write = stream.write 415*cda5da8dSAndroid Build Coastguard Worker indent += self._indent_per_level 416*cda5da8dSAndroid Build Coastguard Worker if self._indent_per_level > 1: 417*cda5da8dSAndroid Build Coastguard Worker write((self._indent_per_level - 1) * ' ') 418*cda5da8dSAndroid Build Coastguard Worker delimnl = ',\n' + ' ' * indent 419*cda5da8dSAndroid Build Coastguard Worker delim = '' 420*cda5da8dSAndroid Build Coastguard Worker width = max_width = self._width - indent + 1 421*cda5da8dSAndroid Build Coastguard Worker it = iter(items) 422*cda5da8dSAndroid Build Coastguard Worker try: 423*cda5da8dSAndroid Build Coastguard Worker next_ent = next(it) 424*cda5da8dSAndroid Build Coastguard Worker except StopIteration: 425*cda5da8dSAndroid Build Coastguard Worker return 426*cda5da8dSAndroid Build Coastguard Worker last = False 427*cda5da8dSAndroid Build Coastguard Worker while not last: 428*cda5da8dSAndroid Build Coastguard Worker ent = next_ent 429*cda5da8dSAndroid Build Coastguard Worker try: 430*cda5da8dSAndroid Build Coastguard Worker next_ent = next(it) 431*cda5da8dSAndroid Build Coastguard Worker except StopIteration: 432*cda5da8dSAndroid Build Coastguard Worker last = True 433*cda5da8dSAndroid Build Coastguard Worker max_width -= allowance 434*cda5da8dSAndroid Build Coastguard Worker width -= allowance 435*cda5da8dSAndroid Build Coastguard Worker if self._compact: 436*cda5da8dSAndroid Build Coastguard Worker rep = self._repr(ent, context, level) 437*cda5da8dSAndroid Build Coastguard Worker w = len(rep) + 2 438*cda5da8dSAndroid Build Coastguard Worker if width < w: 439*cda5da8dSAndroid Build Coastguard Worker width = max_width 440*cda5da8dSAndroid Build Coastguard Worker if delim: 441*cda5da8dSAndroid Build Coastguard Worker delim = delimnl 442*cda5da8dSAndroid Build Coastguard Worker if width >= w: 443*cda5da8dSAndroid Build Coastguard Worker width -= w 444*cda5da8dSAndroid Build Coastguard Worker write(delim) 445*cda5da8dSAndroid Build Coastguard Worker delim = ', ' 446*cda5da8dSAndroid Build Coastguard Worker write(rep) 447*cda5da8dSAndroid Build Coastguard Worker continue 448*cda5da8dSAndroid Build Coastguard Worker write(delim) 449*cda5da8dSAndroid Build Coastguard Worker delim = delimnl 450*cda5da8dSAndroid Build Coastguard Worker self._format(ent, stream, indent, 451*cda5da8dSAndroid Build Coastguard Worker allowance if last else 1, 452*cda5da8dSAndroid Build Coastguard Worker context, level) 453*cda5da8dSAndroid Build Coastguard Worker 454*cda5da8dSAndroid Build Coastguard Worker def _repr(self, object, context, level): 455*cda5da8dSAndroid Build Coastguard Worker repr, readable, recursive = self.format(object, context.copy(), 456*cda5da8dSAndroid Build Coastguard Worker self._depth, level) 457*cda5da8dSAndroid Build Coastguard Worker if not readable: 458*cda5da8dSAndroid Build Coastguard Worker self._readable = False 459*cda5da8dSAndroid Build Coastguard Worker if recursive: 460*cda5da8dSAndroid Build Coastguard Worker self._recursive = True 461*cda5da8dSAndroid Build Coastguard Worker return repr 462*cda5da8dSAndroid Build Coastguard Worker 463*cda5da8dSAndroid Build Coastguard Worker def format(self, object, context, maxlevels, level): 464*cda5da8dSAndroid Build Coastguard Worker """Format object for a specific context, returning a string 465*cda5da8dSAndroid Build Coastguard Worker and flags indicating whether the representation is 'readable' 466*cda5da8dSAndroid Build Coastguard Worker and whether the object represents a recursive construct. 467*cda5da8dSAndroid Build Coastguard Worker """ 468*cda5da8dSAndroid Build Coastguard Worker return self._safe_repr(object, context, maxlevels, level) 469*cda5da8dSAndroid Build Coastguard Worker 470*cda5da8dSAndroid Build Coastguard Worker def _pprint_default_dict(self, object, stream, indent, allowance, context, level): 471*cda5da8dSAndroid Build Coastguard Worker if not len(object): 472*cda5da8dSAndroid Build Coastguard Worker stream.write(repr(object)) 473*cda5da8dSAndroid Build Coastguard Worker return 474*cda5da8dSAndroid Build Coastguard Worker rdf = self._repr(object.default_factory, context, level) 475*cda5da8dSAndroid Build Coastguard Worker cls = object.__class__ 476*cda5da8dSAndroid Build Coastguard Worker indent += len(cls.__name__) + 1 477*cda5da8dSAndroid Build Coastguard Worker stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent)) 478*cda5da8dSAndroid Build Coastguard Worker self._pprint_dict(object, stream, indent, allowance + 1, context, level) 479*cda5da8dSAndroid Build Coastguard Worker stream.write(')') 480*cda5da8dSAndroid Build Coastguard Worker 481*cda5da8dSAndroid Build Coastguard Worker _dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict 482*cda5da8dSAndroid Build Coastguard Worker 483*cda5da8dSAndroid Build Coastguard Worker def _pprint_counter(self, object, stream, indent, allowance, context, level): 484*cda5da8dSAndroid Build Coastguard Worker if not len(object): 485*cda5da8dSAndroid Build Coastguard Worker stream.write(repr(object)) 486*cda5da8dSAndroid Build Coastguard Worker return 487*cda5da8dSAndroid Build Coastguard Worker cls = object.__class__ 488*cda5da8dSAndroid Build Coastguard Worker stream.write(cls.__name__ + '({') 489*cda5da8dSAndroid Build Coastguard Worker if self._indent_per_level > 1: 490*cda5da8dSAndroid Build Coastguard Worker stream.write((self._indent_per_level - 1) * ' ') 491*cda5da8dSAndroid Build Coastguard Worker items = object.most_common() 492*cda5da8dSAndroid Build Coastguard Worker self._format_dict_items(items, stream, 493*cda5da8dSAndroid Build Coastguard Worker indent + len(cls.__name__) + 1, allowance + 2, 494*cda5da8dSAndroid Build Coastguard Worker context, level) 495*cda5da8dSAndroid Build Coastguard Worker stream.write('})') 496*cda5da8dSAndroid Build Coastguard Worker 497*cda5da8dSAndroid Build Coastguard Worker _dispatch[_collections.Counter.__repr__] = _pprint_counter 498*cda5da8dSAndroid Build Coastguard Worker 499*cda5da8dSAndroid Build Coastguard Worker def _pprint_chain_map(self, object, stream, indent, allowance, context, level): 500*cda5da8dSAndroid Build Coastguard Worker if not len(object.maps): 501*cda5da8dSAndroid Build Coastguard Worker stream.write(repr(object)) 502*cda5da8dSAndroid Build Coastguard Worker return 503*cda5da8dSAndroid Build Coastguard Worker cls = object.__class__ 504*cda5da8dSAndroid Build Coastguard Worker stream.write(cls.__name__ + '(') 505*cda5da8dSAndroid Build Coastguard Worker indent += len(cls.__name__) + 1 506*cda5da8dSAndroid Build Coastguard Worker for i, m in enumerate(object.maps): 507*cda5da8dSAndroid Build Coastguard Worker if i == len(object.maps) - 1: 508*cda5da8dSAndroid Build Coastguard Worker self._format(m, stream, indent, allowance + 1, context, level) 509*cda5da8dSAndroid Build Coastguard Worker stream.write(')') 510*cda5da8dSAndroid Build Coastguard Worker else: 511*cda5da8dSAndroid Build Coastguard Worker self._format(m, stream, indent, 1, context, level) 512*cda5da8dSAndroid Build Coastguard Worker stream.write(',\n' + ' ' * indent) 513*cda5da8dSAndroid Build Coastguard Worker 514*cda5da8dSAndroid Build Coastguard Worker _dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map 515*cda5da8dSAndroid Build Coastguard Worker 516*cda5da8dSAndroid Build Coastguard Worker def _pprint_deque(self, object, stream, indent, allowance, context, level): 517*cda5da8dSAndroid Build Coastguard Worker if not len(object): 518*cda5da8dSAndroid Build Coastguard Worker stream.write(repr(object)) 519*cda5da8dSAndroid Build Coastguard Worker return 520*cda5da8dSAndroid Build Coastguard Worker cls = object.__class__ 521*cda5da8dSAndroid Build Coastguard Worker stream.write(cls.__name__ + '(') 522*cda5da8dSAndroid Build Coastguard Worker indent += len(cls.__name__) + 1 523*cda5da8dSAndroid Build Coastguard Worker stream.write('[') 524*cda5da8dSAndroid Build Coastguard Worker if object.maxlen is None: 525*cda5da8dSAndroid Build Coastguard Worker self._format_items(object, stream, indent, allowance + 2, 526*cda5da8dSAndroid Build Coastguard Worker context, level) 527*cda5da8dSAndroid Build Coastguard Worker stream.write('])') 528*cda5da8dSAndroid Build Coastguard Worker else: 529*cda5da8dSAndroid Build Coastguard Worker self._format_items(object, stream, indent, 2, 530*cda5da8dSAndroid Build Coastguard Worker context, level) 531*cda5da8dSAndroid Build Coastguard Worker rml = self._repr(object.maxlen, context, level) 532*cda5da8dSAndroid Build Coastguard Worker stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml)) 533*cda5da8dSAndroid Build Coastguard Worker 534*cda5da8dSAndroid Build Coastguard Worker _dispatch[_collections.deque.__repr__] = _pprint_deque 535*cda5da8dSAndroid Build Coastguard Worker 536*cda5da8dSAndroid Build Coastguard Worker def _pprint_user_dict(self, object, stream, indent, allowance, context, level): 537*cda5da8dSAndroid Build Coastguard Worker self._format(object.data, stream, indent, allowance, context, level - 1) 538*cda5da8dSAndroid Build Coastguard Worker 539*cda5da8dSAndroid Build Coastguard Worker _dispatch[_collections.UserDict.__repr__] = _pprint_user_dict 540*cda5da8dSAndroid Build Coastguard Worker 541*cda5da8dSAndroid Build Coastguard Worker def _pprint_user_list(self, object, stream, indent, allowance, context, level): 542*cda5da8dSAndroid Build Coastguard Worker self._format(object.data, stream, indent, allowance, context, level - 1) 543*cda5da8dSAndroid Build Coastguard Worker 544*cda5da8dSAndroid Build Coastguard Worker _dispatch[_collections.UserList.__repr__] = _pprint_user_list 545*cda5da8dSAndroid Build Coastguard Worker 546*cda5da8dSAndroid Build Coastguard Worker def _pprint_user_string(self, object, stream, indent, allowance, context, level): 547*cda5da8dSAndroid Build Coastguard Worker self._format(object.data, stream, indent, allowance, context, level - 1) 548*cda5da8dSAndroid Build Coastguard Worker 549*cda5da8dSAndroid Build Coastguard Worker _dispatch[_collections.UserString.__repr__] = _pprint_user_string 550*cda5da8dSAndroid Build Coastguard Worker 551*cda5da8dSAndroid Build Coastguard Worker def _safe_repr(self, object, context, maxlevels, level): 552*cda5da8dSAndroid Build Coastguard Worker # Return triple (repr_string, isreadable, isrecursive). 553*cda5da8dSAndroid Build Coastguard Worker typ = type(object) 554*cda5da8dSAndroid Build Coastguard Worker if typ in _builtin_scalars: 555*cda5da8dSAndroid Build Coastguard Worker return repr(object), True, False 556*cda5da8dSAndroid Build Coastguard Worker 557*cda5da8dSAndroid Build Coastguard Worker r = getattr(typ, "__repr__", None) 558*cda5da8dSAndroid Build Coastguard Worker 559*cda5da8dSAndroid Build Coastguard Worker if issubclass(typ, int) and r is int.__repr__: 560*cda5da8dSAndroid Build Coastguard Worker if self._underscore_numbers: 561*cda5da8dSAndroid Build Coastguard Worker return f"{object:_d}", True, False 562*cda5da8dSAndroid Build Coastguard Worker else: 563*cda5da8dSAndroid Build Coastguard Worker return repr(object), True, False 564*cda5da8dSAndroid Build Coastguard Worker 565*cda5da8dSAndroid Build Coastguard Worker if issubclass(typ, dict) and r is dict.__repr__: 566*cda5da8dSAndroid Build Coastguard Worker if not object: 567*cda5da8dSAndroid Build Coastguard Worker return "{}", True, False 568*cda5da8dSAndroid Build Coastguard Worker objid = id(object) 569*cda5da8dSAndroid Build Coastguard Worker if maxlevels and level >= maxlevels: 570*cda5da8dSAndroid Build Coastguard Worker return "{...}", False, objid in context 571*cda5da8dSAndroid Build Coastguard Worker if objid in context: 572*cda5da8dSAndroid Build Coastguard Worker return _recursion(object), False, True 573*cda5da8dSAndroid Build Coastguard Worker context[objid] = 1 574*cda5da8dSAndroid Build Coastguard Worker readable = True 575*cda5da8dSAndroid Build Coastguard Worker recursive = False 576*cda5da8dSAndroid Build Coastguard Worker components = [] 577*cda5da8dSAndroid Build Coastguard Worker append = components.append 578*cda5da8dSAndroid Build Coastguard Worker level += 1 579*cda5da8dSAndroid Build Coastguard Worker if self._sort_dicts: 580*cda5da8dSAndroid Build Coastguard Worker items = sorted(object.items(), key=_safe_tuple) 581*cda5da8dSAndroid Build Coastguard Worker else: 582*cda5da8dSAndroid Build Coastguard Worker items = object.items() 583*cda5da8dSAndroid Build Coastguard Worker for k, v in items: 584*cda5da8dSAndroid Build Coastguard Worker krepr, kreadable, krecur = self.format( 585*cda5da8dSAndroid Build Coastguard Worker k, context, maxlevels, level) 586*cda5da8dSAndroid Build Coastguard Worker vrepr, vreadable, vrecur = self.format( 587*cda5da8dSAndroid Build Coastguard Worker v, context, maxlevels, level) 588*cda5da8dSAndroid Build Coastguard Worker append("%s: %s" % (krepr, vrepr)) 589*cda5da8dSAndroid Build Coastguard Worker readable = readable and kreadable and vreadable 590*cda5da8dSAndroid Build Coastguard Worker if krecur or vrecur: 591*cda5da8dSAndroid Build Coastguard Worker recursive = True 592*cda5da8dSAndroid Build Coastguard Worker del context[objid] 593*cda5da8dSAndroid Build Coastguard Worker return "{%s}" % ", ".join(components), readable, recursive 594*cda5da8dSAndroid Build Coastguard Worker 595*cda5da8dSAndroid Build Coastguard Worker if (issubclass(typ, list) and r is list.__repr__) or \ 596*cda5da8dSAndroid Build Coastguard Worker (issubclass(typ, tuple) and r is tuple.__repr__): 597*cda5da8dSAndroid Build Coastguard Worker if issubclass(typ, list): 598*cda5da8dSAndroid Build Coastguard Worker if not object: 599*cda5da8dSAndroid Build Coastguard Worker return "[]", True, False 600*cda5da8dSAndroid Build Coastguard Worker format = "[%s]" 601*cda5da8dSAndroid Build Coastguard Worker elif len(object) == 1: 602*cda5da8dSAndroid Build Coastguard Worker format = "(%s,)" 603*cda5da8dSAndroid Build Coastguard Worker else: 604*cda5da8dSAndroid Build Coastguard Worker if not object: 605*cda5da8dSAndroid Build Coastguard Worker return "()", True, False 606*cda5da8dSAndroid Build Coastguard Worker format = "(%s)" 607*cda5da8dSAndroid Build Coastguard Worker objid = id(object) 608*cda5da8dSAndroid Build Coastguard Worker if maxlevels and level >= maxlevels: 609*cda5da8dSAndroid Build Coastguard Worker return format % "...", False, objid in context 610*cda5da8dSAndroid Build Coastguard Worker if objid in context: 611*cda5da8dSAndroid Build Coastguard Worker return _recursion(object), False, True 612*cda5da8dSAndroid Build Coastguard Worker context[objid] = 1 613*cda5da8dSAndroid Build Coastguard Worker readable = True 614*cda5da8dSAndroid Build Coastguard Worker recursive = False 615*cda5da8dSAndroid Build Coastguard Worker components = [] 616*cda5da8dSAndroid Build Coastguard Worker append = components.append 617*cda5da8dSAndroid Build Coastguard Worker level += 1 618*cda5da8dSAndroid Build Coastguard Worker for o in object: 619*cda5da8dSAndroid Build Coastguard Worker orepr, oreadable, orecur = self.format( 620*cda5da8dSAndroid Build Coastguard Worker o, context, maxlevels, level) 621*cda5da8dSAndroid Build Coastguard Worker append(orepr) 622*cda5da8dSAndroid Build Coastguard Worker if not oreadable: 623*cda5da8dSAndroid Build Coastguard Worker readable = False 624*cda5da8dSAndroid Build Coastguard Worker if orecur: 625*cda5da8dSAndroid Build Coastguard Worker recursive = True 626*cda5da8dSAndroid Build Coastguard Worker del context[objid] 627*cda5da8dSAndroid Build Coastguard Worker return format % ", ".join(components), readable, recursive 628*cda5da8dSAndroid Build Coastguard Worker 629*cda5da8dSAndroid Build Coastguard Worker rep = repr(object) 630*cda5da8dSAndroid Build Coastguard Worker return rep, (rep and not rep.startswith('<')), False 631*cda5da8dSAndroid Build Coastguard Worker 632*cda5da8dSAndroid Build Coastguard Worker_builtin_scalars = frozenset({str, bytes, bytearray, float, complex, 633*cda5da8dSAndroid Build Coastguard Worker bool, type(None)}) 634*cda5da8dSAndroid Build Coastguard Worker 635*cda5da8dSAndroid Build Coastguard Workerdef _recursion(object): 636*cda5da8dSAndroid Build Coastguard Worker return ("<Recursion on %s with id=%s>" 637*cda5da8dSAndroid Build Coastguard Worker % (type(object).__name__, id(object))) 638*cda5da8dSAndroid Build Coastguard Worker 639*cda5da8dSAndroid Build Coastguard Worker 640*cda5da8dSAndroid Build Coastguard Workerdef _perfcheck(object=None): 641*cda5da8dSAndroid Build Coastguard Worker import time 642*cda5da8dSAndroid Build Coastguard Worker if object is None: 643*cda5da8dSAndroid Build Coastguard Worker object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000 644*cda5da8dSAndroid Build Coastguard Worker p = PrettyPrinter() 645*cda5da8dSAndroid Build Coastguard Worker t1 = time.perf_counter() 646*cda5da8dSAndroid Build Coastguard Worker p._safe_repr(object, {}, None, 0, True) 647*cda5da8dSAndroid Build Coastguard Worker t2 = time.perf_counter() 648*cda5da8dSAndroid Build Coastguard Worker p.pformat(object) 649*cda5da8dSAndroid Build Coastguard Worker t3 = time.perf_counter() 650*cda5da8dSAndroid Build Coastguard Worker print("_safe_repr:", t2 - t1) 651*cda5da8dSAndroid Build Coastguard Worker print("pformat:", t3 - t2) 652*cda5da8dSAndroid Build Coastguard Worker 653*cda5da8dSAndroid Build Coastguard Workerdef _wrap_bytes_repr(object, width, allowance): 654*cda5da8dSAndroid Build Coastguard Worker current = b'' 655*cda5da8dSAndroid Build Coastguard Worker last = len(object) // 4 * 4 656*cda5da8dSAndroid Build Coastguard Worker for i in range(0, len(object), 4): 657*cda5da8dSAndroid Build Coastguard Worker part = object[i: i+4] 658*cda5da8dSAndroid Build Coastguard Worker candidate = current + part 659*cda5da8dSAndroid Build Coastguard Worker if i == last: 660*cda5da8dSAndroid Build Coastguard Worker width -= allowance 661*cda5da8dSAndroid Build Coastguard Worker if len(repr(candidate)) > width: 662*cda5da8dSAndroid Build Coastguard Worker if current: 663*cda5da8dSAndroid Build Coastguard Worker yield repr(current) 664*cda5da8dSAndroid Build Coastguard Worker current = part 665*cda5da8dSAndroid Build Coastguard Worker else: 666*cda5da8dSAndroid Build Coastguard Worker current = candidate 667*cda5da8dSAndroid Build Coastguard Worker if current: 668*cda5da8dSAndroid Build Coastguard Worker yield repr(current) 669*cda5da8dSAndroid Build Coastguard Worker 670*cda5da8dSAndroid Build Coastguard Workerif __name__ == "__main__": 671*cda5da8dSAndroid Build Coastguard Worker _perfcheck() 672