From 3ba3d513b1e3c63d09cb798b982a9e6c369cea4c Mon Sep 17 00:00:00 2001 From: sblondon Date: Wed, 24 Mar 2021 09:23:20 +0100 Subject: bpo-42914: add a pprint underscore_numbers option (GH-24864) pprint() gains a new boolean underscore_numbers kwarg to emit integers with thousands separated by an underscore character for improved readability (for example 1_000_000 instead of 1000000). --- Doc/library/pprint.rst | 23 ++++++++++++++++------ Lib/pprint.py | 21 ++++++++++++++------ Lib/test/test_pprint.py | 13 ++++++++++++ .../2021-03-14-21-47-28.bpo-42914.9U1o33.rst | 3 +++ 4 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-03-14-21-47-28.bpo-42914.9U1o33.rst diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index 16256c5..b3b6ed5 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -36,7 +36,7 @@ The :mod:`pprint` module defines one class: .. index:: single: ...; placeholder .. class:: PrettyPrinter(indent=1, width=80, depth=None, stream=None, *, \ - compact=False, sort_dicts=True) + compact=False, sort_dicts=True, underscore_numbers=False) Construct a :class:`PrettyPrinter` instance. This constructor understands several keyword parameters. An output stream may be set using the *stream* @@ -55,7 +55,10 @@ The :mod:`pprint` module defines one class: will be formatted on a separate line. If *compact* is true, as many items as will fit within the *width* will be formatted on each output line. If *sort_dicts* is true (the default), dictionaries will be formatted with their - keys sorted, otherwise they will display in insertion order. + keys sorted, otherwise they will display in insertion order. If + *underscore_numbers* is true, integers will be formatted with + ```_``` character for a thousands separator, otherwise underscores are not + displayed (the default). .. versionchanged:: 3.4 Added the *compact* parameter. @@ -63,6 +66,8 @@ The :mod:`pprint` module defines one class: .. versionchanged:: 3.8 Added the *sort_dicts* parameter. + .. versionchanged:: 3.10 + Added the *underscore_numbers* parameter. >>> import pprint >>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni'] @@ -91,10 +96,10 @@ The :mod:`pprint` module defines one class: The :mod:`pprint` module also provides several shortcut functions: .. function:: pformat(object, indent=1, width=80, depth=None, *, \ - compact=False, sort_dicts=True) + compact=False, sort_dicts=True, underscore_numbers=False) Return the formatted representation of *object* as a string. *indent*, - *width*, *depth*, *compact* and *sort_dicts* will be passed to the + *width*, *depth*, *compact*, *sort_dicts* and *underscore_numbers* will be passed to the :class:`PrettyPrinter` constructor as formatting parameters. .. versionchanged:: 3.4 @@ -103,6 +108,9 @@ The :mod:`pprint` module also provides several shortcut functions: .. versionchanged:: 3.8 Added the *sort_dicts* parameter. + .. versionchanged:: 3.10 + Added the *underscore_numbers* parameter. + .. function:: pp(object, *args, sort_dicts=False, **kwargs) @@ -116,13 +124,13 @@ The :mod:`pprint` module also provides several shortcut functions: .. function:: pprint(object, stream=None, indent=1, width=80, depth=None, *, \ - compact=False, sort_dicts=True) + compact=False, sort_dicts=True, underscore_numbers=False) Prints the formatted representation of *object* on *stream*, followed by a newline. If *stream* is ``None``, ``sys.stdout`` is used. This may be used in the interactive interpreter instead of the :func:`print` function for inspecting values (you can even reassign ``print = pprint.pprint`` for use - within a scope). *indent*, *width*, *depth*, *compact* and *sort_dicts* will + within a scope). *indent*, *width*, *depth*, *compact*, *sort_dicts* and *underscore_numbers* will be passed to the :class:`PrettyPrinter` constructor as formatting parameters. .. versionchanged:: 3.4 @@ -131,6 +139,9 @@ The :mod:`pprint` module also provides several shortcut functions: .. versionchanged:: 3.8 Added the *sort_dicts* parameter. + .. versionchanged:: 3.10 + Added the *underscore_numbers* parameter. + >>> import pprint >>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni'] >>> stuff.insert(0, stuff) diff --git a/Lib/pprint.py b/Lib/pprint.py index a8af50e..b45cfdd 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -45,18 +45,19 @@ __all__ = ["pprint","pformat","isreadable","isrecursive","saferepr", def pprint(object, stream=None, indent=1, width=80, depth=None, *, - compact=False, sort_dicts=True): + compact=False, sort_dicts=True, underscore_numbers=False): """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) + compact=compact, sort_dicts=sort_dicts, underscore_numbers=False) printer.pprint(object) def pformat(object, indent=1, width=80, depth=None, *, - compact=False, sort_dicts=True): + compact=False, sort_dicts=True, underscore_numbers=False): """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) + compact=compact, sort_dicts=sort_dicts, + underscore_numbers=underscore_numbers).pformat(object) def pp(object, *args, sort_dicts=False, **kwargs): """Pretty-print a Python object""" @@ -102,7 +103,7 @@ def _safe_tuple(t): class PrettyPrinter: def __init__(self, indent=1, width=80, depth=None, stream=None, *, - compact=False, sort_dicts=True): + compact=False, sort_dicts=True, underscore_numbers=False): """Handle pretty printing operations onto a stream using a set of configured parameters. @@ -143,6 +144,7 @@ class PrettyPrinter: self._stream = _sys.stdout self._compact = bool(compact) self._sort_dicts = sort_dicts + self._underscore_numbers = underscore_numbers def pprint(self, object): self._format(object, self._stream, 0, 0, {}, 0) @@ -525,6 +527,13 @@ class PrettyPrinter: return repr(object), True, False r = getattr(typ, "__repr__", None) + + if issubclass(typ, int) and r is int.__repr__: + if self._underscore_numbers: + return f"{object:_d}", True, False + else: + return repr(object), True, False + if issubclass(typ, dict) and r is dict.__repr__: if not object: return "{}", True, False @@ -592,7 +601,7 @@ class PrettyPrinter: rep = repr(object) return rep, (rep and not rep.startswith('<')), False -_builtin_scalars = frozenset({str, bytes, bytearray, int, float, complex, +_builtin_scalars = frozenset({str, bytes, bytearray, float, complex, bool, type(None)}) def _recursion(object): diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index c4a8578..e5d2ac5 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -206,6 +206,7 @@ class QueryTestCase(unittest.TestCase): self.assertEqual(pprint.pformat(simple), native) self.assertEqual(pprint.pformat(simple, width=1, indent=0) .replace('\n', ' '), native) + self.assertEqual(pprint.pformat(simple, underscore_numbers=True), native) self.assertEqual(pprint.saferepr(simple), native) def test_container_repr_override_called(self): @@ -323,6 +324,18 @@ class QueryTestCase(unittest.TestCase): '1 ' '2']]]]]""") + def test_integer(self): + self.assertEqual(pprint.pformat(1234567), '1234567') + self.assertEqual(pprint.pformat(1234567, underscore_numbers=True), '1_234_567') + + class Temperature(int): + def __new__(cls, celsius_degrees): + return super().__new__(Temperature, celsius_degrees) + def __repr__(self): + kelvin_degrees = self + 273.15 + return f"{kelvin_degrees}°K" + self.assertEqual(pprint.pformat(Temperature(1000)), '1273.15°K') + def test_sorted_dict(self): # Starting in Python 2.5, pprint sorts dict displays by key regardless # of how small the dictionary may be. diff --git a/Misc/NEWS.d/next/Library/2021-03-14-21-47-28.bpo-42914.9U1o33.rst b/Misc/NEWS.d/next/Library/2021-03-14-21-47-28.bpo-42914.9U1o33.rst new file mode 100644 index 0000000..ae6ef2f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-03-14-21-47-28.bpo-42914.9U1o33.rst @@ -0,0 +1,3 @@ +:func:`pprint.pprint` gains a new boolean ``underscore_numbers`` optional +argument to emit integers with thousands separated by an underscore character +for improved readability (for example ``1_000_000`` instead of ``1000000``). -- cgit v0.12