Allow subclasses to overwrite attributes (#229)
Simply filter out all attributes from super classes that are present in the current class. Fixes #221
This commit is contained in:
parent
37a421e559
commit
4faf5f9c26
|
@ -0,0 +1 @@
|
|||
Subclasses now can overwrite attribute definitions of their superclass.
|
|
@ -181,11 +181,6 @@ def _transform_attrs(cls, these):
|
|||
|
||||
If *these* is passed, use that and don't look for them on the class.
|
||||
"""
|
||||
super_cls = []
|
||||
for c in reversed(cls.__mro__[1:-1]):
|
||||
sub_attrs = getattr(c, "__attrs_attrs__", None)
|
||||
if sub_attrs is not None:
|
||||
super_cls.extend(a for a in sub_attrs if a not in super_cls)
|
||||
if these is None:
|
||||
ca_list = [(name, attr)
|
||||
for name, attr
|
||||
|
@ -201,6 +196,17 @@ def _transform_attrs(cls, these):
|
|||
for attr_name, ca
|
||||
in sorted(ca_list, key=lambda e: e[1].counter)
|
||||
]
|
||||
|
||||
super_cls = []
|
||||
non_super_names = set(a.name for a in non_super_attrs)
|
||||
for c in reversed(cls.__mro__[1:-1]):
|
||||
sub_attrs = getattr(c, "__attrs_attrs__", None)
|
||||
if sub_attrs is not None:
|
||||
super_cls.extend(
|
||||
a for a in sub_attrs
|
||||
if a not in super_cls and a.name not in non_super_names
|
||||
)
|
||||
|
||||
attr_names = [a.name for a in super_cls + non_super_attrs]
|
||||
|
||||
AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names)
|
||||
|
|
|
@ -271,3 +271,15 @@ class TestDarkMagic(object):
|
|||
return self.x + 1
|
||||
|
||||
assert C(1, 2) == C()
|
||||
|
||||
@pytest.mark.parametrize("slots", [True, False])
|
||||
@pytest.mark.parametrize("frozen", [True, False])
|
||||
def test_attrib_overwrite(self, slots, frozen):
|
||||
"""
|
||||
Subclasses can overwrite attributes of their superclass.
|
||||
"""
|
||||
@attr.s(slots=slots, frozen=frozen)
|
||||
class SubOverwrite(Super):
|
||||
x = attr.ib(default=attr.Factory(list))
|
||||
|
||||
assert SubOverwrite([]) == SubOverwrite()
|
||||
|
|
Loading…
Reference in New Issue