/
dataclasses.py
90 lines (68 loc) · 2.32 KB
/
dataclasses.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
""":mod:`dataclasses` utilities.
Note
----
This is an internal API not covered by versioning policy.
"""
import dataclasses
import typing as t
from operator import attrgetter
if t.TYPE_CHECKING:
from _typeshed import DataclassInstance
class SkipDefaultFieldsReprMixin:
r"""Skip default fields in :func:`~dataclasses.dataclass` object representation.
See Also
--------
:func:`object representation <repr()>`
Notes
-----
Credit: Pietro Oldrati, 2022-05-08, Unilicense
https://stackoverflow.com/a/72161437/1396928
Examples
--------
>>> @dataclasses.dataclass()
... class Item:
... name: str
... unit_price: float = 1.00
... quantity_on_hand: int = 0
...
>>> @dataclasses.dataclass(repr=False)
... class ItemWithMixin(SkipDefaultFieldsReprMixin):
... name: str
... unit_price: float = 1.00
... quantity_on_hand: int = 0
...
>>> Item('Test')
Item(name='Test', unit_price=1.0, quantity_on_hand=0)
>>> ItemWithMixin('Test')
ItemWithMixin(name=Test)
>>> Item('Test', quantity_on_hand=2)
Item(name='Test', unit_price=1.0, quantity_on_hand=2)
>>> ItemWithMixin('Test', quantity_on_hand=2)
ItemWithMixin(name=Test, quantity_on_hand=2)
If you want to copy/paste the :meth:`~.__repr__()`
directly, you can omit the ``repr=False``:
>>> @dataclasses.dataclass
... class ItemWithMixin(SkipDefaultFieldsReprMixin):
... name: str
... unit_price: float = 1.00
... quantity_on_hand: int = 0
... __repr__ = SkipDefaultFieldsReprMixin.__repr__
...
>>> ItemWithMixin('Test')
ItemWithMixin(name=Test)
>>> ItemWithMixin('Test', unit_price=2.00)
ItemWithMixin(name=Test, unit_price=2.0)
>>> item = ItemWithMixin('Test')
>>> item.unit_price = 2.05
>>> item
ItemWithMixin(name=Test, unit_price=2.05)
"""
def __repr__(self: "DataclassInstance") -> str:
"""Omit default fields in object representation."""
nodef_f_vals = (
(f.name, attrgetter(f.name)(self))
for f in dataclasses.fields(self)
if attrgetter(f.name)(self) != f.default
)
nodef_f_repr = ", ".join(f"{name}={value}" for name, value in nodef_f_vals)
return f"{self.__class__.__name__}({nodef_f_repr})"