Code review comment for lp:~lifeless/python-oops-wsgi/extraction

Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Generally good, but a few notes:

=== modified file 'oops_wsgi/middleware.py'
--- oops_wsgi/middleware.py 2011-08-18 00:45:58 +0000
+++ oops_wsgi/middleware.py 2011-08-22 07:04:24 +0000
@@ -85,8 +85,23 @@
                 state['write'] = start_response(status, headers)
                 write = state['write']
             write(bytes)
- def oops_start_response(status, headers):
- state['response'] = (status, headers)
+ def oops_start_response(status, headers, exc_info=None):
+ if exc_info is not None:
+ # The app is explicitly signalling an error (rather than
+ # returning a page describing the error). Capture that and then
+ # forward to the containing element verbatim. In future we might
+ # choose to add the OOPS id to the headers (but we can't fiddle
+ # the body as it is being generated by the contained app.
+ report = config.create(
+ dict(exc_info=exc_info, url=construct_url(environ)))

Careful! You seem to be indenting by 8 instead of 4.

+ ids = config.publish(report)
+ try:
+ state['write'] = start_response(status, headers, exc_info)
+ return state['write']
+ finally:
+ del exc_info

Out of interest, whence the del?

=== modified file 'oops_wsgi/tests/test_middleware.py'
--- oops_wsgi/tests/test_middleware.py 2011-08-18 22:44:58 +0000
+++ oops_wsgi/tests/test_middleware.py 2011-08-22 07:04:24 +0000

@@ -52,7 +53,21 @@
         environ['HTTP_HOST'] = 'example.com'
         environ['PATH_INFO'] = '/demo'
         environ['QUERY_STRING'] = 'param=value'
- def start_response(status, headers):
+ def start_response(status, headers, exc_info=None):
+ if exc_info:
+ # If an exception is raised after we have written (via the app
+ # calling our oops_write) or after we have yielded data, we
+ # must supply exc_info in the call to start_response, per the
+ # wsgi spec. The easiest way to do that is to always supply
+ # exc_info when reporting an exception - that will DTRT if
+ # start_response upstream had already written data. Thus
+ # our test start_response which lives above the oops middleware
+ # captures the fact exc_info was called and all our tests that
+ # expect oopses raised expect the exc_info to be present.
+ self.calls.append(
+ ('start error', status, headers, exc_info[0],
+ exc_info[1].args))

Here too, indentation goes too far. You're not getting tabs, are you?

@@ -191,7 +206,8 @@
              'url': 'http://example.com/demo?param=value',
              'value': u'boom, yo'},
             # Then the middleware responses
- ('500 Internal Server Error', [('Content-Type', 'text/html')]),
+ ('start error', '500 Internal Server Error',
+ [('Content-Type', 'text/html')], ValueError, ('boom, yo',)),

Horrid layout. Your branch didn't start it, so I won't insist that you fix it. But take my review with a grain of salt since I can't really make sense of this in reasonable time.

@@ -250,3 +268,20 @@
         self.wrap_and_run(inner, config)
         self.assertEqual('http://example.com/demo?param=value',
                 self.calls[0]['url'])
+
+ def test_start_response_with_just_exc_info_generates_oops(self):
+ def inner(environ, start_response):
+ try:
+ raise ValueError('boom, yo')
+ except ValueError:
+ exc_info = sys.exc_info()
+ start_response('500 FAIL', [], exc_info)
+ yield 'body'
+ config = self.config_for_oopsing()
+ self.wrap_and_run(inner, config)
+ self.assertEqual([{'id': 1,
+ 'type': 'ValueError',
+ 'url': 'http://example.com/demo?param=value',
+ 'value': u'boom, yo'},
+ ('start error', '500 FAIL', [], ValueError, ('boom, yo',))],
+ self.calls)

In this case though, please do fix the layout! So far the best solution I've found is to move the expected dict into a variable. Not great, but better than any of the alternatives I'm aware of.

Jeroen

review: Approve

« Back to merge proposal