253
253
global needs_read_lock, needs_write_lock
254
254
needs_read_lock = _pretty_needs_read_lock
255
255
needs_write_lock = _pretty_needs_write_lock
258
# This implementation of cachedproperty is copied from Launchpad's
259
# canonical.launchpad.cachedproperty module (with permission from flacoste)
260
# -- spiv & vila 100120
261
def cachedproperty(attrname_or_fn):
262
"""A decorator for methods that makes them properties with their return
265
The value is cached on the instance, using the attribute name provided.
267
If you don't provide a name, the mangled name of the property is used.
269
>>> class CachedPropertyTest(object):
271
... @cachedproperty('_foo_cache')
273
... print 'foo computed'
278
... print 'bar computed'
281
>>> cpt = CachedPropertyTest()
282
>>> getattr(cpt, '_foo_cache', None) is None
294
>>> cpt._bar_cached_value
298
if isinstance(attrname_or_fn, basestring):
299
attrname = attrname_or_fn
300
return _CachedPropertyForAttr(attrname)
303
attrname = '_%s_cached_value' % fn.__name__
304
return _CachedProperty(attrname, fn)
307
class _CachedPropertyForAttr(object):
309
def __init__(self, attrname):
310
self.attrname = attrname
312
def __call__(self, fn):
313
return _CachedProperty(self.attrname, fn)
316
class _CachedProperty(object):
318
def __init__(self, attrname, fn):
320
self.attrname = attrname
321
self.marker = object()
323
def __get__(self, inst, cls=None):
326
cachedresult = getattr(inst, self.attrname, self.marker)
327
if cachedresult is self.marker:
328
result = self.fn(inst)
329
setattr(inst, self.attrname, result)