[Python-Dev] Exceptions *must*? be old-style classes?
Armin Rigo
arigo at tunes.org
Mon Jan 17 11:52:19 CET 2005
Hi,
On Fri, Jan 14, 2005 at 07:20:31PM -0500, Jim Jewett wrote:
> The base of the Exception hierarchy happens to be a classic class.
> But why are they "required" to be classic?
For reference, PyPy doesn't have old-style classes at all so far, so we had to
come up with something about exceptions. After some feedback from python-dev
it appears that the following scheme works reasonably well. Actually it's
surprizing how little problems we actually encountered by removing the
old-/new-style distinction (particularly when compared with the extremely
obscure workarounds we had to go through in PyPy itself, e.g. precisely
because we wanted exceptions that are member of some (new-style) class
hierarchy).
Because a bit of Python code tells more than long and verbose explanations,
here it is:
def app_normalize_exception(etype, value, tb):
"""Normalize an (exc_type, exc_value) pair:
exc_value will be an exception instance and exc_type its class.
"""
# mistakes here usually show up as infinite recursion, which is fun.
while isinstance(etype, tuple):
etype = etype[0]
if isinstance(etype, type):
if not isinstance(value, etype):
if value is None:
# raise Type: we assume we have to instantiate Type
value = etype()
elif isinstance(value, tuple):
# raise Type, Tuple: assume Tuple contains the constructor
# args
value = etype(*value)
else:
# raise Type, X: assume X is the constructor argument
value = etype(value)
# raise Type, Instance: let etype be the exact type of value
etype = value.__class__
elif type(etype) is str:
# XXX warn -- deprecated
if value is not None and type(value) is not str:
raise TypeError("string exceptions can only have a string value")
else:
# raise X: we assume that X is an already-built instance
if value is not None:
raise TypeError("instance exception may not have a separate"
" value")
value = etype
etype = value.__class__
# for the sake of language consistency we should not allow
# things like 'raise 1', but it's probably fine (i.e.
# not ambiguous) to allow them in the explicit form 'raise int, 1'
if not hasattr(value, '__dict__') and not hasattr(value, '__slots__'):
raise TypeError("raising built-in objects can be ambiguous, "
"use 'raise type, value' instead")
return etype, value, tb
Armin
More information about the Python-Dev
mailing list