Browse Source

Register most stuff only once

pull/262/head
Armin Ronacher 14 years ago
parent
commit
f7e71b518f
  1. 4
      flask/app.py
  2. 39
      flask/blueprints.py

4
flask/app.py

@ -583,6 +583,7 @@ class Flask(_PackageBoundObject):
.. versionadded:: 0.7 .. versionadded:: 0.7
""" """
first_registration = False
if blueprint.name in self.blueprints: if blueprint.name in self.blueprints:
assert self.blueprints[blueprint.name] is blueprint, \ assert self.blueprints[blueprint.name] is blueprint, \
'A blueprint\'s name collision ocurred between %r and ' \ 'A blueprint\'s name collision ocurred between %r and ' \
@ -590,7 +591,8 @@ class Flask(_PackageBoundObject):
(blueprint, self.blueprints[blueprint.name], blueprint.name) (blueprint, self.blueprints[blueprint.name], blueprint.name)
else: else:
self.blueprints[blueprint.name] = blueprint self.blueprints[blueprint.name] = blueprint
blueprint.register(self, options) first_registration = True
blueprint.register(self, options, first_registration)
def add_url_rule(self, rule, endpoint=None, view_func=None, **options): def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
"""Connects a URL rule. Works exactly like the :meth:`route` """Connects a URL rule. Works exactly like the :meth:`route`

39
flask/blueprints.py

