"hello" != str(KeyError("hello"))
This is certainly unintuitive; I would have made the same mistake as the Zope guys. In fact, I have tried it for other Exception classes and most do round-trip. To quoteth the Zen:
Special cases aren't special enough to break the rules.
What is so special about KeyError that it gets to break the rules?
Here is a little test I whipped up to explore this:
import unittest
class TestExceptionStringRoundTrip(unittest.TestCase):
def assertStrCast(self, ExceptionClass):
s = "hello"
self.assertEqual(s, str(ExceptionClass(s)))
for builtin in dir(__builtins__):
if builtin.endswith('Error') or builtin.endswith('Exception'):
def _test(self, ExceptionClass=builtin):
self.assertStrCast(getattr(__builtins__, ExceptionClass))
setattr(TestExceptionStringRoundTrip, "test%s" % builtin,
_test)
if __name__ == "__main__":
unittest.main()
There is only one failure: KeyError. There are three errors from UnicodeDecodeError, UnicodeEncodeError and UnicodeTranslateError because they don't accept just a string as an argument (they probably should!)
Anyway, a fun little aside.
UPDATE:
Amaury Forgeot d'Arc has beaten me to the punch with a patch to fix this. I was kind of hoping I would get a crack at this, but this guy is just a coding machine :). Looks like he has a lot more experience with Python's source, so, I trust his patch is probably a little nicer than mine would have been. Here's the bug report for those who are interested (the patch is linked from the report).