1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- # SPDX-License-Identifier: AGPL-3.0-or-later
- # lint: pylint
- # pyright: basic
- """Module for backward compatibility.
- """
- # pylint: disable=C,R
- __all__ = ('cached_property',)
- try:
- from functools import cached_property # type: ignore
- except ImportError:
- # cache_property has been added in py3.8 [1]
- #
- # To support cache_property in py3.7 the implementation from 3.8 has been
- # copied here. This code can be cleanup with EOL of py3.7.
- #
- # [1] https://docs.python.org/3/library/functools.html#functools.cached_property
- from threading import RLock
- _NOT_FOUND = object()
- 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
|