Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added appcontext_pushed and appcontext_popped signals

  • Loading branch information...
commit 0676bb8ab54a575616cd65d3c2ef1cc31fb82a84 1 parent fd99abe
@mitsuhiko authored
View
1  CHANGES
@@ -70,6 +70,7 @@ Release date to be decided.
- Added the ``JSONIFY_PRETTYPRINT_REGULAR`` configuration variable.
- Flask now orders JSON keys by default to not trash HTTP caches due to
different hash seeds between different workers.
+- Added `appcontext_pushed` and `appcontext_popped` signals.
Version 0.9
-----------
View
17 docs/api.rst
@@ -535,7 +535,22 @@ Signals
This signal is sent when the application is tearing down the
application context. This is always called, even if an error happened.
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
View
39 docs/signals.rst
@@ -291,6 +291,45 @@ The following signals exist in Flask:
This will also be passed an `exc` keyword argument that has a reference
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
:noindex:
View
3  flask/__init__.py
@@ -34,7 +34,8 @@
# the signals
from .signals import signals_available, template_rendered, request_started, \
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
# it.
View
3  flask/ctx.py
@@ -18,6 +18,7 @@
from .globals import _request_ctx_stack, _app_ctx_stack
from .module import blueprint_is_module
+from .signals import appcontext_pushed, appcontext_popped
class _AppCtxGlobals(object):
@@ -166,6 +167,7 @@ def push(self):
"""Binds the app context to the current context."""
self._refcnt += 1
_app_ctx_stack.push(self)
+ appcontext_pushed.send(self.app)
def pop(self, exc=None):
"""Pops the app context."""
@@ -177,6 +179,7 @@ def pop(self, exc=None):
rv = _app_ctx_stack.pop()
assert rv is self, 'Popped wrong app context. (%r instead of %r)' \
% (rv, self)
+ appcontext_popped.send(self.app)
def __enter__(self):
self.push()
View
2  flask/signals.py
@@ -50,4 +50,6 @@ def _fail(self, *args, **kwargs):
request_tearing_down = _signals.signal('request-tearing-down')
got_request_exception = _signals.signal('got-request-exception')
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')
View
24 flask/testsuite/signals.py
@@ -96,6 +96,30 @@ def record(sender, exception):
finally:
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):
app = flask.Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
Please sign in to comment.
Something went wrong with that request. Please try again.