Skip to content

Add indentation feature to reprlib.Repr #92734

Closed
@finefoot

Description

@finefoot

With reprlib.Repr, it's possible to print object representations with a limit of recursive depth to increase readability of large objects. "This is used in the Python debugger and may be useful in other contexts as well."[1] For example, I'm using reprlib to log lines for debugging. In the same line of thought, it makes sense to be able to format the output to increase readability even further. One measure to do so is to insert line breaks with indentation.

Example

>>> example = [1, [2, "foo", b"bar", {"a": 1, "b": "abc def ghi", "c": {1: 2, 3: 4, 5: [], 6: {}}}], 3]

At first glance, pprint.PrettyPrinter might be an alternative solution:

>>> import pprint
>>> pprint.pprint(example, indent=4)
[   1,
    [   2,
        'foo',
        b'bar',
        {'a': 1, 'b': 'abc def ghi', 'c': {1: 2, 3: 4, 5: [], 6: {}}}],
    3]
>>> pprint.pprint(example, indent=4, depth=3)
[1, [2, 'foo', b'bar', {'a': 1, 'b': 'abc def ghi', 'c': {...}}], 3]

However, in the first example above, the inner dict has not been expanded by line breaks and indentation. In the second example, after reducing depth, everything is suddenly printed onto one line only. This is the case, because the motivation and goal of pprint is to optimize output for a given width to pretty print - not to produce consistent output for debugging purposes. This becomes even more apparent when reducing width:

>>> pprint.pprint(example, indent=4, depth=3, width=10)
[   1,
    [   2,
        'foo',
        b'bar',
        {   'a': 1,
            'b': 'abc '
                 'def '
                 'ghi',
            'c': {   1: 2,
                     3: 4,
                     5: [   ],
                     6: {   }}}],
    3]

Note how strings that are too long for width, like "abc def ghi" in example, get split into multiple lines. This is not optimal for logging output where the width of the output (i.e. the actual line length) is usually not restricted.

Using json.dumps produces a similar output as the requested indentation feature for reprlib:

>>> import json
>>> print(json.dumps({"a": 1, "b": [2, 3]}, indent=4))
{
    "a": 1,
    "b": [
        2,
        3
    ]
}

However, it is subject to the known restrictions when converting Python objects to JSON:

>>> json.dumps(example)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.9/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python3.9/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.9/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python3.9/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type bytes is not JSON serializable

Therefore, it would be useful to add the following indentation feature to reprlib:

>>> import reprlib
>>> print(reprlib.repr(example))  # regular output
[1, [2, 'foo', b'bar', {'a': 1, 'b': 'abc def ghi', 'c': {1: 2, 3: 4, 5: [], 6: {}}}], 3]
>>> reprlib.aRepr.indent = 4
>>> print(reprlib.repr(example))  # output with 4 spaces indentation
[
    1,
    [
        2,
        'foo',
        b'bar',
        {
            'a': 1,
            'b': 'abc def ghi',
            'c': {
                1: 2,
                3: 4,
                5: [],
                6: {},
            },
        },
    ],
    3,
]
>>> reprlib.aRepr.maxlevel = 3
>>> print(reprlib.repr(example))  # same as above, but with reduced depth
[
    1,
    [
        2,
        'foo',
        b'bar',
        {
            'a': 1,
            'b': 'abc def ghi',
            'c': {...},
        },
    ],
    3,
]
>>> reprlib.aRepr.indent = "........"
>>> print(reprlib.repr(example))  # custom indentation string
[
........1,
........[
................2,
................'foo',
................b'bar',
................{
........................'a': 1,
........................'b': 'abc def ghi',
........................'c': {...},
................},
........],
........3,
]

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibPython modules in the Lib dirtype-featureA feature request or enhancement

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions