mirror of https://github.com/pallets/flask.git
Added appcontext_pushed and appcontext_popped signals
This commit is contained in:
parent
fd99abea57
commit
0676bb8ab5
1
CHANGES
1
CHANGES
|
@ -70,6 +70,7 @@ Release date to be decided.
|
||||||
- Added the ``JSONIFY_PRETTYPRINT_REGULAR`` configuration variable.
|
- Added the ``JSONIFY_PRETTYPRINT_REGULAR`` configuration variable.
|
||||||
- Flask now orders JSON keys by default to not trash HTTP caches due to
|
- Flask now orders JSON keys by default to not trash HTTP caches due to
|
||||||
different hash seeds between different workers.
|
different hash seeds between different workers.
|
||||||
|
- Added `appcontext_pushed` and `appcontext_popped` signals.
|
||||||
|
|
||||||
Version 0.9
|
Version 0.9
|
||||||
-----------
|
-----------
|
||||||
|
|
17
docs/api.rst
17
docs/api.rst
|
@ -535,7 +535,22 @@ Signals
|
||||||
This signal is sent when the application is tearing down the
|
This signal is sent when the application is tearing down the
|
||||||
application context. This is always called, even if an error happened.
|
application context. This is always called, even if an error happened.
|
||||||
An `exc` keyword argument is passed with the exception that caused the
|
An `exc` keyword argument is passed with the exception that caused the
|
||||||
teardown.
|
teardown. The sender is the application.
|
||||||
|
|
||||||
|
.. data:: appcontext_pushed
|
||||||
|
|
||||||
|
This signal is sent when an application context is pushed. The sender
|
||||||
|
is the application.
|
||||||
|
|
||||||
|
.. versionadded:: 0.10
|
||||||
|
|
||||||
|
.. data:: appcontext_popped
|
||||||
|
|
||||||
|
This signal is sent when an application context is popped. The sender
|
||||||
|
is the application. This usually falls in line with the
|
||||||
|
:data:`appcontext_tearing_down` signal.
|
||||||
|
|
||||||
|
.. versionadded:: 0.10
|
||||||
|
|
||||||
.. data:: message_flashed
|
.. data:: message_flashed
|
||||||
|
|
||||||
|
|
|
@ -291,6 +291,45 @@ The following signals exist in Flask:
|
||||||
This will also be passed an `exc` keyword argument that has a reference
|
This will also be passed an `exc` keyword argument that has a reference
|
||||||
to the exception that caused the teardown if there was one.
|
to the exception that caused the teardown if there was one.
|
||||||
|
|
||||||
|
.. data:: flask.appcontext_pushed
|
||||||
|
:noindex:
|
||||||
|
|
||||||
|
This signal is sent when an application context is pushed. The sender
|
||||||
|
is the application. This is usually useful for unittests in order to
|
||||||
|
temporarily hook in information. For instance it can be used to
|
||||||
|
set a resource early onto the `g` object.
|
||||||
|
|
||||||
|
Example usage::
|
||||||
|
|
||||||
|
from contextlib import contextmanager
|
||||||
|
from flask import appcontext_pushed
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def user_set(app, user):
|
||||||
|
def handler(sender, **kwargs):
|
||||||
|
g.user = user
|
||||||
|
with appcontext_pushed.connected_to(handler, app):
|
||||||
|
yield
|
||||||
|
|
||||||
|
And in the testcode::
|
||||||
|
|
||||||
|
def test_user_me(self):
|
||||||
|
with user_set(app, 'john'):
|
||||||
|
c = app.test_client()
|
||||||
|
resp = c.get('/users/me')
|
||||||
|
assert resp.data == 'username=john'
|
||||||
|
|
||||||
|
.. versionadded:: 0.10
|
||||||
|
|
||||||
|
.. data:: appcontext_popped
|
||||||
|
|
||||||
|
This signal is sent when an application context is popped. The sender
|
||||||
|
is the application. This usually falls in line with the
|
||||||
|
:data:`appcontext_tearing_down` signal.
|
||||||
|
|
||||||
|
.. versionadded:: 0.10
|
||||||
|
|
||||||
|
|
||||||
.. data:: flask.message_flashed
|
.. data:: flask.message_flashed
|
||||||
:noindex:
|
:noindex:
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,8 @@ from .templating import render_template, render_template_string
|
||||||
# the signals
|
# the signals
|
||||||
from .signals import signals_available, template_rendered, request_started, \
|
from .signals import signals_available, template_rendered, request_started, \
|
||||||
request_finished, got_request_exception, request_tearing_down, \
|
request_finished, got_request_exception, request_tearing_down, \
|
||||||
appcontext_tearing_down, message_flashed
|
appcontext_tearing_down, appcontext_pushed, \
|
||||||
|
appcontext_popped, message_flashed
|
||||||
|
|
||||||
# We're not exposing the actual json module but a convenient wrapper around
|
# We're not exposing the actual json module but a convenient wrapper around
|
||||||
# it.
|
# it.
|
||||||
|
|
|
@ -18,6 +18,7 @@ from werkzeug.exceptions import HTTPException
|
||||||
|
|
||||||
from .globals import _request_ctx_stack, _app_ctx_stack
|
from .globals import _request_ctx_stack, _app_ctx_stack
|
||||||
from .module import blueprint_is_module
|
from .module import blueprint_is_module
|
||||||
|
from .signals import appcontext_pushed, appcontext_popped
|
||||||
|
|
||||||
|
|
||||||
class _AppCtxGlobals(object):
|
class _AppCtxGlobals(object):
|
||||||
|
@ -166,6 +167,7 @@ class AppContext(object):
|
||||||
"""Binds the app context to the current context."""
|
"""Binds the app context to the current context."""
|
||||||
self._refcnt += 1
|
self._refcnt += 1
|
||||||
_app_ctx_stack.push(self)
|
_app_ctx_stack.push(self)
|
||||||
|
appcontext_pushed.send(self.app)
|
||||||
|
|
||||||
def pop(self, exc=None):
|
def pop(self, exc=None):
|
||||||
"""Pops the app context."""
|
"""Pops the app context."""
|
||||||
|
@ -177,6 +179,7 @@ class AppContext(object):
|
||||||
rv = _app_ctx_stack.pop()
|
rv = _app_ctx_stack.pop()
|
||||||
assert rv is self, 'Popped wrong app context. (%r instead of %r)' \
|
assert rv is self, 'Popped wrong app context. (%r instead of %r)' \
|
||||||
% (rv, self)
|
% (rv, self)
|
||||||
|
appcontext_popped.send(self.app)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.push()
|
self.push()
|
||||||
|
|
|
@ -50,4 +50,6 @@ request_finished = _signals.signal('request-finished')
|
||||||
request_tearing_down = _signals.signal('request-tearing-down')
|
request_tearing_down = _signals.signal('request-tearing-down')
|
||||||
got_request_exception = _signals.signal('got-request-exception')
|
got_request_exception = _signals.signal('got-request-exception')
|
||||||
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')
|
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')
|
||||||
|
appcontext_pushed = _signals.signal('appcontext-pushed')
|
||||||
|
appcontext_popped = _signals.signal('appcontext-popped')
|
||||||
message_flashed = _signals.signal('message-flashed')
|
message_flashed = _signals.signal('message-flashed')
|
||||||
|
|
|
@ -96,6 +96,30 @@ class SignalsTestCase(FlaskTestCase):
|
||||||
finally:
|
finally:
|
||||||
flask.got_request_exception.disconnect(record, app)
|
flask.got_request_exception.disconnect(record, app)
|
||||||
|
|
||||||
|
def test_appcontext_signals(self):
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
recorded = []
|
||||||
|
def record_push(sender, **kwargs):
|
||||||
|
recorded.append('push')
|
||||||
|
def record_pop(sender, **kwargs):
|
||||||
|
recorded.append('push')
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
return 'Hello'
|
||||||
|
|
||||||
|
flask.appcontext_pushed.connect(record_push, app)
|
||||||
|
flask.appcontext_popped.connect(record_pop, app)
|
||||||
|
try:
|
||||||
|
with app.test_client() as c:
|
||||||
|
rv = c.get('/')
|
||||||
|
self.assert_equal(rv.data, b'Hello')
|
||||||
|
self.assert_equal(recorded, ['push'])
|
||||||
|
self.assert_equal(recorded, ['push', 'pop'])
|
||||||
|
finally:
|
||||||
|
flask.appcontext_pushed.disconnect(record_push, app)
|
||||||
|
flask.appcontext_popped.disconnect(record_pop, app)
|
||||||
|
|
||||||
def test_flash_signal(self):
|
def test_flash_signal(self):
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
app.config['SECRET_KEY'] = 'secret'
|
app.config['SECRET_KEY'] = 'secret'
|
||||||
|
|
Loading…
Reference in New Issue