Skip to content

Commit f191809

Browse files
committed
Changed teardown error handling to be more reliable.
1 parent 90e3906 commit f191809

File tree

3 files changed

+30
-6
lines changed

3 files changed

+30
-6
lines changed

CHANGES

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ Release date to be decided.
5959
strongly discouraged as the interface was flawed.
6060
- Python requirements changed: requiring Python 2.6 or 2.7 now to prepare
6161
for Python 3.3 port.
62+
- Changed how the teardown system is informed about exceptions. This is now
63+
more reliable in case something handles an exception halfway through
64+
the error handling process.
6265

6366
Version 0.9
6467
-----------

flask/app.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1510,6 +1510,16 @@ def make_default_options_response(self):
15101510
rv.allow.update(methods)
15111511
return rv
15121512

1513+
def should_ignore_error(self, error):
1514+
"""This is called to figure out if an error should be ignored
1515+
or not as far as the teardown system is concerned. If this
1516+
function returns `True` then the teardown handlers will not be
1517+
passed the error.
1518+
1519+
.. versionadded:: 0.10
1520+
"""
1521+
return False
1522+
15131523
def make_response(self, rv):
15141524
"""Converts the return value from a view function to a real
15151525
response object that is an instance of :attr:`response_class`.
@@ -1790,12 +1800,20 @@ def wsgi_app(self, environ, start_response):
17901800
a list of headers and an optional
17911801
exception context to start the response
17921802
"""
1793-
with self.request_context(environ):
1803+
ctx = self.request_context(environ)
1804+
ctx.push()
1805+
error = None
1806+
try:
17941807
try:
17951808
response = self.full_dispatch_request()
17961809
except Exception as e:
1810+
error = e
17971811
response = self.make_response(self.handle_exception(e))
17981812
return response(environ, start_response)
1813+
finally:
1814+
if self.should_ignore_error(error):
1815+
error = None
1816+
ctx.auto_pop(error)
17991817

18001818
@property
18011819
def modules(self):

flask/ctx.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,13 @@ def pop(self, exc=None):
352352
if app_ctx is not None:
353353
app_ctx.pop(exc)
354354

355+
def auto_pop(self, exc):
356+
if self.request.environ.get('flask._preserve_context') or \
357+
(exc is not None and self.app.preserve_context_on_exception):
358+
self.preserved = True
359+
else:
360+
self.pop(exc)
361+
355362
def __enter__(self):
356363
self.push()
357364
return self
@@ -362,11 +369,7 @@ def __exit__(self, exc_type, exc_value, tb):
362369
# access the request object in the interactive shell. Furthermore
363370
# the context can be force kept alive for the test client.
364371
# See flask.testing for how this works.
365-
if self.request.environ.get('flask._preserve_context') or \
366-
(tb is not None and self.app.preserve_context_on_exception):
367-
self.preserved = True
368-
else:
369-
self.pop(exc_value)
372+
self.auto_pop(exc_value)
370373

371374
def __repr__(self):
372375
return '<%s \'%s\' [%s] of %s>' % (

0 commit comments

Comments
 (0)