Browse Source

Changed teardown error handling to be more reliable.

pull/753/merge
Armin Ronacher 11 years ago
parent
commit
f1918093ac
  1. 3
      CHANGES
  2. 20
      flask/app.py
  3. 13
      flask/ctx.py

3
CHANGES

@ -59,6 +59,9 @@ Release date to be decided.
strongly discouraged as the interface was flawed. strongly discouraged as the interface was flawed.
- Python requirements changed: requiring Python 2.6 or 2.7 now to prepare - Python requirements changed: requiring Python 2.6 or 2.7 now to prepare
for Python 3.3 port. for Python 3.3 port.
- Changed how the teardown system is informed about exceptions. This is now
more reliable in case something handles an exception halfway through
the error handling process.
Version 0.9 Version 0.9
----------- -----------

20
flask/app.py

@ -1510,6 +1510,16 @@ class Flask(_PackageBoundObject):
rv.allow.update(methods) rv.allow.update(methods)
return rv return rv
def should_ignore_error(self, error):
"""This is called to figure out if an error should be ignored
or not as far as the teardown system is concerned. If this
function returns `True` then the teardown handlers will not be
passed the error.
.. versionadded:: 0.10
"""
return False
def make_response(self, rv): def make_response(self, rv):
"""Converts the return value from a view function to a real """Converts the return value from a view function to a real
response object that is an instance of :attr:`response_class`. response object that is an instance of :attr:`response_class`.
@ -1790,12 +1800,20 @@ class Flask(_PackageBoundObject):
a list of headers and an optional a list of headers and an optional
exception context to start the response exception context to start the response
""" """
with self.request_context(environ): ctx = self.request_context(environ)
ctx.push()
error = None
try:
try: try:
response = self.full_dispatch_request() response = self.full_dispatch_request()
except Exception as e: except Exception as e:
error = e
response = self.make_response(self.handle_exception(e)) response = self.make_response(self.handle_exception(e))
return response(environ, start_response) return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)
@property @property
def modules(self): def modules(self):

13
flask/ctx.py

@ -352,6 +352,13 @@ class RequestContext(object):
if app_ctx is not None: if app_ctx is not None:
app_ctx.pop(exc) app_ctx.pop(exc)
def auto_pop(self, exc):
if self.request.environ.get('flask._preserve_context') or \
(exc is not None and self.app.preserve_context_on_exception):
self.preserved = True
else:
self.pop(exc)
def __enter__(self): def __enter__(self):
self.push() self.push()
return self return self
@ -362,11 +369,7 @@ class RequestContext(object):
# access the request object in the interactive shell. Furthermore # access the request object in the interactive shell. Furthermore
# the context can be force kept alive for the test client. # the context can be force kept alive for the test client.
# See flask.testing for how this works. # See flask.testing for how this works.
if self.request.environ.get('flask._preserve_context') or \ self.auto_pop(exc_value)
(tb is not None and self.app.preserve_context_on_exception):
self.preserved = True
else:
self.pop(exc_value)
def __repr__(self): def __repr__(self):
return '<%s \'%s\' [%s] of %s>' % ( return '<%s \'%s\' [%s] of %s>' % (

Loading…
Cancel
Save