aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Lib/pprint.py
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/tools/python3/src/Lib/pprint.py
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/tools/python3/src/Lib/pprint.py')
-rw-r--r--contrib/tools/python3/src/Lib/pprint.py638
1 files changed, 638 insertions, 0 deletions
diff --git a/contrib/tools/python3/src/Lib/pprint.py b/contrib/tools/python3/src/Lib/pprint.py
new file mode 100644
index 0000000000..7c1118a484
--- /dev/null
+++ b/contrib/tools/python3/src/Lib/pprint.py
@@ -0,0 +1,638 @@
+# Author: Fred L. Drake, Jr.
+# fdrake@acm.org
+#
+# This is a simple little module I wrote to make life easier. I didn't
+# see anything quite like it in the library, though I may have overlooked
+# something. I wrote this when I was trying to read some heavily nested
+# tuples with fairly non-descriptive content. This is modeled very much
+# after Lisp/Scheme - style pretty-printing of lists. If you find it
+# useful, thank small children who sleep at night.
+
+"""Support to pretty-print lists, tuples, & dictionaries recursively.
+
+Very simple, but useful, especially in debugging data structures.
+
+Classes
+-------
+
+PrettyPrinter()
+ Handle pretty-printing operations onto a stream using a configured
+ set of formatting parameters.
+
+Functions
+---------
+
+pformat()
+ Format a Python object into a pretty-printed representation.
+
+pprint()
+ Pretty-print a Python object to a stream [default is sys.stdout].
+
+saferepr()
+ Generate a 'standard' repr()-like value, but protect against recursive
+ data structures.
+
+"""
+
+import collections as _collections
+import re
+import sys as _sys
+import types as _types
+from io import StringIO as _StringIO
+
+__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr",
+ "PrettyPrinter", "pp"]
+
+
+def pprint(object, stream=None, indent=1, width=80, depth=None, *,
+ compact=False, sort_dicts=True):
+ """Pretty-print a Python object to a stream [default is sys.stdout]."""
+ printer = PrettyPrinter(
+ stream=stream, indent=indent, width=width, depth=depth,
+ compact=compact, sort_dicts=sort_dicts)
+ printer.pprint(object)
+
+def pformat(object, indent=1, width=80, depth=None, *,
+ compact=False, sort_dicts=True):
+ """Format a Python object into a pretty-printed representation."""
+ return PrettyPrinter(indent=indent, width=width, depth=depth,
+ compact=compact, sort_dicts=sort_dicts).pformat(object)
+
+def pp(object, *args, sort_dicts=False, **kwargs):
+ """Pretty-print a Python object"""
+ pprint(object, *args, sort_dicts=sort_dicts, **kwargs)
+
+def saferepr(object):
+ """Version of repr() which can handle recursive data structures."""
+ return _safe_repr(object, {}, None, 0, True)[0]
+
+def isreadable(object):
+ """Determine if saferepr(object) is readable by eval()."""
+ return _safe_repr(object, {}, None, 0, True)[1]
+
+def isrecursive(object):
+ """Determine if object requires a recursive representation."""
+ return _safe_repr(object, {}, None, 0, True)[2]
+
+class _safe_key:
+ """Helper function for key functions when sorting unorderable objects.
+
+ The wrapped-object will fallback to a Py2.x style comparison for
+ unorderable types (sorting first comparing the type name and then by
+ the obj ids). Does not work recursively, so dict.items() must have
+ _safe_key applied to both the key and the value.
+
+ """
+
+ __slots__ = ['obj']
+
+ def __init__(self, obj):
+ self.obj = obj
+
+ def __lt__(self, other):
+ try:
+ return self.obj < other.obj
+ except TypeError:
+ return ((str(type(self.obj)), id(self.obj)) < \
+ (str(type(other.obj)), id(other.obj)))
+
+def _safe_tuple(t):
+ "Helper function for comparing 2-tuples"
+ return _safe_key(t[0]), _safe_key(t[1])
+
+class PrettyPrinter:
+ def __init__(self, indent=1, width=80, depth=None, stream=None, *,
+ compact=False, sort_dicts=True):
+ """Handle pretty printing operations onto a stream using a set of
+ configured parameters.
+
+ indent
+ Number of spaces to indent for each level of nesting.
+
+ width
+ Attempted maximum number of columns in the output.
+
+ depth
+ The maximum depth to print out nested structures.
+
+ stream
+ The desired output stream. If omitted (or false), the standard
+ output stream available at construction will be used.
+
+ compact
+ If true, several items will be combined in one line.
+
+ sort_dicts
+ If true, dict keys are sorted.
+
+ """
+ indent = int(indent)
+ width = int(width)
+ if indent < 0:
+ raise ValueError('indent must be >= 0')
+ if depth is not None and depth <= 0:
+ raise ValueError('depth must be > 0')
+ if not width:
+ raise ValueError('width must be != 0')
+ self._depth = depth
+ self._indent_per_level = indent
+ self._width = width
+ if stream is not None:
+ self._stream = stream
+ else:
+ self._stream = _sys.stdout
+ self._compact = bool(compact)
+ self._sort_dicts = sort_dicts
+
+ def pprint(self, object):
+ self._format(object, self._stream, 0, 0, {}, 0)
+ self._stream.write("\n")
+
+ def pformat(self, object):
+ sio = _StringIO()
+ self._format(object, sio, 0, 0, {}, 0)
+ return sio.getvalue()
+
+ def isrecursive(self, object):
+ return self.format(object, {}, 0, 0)[2]
+
+ def isreadable(self, object):
+ s, readable, recursive = self.format(object, {}, 0, 0)
+ return readable and not recursive
+
+ def _format(self, object, stream, indent, allowance, context, level):
+ objid = id(object)
+ if objid in context:
+ stream.write(_recursion(object))
+ self._recursive = True
+ self._readable = False
+ return
+ rep = self._repr(object, context, level)
+ max_width = self._width - indent - allowance
+ if len(rep) > max_width:
+ p = self._dispatch.get(type(object).__repr__, None)
+ if p is not None:
+ context[objid] = 1
+ p(self, object, stream, indent, allowance, context, level + 1)
+ del context[objid]
+ return
+ elif isinstance(object, dict):
+ context[objid] = 1
+ self._pprint_dict(object, stream, indent, allowance,
+ context, level + 1)
+ del context[objid]
+ return
+ stream.write(rep)
+
+ _dispatch = {}
+
+ def _pprint_dict(self, object, stream, indent, allowance, context, level):
+ write = stream.write
+ write('{')
+ if self._indent_per_level > 1:
+ write((self._indent_per_level - 1) * ' ')
+ length = len(object)
+ if length:
+ if self._sort_dicts:
+ items = sorted(object.items(), key=_safe_tuple)
+ else:
+ items = object.items()
+ self._format_dict_items(items, stream, indent, allowance + 1,
+ context, level)
+ write('}')
+
+ _dispatch[dict.__repr__] = _pprint_dict
+
+ def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level):
+ if not len(object):
+ stream.write(repr(object))
+ return
+ cls = object.__class__
+ stream.write(cls.__name__ + '(')
+ self._format(list(object.items()), stream,
+ indent + len(cls.__name__) + 1, allowance + 1,
+ context, level)
+ stream.write(')')
+
+ _dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict
+
+ def _pprint_list(self, object, stream, indent, allowance, context, level):
+ stream.write('[')
+ self._format_items(object, stream, indent, allowance + 1,
+ context, level)
+ stream.write(']')
+
+ _dispatch[list.__repr__] = _pprint_list
+
+ def _pprint_tuple(self, object, stream, indent, allowance, context, level):
+ stream.write('(')
+ endchar = ',)' if len(object) == 1 else ')'
+ self._format_items(object, stream, indent, allowance + len(endchar),
+ context, level)
+ stream.write(endchar)
+
+ _dispatch[tuple.__repr__] = _pprint_tuple
+
+ def _pprint_set(self, object, stream, indent, allowance, context, level):
+ if not len(object):
+ stream.write(repr(object))
+ return
+ typ = object.__class__
+ if typ is set:
+ stream.write('{')
+ endchar = '}'
+ else:
+ stream.write(typ.__name__ + '({')
+ endchar = '})'
+ indent += len(typ.__name__) + 1
+ object = sorted(object, key=_safe_key)
+ self._format_items(object, stream, indent, allowance + len(endchar),
+ context, level)
+ stream.write(endchar)
+
+ _dispatch[set.__repr__] = _pprint_set
+ _dispatch[frozenset.__repr__] = _pprint_set
+
+ def _pprint_str(self, object, stream, indent, allowance, context, level):
+ write = stream.write
+ if not len(object):
+ write(repr(object))
+ return
+ chunks = []
+ lines = object.splitlines(True)
+ if level == 1:
+ indent += 1
+ allowance += 1
+ max_width1 = max_width = self._width - indent
+ for i, line in enumerate(lines):
+ rep = repr(line)
+ if i == len(lines) - 1:
+ max_width1 -= allowance
+ if len(rep) <= max_width1:
+ chunks.append(rep)
+ else:
+ # A list of alternating (non-space, space) strings
+ parts = re.findall(r'\S*\s*', line)
+ assert parts
+ assert not parts[-1]
+ parts.pop() # drop empty last part
+ max_width2 = max_width
+ current = ''
+ for j, part in enumerate(parts):
+ candidate = current + part
+ if j == len(parts) - 1 and i == len(lines) - 1:
+ max_width2 -= allowance
+ if len(repr(candidate)) > max_width2:
+ if current:
+ chunks.append(repr(current))
+ current = part
+ else:
+ current = candidate
+ if current:
+ chunks.append(repr(current))
+ if len(chunks) == 1:
+ write(rep)
+ return
+ if level == 1:
+ write('(')
+ for i, rep in enumerate(chunks):
+ if i > 0:
+ write('\n' + ' '*indent)
+ write(rep)
+ if level == 1:
+ write(')')
+
+ _dispatch[str.__repr__] = _pprint_str
+
+ def _pprint_bytes(self, object, stream, indent, allowance, context, level):
+ write = stream.write
+ if len(object) <= 4:
+ write(repr(object))
+ return
+ parens = level == 1
+ if parens:
+ indent += 1
+ allowance += 1
+ write('(')
+ delim = ''
+ for rep in _wrap_bytes_repr(object, self._width - indent, allowance):
+ write(delim)
+ write(rep)
+ if not delim:
+ delim = '\n' + ' '*indent
+ if parens:
+ write(')')
+
+ _dispatch[bytes.__repr__] = _pprint_bytes
+
+ def _pprint_bytearray(self, object, stream, indent, allowance, context, level):
+ write = stream.write
+ write('bytearray(')
+ self._pprint_bytes(bytes(object), stream, indent + 10,
+ allowance + 1, context, level + 1)
+ write(')')
+
+ _dispatch[bytearray.__repr__] = _pprint_bytearray
+
+ def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level):
+ stream.write('mappingproxy(')
+ self._format(object.copy(), stream, indent + 13, allowance + 1,
+ context, level)
+ stream.write(')')
+
+ _dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy
+
+ def _pprint_simplenamespace(self, object, stream, indent, allowance, context, level):
+ if type(object) is _types.SimpleNamespace:
+ # The SimpleNamespace repr is "namespace" instead of the class
+ # name, so we do the same here. For subclasses; use the class name.
+ cls_name = 'namespace'
+ else:
+ cls_name = object.__class__.__name__
+ indent += len(cls_name) + 1
+ delimnl = ',\n' + ' ' * indent
+ items = object.__dict__.items()
+ last_index = len(items) - 1
+
+ stream.write(cls_name + '(')
+ for i, (key, ent) in enumerate(items):
+ stream.write(key)
+ stream.write('=')
+
+ last = i == last_index
+ self._format(ent, stream, indent + len(key) + 1,
+ allowance if last else 1,
+ context, level)
+ if not last:
+ stream.write(delimnl)
+ stream.write(')')
+
+ _dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace
+
+ def _format_dict_items(self, items, stream, indent, allowance, context,
+ level):
+ write = stream.write
+ indent += self._indent_per_level
+ delimnl = ',\n' + ' ' * indent
+ last_index = len(items) - 1
+ for i, (key, ent) in enumerate(items):
+ last = i == last_index
+ rep = self._repr(key, context, level)
+ write(rep)
+ write(': ')
+ self._format(ent, stream, indent + len(rep) + 2,
+ allowance if last else 1,
+ context, level)
+ if not last:
+ write(delimnl)
+
+ def _format_items(self, items, stream, indent, allowance, context, level):
+ write = stream.write
+ indent += self._indent_per_level
+ if self._indent_per_level > 1:
+ write((self._indent_per_level - 1) * ' ')
+ delimnl = ',\n' + ' ' * indent
+ delim = ''
+ width = max_width = self._width - indent + 1
+ it = iter(items)
+ try:
+ next_ent = next(it)
+ except StopIteration:
+ return
+ last = False
+ while not last:
+ ent = next_ent
+ try:
+ next_ent = next(it)
+ except StopIteration:
+ last = True
+ max_width -= allowance
+ width -= allowance
+ if self._compact:
+ rep = self._repr(ent, context, level)
+ w = len(rep) + 2
+ if width < w:
+ width = max_width
+ if delim:
+ delim = delimnl
+ if width >= w:
+ width -= w
+ write(delim)
+ delim = ', '
+ write(rep)
+ continue
+ write(delim)
+ delim = delimnl
+ self._format(ent, stream, indent,
+ allowance if last else 1,
+ context, level)
+
+ def _repr(self, object, context, level):
+ repr, readable, recursive = self.format(object, context.copy(),
+ self._depth, level)
+ if not readable:
+ self._readable = False
+ if recursive:
+ self._recursive = True
+ return repr
+
+ def format(self, object, context, maxlevels, level):
+ """Format object for a specific context, returning a string
+ and flags indicating whether the representation is 'readable'
+ and whether the object represents a recursive construct.
+ """
+ return _safe_repr(object, context, maxlevels, level, self._sort_dicts)
+
+ def _pprint_default_dict(self, object, stream, indent, allowance, context, level):
+ if not len(object):
+ stream.write(repr(object))
+ return
+ rdf = self._repr(object.default_factory, context, level)
+ cls = object.__class__
+ indent += len(cls.__name__) + 1
+ stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent))
+ self._pprint_dict(object, stream, indent, allowance + 1, context, level)
+ stream.write(')')
+
+ _dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict
+
+ def _pprint_counter(self, object, stream, indent, allowance, context, level):
+ if not len(object):
+ stream.write(repr(object))
+ return
+ cls = object.__class__
+ stream.write(cls.__name__ + '({')
+ if self._indent_per_level > 1:
+ stream.write((self._indent_per_level - 1) * ' ')
+ items = object.most_common()
+ self._format_dict_items(items, stream,
+ indent + len(cls.__name__) + 1, allowance + 2,
+ context, level)
+ stream.write('})')
+
+ _dispatch[_collections.Counter.__repr__] = _pprint_counter
+
+ def _pprint_chain_map(self, object, stream, indent, allowance, context, level):
+ if not len(object.maps):
+ stream.write(repr(object))
+ return
+ cls = object.__class__
+ stream.write(cls.__name__ + '(')
+ indent += len(cls.__name__) + 1
+ for i, m in enumerate(object.maps):
+ if i == len(object.maps) - 1:
+ self._format(m, stream, indent, allowance + 1, context, level)
+ stream.write(')')
+ else:
+ self._format(m, stream, indent, 1, context, level)
+ stream.write(',\n' + ' ' * indent)
+
+ _dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map
+
+ def _pprint_deque(self, object, stream, indent, allowance, context, level):
+ if not len(object):
+ stream.write(repr(object))
+ return
+ cls = object.__class__
+ stream.write(cls.__name__ + '(')
+ indent += len(cls.__name__) + 1
+ stream.write('[')
+ if object.maxlen is None:
+ self._format_items(object, stream, indent, allowance + 2,
+ context, level)
+ stream.write('])')
+ else:
+ self._format_items(object, stream, indent, 2,
+ context, level)
+ rml = self._repr(object.maxlen, context, level)
+ stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml))
+
+ _dispatch[_collections.deque.__repr__] = _pprint_deque
+
+ def _pprint_user_dict(self, object, stream, indent, allowance, context, level):
+ self._format(object.data, stream, indent, allowance, context, level - 1)
+
+ _dispatch[_collections.UserDict.__repr__] = _pprint_user_dict
+
+ def _pprint_user_list(self, object, stream, indent, allowance, context, level):
+ self._format(object.data, stream, indent, allowance, context, level - 1)
+
+ _dispatch[_collections.UserList.__repr__] = _pprint_user_list
+
+ def _pprint_user_string(self, object, stream, indent, allowance, context, level):
+ self._format(object.data, stream, indent, allowance, context, level - 1)
+
+ _dispatch[_collections.UserString.__repr__] = _pprint_user_string
+
+# Return triple (repr_string, isreadable, isrecursive).
+
+def _safe_repr(object, context, maxlevels, level, sort_dicts):
+ typ = type(object)
+ if typ in _builtin_scalars:
+ return repr(object), True, False
+
+ r = getattr(typ, "__repr__", None)
+ if issubclass(typ, dict) and r is dict.__repr__:
+ if not object:
+ return "{}", True, False
+ objid = id(object)
+ if maxlevels and level >= maxlevels:
+ return "{...}", False, objid in context
+ if objid in context:
+ return _recursion(object), False, True
+ context[objid] = 1
+ readable = True
+ recursive = False
+ components = []
+ append = components.append
+ level += 1
+ if sort_dicts:
+ items = sorted(object.items(), key=_safe_tuple)
+ else:
+ items = object.items()
+ for k, v in items:
+ krepr, kreadable, krecur = _safe_repr(k, context, maxlevels, level, sort_dicts)
+ vrepr, vreadable, vrecur = _safe_repr(v, context, maxlevels, level, sort_dicts)
+ append("%s: %s" % (krepr, vrepr))
+ readable = readable and kreadable and vreadable
+ if krecur or vrecur:
+ recursive = True
+ del context[objid]
+ return "{%s}" % ", ".join(components), readable, recursive
+
+ if (issubclass(typ, list) and r is list.__repr__) or \
+ (issubclass(typ, tuple) and r is tuple.__repr__):
+ if issubclass(typ, list):
+ if not object:
+ return "[]", True, False
+ format = "[%s]"
+ elif len(object) == 1:
+ format = "(%s,)"
+ else:
+ if not object:
+ return "()", True, False
+ format = "(%s)"
+ objid = id(object)
+ if maxlevels and level >= maxlevels:
+ return format % "...", False, objid in context
+ if objid in context:
+ return _recursion(object), False, True
+ context[objid] = 1
+ readable = True
+ recursive = False
+ components = []
+ append = components.append
+ level += 1
+ for o in object:
+ orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level, sort_dicts)
+ append(orepr)
+ if not oreadable:
+ readable = False
+ if orecur:
+ recursive = True
+ del context[objid]
+ return format % ", ".join(components), readable, recursive
+
+ rep = repr(object)
+ return rep, (rep and not rep.startswith('<')), False
+
+_builtin_scalars = frozenset({str, bytes, bytearray, int, float, complex,
+ bool, type(None)})
+
+def _recursion(object):
+ return ("<Recursion on %s with id=%s>"
+ % (type(object).__name__, id(object)))
+
+
+def _perfcheck(object=None):
+ import time
+ if object is None:
+ object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
+ p = PrettyPrinter()
+ t1 = time.perf_counter()
+ _safe_repr(object, {}, None, 0, True)
+ t2 = time.perf_counter()
+ p.pformat(object)
+ t3 = time.perf_counter()
+ print("_safe_repr:", t2 - t1)
+ print("pformat:", t3 - t2)
+
+def _wrap_bytes_repr(object, width, allowance):
+ current = b''
+ last = len(object) // 4 * 4
+ for i in range(0, len(object), 4):
+ part = object[i: i+4]
+ candidate = current + part
+ if i == last:
+ width -= allowance
+ if len(repr(candidate)) > width:
+ if current:
+ yield repr(current)
+ current = part
+ else:
+ current = candidate
+ if current:
+ yield repr(current)
+
+if __name__ == "__main__":
+ _perfcheck()