Skip to content

Commit 8a027e5

Browse files
committed
-
1 parent 94ad385 commit 8a027e5

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

python_toolbox/caching/cached_property.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def __get__(self, obj, our_type=None):
6161

6262
def __call__(self, method_function):
6363
'''
64-
Decorate method to use value of the `CachedProperty` as a context manager.
64+
Decorate method to use value of `CachedProperty` as a context manager.
6565
'''
6666
def inner(same_method_function, self_obj, *args, **kwargs):
6767
with getattr(self_obj, self.get_our_name(self_obj)):

python_toolbox/monkeypatching_tools.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
'''Tools for monkeypatching.'''
55

66
import types
7+
78
from python_toolbox import decorator_tools
9+
from python_toolbox import caching
810

911

1012
@decorator_tools.helpful_decorator_builder
@@ -27,14 +29,25 @@ def my_method(a):
2729
2830
You may use the `name` argument to specify a method name different from the
2931
function's name.
32+
33+
You can also use this to monkeypatch a `CachedProperty` into a class.
3034
'''
3135
def decorator(function):
3236
# Note that unlike most decorators, this decorator retuns the function
3337
# it was given without modifying it. It modifies the class only.
34-
name_ = name or function.__name__
35-
new_method = types.MethodType(function, None, class_)
36-
# todo: Last line was: `new_method = types.MethodType(function,
37-
# class_)`, is subtly wrong, make tests to prove
38-
setattr(class_, name_, new_method)
39-
return function
38+
if isinstance(function, types.FunctionType):
39+
name_ = name or function.__name__
40+
new_method = types.MethodType(function, None, class_)
41+
# todo: Last line was: `new_method = types.MethodType(function,
42+
# class_)`, is subtly wrong, make tests to prove
43+
setattr(class_, name_, new_method)
44+
return function
45+
else:
46+
assert isinstance(function, caching.CachedProperty)
47+
cached_property = function
48+
if not isinstance(cached_property.getter, types.FunctionType):
49+
raise NotImplemented
50+
name_ = cached_property.getter.__name__
51+
setattr(class_, name_, cached_property)
52+
return cached_property
4053
return decorator

test_python_toolbox/test_monkeypatching_tools.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55

66
from __future__ import with_statement
77

8+
import uuid
9+
810
from python_toolbox import cute_testing
911

1012
from python_toolbox import monkeypatching_tools
13+
from python_toolbox import caching
1114

1215

1316
def test():
@@ -35,6 +38,27 @@ def woof(a):
3538
del meow, woof
3639

3740

41+
def test_monkeypatch_cached_property():
42+
43+
class A(object):
44+
pass
45+
46+
@monkeypatching_tools.monkeypatch_method(A)
47+
@caching.CachedProperty
48+
def meow(a):
49+
return (type(a), uuid.uuid4().hex)
50+
51+
a0 = A()
52+
assert a0.meow == a0.meow == a0.meow == a0.meow
53+
54+
a1 = A()
55+
assert a1.meow == a1.meow == a1.meow == a1.meow
56+
57+
assert a0.meow != a1.meow
58+
assert a0.meow[0] == a1.meow[0] == A
59+
60+
61+
3862
def test_helpful_message_when_forgetting_parentheses():
3963
'''Test user gets a helpful exception when when forgetting parentheses.'''
4064

0 commit comments

Comments
 (0)