Skip to content

Commit 1704015

Browse files
committed
squash! Define __getattribute__() instead of __getattr__() on slotted classes with cached properties
In tests, we replace most custom `__getattr__()` definitions by equivalent `__getattribute__()` ones, except in regression tests where `__getattr__()` is explicitly involved. Also, in test_slots_with_multiple_cached_property_subclasses_works(), we replace the `if hasattr(super(), "__getattr__"):` by a `try:`/`except AttributeError:` as using `hasattr(..., "__getattribute__")` would be meaningless since `__getattribute__()` is always defined.
1 parent 79d39ac commit 1704015

File tree

1 file changed

+19
-18
lines changed

1 file changed

+19
-18
lines changed

tests/test_slots.py

+19-18
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ def f(self) -> int:
786786

787787

788788
@pytest.mark.skipif(not PY_3_8_PLUS, reason="cached_property is 3.8+")
789-
def test_slots_cached_property_with_empty_getattr_raises_attribute_error_of_requested():
789+
def test_slots_cached_property_with_empty_getattribute_raises_attribute_error_of_requested():
790790
"""
791791
Ensures error information is not lost.
792792
"""
@@ -809,8 +809,8 @@ def f(self):
809809
@pytest.mark.skipif(not PY_3_8_PLUS, reason="cached_property is 3.8+")
810810
def test_slots_cached_property_raising_attributeerror():
811811
"""
812-
Ensures AttributeError raised by a property is preserved by __getattr__()
813-
implementation.
812+
Ensures AttributeError raised by a property is preserved by
813+
__getattribute__() implementation.
814814
815815
Regression test for issue https://github.com/python-attrs/attrs/issues/1230
816816
"""
@@ -846,9 +846,9 @@ def q(self):
846846

847847

848848
@pytest.mark.skipif(not PY_3_8_PLUS, reason="cached_property is 3.8+")
849-
def test_slots_cached_property_with_getattr_calls_getattr_for_missing_attributes():
849+
def test_slots_cached_property_with_getattribute_calls_getattr_for_missing_attributes():
850850
"""
851-
Ensure __getattr__ implementation is maintained for non cached_properties.
851+
Ensure __getattribute__ implementation is maintained for non cached_properties.
852852
"""
853853

854854
@attr.s(slots=True)
@@ -859,7 +859,7 @@ class A:
859859
def f(self):
860860
return self.x
861861

862-
def __getattr__(self, item):
862+
def __getattribute__(self, item):
863863
return item
864864

865865
a = A(1)
@@ -868,16 +868,16 @@ def __getattr__(self, item):
868868

869869

870870
@pytest.mark.skipif(not PY_3_8_PLUS, reason="cached_property is 3.8+")
871-
def test_slots_getattr_in_superclass__is_called_for_missing_attributes_when_cached_property_present():
871+
def test_slots_getattribute_in_superclass__is_called_for_missing_attributes_when_cached_property_present():
872872
"""
873-
Ensure __getattr__ implementation is maintained in subclass.
873+
Ensure __getattribute__ implementation is maintained in subclass.
874874
"""
875875

876876
@attr.s(slots=True)
877877
class A:
878878
x = attr.ib()
879879

880-
def __getattr__(self, item):
880+
def __getattribute__(self, item):
881881
return item
882882

883883
@attr.s(slots=True)
@@ -949,9 +949,9 @@ def __getattr__(self, item: str) -> str:
949949

950950

951951
@pytest.mark.skipif(not PY_3_8_PLUS, reason="cached_property is 3.8+")
952-
def test_slots_getattr_in_subclass_gets_superclass_cached_property():
952+
def test_slots_getattribute_in_subclass_gets_superclass_cached_property():
953953
"""
954-
Ensure super() in __getattr__ is not broken through cached_property re-write.
954+
Ensure super() in __getattribute__ is not broken through cached_property re-write.
955955
"""
956956

957957
@attr.s(slots=True)
@@ -962,7 +962,7 @@ class A:
962962
def f(self):
963963
return self.x
964964

965-
def __getattr__(self, item):
965+
def __getattribute__(self, item):
966966
return item
967967

968968
@attr.s(slots=True)
@@ -971,8 +971,8 @@ class B(A):
971971
def g(self):
972972
return self.x
973973

974-
def __getattr__(self, item):
975-
return super().__getattr__(item)
974+
def __getattribute__(self, item):
975+
return super().__getattribute__(item)
976976

977977
b = B(1)
978978
assert b.f == 1
@@ -1023,10 +1023,11 @@ class B:
10231023
def g(self):
10241024
return self.x * 2
10251025

1026-
def __getattr__(self, item):
1027-
if hasattr(super(), "__getattr__"):
1028-
return super().__getattr__(item)
1029-
return item
1026+
def __getattribute__(self, item):
1027+
try:
1028+
return super().__getattribute__(item)
1029+
except AttributeError:
1030+
return item
10301031

10311032
@attr.s(slots=True)
10321033
class AB(A, B):

0 commit comments

Comments
 (0)