Complete the cachedproperty descriptor protocol

Refactor some parts of the cachedproperty property
descriptor (renaming attributes to the standard names
used in descriptor objects) and add on the __set__ and
__delete__ methods to comply with the full descriptor
protocol.

Change-Id: I1f1e8e301271c060d14acc3a77c094dabd120f16
This commit is contained in:
Joshua Harlow
2014-05-20 00:05:10 -07:00
parent 1ebebd453d
commit b9afecb86e

View File

@@ -180,30 +180,37 @@ class cachedproperty(object):
those methods into properties that will be cached in the instance (avoiding
repeated creation checking logic to do the equivalent).
"""
def __init__(self, wrapped):
def __init__(self, fget):
# If a name is provided (as an argument) then this will be the string
# to place the cached attribute under if not then it will be the
# function itself to be wrapped into a property.
if inspect.isfunction(wrapped):
self._wrapped = wrapped
self._wrapped_attr = "_%s" % (wrapped.__name__)
if inspect.isfunction(fget):
self._fget = fget
self._attr_name = "_%s" % (fget.__name__)
else:
self._wrapped_attr = wrapped
self._wrapped = None
self._attr_name = fget
self._fget = None
def __call__(self, fget):
# If __init__ received a string then this will be the function to be
# wrapped as a property (if __init__ got a function then this will not
# be called).
self._wrapped = fget
self._fget = fget
return self
def __get__(self, source, owner):
def __set__(self, instance, value):
raise AttributeError("can't set attribute")
def __delete__(self, instance):
raise AttributeError("can't delete attribute")
def __get__(self, instance, owner):
try:
return getattr(source, self._wrapped_attr)
return getattr(instance, self._attr_name)
except AttributeError:
setattr(source, self._wrapped_attr, self._wrapped(source))
return getattr(source, self._wrapped_attr)
value = self._fget(instance)
setattr(instance, self._attr_name, value)
return value
def wallclock():