Skip to content

Commit b88abd6

Browse files
committed
Fixed django#19872
Made cached_property to behave as property when accessed via class.
1 parent 83ecb7b commit b88abd6

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

django/utils/functional.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ class cached_property(object):
3939
def __init__(self, func):
4040
self.func = func
4141

42-
def __get__(self, instance, type):
42+
def __get__(self, instance, type=None):
43+
if instance is None:
44+
return self
4345
res = instance.__dict__[self.func.__name__] = self.func(instance)
4446
return res
4547

tests/regressiontests/utils/functional.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from django.utils import unittest
2-
from django.utils.functional import lazy, lazy_property
2+
from django.utils.functional import lazy, lazy_property, cached_property
33

44

55
class FunctionalTestCase(unittest.TestCase):
@@ -37,3 +37,30 @@ def _get_do(self):
3737

3838
self.assertRaises(NotImplementedError, lambda: A().do)
3939
self.assertEqual(B().do, 'DO IT')
40+
41+
def test_cached_property(self):
42+
"""
43+
Test that cached_property caches its value,
44+
and that it behaves like a property
45+
"""
46+
47+
class A(object):
48+
49+
@cached_property
50+
def value(self):
51+
return 1, object()
52+
53+
a = A()
54+
55+
# check that it is cached
56+
self.assertEqual(a.value, a.value)
57+
58+
# check that it returns the right thing
59+
self.assertEqual(a.value[0], 1)
60+
61+
# check that state isn't shared between instances
62+
a2 = A()
63+
self.assertNotEqual(a.value, a2.value)
64+
65+
# check that it behaves like a property when there's no instance
66+
self.assertIsInstance(A.value, cached_property)

0 commit comments

Comments
 (0)