mirror of
https://github.com/python/cpython.git
synced 2025-09-20 15:40:32 +00:00
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).
This commit is contained in:
parent
a02683ac38
commit
3ba3d513b1
4 changed files with 48 additions and 12 deletions
|
@ -36,7 +36,7 @@ The :mod:`pprint` module defines one class:
|
||||||
.. index:: single: ...; placeholder
|
.. index:: single: ...; placeholder
|
||||||
|
|
||||||
.. class:: PrettyPrinter(indent=1, width=80, depth=None, stream=None, *, \
|
.. 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
|
Construct a :class:`PrettyPrinter` instance. This constructor understands
|
||||||
several keyword parameters. An output stream may be set using the *stream*
|
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
|
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
|
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
|
*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
|
.. versionchanged:: 3.4
|
||||||
Added the *compact* parameter.
|
Added the *compact* parameter.
|
||||||
|
@ -63,6 +66,8 @@ The :mod:`pprint` module defines one class:
|
||||||
.. versionchanged:: 3.8
|
.. versionchanged:: 3.8
|
||||||
Added the *sort_dicts* parameter.
|
Added the *sort_dicts* parameter.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.10
|
||||||
|
Added the *underscore_numbers* parameter.
|
||||||
|
|
||||||
>>> import pprint
|
>>> import pprint
|
||||||
>>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni']
|
>>> 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:
|
The :mod:`pprint` module also provides several shortcut functions:
|
||||||
|
|
||||||
.. function:: pformat(object, indent=1, width=80, depth=None, *, \
|
.. 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*,
|
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.
|
:class:`PrettyPrinter` constructor as formatting parameters.
|
||||||
|
|
||||||
.. versionchanged:: 3.4
|
.. versionchanged:: 3.4
|
||||||
|
@ -103,6 +108,9 @@ The :mod:`pprint` module also provides several shortcut functions:
|
||||||
.. versionchanged:: 3.8
|
.. versionchanged:: 3.8
|
||||||
Added the *sort_dicts* parameter.
|
Added the *sort_dicts* parameter.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.10
|
||||||
|
Added the *underscore_numbers* parameter.
|
||||||
|
|
||||||
|
|
||||||
.. function:: pp(object, *args, sort_dicts=False, **kwargs)
|
.. 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, *, \
|
.. 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
|
Prints the formatted representation of *object* on *stream*, followed by a
|
||||||
newline. If *stream* is ``None``, ``sys.stdout`` is used. This may be used
|
newline. If *stream* is ``None``, ``sys.stdout`` is used. This may be used
|
||||||
in the interactive interpreter instead of the :func:`print` function for
|
in the interactive interpreter instead of the :func:`print` function for
|
||||||
inspecting values (you can even reassign ``print = pprint.pprint`` for use
|
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.
|
be passed to the :class:`PrettyPrinter` constructor as formatting parameters.
|
||||||
|
|
||||||
.. versionchanged:: 3.4
|
.. versionchanged:: 3.4
|
||||||
|
@ -131,6 +139,9 @@ The :mod:`pprint` module also provides several shortcut functions:
|
||||||
.. versionchanged:: 3.8
|
.. versionchanged:: 3.8
|
||||||
Added the *sort_dicts* parameter.
|
Added the *sort_dicts* parameter.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.10
|
||||||
|
Added the *underscore_numbers* parameter.
|
||||||
|
|
||||||
>>> import pprint
|
>>> import pprint
|
||||||
>>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni']
|
>>> stuff = ['spam', 'eggs', 'lumberjack', 'knights', 'ni']
|
||||||
>>> stuff.insert(0, stuff)
|
>>> stuff.insert(0, stuff)
|
||||||
|
|
|
@ -45,18 +45,19 @@ __all__ = ["pprint","pformat","isreadable","isrecursive","saferepr",
|
||||||
|
|
||||||
|
|
||||||
def pprint(object, stream=None, indent=1, width=80, depth=None, *,
|
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]."""
|
"""Pretty-print a Python object to a stream [default is sys.stdout]."""
|
||||||
printer = PrettyPrinter(
|
printer = PrettyPrinter(
|
||||||
stream=stream, indent=indent, width=width, depth=depth,
|
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)
|
printer.pprint(object)
|
||||||
|
|
||||||
def pformat(object, indent=1, width=80, depth=None, *,
|
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."""
|
"""Format a Python object into a pretty-printed representation."""
|
||||||
return PrettyPrinter(indent=indent, width=width, depth=depth,
|
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):
|
def pp(object, *args, sort_dicts=False, **kwargs):
|
||||||
"""Pretty-print a Python object"""
|
"""Pretty-print a Python object"""
|
||||||
|
@ -102,7 +103,7 @@ def _safe_tuple(t):
|
||||||
|
|
||||||
class PrettyPrinter:
|
class PrettyPrinter:
|
||||||
def __init__(self, indent=1, width=80, depth=None, stream=None, *,
|
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
|
"""Handle pretty printing operations onto a stream using a set of
|
||||||
configured parameters.
|
configured parameters.
|
||||||
|
|
||||||
|
@ -143,6 +144,7 @@ class PrettyPrinter:
|
||||||
self._stream = _sys.stdout
|
self._stream = _sys.stdout
|
||||||
self._compact = bool(compact)
|
self._compact = bool(compact)
|
||||||
self._sort_dicts = sort_dicts
|
self._sort_dicts = sort_dicts
|
||||||
|
self._underscore_numbers = underscore_numbers
|
||||||
|
|
||||||
def pprint(self, object):
|
def pprint(self, object):
|
||||||
self._format(object, self._stream, 0, 0, {}, 0)
|
self._format(object, self._stream, 0, 0, {}, 0)
|
||||||
|
@ -525,6 +527,13 @@ class PrettyPrinter:
|
||||||
return repr(object), True, False
|
return repr(object), True, False
|
||||||
|
|
||||||
r = getattr(typ, "__repr__", None)
|
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 issubclass(typ, dict) and r is dict.__repr__:
|
||||||
if not object:
|
if not object:
|
||||||
return "{}", True, False
|
return "{}", True, False
|
||||||
|
@ -592,7 +601,7 @@ class PrettyPrinter:
|
||||||
rep = repr(object)
|
rep = repr(object)
|
||||||
return rep, (rep and not rep.startswith('<')), False
|
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)})
|
bool, type(None)})
|
||||||
|
|
||||||
def _recursion(object):
|
def _recursion(object):
|
||||||
|
|
|
@ -206,6 +206,7 @@ class QueryTestCase(unittest.TestCase):
|
||||||
self.assertEqual(pprint.pformat(simple), native)
|
self.assertEqual(pprint.pformat(simple), native)
|
||||||
self.assertEqual(pprint.pformat(simple, width=1, indent=0)
|
self.assertEqual(pprint.pformat(simple, width=1, indent=0)
|
||||||
.replace('\n', ' '), native)
|
.replace('\n', ' '), native)
|
||||||
|
self.assertEqual(pprint.pformat(simple, underscore_numbers=True), native)
|
||||||
self.assertEqual(pprint.saferepr(simple), native)
|
self.assertEqual(pprint.saferepr(simple), native)
|
||||||
|
|
||||||
def test_container_repr_override_called(self):
|
def test_container_repr_override_called(self):
|
||||||
|
@ -323,6 +324,18 @@ class QueryTestCase(unittest.TestCase):
|
||||||
'1 '
|
'1 '
|
||||||
'2']]]]]""")
|
'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):
|
def test_sorted_dict(self):
|
||||||
# Starting in Python 2.5, pprint sorts dict displays by key regardless
|
# Starting in Python 2.5, pprint sorts dict displays by key regardless
|
||||||
# of how small the dictionary may be.
|
# of how small the dictionary may be.
|
||||||
|
|
|
@ -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``).
|
Loading…
Add table
Add a link
Reference in a new issue