From f1918093ac70d589a4d67af0d77140734c06c13d Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 30 May 2013 18:15:17 +0100 Subject: [PATCH] Changed teardown error handling to be more reliable. --- CHANGES | 3 +++ flask/app.py | 20 +++++++++++++++++++- flask/ctx.py | 13 ++++++++----- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index fbde1e2a..17290290 100644 --- a/CHANGES +++ b/CHANGES @@ -59,6 +59,9 @@ Release date to be decided. strongly discouraged as the interface was flawed. - Python requirements changed: requiring Python 2.6 or 2.7 now to prepare 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 ----------- diff --git a/flask/app.py b/flask/app.py index bfd615b7..28a0a59a 100644 --- a/flask/app.py +++ b/flask/app.py @@ -1510,6 +1510,16 @@ class Flask(_PackageBoundObject): rv.allow.update(methods) 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): """Converts the return value from a view function to a real response object that is an instance of :attr:`response_class`. @@ -1790,12 +1800,20 @@ class Flask(_PackageBoundObject): a list of headers and an optional exception context to start the response """ - with self.request_context(environ): + ctx = self.request_context(environ) + ctx.push() + error = None + try: try: response = self.full_dispatch_request() except Exception as e: + error = e response = self.make_response(self.handle_exception(e)) return response(environ, start_response) + finally: + if self.should_ignore_error(error): + error = None + ctx.auto_pop(error) @property def modules(self): diff --git a/flask/ctx.py b/flask/ctx.py index 259c5e2f..5e1ee2e3 100644 --- a/flask/ctx.py +++ b/flask/ctx.py @@ -352,6 +352,13 @@ class RequestContext(object): if app_ctx is not None: 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): self.push() return self @@ -362,11 +369,7 @@ class RequestContext(object): # access the request object in the interactive shell. Furthermore # the context can be force kept alive for the test client. # See flask.testing for how this works. - if self.request.environ.get('flask._preserve_context') or \ - (tb is not None and self.app.preserve_context_on_exception): - self.preserved = True - else: - self.pop(exc_value) + self.auto_pop(exc_value) def __repr__(self): return '<%s \'%s\' [%s] of %s>' % (