Merge pull request #3962 from pallets/cached-property

locked_cached_property subclasses Werkzeug's cached_property
This commit is contained in:
David Lord 2021-04-15 23:14:24 -07:00 committed by GitHub
commit f3ed1322a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -18,10 +18,6 @@ from .globals import request
from .globals import session
from .signals import message_flashed
# sentinel
_missing = object()
# what separators does this operating system provide that are not a slash?
# this is used by the send_from_directory function to ensure that nobody is
# able to access files from outside the filesystem.
@ -677,30 +673,33 @@ def send_from_directory(directory, path, **kwargs):
)
class locked_cached_property:
"""A decorator that converts a function into a lazy property. The
function wrapped is called the first time to retrieve the result
and then that calculated result is used the next time you access
the value. Works like the one in Werkzeug but has a lock for
thread safety.
class locked_cached_property(werkzeug.utils.cached_property):
"""A :func:`property` that is only evaluated once. Like
:class:`werkzeug.utils.cached_property` except access uses a lock
for thread safety.
.. versionchanged:: 2.0
Inherits from Werkzeug's ``cached_property`` (and ``property``).
"""
def __init__(self, func, name=None, doc=None):
self.__name__ = name or func.__name__
self.__module__ = func.__module__
self.__doc__ = doc or func.__doc__
self.func = func
def __init__(self, fget, name=None, doc=None):
super().__init__(fget, name=name, doc=doc)
self.lock = RLock()
def __get__(self, obj, type=None):
if obj is None:
return self
with self.lock:
value = obj.__dict__.get(self.__name__, _missing)
if value is _missing:
value = self.func(obj)
obj.__dict__[self.__name__] = value
return value
return super().__get__(obj, type=type)
def __set__(self, obj, value):
with self.lock:
super().__set__(obj, value)
def __delete__(self, obj):
with self.lock:
super().__delete__(obj)
def total_seconds(td):