Reputation: 19245
I'm attempting to set up a test for a caching tool in which the cache is based on the function object and its arguments. To do this test, I need to access the exact function being called in my property, and I can't figure out how to do this.
The caching code looks like this:
def cached(func):
"""
Decorator to cache function calls
"""
@wraps(func)
def wrapper(self, *args):
# The cache lives in the instance so that it gets garbage collected
if (func, args) not in self._cache:
self._cache[(func, args)] = func(self, *args)
return self._cache[(func, args)]
return wrapper
and I have a cached property:
class SpatialMixin(object):
@property
@cached
def longitude_extrema(self):
return 25
The class looks something like this:
class MainClass(SomeOtherBaseClass,SpatialMixin):
pass
MyObject = MainClass()
I can access base_class.SpatialMixin.longitude_extrema.fget
directly, but this is a different object than MyObject.longitude_extrema.fget
(which I'm using to indicate the getter of that property; you can't access it this way because MyObject.longitude_extrema
is just the number 25).
So, how can I access the function underlying the MyObject.longitude_extrema
property?
Upvotes: 0
Views: 264
Reputation: 282198
If you're trying to access the original longitude_extrema
function, you're not finding it through fget
because the original longitude_extrema
function isn't the getter. The wrapper
function created in the cached
decorator is the getter.
On Python 3.4+, a wrapper decorated with functools.wraps
has a __wrapped__
attribute pointing to the function it wraps. You can use that to access the original longitude_extrema
. (This attribute also exists on 3.2 and 3.3, but with slightly buggy behavior.)
On Python 2, functools.wraps
doesn't set __wrapped__
. While it's technically possible to get at the wrapped function anyway with direct closure manipulation, it's awkward, variable-name-dependent, and not a good option, especially since you control the decorator. You could just set __wrapped__
yourself in the cached
decorator.
Upvotes: 1