Created
December 19, 2022 05:05
-
-
Save justquick/4e8286f6ec0c6736b6b6bdc83133f2be to your computer and use it in GitHub Desktop.
from python 3.8.6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class cached_property: | |
def __init__(self, func): | |
self.func = func | |
self.attrname = None | |
self.__doc__ = func.__doc__ | |
self.lock = RLock() | |
def __set_name__(self, owner, name): | |
if self.attrname is None: | |
self.attrname = name | |
elif name != self.attrname: | |
raise TypeError( | |
"Cannot assign the same cached_property to two different names " | |
f"({self.attrname!r} and {name!r})." | |
) | |
def __get__(self, instance, owner=None): | |
if instance is None: | |
return self | |
if self.attrname is None: | |
raise TypeError( | |
"Cannot use cached_property instance without calling __set_name__ on it.") | |
try: | |
cache = instance.__dict__ | |
except AttributeError: # not all objects have __dict__ (e.g. class defines slots) | |
msg = ( | |
f"No '__dict__' attribute on {type(instance).__name__!r} " | |
f"instance to cache {self.attrname!r} property." | |
) | |
raise TypeError(msg) from None | |
val = cache.get(self.attrname, _NOT_FOUND) | |
if val is _NOT_FOUND: | |
with self.lock: | |
# check if another thread filled cache while we awaited lock | |
val = cache.get(self.attrname, _NOT_FOUND) | |
if val is _NOT_FOUND: | |
val = self.func(instance) | |
try: | |
cache[self.attrname] = val | |
except TypeError: | |
msg = ( | |
f"The '__dict__' attribute on {type(instance).__name__!r} instance " | |
f"does not support item assignment for caching {self.attrname!r} property." | |
) | |
raise TypeError(msg) from None | |
return val |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment