Merge pull request #3918 from pgjones/defaultdict

This commit is contained in:
David Lord 2021-03-08 10:15:26 -08:00 committed by GitHub
commit 6d9d79c70d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 27 deletions

View file

@ -430,13 +430,13 @@ class Flask(Scaffold):
#: .. versionadded:: 0.11 #: .. versionadded:: 0.11
self.shell_context_processors = [] self.shell_context_processors = []
#: all the attached blueprints in a dictionary by name. Blueprints #: Maps registered blueprint names to blueprint objects. The
#: can be attached multiple times so this dictionary does not tell #: dict retains the order the blueprints were registered in.
#: you how often they got attached. #: Blueprints can be registered multiple times, this dict does
#: not track how often they were attached.
#: #:
#: .. versionadded:: 0.7 #: .. versionadded:: 0.7
self.blueprints = {} self.blueprints = {}
self._blueprint_order = []
#: a place where extensions can store application specific state. For #: a place where extensions can store application specific state. For
#: example this is where an extension could store database engines and #: example this is where an extension could store database engines and
@ -997,7 +997,6 @@ class Flask(Scaffold):
) )
else: else:
self.blueprints[blueprint.name] = blueprint self.blueprints[blueprint.name] = blueprint
self._blueprint_order.append(blueprint)
first_registration = True first_registration = True
blueprint.register(self, options, first_registration) blueprint.register(self, options, first_registration)
@ -1007,7 +1006,7 @@ class Flask(Scaffold):
.. versionadded:: 0.11 .. versionadded:: 0.11
""" """
return iter(self._blueprint_order) return self.blueprints.values()
@setupmethod @setupmethod
def add_url_rule( def add_url_rule(
@ -1292,7 +1291,7 @@ class Flask(Scaffold):
(request.blueprint, None), (request.blueprint, None),
(None, None), (None, None),
): ):
handler_map = self.error_handler_spec.setdefault(name, {}).get(c) handler_map = self.error_handler_spec[name][c]
if not handler_map: if not handler_map:
continue continue
@ -1753,10 +1752,10 @@ class Flask(Scaffold):
.. versionadded:: 0.7 .. versionadded:: 0.7
""" """
funcs = self.url_default_functions.get(None, ()) funcs = self.url_default_functions[None]
if "." in endpoint: if "." in endpoint:
bp = endpoint.rsplit(".", 1)[0] bp = endpoint.rsplit(".", 1)[0]
funcs = chain(funcs, self.url_default_functions.get(bp, ())) funcs = chain(funcs, self.url_default_functions[bp])
for func in funcs: for func in funcs:
func(endpoint, values) func(endpoint, values)
@ -1794,13 +1793,13 @@ class Flask(Scaffold):
bp = _request_ctx_stack.top.request.blueprint bp = _request_ctx_stack.top.request.blueprint
funcs = self.url_value_preprocessors.get(None, ()) funcs = self.url_value_preprocessors[None]
if bp is not None and bp in self.url_value_preprocessors: if bp is not None and bp in self.url_value_preprocessors:
funcs = chain(funcs, self.url_value_preprocessors[bp]) funcs = chain(funcs, self.url_value_preprocessors[bp])
for func in funcs: for func in funcs:
func(request.endpoint, request.view_args) func(request.endpoint, request.view_args)
funcs = self.before_request_funcs.get(None, ()) funcs = self.before_request_funcs[None]
if bp is not None and bp in self.before_request_funcs: if bp is not None and bp in self.before_request_funcs:
funcs = chain(funcs, self.before_request_funcs[bp]) funcs = chain(funcs, self.before_request_funcs[bp])
for func in funcs: for func in funcs:
@ -1857,7 +1856,7 @@ class Flask(Scaffold):
""" """
if exc is _sentinel: if exc is _sentinel:
exc = sys.exc_info()[1] exc = sys.exc_info()[1]
funcs = reversed(self.teardown_request_funcs.get(None, ())) funcs = reversed(self.teardown_request_funcs[None])
bp = _request_ctx_stack.top.request.blueprint bp = _request_ctx_stack.top.request.blueprint
if bp is not None and bp in self.teardown_request_funcs: if bp is not None and bp in self.teardown_request_funcs:
funcs = chain(funcs, reversed(self.teardown_request_funcs[bp])) funcs = chain(funcs, reversed(self.teardown_request_funcs[bp]))

View file

@ -251,7 +251,7 @@ class Blueprint(Scaffold):
""" """
for key, values in self_dict.items(): for key, values in self_dict.items():
key = self.name if key is None else f"{self.name}.{key}" key = self.name if key is None else f"{self.name}.{key}"
app_dict.setdefault(key, []).extend(values) app_dict[key].extend(values)
def merge_dict_nested(self_dict, app_dict): def merge_dict_nested(self_dict, app_dict):
"""Merges self_dict into app_dict. Replaces None keys with self.name. """Merges self_dict into app_dict. Replaces None keys with self.name.

View file