@ -10,6 +10,7 @@
:license: BSD, see LICENSE for more details. :license: BSD, see LICENSE for more details.
""" """
import os import os
from functools import update_wrapper
from .helpers import _PackageBoundObject, _endpoint_from_view_func from .helpers import _PackageBoundObject, _endpoint_from_view_func
@ -19,10 +20,11 @@ class BlueprintSetupState(object):
application. application.
""" """
def __init__(self, blueprint, app, options): def __init__(self, blueprint, app, options, first_registration):
self.app = app self.app = app
self.blueprint = blueprint self.blueprint = blueprint
self.options = options self.options = options
self.first_registration = first_registration
subdomain = self.options.get('subdomain') subdomain = self.options.get('subdomain')
if subdomain is None: if subdomain is None:
@ -64,17 +66,23 @@ class Blueprint(_PackageBoundObject):
def _record(self, func): def _record(self, func):
self.deferred_functions.append(func) self.deferred_functions.append(func)
def make_setup_state(self, app, options): def _record_once(self, func):
return BlueprintSetupState(self, app, options) def wrapper(state):
if state.first_registration:
func(state)
return self._record(update_wrapper(wrapper, func))
def register(self, app, options): def make_setup_state(self, app, options, first_registration=False):
return BlueprintSetupState(self, app, options, first_registration)
def register(self, app, options, first_registration=False):
"""Called by :meth:`Flask.register_blueprint` to register a blueprint """Called by :meth:`Flask.register_blueprint` to register a blueprint
on the application. This can be overridden to customize the register on the application. This can be overridden to customize the register
behavior. Keyword arguments from behavior. Keyword arguments from
:func:`~flask.Flask.register_blueprint` are directly forwarded to this :func:`~flask.Flask.register_blueprint` are directly forwarded to this
method in the `options` dictionary. method in the `options` dictionary.
""" """
state = self.make_setup_state(app, options) state = self.make_setup_state(app, options, first_registration)
if self.has_static_folder: if self.has_static_folder:
state.add_url_rule(self.static_url_path + '/<path:filename>', state.add_url_rule(self.static_url_path + '/<path:filename>',
view_func=self.send_static_file, view_func=self.send_static_file,
@ -96,9 +104,8 @@ class Blueprint(_PackageBoundObject):
"""Like :meth:`Flask.add_url_rule` but for a module. The endpoint for """Like :meth:`Flask.add_url_rule` but for a module. The endpoint for
the :func:`url_for` function is prefixed with the name of the module. the :func:`url_for` function is prefixed with the name of the module.
""" """
def register_rule(state): self._record(lambda s:
state.add_url_rule(rule, endpoint, view_func, **options) s.add_url_rule(rule, endpoint, view_func, **options))
self._record(register_rule)
def endpoint(self, endpoint): def endpoint(self, endpoint):
"""Like :meth:`Flask.endpoint` but for a module. This does not """Like :meth:`Flask.endpoint` but for a module. This does not
@ -108,7 +115,7 @@ class Blueprint(_PackageBoundObject):
def decorator(f): def decorator(f):
def register_endpoint(state): def register_endpoint(state):
state.app.view_functions[endpoint] = f state.app.view_functions[endpoint] = f
self._record(register_endpoint) self._record_once(register_endpoint)
return f return f
return decorator return decorator
@ -117,7 +124,7 @@ class Blueprint(_PackageBoundObject):
is only executed before each request that is handled by a function of is only executed before each request that is handled by a function of
that module. that module.
""" """
self._record(lambda s: s.app.before_request_funcs self._record_once(lambda s: s.app.before_request_funcs
.setdefault(self.name, []).append(f)) .setdefault(self.name, []).append(f))
return f return f
@ -125,7 +132,7 @@ class Blueprint(_PackageBoundObject):
"""Like :meth:`Flask.before_request`. Such a function is executed """Like :meth:`Flask.before_request`. Such a function is executed
before each request, even if outside of a module. before each request, even if outside of a module.
""" """
self._record(lambda s: s.app.before_request_funcs self._record_once(lambda s: s.app.before_request_funcs
.setdefault(None, []).append(f)) .setdefault(None, []).append(f))
return f return f
@ -134,7 +141,7 @@ class Blueprint(_PackageBoundObject):
is only executed after each request that is handled by a function of is only executed after each request that is handled by a function of
that module. that module.
""" """
self._record(lambda s: s.app.after_request_funcs self._record_once(lambda s: s.app.after_request_funcs
.setdefault(self.name, []).append(f)) .setdefault(self.name, []).append(f))
return f return f
@ -142,7 +149,7 @@ class Blueprint(_PackageBoundObject):
"""Like :meth:`Flask.after_request` but for a module. Such a function """Like :meth:`Flask.after_request` but for a module. Such a function
is executed after each request, even if outside of the module. is executed after each request, even if outside of the module.
""" """
self._record(lambda s: s.app.after_request_funcs self._record_once(lambda s: s.app.after_request_funcs
.setdefault(None, []).append(f)) .setdefault(None, []).append(f))
return f return f
@ -150,7 +157,7 @@ class Blueprint(_PackageBoundObject):
"""Like :meth:`Flask.context_processor` but for a module. This """Like :meth:`Flask.context_processor` but for a module. This
function is only executed for requests handled by a module. function is only executed for requests handled by a module.
""" """
self._record(lambda s: s.app.template_context_processors self._record_once(lambda s: s.app.template_context_processors
.setdefault(self.name, []).append(f)) .setdefault(self.name, []).append(f))
return f return f
@ -158,7 +165,7 @@ class Blueprint(_PackageBoundObject):
"""Like :meth:`Flask.context_processor` but for a module. Such a """Like :meth:`Flask.context_processor` but for a module. Such a
function is executed each request, even if outside of the module. function is executed each request, even if outside of the module.
""" """
self._record(lambda s: s.app.template_context_processors self._record_once(lambda s: s.app.template_context_processors
.setdefault(None, []).append(f)) .setdefault(None, []).append(f))
return f return f
@ -167,6 +174,6 @@ class Blueprint(_PackageBoundObject):
handler is used for all requests, even if outside of the module. handler is used for all requests, even if outside of the module.
""" """
def decorator(f): def decorator(f):
self._record(lambda s: s.app.errorhandler(code)(f)) self._record_once(lambda s: s.app.errorhandler(code)(f))
return f return f
return decorator return decorator

Loading…
Cancel
Save