urgent: string exceptions
Hi. I'm stuck with trying to catch a string exception from the zope core within a python script of cmf. When using invokeFactory one can expect it to raise a "Bad Request" (string) exception e.g. when you want to create an object with a duplicate id. Within a python script I tried: try: ... invokeFactory ... except "Bad Request", v: ... but that doesn't catch the exception. Using an anonymous except: clause is not an acceptable way because a) they are evil b) i can't get to the exception value anymore. I need to solve a problem related to that soon. I now have some things I can imagine to do: a) Remove "Bad Request" beeing a String exception and make it a class exception b) Get a hint on how to actually catch the string exception within a python script and get to the exception value c) (Not good but if it works) Catch it anonymously *and* get to the exception value. Thanks for listening, Christian -- Christian Theune, gocept gmbh & co. kg http://www.gocept.com - ct@gocept.com fon: 03496 3099112 fax: 03496 3099118 mobile: 0179 7808366
You can catch most string exceptions. "Bad Request" cannot be caught because (afaik) the string isn't interned because it has a space in it. As a workaround, I'd use except: then do try: something except: e = sys.exc_info() if e[0] == 'Bad Request': do something raise On Fri, 2003-04-11 at 05:57, Lennart Regebro wrote:
Christian Theune wrote:
a) Remove "Bad Request" beeing a String exception and make it a class exception
Yup. Don't use String Exceptions. One reason is that you can't catch them. :)
_______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope )
You can catch most string exceptions. "Bad Request" cannot be caught because (afaik) the string isn't interned because it has a space in it.
You're skating on thin ice there, mate! This is an accident of the implementation.
As a workaround, I'd use except: then do
try: something except: e = sys.exc_info() if e[0] == 'Bad Request': do something raise
Why is there code writing raise 'Bad Request' That code should be fixed! It ought to use a class exception; if that's not possible, it ought to at least give the string a global name, like so: BadRequest = 'Bad Request' . . . raise BadRequest --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum writes: [...]
Why is there code writing
raise 'Bad Request'
That code should be fixed! It ought to use a class exception; if that's not possible, it ought to at least give the string a global name, like so:
BadRequest = 'Bad Request'
. . . raise BadRequest [...]
The verbatim raise 'BadRequest' is used in ca 40 places in the current zope sources (as 2.6.1, HEAD may differ). However for the problem at hand, the approach is actually quite like the proposed named string (OFS/ObjectManager, around line 47; ist named a bit different: BadRequestException = 'Bad Request' It seems this actually may cause the problem, because this module variable BadRequest is maybe equal, but not the same as bare string "Bad Request" (wild guess of mine) ? Unfortunately the exception string module variable cannt be imported from a python script, as not even OFS.ObjectManager is allowed in a python script. (for some good reason, I guess.) If thinking about improving the current implementation: maybe the BadRequest exception should be defined in some central place, where comon exceptions are defined? e.g. in the zExceptions module (do not know if this is actually intended to be used as a central exception pool...) Chris McDonough writes:
That'd be fine, but it would require a code audit. And third party products might fail.
Er, yes, they may. Possibly it would help them, if they know the exception is defined in one place, and all they have to do is to revert the exception class to a string? just my 2 cents, clemens
On Fri, 2003-04-11 at 10:04, Guido van Rossum wrote:
Why is there code writing
raise 'Bad Request'
That code should be fixed! It ought to use a class exception; if that's not possible, it ought to at least give the string a global name, like so:
BadRequest = 'Bad Request'
Most of the code using it was written before class exceptions existed, and I don't think anybody who raised or used the exception understood that it couldn't be caught by value at the time. Many people have threatened to fix it, but no one has done so yet. - C
Chris McDonough wrote:
You can catch most string exceptions.
I hate it when this happens. I thought you could, so I tried it, and it didn't work. Now you say that is should work, so I try it again, and it does... So stop telling my Python interpreter that it can do things it couldn't before, I get all confused. :p
"Bad Request" cannot be caught because (afaik) the string isn't interned because it has a space in it.
Strangely enough, I now succeed in cathing 'Bad Request' exceptions when I try it, so there is something more to this that my Zen-level doesn't grok.
Chris McDonough wrote:
You can catch most string exceptions.
[Lennart]
I hate it when this happens. I thought you could, so I tried it, and it didn't work. Now you say that is should work, so I try it again, and it does... So stop telling my Python interpreter that it can do things it couldn't before, I get all confused. :p
"Bad Request" cannot be caught because (afaik) the string isn't interned because it has a space in it.
Strangely enough, I now succeed in cathing 'Bad Request' exceptions when I try it, so there is something more to this that my Zen-level doesn't grok.
Depends on how you try it. If in one function you have raise "Bad Request" and in another you have try: ... except "Bad Request": ... it will fail. OTOH if you have this in the same function, it will succeed, because the bytecode compiler collapses identical constants within one function even if they are not interned. --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum wrote:
Depends on how you try it. If in one function you have
raise "Bad Request"
and in another you have
try: ... except "Bad Request": ...
it will fail. OTOH if you have this in the same function, it will succeed, because the bytecode compiler collapses identical constants within one function even if they are not interned.
Ah. Thanks for the explanation.
Lennart Regebro wrote:
Christian Theune wrote:
a) Remove "Bad Request" beeing a String exception and make it a class exception
Yup. Don't use String Exceptions. One reason is that you can't catch them. :)
Unfortunately Zope is full of them... if you can change them in the Zope core that would be wonderful. For dirty hackers like myself I've done c) before and it worked. -- Andy McKay
"Bad Request" is a special scenario that harkens back to Bobo (ZPublisher). One of the elements of Bobo was that you could raise HTTP exceptions, and it would be turned into a proper (or as proper as possible) HTTP Response Code, like 302 or 404 or whatever. This is some of the oldest code in Zope, and no one's really dealt with it (at least, not for Zope 2), because it's a decent effort to chase down all of the uses of it and patch things all the way down to the core to make use of it. This is made even more prescient by the fact that this is core core core ZPublisher behavior and is not even really Zope specific, so it's questionable where to put the class based exceptions and where to declare their security options so that they can get used in scripts. I'm not saying that it shouldn't be done, but that one has to understand the meaning behind it as well as the depth of the problem. Because of its potential impact, a well-thought proposal would have to be written up by someone who knew ZPublisher and Zope well enough to suggest a solution and document the potential impacts/risks involved with the change. On Friday, April 11, 2003, at 02:26 AM, Christian Theune wrote:
Hi.
I'm stuck with trying to catch a string exception from the zope core within a python script of cmf.
When using invokeFactory one can expect it to raise a "Bad Request" (string) exception e.g. when you want to create an object with a duplicate id.
Within a python script I tried:
try: ... invokeFactory ... except "Bad Request", v: ...
but that doesn't catch the exception. Using an anonymous except: clause is not an acceptable way because a) they are evil b) i can't get to the exception value anymore.
I need to solve a problem related to that soon. I now have some things I can imagine to do:
a) Remove "Bad Request" beeing a String exception and make it a class exception
b) Get a hint on how to actually catch the string exception within a python script and get to the exception value
c) (Not good but if it works) Catch it anonymously *and* get to the exception value.
Thanks for listening, Christian
-- Christian Theune, gocept gmbh & co. kg http://www.gocept.com - ct@gocept.com fon: 03496 3099112 fax: 03496 3099118 mobile: 0179 7808366
_______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope )
In article <8DEB15B9-6C79-11D7-AFD7-003065D2A224@cuemedia.com> you write:
"Bad Request" is a special scenario that harkens back to Bobo (ZPublisher). One of the elements of Bobo was that you could raise HTTP exceptions, and it would be turned into a proper (or as proper as possible) HTTP Response Code, like 302 or 404 or whatever.
This is some of the oldest code in Zope, and no one's really dealt with it (at least, not for Zope 2), because it's a decent effort to chase down all of the uses of it and patch things all the way down to the core to make use of it. This is made even more prescient by the fact that this is core core core ZPublisher behavior and is not even really Zope specific, so it's questionable where to put the class based exceptions and where to declare their security options so that they can get used in scripts.
I'm not saying that it shouldn't be done, but that one has to understand the meaning behind it as well as the depth of the problem. Because of its potential impact, a well-thought proposal would have to be written up by someone who knew ZPublisher and Zope well enough to suggest a solution and document the potential impacts/risks involved with the change.
For those interested, the code is in ZPublisher/HTTPResponse.py. There is a mapping (status_code) used to produce the return values sent to the HTTP server. The method exception() is called by ZPublisher.Publish.publish_module when an exception is caught, and it uses status_code to decide what to do. status_code is constructed in such a way that many aliases are allowed, in particular those without spaces in them: for key, val in status_reasons.items(): status_codes[''.join(val.split(' ')).lower()] = key status_codes[val.lower()] = key status_codes[key] = key status_codes[str(key)] = key So it's perfectly correct to do: BadRequest = 'BadRequest' raise BadRequest Besides, a lot of code already does: raise 'BadRequest' For those interested, is also because of this that you can do a: raise 'Redirect', 'http://foo' and have it work, because exception() knows how to handle all codes from 300 to 399 (of which Redirect is an instance) and set a Location header for them. So the cleanup can proceed without fear :-) Florent -- Florent Guillaume, Nuxeo (Paris, France) +33 1 40 33 79 87 http://nuxeo.com mailto:fg@nuxeo.com
participants (8)
-
Andy McKay -
Chris McDonough -
Christian Theune -
Clemens Robbenhaar -
Florent Guillaume -
Guido van Rossum -
Jeffrey P Shell -
Lennart Regebro