I think the only way to do this would be to remove error handling from the CP core completely, and move it to WSGI middleware. Anyone want to take a crack at it? Or is there one somewhere else we should use (e.g. Paste)?
Paste has paste.errormiddleware, which is what I was trying to use when I discovered this issue.
Does the wsgi pep discuss what should be done with exceptions in the application?
"In general, applications should try to trap their own, internal errors, and display a helpful message in the browser. (It is up to the application to decide what "helpful" means in this context.)"
That's the approach I followed in _cpwsgi. If followed strictly, the only errors that paste should receive and handle would be errors in paste itself, or in WSGI middleware between CP and paste (but not between paste and the server). In other words, sticking paste.errormiddleware between _cpwsgi and _cpwsgiserver doesn't buy you anything unless you have other middleware.
Well, in WSGI, the middleware is also defined as the "application", isn't it? :-)
I think you could make a case either way, but for maximum utility and ease of set up, CP should have a way to let exceptions escape itself so that something like paste.errormiddleware could handle them.
How about a global config option that allows that? Put the check in the except clause of handleError and if set, just re raise the exception? You'd still have to raise the exception in _cpOnError though unless this setting also affected that.
Personally I disagree with the PEP here, though since it's just a suggestion in the PEP it doesn't matter too much.
If the Paste error middleware is installed, the WSGI environment will have a "paste.throw_errors" key in it (that will be true). This should signal that there is an error handler already installed, and ''unexpected'' exceptions should not be caught. (Expected exceptions can always be caught, of course, like a redirect exception.) I also use this in tests, where I want the exception to go up to the test runner.
So, a special case for that key, that re-raises the exception, would do it. I would like this to actually be a "wsgi.throw_errors" key, i.e., a standard way of saying that unexpected errors shouldn't be caught. I've brought it up on Web-SIG -- there weren't any objections, but also no interest. If CherryPy people want to bring it up too, we could probably make this generally standard.
For exceptions, there's a little-known property of "raise", that you can pass it three arguments, that are the values that sys.exc_info() returns. This preserves the traceback. This might be useful during implementation.
The current dilemma with this: you have to tell both the CherryPy request (_cphttptools) and the wsgi interface (_cpwsgi) that you want to re-raise trapped errors. The first should probably inspect a CP config entry, but the second should respect a "wsgi.throw_errors" entry. However, requiring both seems a bit cumbersome.