summaryrefslogtreecommitdiff
path: root/paste/exceptions
diff options
context:
space:
mode:
authorianb <devnull@localhost>2006-10-03 22:39:44 +0000
committerianb <devnull@localhost>2006-10-03 22:39:44 +0000
commita2431a14e59e8581b1e30cf45ca89743d8c33aeb (patch)
tree50805b64a82b5032bd859e6f399c959e0517bcad /paste/exceptions
parent4ff3dbeb002b5683383b3fd252493356585db50e (diff)
downloadpaste-a2431a14e59e8581b1e30cf45ca89743d8c33aeb.tar.gz
Fixed problem where the errorcatching middleware doesn't expose the close method of the app_iter that it is wrapping
Diffstat (limited to 'paste/exceptions')
-rw-r--r--paste/exceptions/errormiddleware.py91
1 files changed, 67 insertions, 24 deletions
diff --git a/paste/exceptions/errormiddleware.py b/paste/exceptions/errormiddleware.py
index 2c59459..da12701 100644
--- a/paste/exceptions/errormiddleware.py
+++ b/paste/exceptions/errormiddleware.py
@@ -138,7 +138,7 @@ class ErrorMiddleware(object):
try:
__traceback_supplement__ = Supplement, self, environ
app_iter = self.application(environ, detect_start_response)
- return self.catching_iter(app_iter, environ)
+ return self.make_catching_iter(app_iter, environ)
except:
exc_info = sys.exc_info()
try:
@@ -158,29 +158,11 @@ class ErrorMiddleware(object):
# clean up locals...
exc_info = None
- def catching_iter(self, app_iter, environ):
- __traceback_supplement__ = Supplement, self, environ
- if not app_iter:
- raise StopIteration
- error_on_close = False
- try:
- for v in app_iter:
- yield v
- if hasattr(app_iter, 'close'):
- error_on_close = True
- app_iter.close()
- except:
- response = self.exception_handler(sys.exc_info(), environ)
- if not error_on_close and hasattr(app_iter, 'close'):
- try:
- app_iter.close()
- except:
- close_response = self.exception_handler(
- sys.exc_info(), environ)
- response += (
- '<hr noshade>Error in .close():<br>%s'
- % close_response)
- yield response
+ def make_catching_iter(self, app_iter, environ):
+ if isinstance(app_iter, (list, tuple)):
+ # These don't raise
+ return app_iter
+ return CatchingIter(app_iter, environ, self)
def exception_handler(self, exc_info, environ):
simple_html_error = False
@@ -201,6 +183,67 @@ class ErrorMiddleware(object):
error_message=self.error_message,
simple_html_error=simple_html_error)
+class CatchingIter(object):
+
+ """
+ A wrapper around the application iterator that will catch
+ exceptions raised by the a generator, or by the close method, and
+ display or report as necessary.
+ """
+
+ def __init__(self, app_iter, environ, error_middleware):
+ self.app_iterable = app_iter
+ self.app_iterator = iter(app_iter)
+ self.environ = environ
+ self.error_middleware = error_middleware
+ self.closed = False
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ __traceback_supplement__ = (
+ Supplement, self.error_middleware, self.environ)
+ if self.closed:
+ raise StopIteration
+ try:
+ return self.app_iterator.next()
+ except StopIteration:
+ self.closed = True
+ close_response = self._close()
+ if close_response is not None:
+ return close_response
+ else:
+ raise StopIteration
+ except:
+ self.closed = True
+ close_response = self._close()
+ response = self.error_middleware.exception_handler(
+ sys.exc_info(), self.environ)
+ if close_response is not None:
+ response += (
+ '<hr noshade>Error in .close():<br>%s'
+ % close_response)
+ return response
+
+ def close(self):
+ # This should at least print something to stderr if the
+ # close method fails at this point
+ self._close()
+
+ def _close(self):
+ """Close and return any error message"""
+ if not hasattr(self.app_iterable, 'close'):
+ return None
+ try:
+ self.app_iterable.close()
+ return None
+ except:
+ close_response = self.error_middleware.exception_handler(
+ sys.exc_info(), self.environ)
+ return close_response
+
+
class Supplement(object):
"""