forked from orbit-oss/flask
Merge pull request #3962 from pallets/cached-property
locked_cached_property subclasses Werkzeug's cached_property
This commit is contained in:
commit
f3ed1322a6
1 changed files with 19 additions and 20 deletions
|
|
@ -18,10 +18,6 @@ from .globals import request
|
||||||
from .globals import session
|
from .globals import session
|
||||||
from .signals import message_flashed
|
from .signals import message_flashed
|
||||||
|
|
||||||
# sentinel
|
|
||||||
_missing = object()
|
|
||||||
|
|
||||||
|
|
||||||
# what separators does this operating system provide that are not a slash?
|
# 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
|
# this is used by the send_from_directory function to ensure that nobody is
|
||||||
# able to access files from outside the filesystem.
|
# able to access files from outside the filesystem.
|
||||||
|
|
@ -677,30 +673,33 @@ def send_from_directory(directory, path, **kwargs):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class locked_cached_property:
|
class locked_cached_property(werkzeug.utils.cached_property):
|
||||||
"""A decorator that converts a function into a lazy property. The
|
"""A :func:`property` that is only evaluated once. Like
|
||||||
function wrapped is called the first time to retrieve the result
|
:class:`werkzeug.utils.cached_property` except access uses a lock
|
||||||
and then that calculated result is used the next time you access
|
for thread safety.
|
||||||
the value. Works like the one in Werkzeug but has a lock for
|
|
||||||
thread safety.
|
.. versionchanged:: 2.0
|
||||||
|
Inherits from Werkzeug's ``cached_property`` (and ``property``).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, func, name=None, doc=None):
|
def __init__(self, fget, name=None, doc=None):
|
||||||
self.__name__ = name or func.__name__
|
super().__init__(fget, name=name, doc=doc)
|
||||||
self.__module__ = func.__module__
|
|
||||||
self.__doc__ = doc or func.__doc__
|
|
||||||
self.func = func
|
|
||||||
self.lock = RLock()
|
self.lock = RLock()
|
||||||
|
|
||||||
def __get__(self, obj, type=None):
|
def __get__(self, obj, type=None):
|
||||||
if obj is None:
|
if obj is None:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
with self.lock:
|
with self.lock:
|
||||||
value = obj.__dict__.get(self.__name__, _missing)
|
return super().__get__(obj, type=type)
|
||||||
if value is _missing:
|
|
||||||
value = self.func(obj)
|
def __set__(self, obj, value):
|
||||||
obj.__dict__[self.__name__] = value
|
with self.lock:
|
||||||
return value
|
super().__set__(obj, value)
|
||||||
|
|
||||||
|
def __delete__(self, obj):
|
||||||
|
with self.lock:
|
||||||
|
super().__delete__(obj)
|
||||||
|
|
||||||
|
|
||||||
def total_seconds(td):
|
def total_seconds(td):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue