Skip to content

Commit

Permalink
Reset __attrs_own_setattr__ along with __setattr__
Browse files Browse the repository at this point in the history
Signed-off-by: Hynek Schlawack <hs@ox.cx>
  • Loading branch information
hynek committed Sep 3, 2020
1 parent 5644d21 commit f144cfa
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 3 deletions.
9 changes: 6 additions & 3 deletions src/attr/_make.py
Expand Up @@ -655,6 +655,7 @@ def _patch_original_class(self):
cls, "__attrs_own_setattr__", False
):
cls.__setattr__ = object.__setattr__
cls.__attrs_own_setattr__ = False

return cls

Expand All @@ -669,9 +670,10 @@ def _create_slots_class(self):
if k not in tuple(self._attr_names) + ("__dict__", "__weakref__")
}

# If our class doesn't have an own __setattr__ (either from the user or
# by us), check the bases, if one of them has an attrs-made
# __setattr__, that needs to be reset.
# If our class doesn't have its own implementation of __setattr__
# (either from the user or by us), check the bases, if one of them has
# an attrs-made __setattr__, that needs to be reset. We don't walk the
# MRO because we only care about our immediate base classes.
# XXX: This can be confused by subclassing a slotted attrs class with
# XXX: a non-attrs class and subclass the resulting class with an attrs
# XXX: class. See `test_slotted_confused for details. For now that's
Expand All @@ -682,6 +684,7 @@ def _create_slots_class(self):
for base_cls in getattr(self._cls, "__bases__", ()):
if base_cls.__dict__.get("__attrs_own_setattr__", False):
cd["__setattr__"] = object.__setattr__
cd["__attrs_own_setattr__"] = False
break

# Traverse the MRO to check for an existing __weakref__.
Expand Down
3 changes: 3 additions & 0 deletions tests/test_setattr.py
Expand Up @@ -227,6 +227,9 @@ class NoHook(WithOnSetAttrHook):
assert NoHook.__setattr__ == object.__setattr__

assert 1 == NoHook(1).x
assert Hooked.__attrs_own_setattr__
assert not NoHook.__attrs_own_setattr__
assert WithOnSetAttrHook.__attrs_own_setattr__

@pytest.mark.parametrize("slots", [True, False])
def test_setattr_inherited_do_not_reset(self, slots):
Expand Down

0 comments on commit f144cfa

Please sign in to comment.