cache blueprint path calculation
This commit is contained in:
parent
c2920e2bd9
commit
67b0b7e30d
3 changed files with 56 additions and 30 deletions
|
|
@ -36,6 +36,7 @@ from .globals import _request_ctx_stack
|
||||||
from .globals import g
|
from .globals import g
|
||||||
from .globals import request
|
from .globals import request
|
||||||
from .globals import session
|
from .globals import session
|
||||||
|
from .helpers import _split_blueprint_path
|
||||||
from .helpers import get_debug_flag
|
from .helpers import get_debug_flag
|
||||||
from .helpers import get_env
|
from .helpers import get_env
|
||||||
from .helpers import get_flashed_messages
|
from .helpers import get_flashed_messages
|
||||||
|
|
@ -1790,13 +1791,11 @@ class Flask(Scaffold):
|
||||||
funcs: t.Iterable[URLDefaultCallable] = self.url_default_functions[None]
|
funcs: t.Iterable[URLDefaultCallable] = self.url_default_functions[None]
|
||||||
|
|
||||||
if "." in endpoint:
|
if "." in endpoint:
|
||||||
bps: t.List[str] = [endpoint.rsplit(".", 1)[0]]
|
# This is called by url_for, which can be called outside a
|
||||||
|
# request, can't use request.blueprints.
|
||||||
while "." in bps[-1]:
|
bps = _split_blueprint_path(endpoint.rpartition(".")[0])
|
||||||
bps.append(bps[-1].rpartition(".")[0])
|
bp_funcs = chain.from_iterable(self.url_default_functions[bp] for bp in bps)
|
||||||
|
funcs = chain(funcs, bp_funcs)
|
||||||
for bp in bps:
|
|
||||||
funcs = chain(funcs, self.url_default_functions[bp])
|
|
||||||
|
|
||||||
for func in funcs:
|
for func in funcs:
|
||||||
func(endpoint, values)
|
func(endpoint, values)
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import typing as t
|
||||||
import warnings
|
import warnings
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from functools import lru_cache
|
||||||
from functools import update_wrapper
|
from functools import update_wrapper
|
||||||
from threading import RLock
|
from threading import RLock
|
||||||
|
|
||||||
|
|
@ -821,3 +822,13 @@ def is_ip(value: str) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=None)
|
||||||
|
def _split_blueprint_path(name: str) -> t.List[str]:
|
||||||
|
out: t.List[str] = [name]
|
||||||
|
|
||||||
|
if "." in name:
|
||||||
|
out.extend(_split_blueprint_path(name.rpartition(".")[0]))
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import typing as t
|
import typing as t
|
||||||
|
|
||||||
from werkzeug.exceptions import BadRequest
|
from werkzeug.exceptions import BadRequest
|
||||||
from werkzeug.utils import cached_property
|
|
||||||
from werkzeug.wrappers import Request as RequestBase
|
from werkzeug.wrappers import Request as RequestBase
|
||||||
from werkzeug.wrappers import Response as ResponseBase
|
from werkzeug.wrappers import Response as ResponseBase
|
||||||
|
|
||||||
from . import json
|
from . import json
|
||||||
from .globals import current_app
|
from .globals import current_app
|
||||||
|
from .helpers import _split_blueprint_path
|
||||||
|
|
||||||
if t.TYPE_CHECKING:
|
if t.TYPE_CHECKING:
|
||||||
import typing_extensions as te
|
import typing_extensions as te
|
||||||
|
|
@ -60,38 +60,54 @@ class Request(RequestBase):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def endpoint(self) -> t.Optional[str]:
|
def endpoint(self) -> t.Optional[str]:
|
||||||
"""The endpoint that matched the request. This in combination with
|
"""The endpoint that matched the request URL.
|
||||||
:attr:`view_args` can be used to reconstruct the same or a
|
|
||||||
modified URL. If an exception happened when matching, this will
|
This will be ``None`` if matching failed or has not been
|
||||||
be ``None``.
|
performed yet.
|
||||||
|
|
||||||
|
This in combination with :attr:`view_args` can be used to
|
||||||
|
reconstruct the same URL or a modified URL.
|
||||||
"""
|
"""
|
||||||
if self.url_rule is not None:
|
if self.url_rule is not None:
|
||||||
return self.url_rule.endpoint
|
return self.url_rule.endpoint
|
||||||
else:
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def blueprint(self) -> t.Optional[str]:
|
def blueprint(self) -> t.Optional[str]:
|
||||||
"""The name of the current blueprint"""
|
"""The registered name of the current blueprint.
|
||||||
if self.url_rule and "." in self.url_rule.endpoint:
|
|
||||||
return self.url_rule.endpoint.rsplit(".", 1)[0]
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
@cached_property
|
This will be ``None`` if the endpoint is not part of a
|
||||||
def blueprints(self) -> t.List[str]:
|
blueprint, or if URL matching failed or has not been performed
|
||||||
"""The names of the current blueprint upwards through parent
|
yet.
|
||||||
blueprints.
|
|
||||||
|
This does not necessarily match the name the blueprint was
|
||||||
|
created with. It may have been nested, or registered with a
|
||||||
|
different name.
|
||||||
"""
|
"""
|
||||||
if self.blueprint is None:
|
endpoint = self.endpoint
|
||||||
|
|
||||||
|
if endpoint is not None and "." in endpoint:
|
||||||
|
return endpoint.rpartition(".")[0]
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def blueprints(self) -> t.List[str]:
|
||||||
|
"""The registered names of the current blueprint upwards through
|
||||||
|
parent blueprints.
|
||||||
|
|
||||||
|
This will be an empty list if there is no current blueprint, or
|
||||||
|
if URL matching failed.
|
||||||
|
|
||||||
|
.. versionadded:: 2.0.1
|
||||||
|
"""
|
||||||
|
name = self.blueprint
|
||||||
|
|
||||||
|
if name is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
bps: t.List[str] = [self.blueprint]
|
return _split_blueprint_path(name)
|
||||||
|
|
||||||
while "." in bps[-1]:
|
|
||||||
bps.append(bps[-1].rpartition(".")[0])
|
|
||||||
|
|
||||||
return bps
|
|
||||||
|
|
||||||
def _load_form_data(self) -> None:
|
def _load_form_data(self) -> None:
|
||||||
RequestBase._load_form_data(self)
|
RequestBase._load_form_data(self)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue