From 4256fc63044fa0d9c2135443461689b1adaf386d Mon Sep 17 00:00:00 2001 From: David Lord Date: Thu, 23 Feb 2023 10:05:57 -0800 Subject: [PATCH] deprecate locked_cached_property --- CHANGES.rst | 4 ++++ src/flask/app.py | 8 ++++---- src/flask/helpers.py | 12 ++++++++++++ src/flask/scaffold.py | 4 ++-- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index a50bc18d..88bfbc68 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -26,6 +26,10 @@ Unreleased - Importing ``escape`` and ``Markup`` from ``flask`` is deprecated. Import them directly from ``markupsafe`` instead. :pr:`4996` - The ``app.got_first_request`` property is deprecated. :pr:`4997` +- The ``locked_cached_property`` decorator is deprecated. Use a lock inside the + decorated function if locking is needed. :issue:`4993` +- Remove uses of locks that could cause requests to block each other very briefly. + :issue:`4993` - Use modern packaging metadata with ``pyproject.toml`` instead of ``setup.cfg``. :pr:`4947` - Ensure subdomains are applied with nested blueprints. :issue:`4834` diff --git a/src/flask/app.py b/src/flask/app.py index 493934d5..0070de89 100644 --- a/src/flask/app.py +++ b/src/flask/app.py @@ -26,6 +26,7 @@ from werkzeug.routing import RoutingException from werkzeug.routing import Rule from werkzeug.serving import is_running_from_reloader from werkzeug.urls import url_quote +from werkzeug.utils import cached_property from werkzeug.utils import redirect as _wz_redirect from werkzeug.wrappers import Response as BaseResponse @@ -46,7 +47,6 @@ from .helpers import _split_blueprint_path from .helpers import get_debug_flag from .helpers import get_flashed_messages from .helpers import get_load_dotenv -from .helpers import locked_cached_property from .json.provider import DefaultJSONProvider from .json.provider import JSONProvider from .logging import create_logger @@ -531,7 +531,7 @@ class Flask(Scaffold): " running it." ) - @locked_cached_property + @cached_property def name(self) -> str: # type: ignore """The name of the application. This is usually the import name with the difference that it's guessed from the run file if the @@ -548,7 +548,7 @@ class Flask(Scaffold): return os.path.splitext(os.path.basename(fn))[0] return self.import_name - @locked_cached_property + @cached_property def logger(self) -> logging.Logger: """A standard Python :class:`~logging.Logger` for the app, with the same name as :attr:`name`. @@ -575,7 +575,7 @@ class Flask(Scaffold): """ return create_logger(self) - @locked_cached_property + @cached_property def jinja_env(self) -> Environment: """The Jinja environment used to load templates. diff --git a/src/flask/helpers.py b/src/flask/helpers.py index 2bf2e628..939508d2 100644 --- a/src/flask/helpers.py +++ b/src/flask/helpers.py @@ -613,6 +613,10 @@ class locked_cached_property(werkzeug.utils.cached_property): :class:`werkzeug.utils.cached_property` except access uses a lock for thread safety. + .. deprecated:: 2.3 + Will be removed in Flask 2.4. Use a lock inside the decorated function if + locking is needed. + .. versionchanged:: 2.0 Inherits from Werkzeug's ``cached_property`` (and ``property``). """ @@ -623,6 +627,14 @@ class locked_cached_property(werkzeug.utils.cached_property): name: t.Optional[str] = None, doc: t.Optional[str] = None, ) -> None: + import warnings + + warnings.warn( + "'locked_cached_property' is deprecated and will be removed in Flask 2.4." + " Use a lock inside the decorated function if locking is needed.", + DeprecationWarning, + stacklevel=2, + ) super().__init__(fget, name=name, doc=doc) self.lock = RLock() diff --git a/src/flask/scaffold.py b/src/flask/scaffold.py index faa1ce43..bb583e4c 100644 --- a/src/flask/scaffold.py +++ b/src/flask/scaffold.py @@ -11,12 +11,12 @@ from functools import update_wrapper from jinja2 import FileSystemLoader from werkzeug.exceptions import default_exceptions from werkzeug.exceptions import HTTPException +from werkzeug.utils import cached_property from . import typing as ft from .cli import AppGroup from .globals import current_app from .helpers import get_root_path -from .helpers import locked_cached_property from .helpers import send_from_directory from .templating import _default_template_ctx_processor @@ -317,7 +317,7 @@ class Scaffold: t.cast(str, self.static_folder), filename, max_age=max_age ) - @locked_cached_property + @cached_property def jinja_loader(self) -> t.Optional[FileSystemLoader]: """The Jinja loader for this object's templates. By default this is a class :class:`jinja2.loaders.FileSystemLoader` to