As per http://webpy.org/cookbook/testing_with_paste_and_nose I've been
working with TestApp to test my web.py application. However, there's a
problem with the way web.py handles errors, demonstrated by the
following trivial script:

------------------------------------------------------------------------------
import unittest
from web import application
from paste.fixture import TestApp

urls = ("/", "thing")
app = application(urls, globals())
class thing:
     def GET(self):
         raise Exception("something went wrong")

class TestWebUI(unittest.TestCase):
    def setUp(self):
        middleware = []
        self.client = TestApp(app.wsgifunc(*middleware))

    def test_index(self):
        r = self.client.get('/')

if __name__ == "__main__":
    unittest.main()
------------------------------------------------------------------------------

TestApp doesn't like it if anything is printed to the error stream
(according to Ian Bicking, who would know :)). You get an exception
that looks like this:

------------------------------------------------------------------------------
$ python ~/Scratch/demo_webpy_traceback_problem.py
F
======================================================================
FAIL: test_index (__main__.TestWebUI)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/aquarius/Scratch/demo_webpy_traceback_problem.py", line
17, in test_index
    r = self.client.get('/')
  File "/usr/lib/pymodules/python2.6/paste/fixture.py", line 208, in
get
    return self.do_request(req, status=status)
  File "/usr/lib/pymodules/python2.6/paste/fixture.py", line 389, in
do_request
    **req.environ)
  File "/usr/lib/pymodules/python2.6/paste/wsgilib.py", line 343, in
raw_interactive
    app_iter = application(basic_environ, start_response)
  File "/usr/lib/pymodules/python2.6/paste/lint.py", line 170, in
lint_app
    iterator = application(environ, start_response_wrapper)
  File "/home/aquarius/Programs/Mine/myapp/trunk/lib/web/
application.py", line 282, in wsgi
    result = self.handle_with_processors()
  File "/home/aquarius/Programs/Mine/myapp/trunk/lib/web/
application.py", line 252, in handle_with_processors
    return process(self.processors)
  File "/home/aquarius/Programs/Mine/myapp/trunk/lib/web/
application.py", line 248, in process
    print >> web.debug, traceback.format_exc()
  File "/home/aquarius/Programs/Mine/myapp/trunk/lib/web/webapi.py",
line 339, in _debugwrite
    out.write(x)
  File "/usr/lib/pymodules/python2.6/paste/lint.py", line 221, in
write
    self.errors.write(s)
  File "/usr/lib/pymodules/python2.6/paste/wsgilib.py", line 375, in
write
    "No errors should be written (got: %r)" % value)
