Ricardo Kirkner has proposed merging 
lp:~ricardokirkner/python-oops-wsgi/close-iterable into lp:python-oops-wsgi.

Commit message:
fix generator_tracker to behave properly according to WSGI standard

according to 
http://blog.dscpl.com.au/2012/10/obligations-for-calling-close-on.html
any iterable returned by a WSGI application needs to have .close() called on it

Since django 1.5 this causes connections to be left open as "IDLE in 
transaction"
when the iterator is not closed

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~ricardokirkner/python-oops-wsgi/close-iterable/+merge/165192
-- 
https://code.launchpad.net/~ricardokirkner/python-oops-wsgi/close-iterable/+merge/165192
Your team Launchpad code reviewers is requested to review the proposed merge of 
lp:~ricardokirkner/python-oops-wsgi/close-iterable into lp:python-oops-wsgi.
=== modified file 'oops_wsgi/middleware.py'
--- oops_wsgi/middleware.py	2012-01-25 02:29:32 +0000
+++ oops_wsgi/middleware.py	2013-05-22 16:03:30 +0000
@@ -87,7 +87,7 @@
         the key determines the name given in the OOPS context. If None is passed
         the default_map_environ is used. Pass {} in to entirely disable mapping.
     :param tracker: A factory function to create a tracker. Trackers are used
-        to allow variations on the WSGI environment to still use oops_wsgi. 
+        to allow variations on the WSGI environment to still use oops_wsgi.
         See generator_tracker for the reference tracker used in regular WSGI
         environments. generator_tracker is used by default or when
         tracker=None.
@@ -250,3 +250,6 @@
     except Exception:
         exc_info = sys.exc_info()
         yield on_error(exc_info)
+    finally:
+        if hasattr(app_body, 'close'):
+            app_body.close()

=== modified file 'oops_wsgi/tests/test_middleware.py'
--- oops_wsgi/tests/test_middleware.py	2012-01-25 03:00:02 +0000
+++ oops_wsgi/tests/test_middleware.py	2013-05-22 16:03:30 +0000
@@ -630,3 +630,14 @@
         self.assertThat(lambda:tracker.next(), raises(ValueError('fail')))
         self.assertEqual(['on exception foo'], self.calls)
 
+    def test_closes_iterator(self):
+        class mock_iterator(list):
+            def close(self):
+                self.close_called = True
+
+        mock_app_body = mock_iterator()
+        tracker = generator_tracker(
+            self.on_first_bytes, self.on_finish, None, mock_app_body)
+        for result in tracker:
+            pass
+        self.assertTrue(mock_app_body.close_called)

_______________________________________________
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp

Reply via email to