xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/pprint.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
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