AssertionError: No errors should be written (got: 'Traceback (most
recent call last):\n  File "/home/aquarius/Programs/Mine/myapp/trunk/
lib/web/application.py", line 240, in process\n    return p(lambda:
process(processors))\n  File "/home/aquarius/Programs/Mine/myapp/trunk/
lib/web/application.py", line 561, in processor\n    return handler()
\n  File "/home/aquarius/Programs/Mine/myapp/trunk/lib/web/
application.py", line 240, in <lambda>\n    return p(lambda:
process(processors))\n  File "/home/aquarius/Programs/Mine/myapp/trunk/
lib/web/application.py", line 248, in process\n    print >> web.debug,
traceback.format_exc()\n  File "/home/aquarius/Programs/Mine/myapp/
trunk/lib/web/webapi.py", line 339, in _debugwrite\n    out.write(x)
\n  File "/usr/lib/pymodules/python2.6/paste/lint.py", line 221, in
write\n    self.errors.write(s)\n  File "/usr/lib/pymodules/python2.6/
paste/wsgilib.py", line 375, in write\n    "No errors should be
written (got: %r)" % value)\nAssertionError: No errors should be
written (got: \'Traceback (most recent call last):\\n  File "/home/
aquarius/Programs/Mine/myapp/trunk/lib/web/application.py", line 240,
in process\\n    return p(lambda: process(processors))\\n  File "/home/
aquarius/Programs/Mine/myapp/trunk/lib/web/application.py", line 576,
in processor\\n    result = handler()\\n  File "/home/aquarius/
Programs/Mine/myapp/trunk/lib/web/application.py", line 240, in
<lambda>\\n    return p(lambda: process(processors))\\n  File "/home/
aquarius/Programs/Mine/myapp/trunk/lib/web/application.py", line 248,
in process\\n    print >> web.debug, traceback.format_exc()\\n  File "/
home/aquarius/Programs/Mine/myapp/trunk/lib/web/webapi.py", line 339,
in _debugwrite\\n    out.write(x)\\n  File "/usr/lib/pymodules/
python2.6/paste/lint.py", line 221, in write\\n    self.errors.write(s)
\\n  File "/usr/lib/pymodules/python2.6/paste/wsgilib.py", line 375,
in write\\n    "No errors should be written (got: %r)" % value)\
\nAssertionError: No errors should be written (got: \\\'Traceback
(most recent call last):\\\\n  File "/home/aquarius/Programs/Mine/
myapp/trunk/lib/web/application.py", line 240, in process\\\\n
return p(lambda: process(processors))\\\\n  File "/home/aquarius/
Programs/Mine/myapp/trunk/lib/web/application.py", line 561, in
processor\\\\n    return handler()\\\\n  File "/home/aquarius/Programs/
Mine/myapp/trunk/lib/web/application.py", line 240, in <lambda>\\\
\n    return p(lambda: process(processors))\\\\n  File "/home/aquarius/
Programs/Mine/myapp/trunk/lib/web/application.py", line 248, in process
\\\\n    print >> web.debug, traceback.format_exc()\\\\n  File "/home/
aquarius/Programs/Mine/myapp/trunk/lib/web/webapi.py", line 339, in
_debugwrite\\\\n    out.write(x)\\\\n  File "/usr/lib/pymodules/
python2.6/paste/lint.py", line 221, in write\\\\n
self.errors.write(s)\\\\n  File "/usr/lib/pymodules/python2.6/paste/
wsgilib.py", line 375, in write\\\\n    "No errors should be written
(got: %r)" % value)\\\\nAssertionError: No errors should be written
(got: \\\\\\\'Traceback (most recent call last):\\\\\\\\n  File "/home/
aquarius/Programs/Mine/myapp/trunk/lib/web/application.py", line 240,
in process\\\\\\\\n    return p(lambda: process(processors))\\\\\\\\n
File "/home/aquarius/Programs/Mine/myapp/trunk/lib/web/
application.py", line 561, in processor\\\\\\\\n    return handler()\\\
\\\\\n  File "/home/aquarius/Programs/Mine/myapp/trunk/lib/web/
application.py", line 240, in <lambda>\\\\\\\\n    return p(lambda:
process(processors))\\\\\\\\n  File "/home/aquarius/Programs/Mine/
myapp/trunk/lib/web/application.py", line 248, in process\\\\\\\\n
print >> web.debug, traceback.format_exc()\\\\\\\\n  File "/home/
aquarius/Programs/Mine/myapp/trunk/lib/web/webapi.py", line 339, in
_debugwrite\\\\\\\\n    out.write(x)\\\\\\\\n  File "/usr/lib/
pymodules/python2.6/paste/lint.py", line 221, in write\\\\\\\\n
self.errors.write(s)\\\\\\\\n  File "/usr/lib/pymodules/python2.6/
paste/wsgilib.py", line 375, in write\\\\\\\\n    "No errors should be
written (got: %r)" % value)\\\\\\\\nAssertionError: No errors should
be written (got: \\\\\\\\\\\\\\\'Traceback (most recent call last):\\\\
\\\\\\\\\\\\n  File "/home/aquarius/Programs/Mine/myapp/trunk/lib/web/
application.py", line 242, in process\\\\\\\\\\\\\\\\n    return
self.handle()\\\\\\\\\\\\\\\\n  File "/home/aquarius/Programs/Mine/
myapp/trunk/lib/web/application.py", line 233, in handle\\\\\\\\\\\\\\\
\n    return self._delegate(fn, self.fvars, args)\\\\\\\\\\\\\\\\n
File "/home/aquarius/Programs/Mine/myapp/trunk/lib/web/
application.py", line 415, in _delegate\\\\\\\\\\\\\\\\n    return
handle_class(cls)\\\\\\\\\\\\\\\\n  File "/home/aquarius/Programs/Mine/
myapp/trunk/lib/web/application.py", line 390, in handle_class\\\\\\\\\
\\\\\\\n    return tocall(*args)\\\\\\\\\\\\\\\\n  File "/home/
aquarius/Scratch/demo_webpy_traceback_problem.py", line 9, in GET\\\\\\
\\\\\\\\\\n    raise Exception("something went wrong")\\\\\\\\\\\\\\\
\nException: something went wrong\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\')\\\\
\\\\n\\\\\\\')\\\\n\\\')\\n\')\n')

----------------------------------------------------------------------
Ran 1 test in 0.015s

FAILED (failures=1)
------------------------------------------------------------------------------

which is obviously horrid. paste.fixture sets a value in the
environment so you can know whether to handle errors yourself or pass
them up to the paste testing infrastructure. The below patch against
git HEAD implements a check for this, so that any errors caused don't
make paste mangle the exceptions.

------------------------------------------------------------------------------
diff --git a/web/application.py b/web/application.py
index 4104fe7..d1d3af4 100755
--- a/web/application.py
+++ b/web/application.py
@@ -245,8 +245,11 @@ class application:
             except (KeyboardInterrupt, SystemExit):
                 raise
             except:
-                print >> web.debug, traceback.format_exc()
-                raise self.internalerror()
+                if web.ctx.env.get("paste.throw_errors", False):
+                    raise
+                else:
+                    print >> web.debug, traceback.format_exc()
+                    raise self.internalerror()

         # processors must be applied in the resvere order. (??)
         return process(self.processors)

------------------------------------------------------------------------------


Cheers,

sil

-- 
You received this message because you are subscribed to the Google Groups 
"web.py" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/webpy?hl=en.

Reply via email to