@ -1,3 +1,4 @@
from collections import defaultdict
from functools import update_wrapper from functools import update_wrapper
from werkzeug.exceptions import default_exceptions from werkzeug.exceptions import default_exceptions
@ -86,21 +87,21 @@ class Scaffold(_PackageBoundObject):
#: #:
#: To register an error handler, use the :meth:`errorhandler` #: To register an error handler, use the :meth:`errorhandler`
#: decorator. #: decorator.
self.error_handler_spec = {} self.error_handler_spec = defaultdict(lambda: defaultdict(dict))
#: A dictionary with lists of functions that will be called at the #: A dictionary with lists of functions that will be called at the
#: beginning of each request. The key of the dictionary is the name of #: beginning of each request. The key of the dictionary is the name of
#: the blueprint this function is active for, or ``None`` for all #: the blueprint this function is active for, or ``None`` for all
#: requests. To register a function, use the :meth:`before_request` #: requests. To register a function, use the :meth:`before_request`
#: decorator. #: decorator.
self.before_request_funcs = {} self.before_request_funcs = defaultdict(list)
#: A dictionary with lists of functions that should be called after #: A dictionary with lists of functions that should be called after
#: each request. The key of the dictionary is the name of the blueprint #: each request. The key of the dictionary is the name of the blueprint
#: this function is active for, ``None`` for all requests. This can for #: this function is active for, ``None`` for all requests. This can for
#: example be used to close database connections. To register a function #: example be used to close database connections. To register a function
#: here, use the :meth:`after_request` decorator. #: here, use the :meth:`after_request` decorator.
self.after_request_funcs = {} self.after_request_funcs = defaultdict(list)
#: A dictionary with lists of functions that are called after #: A dictionary with lists of functions that are called after
#: each request, even if an exception has occurred. The key of the #: each request, even if an exception has occurred. The key of the
@ -112,7 +113,7 @@ class Scaffold(_PackageBoundObject):
#: :meth:`teardown_request` decorator. #: :meth:`teardown_request` decorator.
#: #:
#: .. versionadded:: 0.7 #: .. versionadded:: 0.7
self.teardown_request_funcs = {} self.teardown_request_funcs = defaultdict(list)
#: A dictionary with list of functions that are called without argument #: A dictionary with list of functions that are called without argument
#: to populate the template context. The key of the dictionary is the #: to populate the template context. The key of the dictionary is the
@ -120,7 +121,9 @@ class Scaffold(_PackageBoundObject):
#: requests. Each returns a dictionary that the template context is #: requests. Each returns a dictionary that the template context is
#: updated with. To register a function here, use the #: updated with. To register a function here, use the
#: :meth:`context_processor` decorator. #: :meth:`context_processor` decorator.
self.template_context_processors = {None: [_default_template_ctx_processor]} self.template_context_processors = defaultdict(
list, {None: [_default_template_ctx_processor]}
)
#: A dictionary with lists of functions that are called before the #: A dictionary with lists of functions that are called before the
#: :attr:`before_request_funcs` functions. The key of the dictionary is #: :attr:`before_request_funcs` functions. The key of the dictionary is
@ -129,7 +132,7 @@ class Scaffold(_PackageBoundObject):
#: :meth:`url_value_preprocessor`. #: :meth:`url_value_preprocessor`.
#: #:
#: .. versionadded:: 0.7 #: .. versionadded:: 0.7
self.url_value_preprocessors = {} self.url_value_preprocessors = defaultdict(list)
#: A dictionary with lists of functions that can be used as URL value #: A dictionary with lists of functions that can be used as URL value
#: preprocessors. The key ``None`` here is used for application wide #: preprocessors. The key ``None`` here is used for application wide
@ -141,7 +144,7 @@ class Scaffold(_PackageBoundObject):
#: automatically again that were removed that way. #: automatically again that were removed that way.
#: #:
#: .. versionadded:: 0.7 #: .. versionadded:: 0.7
self.url_default_functions = {} self.url_default_functions = defaultdict(list)
def _is_setup_finished(self): def _is_setup_finished(self):
raise NotImplementedError raise NotImplementedError
@ -258,7 +261,7 @@ class Scaffold(_PackageBoundObject):
non-None value, the value is handled as if it was the return value from non-None value, the value is handled as if it was the return value from
the view, and further request handling is stopped. the view, and further request handling is stopped.
""" """
self.before_request_funcs.setdefault(None, []).append(f) self.before_request_funcs[None].append(f)
return f return f
@setupmethod @setupmethod
@ -272,7 +275,7 @@ class Scaffold(_PackageBoundObject):
As of Flask 0.7 this function might not be executed at the end of the As of Flask 0.7 this function might not be executed at the end of the
request in case an unhandled exception occurred. request in case an unhandled exception occurred.
""" """
self.after_request_funcs.setdefault(None, []).append(f) self.after_request_funcs[None].append(f)
return f return f
@setupmethod @setupmethod
@ -311,7 +314,7 @@ class Scaffold(_PackageBoundObject):
debugger can still access it. This behavior can be controlled debugger can still access it. This behavior can be controlled
by the ``PRESERVE_CONTEXT_ON_EXCEPTION`` configuration variable. by the ``PRESERVE_CONTEXT_ON_EXCEPTION`` configuration variable.
""" """
self.teardown_request_funcs.setdefault(None, []).append(f) self.teardown_request_funcs[None].append(f)
return f return f
@setupmethod @setupmethod
@ -334,7 +337,7 @@ class Scaffold(_PackageBoundObject):
The function is passed the endpoint name and values dict. The return The function is passed the endpoint name and values dict. The return
value is ignored. value is ignored.
""" """
self.url_value_preprocessors.setdefault(None, []).append(f) self.url_value_preprocessors[None].append(f)
return f return f
@setupmethod @setupmethod
@ -343,7 +346,7 @@ class Scaffold(_PackageBoundObject):
application. It's called with the endpoint and values and should application. It's called with the endpoint and values and should
update the values passed in place. update the values passed in place.
""" """
self.url_default_functions.setdefault(None, []).append(f) self.url_default_functions[None].append(f)
return f return f
@setupmethod @setupmethod
@ -416,8 +419,7 @@ class Scaffold(_PackageBoundObject):
" instead." " instead."
) )
handlers = self.error_handler_spec.setdefault(key, {}).setdefault(code, {}) self.error_handler_spec[key][code][exc_class] = f
handlers[exc_class] = f
@staticmethod @staticmethod
def _get_exc_class_and_code(exc_class_or_code): def _get_exc_class_and_code(exc_class_or_code):