Skip to content

Subclassing PrettyPrinter.format doesn't work in all cases #132855

Open
@gsnedders

Description

@gsnedders

Bug report

Bug description:

See also the earlier fixed #73036. This appears to have only been a partial fix, or it has regressed.

import collections
import pprint
import types


SENTINAL = object()


class _hashable:
    def __hash__(self):
        return 1


HASHABLE_SENTINAL = _hashable()


class CustomPrettyPrinter(pprint.PrettyPrinter):
    def format(self, obj, context, maxlevels, level):
        if obj is SENTINAL:
            return "SENTINAL", True, False
        elif obj is HASHABLE_SENTINAL:
            return "HASHABLE_SENTINAL", True, False
        else:
            return super().format(obj, context, maxlevels, level)


if __name__ == "__main__":
    printer = CustomPrettyPrinter(sort_dicts=False)

    test_data = {
        "item": SENTINAL,
        "dict": {"a": SENTINAL},
        "dict_key": {HASHABLE_SENTINAL: 1},
        "OrderedDict": collections.OrderedDict({"a": SENTINAL}),
        "OrderedDict_key": collections.OrderedDict({HASHABLE_SENTINAL: 1}),
        "list": [SENTINAL],
        "tuple": (SENTINAL,),
        "set": {SENTINAL},
        "frozenset": frozenset({SENTINAL}),
        "mappingproxy": types.MappingProxyType({"a": SENTINAL}),
        "mappingproxy_key": types.MappingProxyType({HASHABLE_SENTINAL: 1}),
        "SimpleNamespace": types.SimpleNamespace(a=SENTINAL),
        "defaultdict": collections.defaultdict(list, {"a": SENTINAL}),
        "defaultdict_key": collections.defaultdict(list, {HASHABLE_SENTINAL: 1}),
        "Counter": collections.Counter({"a": SENTINAL}),
        "Counter_key": collections.Counter({HASHABLE_SENTINAL: 1}),
        "deque": collections.deque([SENTINAL]),
    }

    printer.pprint(test_data)

This outputs:

{'item': SENTINAL,
 'dict': {'a': SENTINAL},
 'dict_key': {HASHABLE_SENTINAL: 1},
 'OrderedDict': OrderedDict({'a': <object object at 0x1041f4660>}),
 'OrderedDict_key': OrderedDict([(HASHABLE_SENTINAL, 1)]),
 'list': [SENTINAL],
 'tuple': (SENTINAL,),
 'set': {<object object at 0x1041f4660>},
 'frozenset': frozenset({<object object at 0x1041f4660>}),
 'mappingproxy': mappingproxy({'a': <object object at 0x1041f4660>}),
 'mappingproxy_key': mappingproxy({HASHABLE_SENTINAL: 1}),
 'SimpleNamespace': namespace(a=<object object at 0x1041f4660>),
 'defaultdict': defaultdict(<class 'list'>,
                            {'a': SENTINAL}),
 'defaultdict_key': defaultdict(<class 'list'>,
                                {HASHABLE_SENTINAL: 1}),
 'Counter': Counter({'a': <object object at 0x1041f4660>}),
 'Counter_key': Counter({<__main__._hashable object at 0x1045e4d70>: 1}),
 'deque': deque([<object object at 0x1041f4660>])}

Every instance of < in that output is a bug.

CPython versions tested on:

3.13

Operating systems tested on:

macOS

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibPython modules in the Lib dirtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions