documentating release and making small documentation tweaks
[cached-property.git] / cached_property.py
1 # -*- coding: utf-8 -*-
2
3 __author__ = 'Daniel Greenfeld'
4 __email__ = 'pydanny@gmail.com'
5 __version__ = '0.1.5'
6 __license__ = 'BSD'
7
8 import threading
9
10
11 class cached_property(object):
12 """ A property that is only computed once per instance and then replaces
13 itself with an ordinary attribute. Deleting the attribute resets the
14 property.
15
16 Source: https://github.com/bottlepy/bottle/commit/fa7733e075da0d790d809aa3d2f53071897e6f76
17 """
18
19 def __init__(self, func):
20 self.__doc__ = getattr(func, '__doc__')
21 self.func = func
22
23 def __get__(self, obj, cls):
24 if obj is None:
25 return self
26 value = obj.__dict__[self.func.__name__] = self.func(obj)
27 return value
28
29
30 class threaded_cached_property(cached_property):
31 """ A cached_property version for use in environments where multiple
32 threads might concurrently try to access the property.
33 """
34 def __init__(self, func):
35 super(threaded_cached_property, self).__init__(func)
36 self.lock = threading.RLock()
37
38 def __get__(self, obj, cls):
39 with self.lock:
40 # Double check if the value was computed before the lock was
41 # acquired.
42 prop_name = self.func.__name__
43 if prop_name in obj.__dict__:
44 return obj.__dict__[prop_name]
45
46 # If not, do the calculation and release the lock.
47 return super(threaded_cached_property, self).__get__(obj, cls)