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 request
|
||||
from .globals import session
|
||||
from .helpers import _split_blueprint_path
|
||||
from .helpers import get_debug_flag
|
||||
from .helpers import get_env
|
||||
from .helpers import get_flashed_messages
|
||||
|
|
@ -1790,13 +1791,11 @@ class Flask(Scaffold):
|
|||
funcs: t.Iterable[URLDefaultCallable] = self.url_default_functions[None]
|
||||
|
||||
if "." in endpoint:
|
||||
bps: t.List[str] = [endpoint.rsplit(".", 1)[0]]
|
||||
|
||||
while "." in bps[-1]:
|
||||
bps.append(bps[-1].rpartition(".")[0])
|
||||
|
||||
for bp in bps:
|
||||
funcs = chain(funcs, self.url_default_functions[bp])
|
||||
# This is called by url_for, which can be called outside a
|
||||
# request, can't use request.blueprints.
|
||||
bps = _split_blueprint_path(endpoint.rpartition(".")[0])
|
||||
bp_funcs = chain.from_iterable(self.url_default_functions[bp] for bp in bps)
|
||||
funcs = chain(funcs, bp_funcs)
|
||||
|
||||
for func in funcs:
|
||||
func(endpoint, values)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import typing as t
|
|||
import warnings
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from functools import lru_cache
|
||||
from functools import update_wrapper
|
||||
from threading import RLock
|
||||
|
||||
|
|
@ -821,3 +822,13 @@ def is_ip(value: str) -> bool:
|
|||
return True
|
||||
|
||||
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
|
||||
|
||||
from werkzeug.exceptions import BadRequest
|
||||
from werkzeug.utils import cached_property
|
||||
from werkzeug.wrappers import Request as RequestBase
|
||||
from werkzeug.wrappers import Response as ResponseBase
|
||||
|
||||
from . import json
|
||||
from .globals import current_app
|
||||
from .helpers import _split_blueprint_path
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
import typing_extensions as te
|
||||
|
|
@ -60,38 +60,54 @@ class Request(RequestBase):
|
|||
|
||||
@property
|
||||
def endpoint(self) -> t.Optional[str]:
|
||||
"""The endpoint that matched the request. This in combination with
|
||||
:attr:`view_args` can be used to reconstruct the same or a
|
||||
modified URL. If an exception happened when matching, this will
|
||||
be ``None``.
|
||||
"""The endpoint that matched the request URL.
|
||||
|
||||
This will be ``None`` if matching failed or has not been
|
||||
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:
|
||||
return self.url_rule.endpoint
|
||||
else:
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
@property
|
||||
def blueprint(self) -> t.Optional[str]:
|
||||
"""The 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
|
||||
"""The registered name of the current blueprint.
|
||||
|
||||
@cached_property
|
||||
def blueprints(self) -> t.List[str]:
|
||||
"""The names of the current blueprint upwards through parent
|
||||
blueprints.
|
||||
This will be ``None`` if the endpoint is not part of a
|
||||
blueprint, or if URL matching failed or has not been performed
|
||||
yet.
|
||||
|
||||
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 []
|
||||
|
||||
bps: t.List[str] = [self.blueprint]
|
||||
|
||||
while "." in bps[-1]:
|
||||
bps.append(bps[-1].rpartition(".")[0])
|
||||
|
||||
return bps
|
||||
return _split_blueprint_path(name)
|
||||
|
||||
def _load_form_data(self) -> None:
|
||||
RequestBase._load_form_data(self)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue