summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-07-05 23:31:54 (GMT)
committerGitHub <noreply@github.com>2023-07-05 23:31:54 (GMT)
commit7b615a1573b8a119e8ad27915912da745756a547 (patch)
treef854d9b388f6fd0dcd1aabbd6e08bf1ec38f2c9a /Lib
parentbb17e6f5de2bca85746a06d504029f90e85e3892 (diff)
downloadcpython-7b615a1573b8a119e8ad27915912da745756a547.zip
cpython-7b615a1573b8a119e8ad27915912da745756a547.tar.gz
cpython-7b615a1573b8a119e8ad27915912da745756a547.tar.bz2
[3.12] gh-106292: restore checking __dict__ in cached_property.__get__ (GH-106380) (#106469)
gh-106292: restore checking __dict__ in cached_property.__get__ (GH-106380) * gh-106292: restore checking __dict__ in cached_property.__get__ (cherry picked from commit 838406b4fc044c0b2f397c23275c69f16a76205b) Co-authored-by: Carl Meyer <carl@oddbird.net> Co-authored-by: Dong-hee Na <donghee.na92@gmail.com>
Diffstat (limited to 'Lib')
-rw-r--r--Lib/functools.py23
-rw-r--r--Lib/test/test_functools.py19
2 files changed, 32 insertions, 10 deletions
diff --git a/Lib/functools.py b/Lib/functools.py
index 72b2103..2ae4290 100644
--- a/Lib/functools.py
+++ b/Lib/functools.py
@@ -956,9 +956,10 @@ class singledispatchmethod:
################################################################################
-### cached_property() - computed once per instance, cached as attribute
+### cached_property() - property result cached as instance attribute
################################################################################
+_NOT_FOUND = object()
class cached_property:
def __init__(self, func):
@@ -989,15 +990,17 @@ class cached_property:
f"instance to cache {self.attrname!r} property."
)
raise TypeError(msg) from None
- val = self.func(instance)
- try:
- cache[self.attrname] = val
- except TypeError:
- msg = (
- f"The '__dict__' attribute on {type(instance).__name__!r} instance "
- f"does not support item assignment for caching {self.attrname!r} property."
- )
- raise TypeError(msg) from None
+ val = cache.get(self.attrname, _NOT_FOUND)
+ if val is _NOT_FOUND:
+ val = self.func(instance)
+ try:
+ cache[self.attrname] = val
+ except TypeError:
+ msg = (
+ f"The '__dict__' attribute on {type(instance).__name__!r} instance "
+ f"does not support item assignment for caching {self.attrname!r} property."
+ )
+ raise TypeError(msg) from None
return val
__class_getitem__ = classmethod(GenericAlias)
diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py
index d668fa4..c4eca0f 100644
--- a/Lib/test/test_functools.py
+++ b/Lib/test/test_functools.py
@@ -3037,6 +3037,25 @@ class TestCachedProperty(unittest.TestCase):
def test_doc(self):
self.assertEqual(CachedCostItem.cost.__doc__, "The cost of the item.")
+ def test_subclass_with___set__(self):
+ """Caching still works for a subclass defining __set__."""
+ class readonly_cached_property(py_functools.cached_property):
+ def __set__(self, obj, value):
+ raise AttributeError("read only property")
+
+ class Test:
+ def __init__(self, prop):
+ self._prop = prop
+
+ @readonly_cached_property
+ def prop(self):
+ return self._prop
+
+ t = Test(1)
+ self.assertEqual(t.prop, 1)
+ t._prop = 999
+ self.assertEqual(t.prop, 1)
+
if __name__ == '__main__':
unittest.main()