Modified bluprints.py and debughelpers.py to adhere more to PEP8 standards
This commit is contained in:
parent
7f2a0f4806
commit
8a72c556d6
2 changed files with 55 additions and 13 deletions
|
|
@ -12,6 +12,7 @@ from .scaffold import setupmethod
|
|||
if t.TYPE_CHECKING: # pragma: no cover
|
||||
from .app import Flask
|
||||
|
||||
|
||||
DeferredSetupFunction = t.Callable[["BlueprintSetupState"], t.Callable]
|
||||
|
||||
|
||||
|
|
@ -68,6 +69,7 @@ class BlueprintSetupState:
|
|||
self.url_defaults = dict(self.blueprint.url_values_defaults)
|
||||
self.url_defaults.update(self.options.get("url_defaults", ()))
|
||||
|
||||
|
||||
def add_url_rule(
|
||||
self,
|
||||
rule: str,
|
||||
|
|
@ -82,12 +84,17 @@ class BlueprintSetupState:
|
|||
if self.url_prefix is not None:
|
||||
if rule:
|
||||
rule = "/".join((self.url_prefix.rstrip("/"), rule.lstrip("/")))
|
||||
|
||||
else:
|
||||
rule = self.url_prefix
|
||||
|
||||
options.setdefault("subdomain", self.subdomain)
|
||||
|
||||
if endpoint is None:
|
||||
endpoint = _endpoint_from_view_func(view_func) # type: ignore
|
||||
|
||||
defaults = self.url_defaults
|
||||
|
||||
if "defaults" in options:
|
||||
defaults = dict(defaults, **options.pop("defaults"))
|
||||
|
||||
|
|
@ -162,6 +169,7 @@ class Blueprint(Scaffold):
|
|||
#: the app's :class:`~flask.Flask.json_decoder`.
|
||||
json_decoder = None
|
||||
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
|
|
@ -198,7 +206,9 @@ class Blueprint(Scaffold):
|
|||
self.cli_group = cli_group
|
||||
self._blueprints: t.List[t.Tuple["Blueprint", dict]] = []
|
||||
|
||||
|
||||
def _check_setup_finished(self, f_name: str) -> None:
|
||||
# TODO - This method is missing a docstring - please advise
|
||||
if self._got_registered_once:
|
||||
import warnings
|
||||
|
||||
|
|
@ -215,6 +225,7 @@ class Blueprint(Scaffold):
|
|||
stacklevel=3,
|
||||
)
|
||||
|
||||
|
||||
@setupmethod
|
||||
def record(self, func: t.Callable) -> None:
|
||||
"""Registers a function that is called when the blueprint is
|
||||
|
|
@ -224,6 +235,7 @@ class Blueprint(Scaffold):
|
|||
"""
|
||||
self.deferred_functions.append(func)
|
||||
|
||||
|
||||
@setupmethod
|
||||
def record_once(self, func: t.Callable) -> None:
|
||||
"""Works like :meth:`record` but wraps the function in another
|
||||
|
|
@ -231,13 +243,13 @@ class Blueprint(Scaffold):
|
|||
blueprint is registered a second time on the application, the
|
||||
function passed is not called.
|
||||
"""
|
||||
|
||||
def wrapper(state: BlueprintSetupState) -> None:
|
||||
if state.first_registration:
|
||||
func(state)
|
||||
|
||||
return self.record(update_wrapper(wrapper, func))
|
||||
|
||||
|
||||
def make_setup_state(
|
||||
self, app: "Flask", options: dict, first_registration: bool = False
|
||||
) -> BlueprintSetupState:
|
||||
|
|
@ -247,6 +259,7 @@ class Blueprint(Scaffold):
|
|||
"""
|
||||
return BlueprintSetupState(self, app, options, first_registration)
|
||||
|
||||
|
||||
@setupmethod
|
||||
def register_blueprint(self, blueprint: "Blueprint", **options: t.Any) -> None:
|
||||
"""Register a :class:`~flask.Blueprint` on this blueprint. Keyword
|
||||
|
|
@ -265,6 +278,7 @@ class Blueprint(Scaffold):
|
|||
raise ValueError("Cannot register a blueprint on itself")
|
||||
self._blueprints.append((blueprint, options))
|
||||
|
||||
|
||||
def register(self, app: "Flask", options: dict) -> None:
|
||||
"""Called by :meth:`Flask.register_blueprint` to register all
|
||||
views and callbacks registered on the blueprint with the
|
||||
|
|
@ -322,11 +336,13 @@ class Blueprint(Scaffold):
|
|||
# Merge blueprint data into parent.
|
||||
if first_bp_registration or first_name_registration:
|
||||
|
||||
|
||||
def extend(bp_dict, parent_dict):
|
||||
for key, values in bp_dict.items():
|
||||
key = name if key is None else f"{name}.{key}"
|
||||
parent_dict[key].extend(values)
|
||||
|
||||
|
||||
for key, value in self.error_handler_spec.items():
|
||||
key = name if key is None else f"{name}.{key}"
|
||||
value = defaultdict(
|
||||
|
|
@ -361,9 +377,11 @@ class Blueprint(Scaffold):
|
|||
if self.cli.commands:
|
||||
if cli_resolved_group is None:
|
||||
app.cli.commands.update(self.cli.commands)
|
||||
|
||||
elif cli_resolved_group is _sentinel:
|
||||
self.cli.name = name
|
||||
app.cli.add_command(self.cli)
|
||||
|
||||
else:
|
||||
self.cli.name = cli_resolved_group
|
||||
app.cli.add_command(self.cli)
|
||||
|
|
@ -379,14 +397,17 @@ class Blueprint(Scaffold):
|
|||
bp_options["url_prefix"] = (
|
||||
state.url_prefix.rstrip("/") + "/" + bp_url_prefix.lstrip("/")
|
||||
)
|
||||
|
||||
elif bp_url_prefix is not None:
|
||||
bp_options["url_prefix"] = bp_url_prefix
|
||||
|
||||
elif state.url_prefix is not None:
|
||||
bp_options["url_prefix"] = state.url_prefix
|
||||
|
||||
bp_options["name_prefix"] = name
|
||||
blueprint.register(app, bp_options)
|
||||
|
||||
|
||||
@setupmethod
|
||||
def add_url_rule(
|
||||
self,
|
||||
|
|
@ -415,6 +436,7 @@ class Blueprint(Scaffold):
|
|||
)
|
||||
)
|
||||
|
||||
|
||||
@setupmethod
|
||||
def app_template_filter(
|
||||
self, name: t.Optional[str] = None
|
||||
|
|
@ -425,13 +447,13 @@ class Blueprint(Scaffold):
|
|||
:param name: the optional name of the filter, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
|
||||
def decorator(f: ft.TemplateFilterCallable) -> ft.TemplateFilterCallable:
|
||||
self.add_app_template_filter(f, name=name)
|
||||
return f
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
@setupmethod
|
||||
def add_app_template_filter(
|
||||
self, f: ft.TemplateFilterCallable, name: t.Optional[str] = None
|
||||
|
|
@ -443,12 +465,12 @@ class Blueprint(Scaffold):
|
|||
:param name: the optional name of the filter, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
|
||||
def register_template(state: BlueprintSetupState) -> None:
|
||||
state.app.jinja_env.filters[name or f.__name__] = f
|
||||
|
||||
self.record_once(register_template)
|
||||
|
||||
|
||||
@setupmethod
|
||||
def app_template_test(
|
||||
self, name: t.Optional[str] = None
|
||||
|
|
@ -461,7 +483,6 @@ class Blueprint(Scaffold):
|
|||
:param name: the optional name of the test, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
|
||||
def decorator(f: ft.TemplateTestCallable) -> ft.TemplateTestCallable:
|
||||
self.add_app_template_test(f, name=name)
|
||||
return f
|
||||
|
|
@ -481,12 +502,12 @@ class Blueprint(Scaffold):
|
|||
:param name: the optional name of the test, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
|
||||
def register_template(state: BlueprintSetupState) -> None:
|
||||
state.app.jinja_env.tests[name or f.__name__] = f
|
||||
|
||||
self.record_once(register_template)
|
||||
|
||||
|
||||
@setupmethod
|
||||
def app_template_global(
|
||||
self, name: t.Optional[str] = None
|
||||
|
|
@ -499,13 +520,13 @@ class Blueprint(Scaffold):
|
|||
:param name: the optional name of the global, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
|
||||
def decorator(f: ft.TemplateGlobalCallable) -> ft.TemplateGlobalCallable:
|
||||
self.add_app_template_global(f, name=name)
|
||||
return f
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
@setupmethod
|
||||
def add_app_template_global(
|
||||
self, f: ft.TemplateGlobalCallable, name: t.Optional[str] = None
|
||||
|
|
@ -519,12 +540,12 @@ class Blueprint(Scaffold):
|
|||
:param name: the optional name of the global, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
|
||||
def register_template(state: BlueprintSetupState) -> None:
|
||||
state.app.jinja_env.globals[name or f.__name__] = f
|
||||
|
||||
self.record_once(register_template)
|
||||
|
||||
|
||||
@setupmethod
|
||||
def before_app_request(
|
||||
self, f: ft.BeforeRequestCallable
|
||||
|
|
@ -537,6 +558,7 @@ class Blueprint(Scaffold):
|
|||
)
|
||||
return f
|
||||
|
||||
|
||||
@setupmethod
|
||||
def before_app_first_request(
|
||||
self, f: ft.BeforeFirstRequestCallable
|
||||
|
|
@ -557,9 +579,11 @@ class Blueprint(Scaffold):
|
|||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
self.record_once(lambda s: s.app.before_first_request_funcs.append(f))
|
||||
return f
|
||||
|
||||
|
||||
def after_app_request(self, f: ft.AfterRequestCallable) -> ft.AfterRequestCallable:
|
||||
"""Like :meth:`Flask.after_request` but for a blueprint. Such a function
|
||||
is executed after each request, even if outside of the blueprint.
|
||||
|
|
@ -569,6 +593,7 @@ class Blueprint(Scaffold):
|
|||
)
|
||||
return f
|
||||
|
||||
|
||||
@setupmethod
|
||||
def teardown_app_request(self, f: ft.TeardownCallable) -> ft.TeardownCallable:
|
||||
"""Like :meth:`Flask.teardown_request` but for a blueprint. Such a
|
||||
|
|
@ -580,6 +605,7 @@ class Blueprint(Scaffold):
|
|||
)
|
||||
return f
|
||||
|
||||
|
||||
@setupmethod
|
||||
def app_context_processor(
|
||||
self, f: ft.TemplateContextProcessorCallable
|
||||
|
|
@ -592,6 +618,7 @@ class Blueprint(Scaffold):
|
|||
)
|
||||
return f
|
||||
|
||||
|
||||
@setupmethod
|
||||
def app_errorhandler(
|
||||
self, code: t.Union[t.Type[Exception], int]
|
||||
|
|
@ -599,13 +626,13 @@ class Blueprint(Scaffold):
|
|||
"""Like :meth:`Flask.errorhandler` but for a blueprint. This
|
||||
handler is used for all requests, even if outside of the blueprint.
|
||||
"""
|
||||
|
||||
def decorator(f: ft.ErrorHandlerDecorator) -> ft.ErrorHandlerDecorator:
|
||||
self.record_once(lambda s: s.app.errorhandler(code)(f))
|
||||
return f
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
@setupmethod
|
||||
def app_url_value_preprocessor(
|
||||
self, f: ft.URLValuePreprocessorCallable
|
||||
|
|
@ -616,6 +643,7 @@ class Blueprint(Scaffold):
|
|||
)
|
||||
return f
|
||||
|
||||
|
||||
@setupmethod
|
||||
def app_url_defaults(self, f: ft.URLDefaultCallable) -> ft.URLDefaultCallable:
|
||||
"""Same as :meth:`url_defaults` but application wide."""
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ class UnexpectedUnicodeError(AssertionError, UnicodeError):
|
|||
"""Raised in places where we want some better error reporting for
|
||||
unexpected unicode or binary data.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class DebugFilesKeyError(KeyError, AssertionError):
|
||||
|
|
@ -26,6 +27,7 @@ class DebugFilesKeyError(KeyError, AssertionError):
|
|||
" were transmitted. To fix this error you should provide"
|
||||
' enctype="multipart/form-data" in your form.'
|
||||
]
|
||||
|
||||
if form_matches:
|
||||
names = ", ".join(repr(x) for x in form_matches)
|
||||
buf.append(
|
||||
|
|
@ -71,16 +73,16 @@ class FormDataRoutingRedirect(AssertionError):
|
|||
def attach_enctype_error_multidict(request):
|
||||
"""Patch ``request.files.__getitem__`` to raise a descriptive error
|
||||
about ``enctype=multipart/form-data``.
|
||||
|
||||
:param request: The request to patch.
|
||||
:meta private:
|
||||
"""
|
||||
oldcls = request.files.__class__
|
||||
|
||||
class newcls(oldcls):
|
||||
class NewCls(oldcls):
|
||||
def __getitem__(self, key):
|
||||
try:
|
||||
return super().__getitem__(key)
|
||||
|
||||
except KeyError as e:
|
||||
if key not in request.form:
|
||||
raise
|
||||
|
|
@ -89,23 +91,28 @@ def attach_enctype_error_multidict(request):
|
|||
e.__traceback__
|
||||
) from None
|
||||
|
||||
newcls.__name__ = oldcls.__name__
|
||||
newcls.__module__ = oldcls.__module__
|
||||
request.files.__class__ = newcls
|
||||
NewCls.__name__ = oldcls.__name__
|
||||
NewCls.__module__ = oldcls.__module__
|
||||
request.files.__class__ = NewCls
|
||||
|
||||
|
||||
def _dump_loader_info(loader) -> t.Generator:
|
||||
# TODO - This method is missing a docstring - please advise
|
||||
yield f"class: {type(loader).__module__}.{type(loader).__name__}"
|
||||
|
||||
for key, value in sorted(loader.__dict__.items()):
|
||||
if key.startswith("_"):
|
||||
continue
|
||||
|
||||
if isinstance(value, (tuple, list)):
|
||||
if not all(isinstance(x, str) for x in value):
|
||||
continue
|
||||
yield f"{key}:"
|
||||
|
||||
for item in value:
|
||||
yield f" - {item}"
|
||||
continue
|
||||
|
||||
elif not isinstance(value, (str, int, float, bool)):
|
||||
continue
|
||||
yield f"{key}: {value!r}"
|
||||
|
|
@ -117,14 +124,17 @@ def explain_template_loading_attempts(app: Flask, template, attempts) -> None:
|
|||
total_found = 0
|
||||
blueprint = None
|
||||
reqctx = _request_ctx_stack.top
|
||||
|
||||
if reqctx is not None and reqctx.request.blueprint is not None:
|
||||
blueprint = reqctx.request.blueprint
|
||||
|
||||
for idx, (loader, srcobj, triple) in enumerate(attempts):
|
||||
if isinstance(srcobj, Flask):
|
||||
src_info = f"application {srcobj.import_name!r}"
|
||||
|
||||
elif isinstance(srcobj, Blueprint):
|
||||
src_info = f"blueprint {srcobj.name!r} ({srcobj.import_name})"
|
||||
|
||||
else:
|
||||
src_info = repr(srcobj)
|
||||
|
||||
|
|
@ -135,15 +145,19 @@ def explain_template_loading_attempts(app: Flask, template, attempts) -> None:
|
|||
|
||||
if triple is None:
|
||||
detail = "no match"
|
||||
|
||||
else:
|
||||
detail = f"found ({triple[1] or '<string>'!r})"
|
||||
total_found += 1
|
||||
|
||||
info.append(f" -> {detail}")
|
||||
|
||||
seems_fishy = False
|
||||
|
||||
if total_found == 0:
|
||||
info.append("Error: the template could not be found.")
|
||||
seems_fishy = True
|
||||
|
||||
elif total_found > 1:
|
||||
info.append("Warning: multiple loaders returned a match for the template.")
|
||||
seems_fishy = True
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue