[Zope-dev] Zope 2: ZPublisher exception handling

yuppie y.2010 at wcm-solutions.de
Mon Apr 12 05:33:37 EDT 2010


Hi!


Summary:
========

In Zope 2.10 'raise_standardErrorMessage', 'zpublisher_exception_hook' 
and therefore 'Publish.publish' did always (re-)raise errors after 
rendering. That made sure 'HTTPResponse.exception' was called and 
CookieCrumbler was able to hook into 'HTTPResponse._unauthorized'.

I'm now trying to figure out how this bug could be fixed:
https://bugs.launchpad.net/zope-cmf/+bug/558340


Some details:
=============

In Zope 2.10 and earlier the code did (re-)raise errors this way:

     raise error_type, error_value, traceback

'error_type' is the original error class, 'error_value' the rendered 
error message. Python creates a new error instance, basically trying to 
do this:

     error_instance = error_type(error_value)

That doesn't work if the error class constructor requires more than one 
argument.


This was the first change that broke the old behavior:
http://svn.zope.org/?view=rev&rev=77459

The comment in Zope2/App/startup.py is interesting because it says 
"raise the rendered value" while the code actually *returns* it:

     # Lookup a view for the exception and render it, then
     # raise the rendered value as the exception value
     # (basically the same that 'raise_standardErrorMessage'
     # does.

I guess the checkin message for http://svn.zope.org/?view=rev&rev=92767 
explains why:

"Rather nasty fix to work around Zope 3 exceptions that have more than 
one positional argument on the constructor."

The old machinery doesn't work with ZTK exceptions like 
zope.publisher.interfaces.NotFound because they take additional 
arguments and have are more complex __str__ method.


There is an inconsistency in revision 92767 (
http://svn.zope.org/Zope/trunk/lib/python/OFS/SimpleItem.py?rev=92767&view=diff&r1=92767&r2=92766 
):

The checkin message says: "work around Zope 3 exceptions that have *more 
than one* positional argument". I think that's correct.

The comment in SimpleItem.py says something different:

     # Can we re-raise the exception with a rendered-to-HTML
     # exception value? To be able to do so, the exception
     # constructor needs to be able to take more than two
     # arguments (some Zope exceptions can't).

The code follows that comment, so 'can_raise' is sometimes wrong.

E.g. can_raise is True for zope.publisher.interfaces.NotFound, but 
re-raising with the rendered value as only argument doesn't work.


Proposal:
=========

We could try to fix bugs like the one mentioned above. And we could 
restore the old behavior for normal Zope 2 exceptions, fixing the 
CookieCrumbler issue.

But the whole thing looks like a big mess. I think we should try to find 
a way to treat all kinds of errors the same way.

I see two possible approaches:

1.) Stop re-raising errors. Always return rendered values and pass them 
on to the places where the errors are currently catched.

2.) Re-raise the original errors. And store the rendered value somewhere 
else. Maybe in the response object.

What do you think? Any comments are welcome.


Cheers,

	Yuppie



More information about the Zope-Dev mailing list