Browse Source

Merge branch 'mjpieters-appcontext_ignore_handled_exception'

pull/1367/merge
Markus Unterwaditzer 10 years ago
parent
commit
33bad011c3
  1. 1
      AUTHORS
  2. 2
      CHANGES
  3. 11
      flask/app.py
  4. 12
      flask/ctx.py
  5. 15
      tests/test_appctx.py
  6. 15
      tests/test_reqctx.py

1
AUTHORS

@ -22,6 +22,7 @@ Patches and Suggestions
- Kenneth Reitz - Kenneth Reitz
- Keyan Pishdadian - Keyan Pishdadian
- Marian Sigler - Marian Sigler
- Martijn Pieters
- Matt Campell - Matt Campell
- Matthew Frazier - Matthew Frazier
- Michael van Tellingen - Michael van Tellingen

2
CHANGES

@ -63,6 +63,8 @@ Version 1.0
``options`` (issue ``#1288``). ``options`` (issue ``#1288``).
- ``flask.json.jsonify`` now supports the ``datetime.date`` type (pull request - ``flask.json.jsonify`` now supports the ``datetime.date`` type (pull request
``#1326``). ``#1326``).
- Don't leak exception info of already catched exceptions to context teardown
handlers (pull request ``#1393``).
Version 0.10.2 Version 0.10.2
-------------- --------------

11
flask/app.py

@ -38,6 +38,9 @@ from ._compat import reraise, string_types, text_type, integer_types
# a lock used for logger initialization # a lock used for logger initialization
_logger_lock = Lock() _logger_lock = Lock()
# a singleton sentinel value for parameter defaults
_sentinel = object()
def _make_timedelta(value): def _make_timedelta(value):
if not isinstance(value, timedelta): if not isinstance(value, timedelta):
@ -1774,7 +1777,7 @@ class Flask(_PackageBoundObject):
self.save_session(ctx.session, response) self.save_session(ctx.session, response)
return response return response
def do_teardown_request(self, exc=None): def do_teardown_request(self, exc=_sentinel):
"""Called after the actual request dispatching and will """Called after the actual request dispatching and will
call every as :meth:`teardown_request` decorated function. This is call every as :meth:`teardown_request` decorated function. This is
not actually called by the :class:`Flask` object itself but is always not actually called by the :class:`Flask` object itself but is always
@ -1785,7 +1788,7 @@ class Flask(_PackageBoundObject):
Added the `exc` argument. Previously this was always using the Added the `exc` argument. Previously this was always using the
current exception information. current exception information.
""" """
if exc is None: 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.get(None, ()))
bp = _request_ctx_stack.top.request.blueprint bp = _request_ctx_stack.top.request.blueprint
@ -1795,14 +1798,14 @@ class Flask(_PackageBoundObject):
func(exc) func(exc)
request_tearing_down.send(self, exc=exc) request_tearing_down.send(self, exc=exc)
def do_teardown_appcontext(self, exc=None): def do_teardown_appcontext(self, exc=_sentinel):
"""Called when an application context is popped. This works pretty """Called when an application context is popped. This works pretty
much the same as :meth:`do_teardown_request` but for the application much the same as :meth:`do_teardown_request` but for the application
context. context.
.. versionadded:: 0.9 .. versionadded:: 0.9
""" """
if exc is None: if exc is _sentinel:
exc = sys.exc_info()[1] exc = sys.exc_info()[1]
for func in reversed(self.teardown_appcontext_funcs): for func in reversed(self.teardown_appcontext_funcs):
func(exc) func(exc)

12
flask/ctx.py

@ -21,6 +21,10 @@ from .signals import appcontext_pushed, appcontext_popped
from ._compat import BROKEN_PYPY_CTXMGR_EXIT, reraise from ._compat import BROKEN_PYPY_CTXMGR_EXIT, reraise
# a singleton sentinel value for parameter defaults
_sentinel = object()
class _AppCtxGlobals(object): class _AppCtxGlobals(object):
"""A plain object.""" """A plain object."""
@ -168,11 +172,11 @@ class AppContext(object):
_app_ctx_stack.push(self) _app_ctx_stack.push(self)
appcontext_pushed.send(self.app) appcontext_pushed.send(self.app)
def pop(self, exc=None): def pop(self, exc=_sentinel):
"""Pops the app context.""" """Pops the app context."""
self._refcnt -= 1 self._refcnt -= 1
if self._refcnt <= 0: if self._refcnt <= 0:
if exc is None: if exc is _sentinel:
exc = sys.exc_info()[1] exc = sys.exc_info()[1]
self.app.do_teardown_appcontext(exc) self.app.do_teardown_appcontext(exc)
rv = _app_ctx_stack.pop() rv = _app_ctx_stack.pop()
@ -320,7 +324,7 @@ class RequestContext(object):
if self.session is None: if self.session is None:
self.session = self.app.make_null_session() self.session = self.app.make_null_session()
def pop(self, exc=None): def pop(self, exc=_sentinel):
"""Pops the request context and unbinds it by doing that. This will """Pops the request context and unbinds it by doing that. This will
also trigger the execution of functions registered by the also trigger the execution of functions registered by the
:meth:`~flask.Flask.teardown_request` decorator. :meth:`~flask.Flask.teardown_request` decorator.
@ -334,7 +338,7 @@ class RequestContext(object):
if not self._implicit_app_ctx_stack: if not self._implicit_app_ctx_stack:
self.preserved = False self.preserved = False
self._preserved_exc = None self._preserved_exc = None
if exc is None: if exc is _sentinel:
exc = sys.exc_info()[1] exc = sys.exc_info()[1]
self.app.do_teardown_request(exc) self.app.do_teardown_request(exc)

15
tests/test_appctx.py

@ -78,6 +78,21 @@ def test_app_tearing_down_with_previous_exception():
assert cleanup_stuff == [None] assert cleanup_stuff == [None]
def test_app_tearing_down_with_handled_exception():
cleanup_stuff = []
app = flask.Flask(__name__)
@app.teardown_appcontext
def cleanup(exception):
cleanup_stuff.append(exception)
with app.app_context():
try:
raise Exception('dummy')
except Exception:
pass
assert cleanup_stuff == [None]
def test_custom_app_ctx_globals_class(): def test_custom_app_ctx_globals_class():
class CustomRequestGlobals(object): class CustomRequestGlobals(object):
def __init__(self): def __init__(self):

15
tests/test_reqctx.py

@ -48,6 +48,21 @@ def test_teardown_with_previous_exception():
assert buffer == [] assert buffer == []
assert buffer == [None] assert buffer == [None]
def test_teardown_with_handled_exception():
buffer = []
app = flask.Flask(__name__)
@app.teardown_request
def end_of_request(exception):
buffer.append(exception)
with app.test_request_context():
assert buffer == []
try:
raise Exception('dummy')
except Exception:
pass
assert buffer == [None]
def test_proper_test_request_context(): def test_proper_test_request_context():
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.config.update( app.config.update(

Loading…
Cancel
Save