diff options
author | David Lord <davidism@gmail.com> | 2022-02-07 07:33:31 -0800 |
---|---|---|
committer | David Lord <davidism@gmail.com> | 2022-02-07 07:41:58 -0800 |
commit | 87d5dd167d1fae08365749874bdc07cabb67e53d (patch) | |
tree | 434dd31b3e6afc87da8b45a9f7b7deffe0dbe2c3 /src/werkzeug/utils.py | |
parent | 27cc7651ece0e84c7ccca837832e31b28c8fef52 (diff) | |
download | werkzeug-87d5dd167d1fae08365749874bdc07cabb67e53d.tar.gz |
cached_property for __slots__
Diffstat (limited to 'src/werkzeug/utils.py')
-rw-r--r-- | src/werkzeug/utils.py | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/src/werkzeug/utils.py b/src/werkzeug/utils.py index c13ab586..eb8b5172 100644 --- a/src/werkzeug/utils.py +++ b/src/werkzeug/utils.py @@ -64,7 +64,12 @@ class cached_property(property, t.Generic[_T]): e.value = 16 # sets cache del e.value # clears cache - The class must have a ``__dict__`` for this to work. + If the class defines ``__slots__``, it must add ``_cache_{name}`` as + a slot. Alternatively, it can add ``__dict__``, but that's usually + not desirable. + + .. versionchanged:: 2.1 + Works with ``__slots__``. .. versionchanged:: 2.0 ``del obj.name`` clears the cached value. @@ -78,25 +83,41 @@ class cached_property(property, t.Generic[_T]): ) -> None: super().__init__(fget, doc=doc) self.__name__ = name or fget.__name__ + self.slot_name = f"_cache_{self.__name__}" self.__module__ = fget.__module__ def __set__(self, obj: object, value: _T) -> None: - obj.__dict__[self.__name__] = value + if hasattr(obj, "__dict__"): + obj.__dict__[self.__name__] = value + else: + setattr(obj, self.slot_name, value) def __get__(self, obj: object, type: type = None) -> _T: # type: ignore if obj is None: return self # type: ignore - value: _T = obj.__dict__.get(self.__name__, _missing) + obj_dict = getattr(obj, "__dict__", None) + + if obj_dict is not None: + value: _T = obj_dict.get(self.__name__, _missing) + else: + value = getattr(obj, self.slot_name, _missing) # type: ignore[arg-type] if value is _missing: value = self.fget(obj) # type: ignore - obj.__dict__[self.__name__] = value + + if obj_dict is not None: + obj.__dict__[self.__name__] = value + else: + setattr(obj, self.slot_name, value) return value def __delete__(self, obj: object) -> None: - del obj.__dict__[self.__name__] + if hasattr(obj, "__dict__"): + del obj.__dict__[self.__name__] + else: + setattr(obj, self.slot_name, _missing) class environ_property(_DictAccessorProperty[_TAccessorValue]): |