Respect Custom Repr

This commit is contained in:
Venkata Ramana Menda 2025-12-11 21:37:56 +05:30
parent f82a399d58
commit 89d7604f2f
2 changed files with 40 additions and 1 deletions

View file

@ -67,6 +67,24 @@ def _get_attr_fields(obj: Any) -> Sequence["_attr_module.Attribute[Any]"]:
return _attr_module.fields(type(obj)) if _has_attrs else []
def _is_attr_repr(obj: object) -> bool:
"""Check if an instance of an attrs class contains the default repr.
Args:
obj (object): An attrs instance.
Returns:
bool: True if the default repr is used, False if there is a custom repr.
"""
if not _has_attrs:
return False
try:
# attrs-generated repr methods have a source file containing "<attrs generated repr"
return isinstance(type(obj).__repr__.__code__.co_filename, str) and "<attrs generated repr" in type(obj).__repr__.__code__.co_filename
except Exception:
return False
def _is_dataclass_repr(obj: object) -> bool:
"""Check if an instance of a dataclass contains the default repr.
@ -711,7 +729,7 @@ def traverse(
last=root,
)
pop_visited(obj_id)
elif _is_attr_object(obj) and not fake_attributes:
elif _is_attr_object(obj) and not fake_attributes and _is_attr_repr(obj):
push_visited(obj_id)
children = []
append = children.append

View file

@ -675,6 +675,27 @@ def test_attrs_broken_310() -> None:
assert result == expected
def test_attrs_custom_repr() -> None:
@attr.define
class Foo:
x: int = 1
def __repr__(self) -> str:
return "CustomFoo"
assert pretty_repr(Foo()) == "CustomFoo"
def test_attrs_default_repr() -> None:
@attr.define
class Bar:
x: int = 5
y: str = "test"
result = pretty_repr(Bar())
assert result == "Bar(x=5, y='test')"
def test_user_dict() -> None:
class D1(UserDict):
pass