summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmer Katz <omer.drow@gmail.com>2021-03-15 17:02:44 +0200
committerOmer Katz <omer.drow@gmail.com>2021-03-15 17:29:29 +0200
commit923369f412fecd8b40ac5fe56453562e4418238c (patch)
tree001ec9d70274ceeefa33791a1b2d970556ec304a
parentae9ce769c3a51d19f101f83b6fbcb8087388bc43 (diff)
downloadkombu-923369f412fecd8b40ac5fe56453562e4418238c.tar.gz
Use a thread-safe implementation of cached_property.
-rw-r--r--kombu/utils/objects.py66
-rw-r--r--requirements/default.txt1
-rw-r--r--t/unit/utils/test_objects.py51
3 files changed, 6 insertions, 112 deletions
diff --git a/kombu/utils/objects.py b/kombu/utils/objects.py
index 4f220439..04f2e1be 100644
--- a/kombu/utils/objects.py
+++ b/kombu/utils/objects.py
@@ -1,64 +1,8 @@
"""Object Utilities."""
-class cached_property:
- """Cached property descriptor.
-
- Caches the return value of the get method on first call.
-
- Examples:
- .. code-block:: python
-
- @cached_property
- def connection(self):
- return Connection()
-
- @connection.setter # Prepares stored value
- def connection(self, value):
- if value is None:
- raise TypeError('Connection must be a connection')
- return value
-
- @connection.deleter
- def connection(self, value):
- # Additional action to do at del(self.attr)
- if value is not None:
- print('Connection {0!r} deleted'.format(value)
- """
-
- def __init__(self, fget=None, fset=None, fdel=None, doc=None):
- self.__get = fget
- self.__set = fset
- self.__del = fdel
- self.__doc__ = doc or fget.__doc__
- self.__name__ = fget.__name__
- self.__module__ = fget.__module__
-
- def __get__(self, obj, type=None):
- if obj is None:
- return self
- try:
- return obj.__dict__[self.__name__]
- except KeyError:
- value = obj.__dict__[self.__name__] = self.__get(obj)
- return value
-
- def __set__(self, obj, value):
- if obj is None:
- return self
- if self.__set is not None:
- value = self.__set(obj, value)
- obj.__dict__[self.__name__] = value
-
- def __delete__(self, obj, _sentinel=object()):
- if obj is None:
- return self
- value = obj.__dict__.pop(self.__name__, _sentinel)
- if self.__del is not None and value is not _sentinel:
- self.__del(obj, value)
-
- def setter(self, fset):
- return self.__class__(self.__get, fset, self.__del)
-
- def deleter(self, fdel):
- return self.__class__(self.__get, self.__set, fdel)
+try:
+ from functools import cached_property
+except ImportError:
+ # TODO: Remove this fallback once we drop support for Python < 3.8
+ from cached_property import threaded_cached_property as cached_property
diff --git a/requirements/default.txt b/requirements/default.txt
index 79b0868d..fd2e8a61 100644
--- a/requirements/default.txt
+++ b/requirements/default.txt
@@ -1,3 +1,4 @@
importlib-metadata>=0.18; python_version<"3.8"
+cached_property; python_version<"3.8"
amqp>=5.0.5,<6.0.0
vine
diff --git a/t/unit/utils/test_objects.py b/t/unit/utils/test_objects.py
deleted file mode 100644
index a1ad2000..00000000
--- a/t/unit/utils/test_objects.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from kombu.utils.objects import cached_property
-
-
-class test_cached_property:
-
- def test_deleting(self):
-
- class X:
- xx = False
-
- @cached_property
- def foo(self):
- return 42
-
- @foo.deleter # noqa
- def foo(self, value):
- self.xx = value
-
- x = X()
- del(x.foo)
- assert not x.xx
- x.__dict__['foo'] = 'here'
- del(x.foo)
- assert x.xx == 'here'
-
- def test_when_access_from_class(self):
-
- class X:
- xx = None
-
- @cached_property
- def foo(self):
- return 42
-
- @foo.setter # noqa
- def foo(self, value):
- self.xx = 10
-
- desc = X.__dict__['foo']
- assert X.foo is desc
-
- assert desc.__get__(None) is desc
- assert desc.__set__(None, 1) is desc
- assert desc.__delete__(None) is desc
- assert desc.setter(1)
-
- x = X()
- x.foo = 30
- assert x.xx == 10
-
- del(x.foo)