PEP 352 implementation. Creates a new base class, BaseException, which has an
added message attribute compared to the previous version of Exception. It is also a new-style class, making all exceptions now new-style. KeyboardInterrupt and SystemExit inherit from BaseException directly. String exceptions now raise DeprecationWarning. Applies patch 1104669, and closes bugs 1012952 and 518846.
This commit is contained in:
parent
762467475d
commit
bf36409e2a
|
@ -26,9 +26,32 @@ PyAPI_FUNC(int) PyErr_GivenExceptionMatches(PyObject *, PyObject *);
|
|||
PyAPI_FUNC(int) PyErr_ExceptionMatches(PyObject *);
|
||||
PyAPI_FUNC(void) PyErr_NormalizeException(PyObject**, PyObject**, PyObject**);
|
||||
|
||||
/* */
|
||||
|
||||
#define PyExceptionClass_Check(x) \
|
||||
(PyClass_Check((x)) \
|
||||
|| (PyType_Check((x)) && PyType_IsSubtype( \
|
||||
(PyTypeObject*)(x), (PyTypeObject*)PyExc_BaseException)))
|
||||
|
||||
|
||||
#define PyExceptionInstance_Check(x) \
|
||||
(PyInstance_Check((x)) || \
|
||||
(PyType_IsSubtype((x)->ob_type, (PyTypeObject*)PyExc_BaseException)))
|
||||
|
||||
#define PyExceptionClass_Name(x) \
|
||||
(PyClass_Check((x)) \
|
||||
? PyString_AS_STRING(((PyClassObject*)(x))->cl_name) \
|
||||
: (char *)(((PyTypeObject*)(x))->tp_name))
|
||||
|
||||
#define PyExceptionInstance_Class(x) \
|
||||
((PyInstance_Check((x)) \
|
||||
? (PyObject*)((PyInstanceObject*)(x))->in_class \
|
||||
: (PyObject*)((x)->ob_type)))
|
||||
|
||||
|
||||
/* Predefined exceptions */
|
||||
|
||||
PyAPI_DATA(PyObject *) PyExc_BaseException;
|
||||
PyAPI_DATA(PyObject *) PyExc_Exception;
|
||||
PyAPI_DATA(PyObject *) PyExc_StopIteration;
|
||||
PyAPI_DATA(PyObject *) PyExc_GeneratorExit;
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
BaseException
|
||||
+-- SystemExit
|
||||
+-- KeyboardInterrupt
|
||||
+-- Exception
|
||||
+-- GeneratorExit
|
||||
+-- StopIteration
|
||||
+-- StandardError
|
||||
| +-- ArithmeticError
|
||||
| | +-- FloatingPointError
|
||||
| | +-- OverflowError
|
||||
| | +-- ZeroDivisionError
|
||||
| +-- AssertionError
|
||||
| +-- AttributeError
|
||||
| +-- EnvironmentError
|
||||
| | +-- IOError
|
||||
| | +-- OSError
|
||||
| | +-- WindowsError (Windows)
|
||||
| +-- EOFError
|
||||
| +-- ImportError
|
||||
| +-- LookupError
|
||||
| | +-- IndexError
|
||||
| | +-- KeyError
|
||||
| +-- MemoryError
|
||||
| +-- NameError
|
||||
| | +-- UnboundLocalError
|
||||
| +-- ReferenceError
|
||||
| +-- RuntimeError
|
||||
| | +-- NotImplementedError
|
||||
| +-- SyntaxError
|
||||
| | +-- IndentationError
|
||||
| | +-- TabError
|
||||
| +-- SystemError
|
||||
| +-- TypeError
|
||||
| +-- ValueError
|
||||
| | +-- UnicodeError
|
||||
| | +-- UnicodeDecodeError
|
||||
| | +-- UnicodeEncodeError
|
||||
| | +-- UnicodeTranslateError
|
||||
+-- Warning
|
||||
+-- DeprecationWarning
|
||||
+-- PendingDeprecationWarning
|
||||
+-- RuntimeWarning
|
||||
+-- SyntaxWarning
|
||||
+-- UserWarning
|
||||
+-- FutureWarning
|
||||
+-- OverflowWarning [not generated by the interpreter]
|
|
@ -488,12 +488,12 @@ INFO:a.b.c.d:Info 5
|
|||
-- log_test4 begin ---------------------------------------------------
|
||||
config0: ok.
|
||||
config1: ok.
|
||||
config2: exceptions.AttributeError
|
||||
config3: exceptions.KeyError
|
||||
config2: <class 'exceptions.AttributeError'>
|
||||
config3: <class 'exceptions.KeyError'>
|
||||
-- log_test4 end ---------------------------------------------------
|
||||
-- log_test5 begin ---------------------------------------------------
|
||||
ERROR:root:just testing
|
||||
exceptions.KeyError... Don't panic!
|
||||
<class 'exceptions.KeyError'>... Don't panic!
|
||||
-- log_test5 end ---------------------------------------------------
|
||||
-- logrecv output begin ---------------------------------------------------
|
||||
ERR -> CRITICAL: Message 0 (via logrecv.tcp.ERR)
|
||||
|
|
|
@ -96,7 +96,7 @@ def do_infix_binops():
|
|||
x = eval('a %s b' % op)
|
||||
except:
|
||||
error = sys.exc_info()[:2]
|
||||
print '... %s' % error[0]
|
||||
print '... %s.%s' % (error[0].__module__, error[0].__name__)
|
||||
else:
|
||||
print '=', format_result(x)
|
||||
try:
|
||||
|
@ -108,7 +108,7 @@ def do_infix_binops():
|
|||
exec('z %s= b' % op)
|
||||
except:
|
||||
error = sys.exc_info()[:2]
|
||||
print '... %s' % error[0]
|
||||
print '... %s.%s' % (error[0].__module__, error[0].__name__)
|
||||
else:
|
||||
print '=>', format_result(z)
|
||||
|
||||
|
@ -121,7 +121,7 @@ def do_prefix_binops():
|
|||
x = eval('%s(a, b)' % op)
|
||||
except:
|
||||
error = sys.exc_info()[:2]
|
||||
print '... %s' % error[0]
|
||||
print '... %s.%s' % (error[0].__module__, error[0].__name__)
|
||||
else:
|
||||
print '=', format_result(x)
|
||||
|
||||
|
|
|
@ -3355,31 +3355,6 @@ def docdescriptor():
|
|||
vereq(NewClass.__doc__, 'object=None; type=NewClass')
|
||||
vereq(NewClass().__doc__, 'object=NewClass instance; type=NewClass')
|
||||
|
||||
def string_exceptions():
|
||||
if verbose:
|
||||
print "Testing string exceptions ..."
|
||||
|
||||
# Ensure builtin strings work OK as exceptions.
|
||||
astring = "An exception string."
|
||||
try:
|
||||
raise astring
|
||||
except astring:
|
||||
pass
|
||||
else:
|
||||
raise TestFailed, "builtin string not usable as exception"
|
||||
|
||||
# Ensure string subclass instances do not.
|
||||
class MyStr(str):
|
||||
pass
|
||||
|
||||
newstring = MyStr("oops -- shouldn't work")
|
||||
try:
|
||||
raise newstring
|
||||
except TypeError:
|
||||
pass
|
||||
except:
|
||||
raise TestFailed, "string subclass allowed as exception"
|
||||
|
||||
def copy_setstate():
|
||||
if verbose:
|
||||
print "Testing that copy.*copy() correctly uses __setstate__..."
|
||||
|
@ -4172,7 +4147,6 @@ def test_main():
|
|||
funnynew()
|
||||
imulbug()
|
||||
docdescriptor()
|
||||
string_exceptions()
|
||||
copy_setstate()
|
||||
slices()
|
||||
subtype_resurrection()
|
||||
|
|
|
@ -29,10 +29,7 @@ def test_raise_catch(exc):
|
|||
|
||||
def r(thing):
|
||||
test_raise_catch(thing)
|
||||
if isinstance(thing, ClassType):
|
||||
print thing.__name__
|
||||
else:
|
||||
print thing
|
||||
print getattr(thing, '__name__', thing)
|
||||
|
||||
r(AttributeError)
|
||||
import sys
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
import unittest
|
||||
import __builtin__
|
||||
import exceptions
|
||||
import warnings
|
||||
from test.test_support import run_unittest
|
||||
import os
|
||||
from platform import system as platform_system
|
||||
|
||||
class ExceptionClassTests(unittest.TestCase):
|
||||
|
||||
"""Tests for anything relating to exception objects themselves (e.g.,
|
||||
inheritance hierarchy)"""
|
||||
|
||||
def test_builtins_new_style(self):
|
||||
self.failUnless(issubclass(Exception, object))
|
||||
|
||||
def verify_instance_interface(self, ins):
|
||||
for attr in ("args", "message", "__str__", "__unicode__", "__repr__",
|
||||
"__getitem__"):
|
||||
self.failUnless(hasattr(ins, attr), "%s missing %s attribute" %
|
||||
(ins.__class__.__name__, attr))
|
||||
|
||||
def test_inheritance(self):
|
||||
# Make sure the inheritance hierarchy matches the documentation
|
||||
exc_set = set(x for x in dir(exceptions) if not x.startswith('_'))
|
||||
inheritance_tree = open(os.path.join(os.path.split(__file__)[0],
|
||||
'exception_hierarchy.txt'))
|
||||
try:
|
||||
superclass_name = inheritance_tree.readline().rstrip()
|
||||
try:
|
||||
last_exc = getattr(__builtin__, superclass_name)
|
||||
except AttributeError:
|
||||
self.fail("base class %s not a built-in" % superclass_name)
|
||||
self.failUnless(superclass_name in exc_set)
|
||||
exc_set.discard(superclass_name)
|
||||
superclasses = [] # Loop will insert base exception
|
||||
last_depth = 0
|
||||
for exc_line in inheritance_tree:
|
||||
exc_line = exc_line.rstrip()
|
||||
depth = exc_line.rindex('-')
|
||||
exc_name = exc_line[depth+2:] # Slice past space
|
||||
if '(' in exc_name:
|
||||
paren_index = exc_name.index('(')
|
||||
platform_name = exc_name[paren_index+1:-1]
|
||||
if platform_system() != platform_name:
|
||||
exc_set.discard(exc_name)
|
||||
continue
|
||||
if '[' in exc_name:
|
||||
left_bracket = exc_name.index('[')
|
||||
exc_name = exc_name[:left_bracket-1] # cover space
|
||||
try:
|
||||
exc = getattr(__builtin__, exc_name)
|
||||
except AttributeError:
|
||||
self.fail("%s not a built-in exception" % exc_name)
|
||||
if last_depth < depth:
|
||||
superclasses.append((last_depth, last_exc))
|
||||
elif last_depth > depth:
|
||||
while superclasses[-1][0] >= depth:
|
||||
superclasses.pop()
|
||||
self.failUnless(issubclass(exc, superclasses[-1][1]),
|
||||
"%s is not a subclass of %s" % (exc.__name__,
|
||||
superclasses[-1][1].__name__))
|
||||
try: # Some exceptions require arguments; just skip them
|
||||
self.verify_instance_interface(exc())
|
||||
except TypeError:
|
||||
pass
|
||||
self.failUnless(exc_name in exc_set)
|
||||
exc_set.discard(exc_name)
|
||||
last_exc = exc
|
||||
last_depth = depth
|
||||
finally:
|
||||
inheritance_tree.close()
|
||||
self.failUnlessEqual(len(exc_set), 0, "%s not accounted for" % exc_set)
|
||||
|
||||
interface_tests = ("length", "args", "message", "str", "unicode", "repr",
|
||||
"indexing")
|
||||
|
||||
def interface_test_driver(self, results):
|
||||
for test_name, (given, expected) in zip(self.interface_tests, results):
|
||||
self.failUnlessEqual(given, expected, "%s: %s != %s" % (test_name,
|
||||
given, expected))
|
||||
|
||||
def test_interface_single_arg(self):
|
||||
# Make sure interface works properly when given a single argument
|
||||
arg = "spam"
|
||||
exc = Exception(arg)
|
||||
results = ([len(exc.args), 1], [exc.args[0], arg], [exc.message, arg],
|
||||
[str(exc), str(arg)], [unicode(exc), unicode(arg)],
|
||||
[repr(exc), exc.__class__.__name__ + repr(exc.args)], [exc[0], arg])
|
||||
self.interface_test_driver(results)
|
||||
|
||||
def test_interface_multi_arg(self):
|
||||
# Make sure interface correct when multiple arguments given
|
||||
arg_count = 3
|
||||
args = tuple(range(arg_count))
|
||||
exc = Exception(*args)
|
||||
results = ([len(exc.args), arg_count], [exc.args, args],
|
||||
[exc.message, ''], [str(exc), str(args)],
|
||||
[unicode(exc), unicode(args)],
|
||||
[repr(exc), exc.__class__.__name__ + repr(exc.args)],
|
||||
[exc[-1], args[-1]])
|
||||
self.interface_test_driver(results)
|
||||
|
||||
def test_interface_no_arg(self):
|
||||
# Make sure that with no args that interface is correct
|
||||
exc = Exception()
|
||||
results = ([len(exc.args), 0], [exc.args, tuple()], [exc.message, ''],
|
||||
[str(exc), ''], [unicode(exc), u''],
|
||||
[repr(exc), exc.__class__.__name__ + '()'], [True, True])
|
||||
self.interface_test_driver(results)
|
||||
|
||||
class UsageTests(unittest.TestCase):
|
||||
|
||||
"""Test usage of exceptions"""
|
||||
|
||||
def setUp(self):
|
||||
self._filters = warnings.filters[:]
|
||||
|
||||
def tearDown(self):
|
||||
warnings.filters = self._filters[:]
|
||||
|
||||
def test_raise_classic(self):
|
||||
class ClassicClass:
|
||||
pass
|
||||
try:
|
||||
raise ClassicClass
|
||||
except ClassicClass:
|
||||
pass
|
||||
except:
|
||||
self.fail("unable to raise classic class")
|
||||
try:
|
||||
raise ClassicClass()
|
||||
except ClassicClass:
|
||||
pass
|
||||
except:
|
||||
self.fail("unable to raise class class instance")
|
||||
|
||||
def test_raise_new_style_non_exception(self):
|
||||
class NewStyleClass(object):
|
||||
pass
|
||||
try:
|
||||
raise NewStyleClass
|
||||
except TypeError:
|
||||
pass
|
||||
except:
|
||||
self.fail("unable to raise new-style class")
|
||||
try:
|
||||
raise NewStyleClass()
|
||||
except TypeError:
|
||||
pass
|
||||
except:
|
||||
self.fail("unable to raise new-style class instance")
|
||||
|
||||
def test_raise_string(self):
|
||||
warnings.resetwarnings()
|
||||
warnings.filterwarnings("error")
|
||||
try:
|
||||
raise "spam"
|
||||
except DeprecationWarning:
|
||||
pass
|
||||
except:
|
||||
self.fail("raising a string did not cause a DeprecationWarning")
|
||||
|
||||
def test_catch_string(self):
|
||||
# Test will be pertinent when catching exceptions raises a
|
||||
# DeprecationWarning
|
||||
warnings.filterwarnings("ignore", "raising")
|
||||
str_exc = "spam"
|
||||
try:
|
||||
raise str_exc
|
||||
except str_exc:
|
||||
pass
|
||||
except:
|
||||
self.fail("catching a string exception failed")
|
||||
|
||||
def test_main():
|
||||
run_unittest(ExceptionClassTests, UsageTests)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_main()
|
|
@ -157,7 +157,8 @@ def format_exception_only(etype, value):
|
|||
which exception occurred is the always last string in the list.
|
||||
"""
|
||||
list = []
|
||||
if type(etype) == types.ClassType:
|
||||
if (type(etype) == types.ClassType
|
||||
or (isinstance(etype, type) and issubclass(etype, Exception))):
|
||||
stype = etype.__name__
|
||||
else:
|
||||
stype = etype
|
||||
|
|
|
@ -145,7 +145,8 @@ def filterwarnings(action, message="", category=Warning, module="", lineno=0,
|
|||
assert action in ("error", "ignore", "always", "default", "module",
|
||||
"once"), "invalid action: %r" % (action,)
|
||||
assert isinstance(message, basestring), "message must be a string"
|
||||
assert isinstance(category, types.ClassType), "category must be a class"
|
||||
assert isinstance(category, (type, types.ClassType)), \
|
||||
"category must be a class"
|
||||
assert issubclass(category, Warning), "category must be a Warning subclass"
|
||||
assert isinstance(module, basestring), "module must be a string"
|
||||
assert isinstance(lineno, int) and lineno >= 0, \
|
||||
|
|
|
@ -12,6 +12,11 @@ What's New in Python 2.5 alpha 1?
|
|||
Core and builtins
|
||||
-----------------
|
||||
|
||||
- PEP 352, patch #1104669: Make exceptions new-style objects. Introduced the
|
||||
new exception base class, BaseException, which has a new message attribute.
|
||||
KeyboardInterrupt and SystemExit to directly inherit from BaseException now.
|
||||
Raising a string exception now raises a DeprecationWarning.
|
||||
|
||||
- Patch #1438387, PEP 328: relative and absolute imports. Imports can now be
|
||||
explicitly relative, using 'from .module import name' to mean 'from the same
|
||||
package as this module is in. Imports without dots still default to the
|
||||
|
|
|
@ -230,11 +230,11 @@ gen_throw(PyGenObject *gen, PyObject *args)
|
|||
Py_XINCREF(val);
|
||||
Py_XINCREF(tb);
|
||||
|
||||
if (PyClass_Check(typ)) {
|
||||
if (PyExceptionClass_Check(typ)) {
|
||||
PyErr_NormalizeException(&typ, &val, &tb);
|
||||
}
|
||||
|
||||
else if (PyInstance_Check(typ)) {
|
||||
else if (PyExceptionInstance_Check(typ)) {
|
||||
/* Raising an instance. The value should be a dummy. */
|
||||
if (val && val != Py_None) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
|
@ -245,7 +245,7 @@ gen_throw(PyGenObject *gen, PyObject *args)
|
|||
/* Normalize to raise <class>, <instance> */
|
||||
Py_XDECREF(val);
|
||||
val = typ;
|
||||
typ = (PyObject*) ((PyInstanceObject*)typ)->in_class;
|
||||
typ = PyExceptionInstance_Class(typ);
|
||||
Py_INCREF(typ);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1685,7 +1685,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throw)
|
|||
why == WHY_CONTINUE)
|
||||
retval = POP();
|
||||
}
|
||||
else if (PyClass_Check(v) || PyString_Check(v)) {
|
||||
else if (PyExceptionClass_Check(v) || PyString_Check(v)) {
|
||||
w = POP();
|
||||
u = POP();
|
||||
PyErr_Restore(v, w, u);
|
||||
|
@ -3026,14 +3026,14 @@ do_raise(PyObject *type, PyObject *value, PyObject *tb)
|
|||
/* Raising builtin string is deprecated but still allowed --
|
||||
* do nothing. Raising an instance of a new-style str
|
||||
* subclass is right out. */
|
||||
if (-1 == PyErr_Warn(PyExc_PendingDeprecationWarning,
|
||||
if (PyErr_Warn(PyExc_DeprecationWarning,
|
||||
"raising a string exception is deprecated"))
|
||||
goto raise_error;
|
||||
}
|
||||
else if (PyClass_Check(type))
|
||||
else if (PyExceptionClass_Check(type))
|
||||
PyErr_NormalizeException(&type, &value, &tb);
|
||||
|
||||
else if (PyInstance_Check(type)) {
|
||||
else if (PyExceptionInstance_Check(type)) {
|
||||
/* Raising an instance. The value should be a dummy. */
|
||||
if (value != Py_None) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
|
@ -3044,7 +3044,7 @@ do_raise(PyObject *type, PyObject *value, PyObject *tb)
|
|||
/* Normalize to raise <class>, <instance> */
|
||||
Py_DECREF(value);
|
||||
value = type;
|
||||
type = (PyObject*) ((PyInstanceObject*)type)->in_class;
|
||||
type = PyExceptionInstance_Class(type);
|
||||
Py_INCREF(type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -448,9 +448,8 @@ static void wrong_exception_type(PyObject *exc)
|
|||
|
||||
PyObject *PyCodec_StrictErrors(PyObject *exc)
|
||||
{
|
||||
if (PyInstance_Check(exc))
|
||||
PyErr_SetObject((PyObject*)((PyInstanceObject*)exc)->in_class,
|
||||
exc);
|
||||
if (PyExceptionInstance_Check(exc))
|
||||
PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
|
||||
else
|
||||
PyErr_SetString(PyExc_TypeError, "codec must pass exception instance");
|
||||
return NULL;
|
||||
|
|
|
@ -97,11 +97,14 @@ PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)
|
|||
return 0;
|
||||
}
|
||||
/* err might be an instance, so check its class. */
|
||||
if (PyInstance_Check(err))
|
||||
err = (PyObject*)((PyInstanceObject*)err)->in_class;
|
||||
if (PyExceptionInstance_Check(err))
|
||||
err = PyExceptionInstance_Class(err);
|
||||
|
||||
if (PyClass_Check(err) && PyClass_Check(exc))
|
||||
return PyClass_IsSubclass(err, exc);
|
||||
if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) {
|
||||
/* problems here!? not sure PyObject_IsSubclass expects to
|
||||
be called with an exception pending... */
|
||||
return PyObject_IsSubclass(err, exc);
|
||||
}
|
||||
|
||||
return err == exc;
|
||||
}
|
||||
|
@ -138,19 +141,19 @@ PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
|
|||
Py_INCREF(value);
|
||||
}
|
||||
|
||||
if (PyInstance_Check(value))
|
||||
inclass = (PyObject*)((PyInstanceObject*)value)->in_class;
|
||||
if (PyExceptionInstance_Check(value))
|
||||
inclass = PyExceptionInstance_Class(value);
|
||||
|
||||
/* Normalize the exception so that if the type is a class, the
|
||||
value will be an instance.
|
||||
*/
|
||||
if (PyClass_Check(type)) {
|
||||
if (PyExceptionClass_Check(type)) {
|
||||
/* if the value was not an instance, or is not an instance
|
||||
whose class is (or is derived from) type, then use the
|
||||
value as an argument to instantiation of the type
|
||||
class.
|
||||
*/
|
||||
if (!inclass || !PyClass_IsSubclass(inclass, type)) {
|
||||
if (!inclass || !PyObject_IsSubclass(inclass, type)) {
|
||||
PyObject *args, *res;
|
||||
|
||||
if (value == Py_None)
|
||||
|
@ -574,7 +577,24 @@ PyErr_WriteUnraisable(PyObject *obj)
|
|||
if (f != NULL) {
|
||||
PyFile_WriteString("Exception ", f);
|
||||
if (t) {
|
||||
PyFile_WriteObject(t, f, Py_PRINT_RAW);
|
||||
char* className = PyExceptionClass_Name(t);
|
||||
PyObject* moduleName =
|
||||
PyObject_GetAttrString(t, "__module__");
|
||||
|
||||
if (moduleName == NULL)
|
||||
PyFile_WriteString("<unknown>", f);
|
||||
else {
|
||||
char* modstr = PyString_AsString(moduleName);
|
||||
if (modstr)
|
||||
{
|
||||
PyFile_WriteString(modstr, f);
|
||||
PyFile_WriteString(".", f);
|
||||
}
|
||||
}
|
||||
if (className == NULL)
|
||||
PyFile_WriteString("<unknown>", f);
|
||||
else
|
||||
PyFile_WriteString(className, f);
|
||||
if (v && v != Py_None) {
|
||||
PyFile_WriteString(": ", f);
|
||||
PyFile_WriteObject(v, f, 0);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
* 98-08-19 fl created (for pyexe)
|
||||
* 00-02-08 fl updated for 1.5.2
|
||||
* 26-May-2000 baw vetted for Python 1.6
|
||||
* XXX
|
||||
*
|
||||
* written by Fredrik Lundh
|
||||
* modifications, additions, cleanups, and proofreading by Barry Warsaw
|
||||
|
@ -33,99 +34,19 @@
|
|||
PyDoc_STRVAR(module__doc__,
|
||||
"Python's standard exception class hierarchy.\n\
|
||||
\n\
|
||||
Before Python 1.5, the standard exceptions were all simple string objects.\n\
|
||||
In Python 1.5, the standard exceptions were converted to classes organized\n\
|
||||
into a relatively flat hierarchy. String-based standard exceptions were\n\
|
||||
optional, or used as a fallback if some problem occurred while importing\n\
|
||||
the exception module. With Python 1.6, optional string-based standard\n\
|
||||
exceptions were removed (along with the -X command line flag).\n\
|
||||
\n\
|
||||
The class exceptions were implemented in such a way as to be almost\n\
|
||||
completely backward compatible. Some tricky uses of IOError could\n\
|
||||
potentially have broken, but by Python 1.6, all of these should have\n\
|
||||
been fixed. As of Python 1.6, the class-based standard exceptions are\n\
|
||||
now implemented in C, and are guaranteed to exist in the Python\n\
|
||||
interpreter.\n\
|
||||
\n\
|
||||
Here is a rundown of the class hierarchy. The classes found here are\n\
|
||||
inserted into both the exceptions module and the `built-in' module. It is\n\
|
||||
recommended that user defined class based exceptions be derived from the\n\
|
||||
`Exception' class, although this is currently not enforced.\n"
|
||||
Exceptions found here are defined both in the exceptions module and the \n\
|
||||
built-in namespace. It is recommended that user-defined exceptions inherit \n\
|
||||
from Exception.\n\
|
||||
"
|
||||
|
||||
/* keep string pieces "small" */
|
||||
"\n\
|
||||
Exception\n\
|
||||
|\n\
|
||||
+-- SystemExit\n\
|
||||
+-- StopIteration\n\
|
||||
+-- GeneratorExit\n\
|
||||
+-- StandardError\n\
|
||||
| |\n\
|
||||
| +-- KeyboardInterrupt\n\
|
||||
| +-- ImportError\n\
|
||||
| +-- EnvironmentError\n\
|
||||
| | |\n\
|
||||
| | +-- IOError\n\
|
||||
| | +-- OSError\n\
|
||||
| | |\n\
|
||||
| | +-- WindowsError\n\
|
||||
| | +-- VMSError\n\
|
||||
| |\n\
|
||||
| +-- EOFError\n\
|
||||
| +-- RuntimeError\n\
|
||||
| | |\n\
|
||||
| | +-- NotImplementedError\n\
|
||||
| |\n\
|
||||
| +-- NameError\n\
|
||||
| | |\n\
|
||||
| | +-- UnboundLocalError\n\
|
||||
| |\n\
|
||||
| +-- AttributeError\n\
|
||||
| +-- SyntaxError\n\
|
||||
| | |\n\
|
||||
| | +-- IndentationError\n\
|
||||
| | |\n\
|
||||
| | +-- TabError\n\
|
||||
| |\n\
|
||||
| +-- TypeError\n\
|
||||
| +-- AssertionError\n\
|
||||
| +-- LookupError\n\
|
||||
| | |\n\
|
||||
| | +-- IndexError\n\
|
||||
| | +-- KeyError\n\
|
||||
| |\n\
|
||||
| +-- ArithmeticError\n\
|
||||
| | |\n\
|
||||
| | +-- OverflowError\n\
|
||||
| | +-- ZeroDivisionError\n\
|
||||
| | +-- FloatingPointError\n\
|
||||
| |\n\
|
||||
| +-- ValueError\n\
|
||||
| | |\n\
|
||||
| | +-- UnicodeError\n\
|
||||
| | |\n\
|
||||
| | +-- UnicodeEncodeError\n\
|
||||
| | +-- UnicodeDecodeError\n\
|
||||
| | +-- UnicodeTranslateError\n\
|
||||
| |\n\
|
||||
| +-- ReferenceError\n\
|
||||
| +-- SystemError\n\
|
||||
| +-- MemoryError\n\
|
||||
|\n\
|
||||
+---Warning\n\
|
||||
|\n\
|
||||
+-- UserWarning\n\
|
||||
+-- DeprecationWarning\n\
|
||||
+-- PendingDeprecationWarning\n\
|
||||
+-- SyntaxWarning\n\
|
||||
+-- OverflowWarning\n\
|
||||
+-- RuntimeWarning\n\
|
||||
+-- FutureWarning"
|
||||
/* XXX exception hierarchy from Lib/test/exception_hierarchy.txt */
|
||||
);
|
||||
|
||||
|
||||
/* Helper function for populating a dictionary with method wrappers. */
|
||||
static int
|
||||
populate_methods(PyObject *klass, PyObject *dict, PyMethodDef *methods)
|
||||
populate_methods(PyObject *klass, PyMethodDef *methods)
|
||||
{
|
||||
PyObject *module;
|
||||
int status = -1;
|
||||
|
@ -151,7 +72,7 @@ populate_methods(PyObject *klass, PyObject *dict, PyMethodDef *methods)
|
|||
}
|
||||
|
||||
/* add method to dictionary */
|
||||
status = PyDict_SetItemString(dict, methods->ml_name, meth);
|
||||
status = PyObject_SetAttrString(klass, methods->ml_name, meth);
|
||||
Py_DECREF(meth);
|
||||
Py_DECREF(func);
|
||||
|
||||
|
@ -196,7 +117,7 @@ make_class(PyObject **klass, PyObject *base,
|
|||
if (!(*klass = PyErr_NewException(name, base, dict)))
|
||||
goto finally;
|
||||
|
||||
if (populate_methods(*klass, dict, methods)) {
|
||||
if (populate_methods(*klass, methods)) {
|
||||
Py_DECREF(*klass);
|
||||
*klass = NULL;
|
||||
goto finally;
|
||||
|
@ -232,47 +153,81 @@ get_self(PyObject *args)
|
|||
/* Notes on bootstrapping the exception classes.
|
||||
*
|
||||
* First thing we create is the base class for all exceptions, called
|
||||
* appropriately enough: Exception. Creation of this class makes no
|
||||
* appropriately BaseException. Creation of this class makes no
|
||||
* assumptions about the existence of any other exception class -- except
|
||||
* for TypeError, which can conditionally exist.
|
||||
*
|
||||
* Next, StandardError is created (which is quite simple) followed by
|
||||
* Next, Exception is created since it is the common subclass for the rest of
|
||||
* the needed exceptions for this bootstrapping to work. StandardError is
|
||||
* created (which is quite simple) followed by
|
||||
* TypeError, because the instantiation of other exceptions can potentially
|
||||
* throw a TypeError. Once these exceptions are created, all the others
|
||||
* can be created in any order. See the static exctable below for the
|
||||
* explicit bootstrap order.
|
||||
*
|
||||
* All classes after Exception can be created using PyErr_NewException().
|
||||
* All classes after BaseException can be created using PyErr_NewException().
|
||||
*/
|
||||
|
||||
PyDoc_STRVAR(Exception__doc__, "Common base class for all exceptions.");
|
||||
PyDoc_STRVAR(BaseException__doc__, "Common base class for all exceptions");
|
||||
|
||||
/*
|
||||
Set args and message attributes.
|
||||
|
||||
Assumes self and args have already been set properly with set_self, etc.
|
||||
*/
|
||||
static int
|
||||
set_args_and_message(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *message_val;
|
||||
Py_ssize_t args_len = PySequence_Length(args);
|
||||
|
||||
if (args_len < 0)
|
||||
return 0;
|
||||
|
||||
/* set args */
|
||||
if (PyObject_SetAttrString(self, "args", args) < 0)
|
||||
return 0;
|
||||
|
||||
/* set message */
|
||||
if (args_len == 1)
|
||||
message_val = PySequence_GetItem(args, 0);
|
||||
else
|
||||
message_val = PyString_FromString("");
|
||||
if (!message_val)
|
||||
return 0;
|
||||
|
||||
if (PyObject_SetAttrString(self, "message", message_val) < 0) {
|
||||
Py_DECREF(message_val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py_DECREF(message_val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
Exception__init__(PyObject *self, PyObject *args)
|
||||
BaseException__init__(PyObject *self, PyObject *args)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!(self = get_self(args)))
|
||||
return NULL;
|
||||
|
||||
/* set args attribute */
|
||||
/* XXX size is only a hint */
|
||||
args = PySequence_GetSlice(args, 1, PySequence_Size(args));
|
||||
/* set args and message attribute */
|
||||
args = PySequence_GetSlice(args, 1, PySequence_Length(args));
|
||||
if (!args)
|
||||
return NULL;
|
||||
status = PyObject_SetAttrString(self, "args", args);
|
||||
Py_DECREF(args);
|
||||
if (status < 0)
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
if (!set_args_and_message(self, args)) {
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_DECREF(args);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
Exception__str__(PyObject *self, PyObject *args)
|
||||
BaseException__str__(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *out;
|
||||
|
||||
|
@ -310,9 +265,116 @@ Exception__str__(PyObject *self, PyObject *args)
|
|||
return out;
|
||||
}
|
||||
|
||||
#ifdef Py_USING_UNICODE
|
||||
static PyObject *
|
||||
BaseException__unicode__(PyObject *self, PyObject *args)
|
||||
{
|
||||
Py_ssize_t args_len;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O:__unicode__", &self))
|
||||
return NULL;
|
||||
|
||||
args = PyObject_GetAttrString(self, "args");
|
||||
if (!args)
|
||||
return NULL;
|
||||
|
||||
args_len = PySequence_Size(args);
|
||||
if (args_len < 0) {
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (args_len == 0) {
|
||||
Py_DECREF(args);
|
||||
return PyUnicode_FromUnicode(NULL, 0);
|
||||
}
|
||||
else if (args_len == 1) {
|
||||
PyObject *temp = PySequence_GetItem(args, 0);
|
||||
if (!temp) {
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(args);
|
||||
return PyObject_Unicode(temp);
|
||||
}
|
||||
else {
|
||||
Py_DECREF(args);
|
||||
return PyObject_Unicode(args);
|
||||
}
|
||||
}
|
||||
#endif /* Py_USING_UNICODE */
|
||||
|
||||
static PyObject *
|
||||
Exception__getitem__(PyObject *self, PyObject *args)
|
||||
BaseException__repr__(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *args_attr;
|
||||
Py_ssize_t args_len;
|
||||
PyObject *repr_suffix;
|
||||
PyObject *repr;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O:__repr__", &self))
|
||||
return NULL;
|
||||
|
||||
args_attr = PyObject_GetAttrString(self, "args");
|
||||
if (!args_attr)
|
||||
return NULL;
|
||||
|
||||
args_len = PySequence_Length(args_attr);
|
||||
if (args_len < 0) {
|
||||
Py_DECREF(args_attr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (args_len == 0) {
|
||||
Py_DECREF(args_attr);
|
||||
repr_suffix = PyString_FromString("()");
|
||||
if (!repr_suffix)
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
PyObject *args_repr;
|
||||
/*PyObject *right_paren;
|
||||
|
||||
repr_suffix = PyString_FromString("(*");
|
||||
if (!repr_suffix) {
|
||||
Py_DECREF(args_attr);
|
||||
return NULL;
|
||||
}*/
|
||||
|
||||
args_repr = PyObject_Repr(args_attr);
|
||||
Py_DECREF(args_attr);
|
||||
if (!args_repr)
|
||||
return NULL;
|
||||
|
||||
repr_suffix = args_repr;
|
||||
|
||||
/*PyString_ConcatAndDel(&repr_suffix, args_repr);
|
||||
if (!repr_suffix)
|
||||
return NULL;
|
||||
|
||||
right_paren = PyString_FromString(")");
|
||||
if (!right_paren) {
|
||||
Py_DECREF(repr_suffix);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyString_ConcatAndDel(&repr_suffix, right_paren);
|
||||
if (!repr_suffix)
|
||||
return NULL;*/
|
||||
}
|
||||
|
||||
repr = PyString_FromString(self->ob_type->tp_name);
|
||||
if (!repr) {
|
||||
Py_DECREF(repr_suffix);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyString_ConcatAndDel(&repr, repr_suffix);
|
||||
return repr;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
BaseException__getitem__(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *out;
|
||||
PyObject *index;
|
||||
|
@ -331,21 +393,27 @@ Exception__getitem__(PyObject *self, PyObject *args)
|
|||
|
||||
|
||||
static PyMethodDef
|
||||
Exception_methods[] = {
|
||||
/* methods for the Exception class */
|
||||
{ "__getitem__", Exception__getitem__, METH_VARARGS},
|
||||
{ "__str__", Exception__str__, METH_VARARGS},
|
||||
{ "__init__", Exception__init__, METH_VARARGS},
|
||||
{ NULL, NULL }
|
||||
BaseException_methods[] = {
|
||||
/* methods for the BaseException class */
|
||||
{"__getitem__", BaseException__getitem__, METH_VARARGS},
|
||||
{"__repr__", BaseException__repr__, METH_VARARGS},
|
||||
{"__str__", BaseException__str__, METH_VARARGS},
|
||||
#ifdef Py_USING_UNICODE
|
||||
{"__unicode__", BaseException__unicode__, METH_VARARGS},
|
||||
#endif /* Py_USING_UNICODE */
|
||||
{"__init__", BaseException__init__, METH_VARARGS},
|
||||
{NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
make_Exception(char *modulename)
|
||||
make_BaseException(char *modulename)
|
||||
{
|
||||
PyObject *dict = PyDict_New();
|
||||
PyObject *str = NULL;
|
||||
PyObject *name = NULL;
|
||||
PyObject *emptytuple = NULL;
|
||||
PyObject *argstuple = NULL;
|
||||
int status = -1;
|
||||
|
||||
if (!dict)
|
||||
|
@ -360,20 +428,28 @@ make_Exception(char *modulename)
|
|||
if (PyDict_SetItemString(dict, "__module__", str))
|
||||
goto finally;
|
||||
Py_DECREF(str);
|
||||
if (!(str = PyString_FromString(Exception__doc__)))
|
||||
|
||||
if (!(str = PyString_FromString(BaseException__doc__)))
|
||||
goto finally;
|
||||
if (PyDict_SetItemString(dict, "__doc__", str))
|
||||
goto finally;
|
||||
|
||||
if (!(name = PyString_FromString("Exception")))
|
||||
if (!(name = PyString_FromString("BaseException")))
|
||||
goto finally;
|
||||
|
||||
if (!(PyExc_Exception = PyClass_New(NULL, dict, name)))
|
||||
if (!(emptytuple = PyTuple_New(0)))
|
||||
goto finally;
|
||||
|
||||
if (!(argstuple = PyTuple_Pack(3, name, emptytuple, dict)))
|
||||
goto finally;
|
||||
|
||||
if (!(PyExc_BaseException = PyType_Type.tp_new(&PyType_Type, argstuple,
|
||||
NULL)))
|
||||
goto finally;
|
||||
|
||||
/* Now populate the dictionary with the method suite */
|
||||
if (populate_methods(PyExc_Exception, dict, Exception_methods))
|
||||
/* Don't need to reclaim PyExc_Exception here because that'll
|
||||
if (populate_methods(PyExc_BaseException, BaseException_methods))
|
||||
/* Don't need to reclaim PyExc_BaseException here because that'll
|
||||
* happen during interpreter shutdown.
|
||||
*/
|
||||
goto finally;
|
||||
|
@ -384,13 +460,18 @@ make_Exception(char *modulename)
|
|||
Py_XDECREF(dict);
|
||||
Py_XDECREF(str);
|
||||
Py_XDECREF(name);
|
||||
Py_XDECREF(emptytuple);
|
||||
Py_XDECREF(argstuple);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyDoc_STRVAR(Exception__doc__, "Common base class for all non-exit exceptions.");
|
||||
|
||||
PyDoc_STRVAR(StandardError__doc__,
|
||||
"Base class for all standard Python exceptions.");
|
||||
"Base class for all standard Python exceptions that do not represent"
|
||||
"interpreter exiting.");
|
||||
|
||||
PyDoc_STRVAR(TypeError__doc__, "Inappropriate argument type.");
|
||||
|
||||
|
@ -411,14 +492,12 @@ SystemExit__init__(PyObject *self, PyObject *args)
|
|||
if (!(self = get_self(args)))
|
||||
return NULL;
|
||||
|
||||
/* Set args attribute. */
|
||||
if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
|
||||
return NULL;
|
||||
|
||||
status = PyObject_SetAttrString(self, "args", args);
|
||||
if (status < 0) {
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
if (!set_args_and_message(self, args)) {
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set code attribute */
|
||||
|
@ -445,8 +524,7 @@ SystemExit__init__(PyObject *self, PyObject *args)
|
|||
if (status < 0)
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -482,8 +560,12 @@ EnvironmentError__init__(PyObject *self, PyObject *args)
|
|||
if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
|
||||
return NULL;
|
||||
|
||||
if (PyObject_SetAttrString(self, "args", args) ||
|
||||
PyObject_SetAttrString(self, "errno", Py_None) ||
|
||||
if (!set_args_and_message(self, args)) {
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyObject_SetAttrString(self, "errno", Py_None) ||
|
||||
PyObject_SetAttrString(self, "strerror", Py_None) ||
|
||||
PyObject_SetAttrString(self, "filename", Py_None))
|
||||
{
|
||||
|
@ -624,9 +706,9 @@ EnvironmentError__str__(PyObject *self, PyObject *args)
|
|||
* return StandardError.__str__(self)
|
||||
*
|
||||
* but there is no StandardError__str__() function; we happen to
|
||||
* know that's just a pass through to Exception__str__().
|
||||
* know that's just a pass through to BaseException__str__().
|
||||
*/
|
||||
rtnval = Exception__str__(originalself, args);
|
||||
rtnval = BaseException__str__(originalself, args);
|
||||
|
||||
finally:
|
||||
Py_XDECREF(filename);
|
||||
|
@ -712,8 +794,10 @@ SyntaxError__init__(PyObject *self, PyObject *args)
|
|||
if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
|
||||
return NULL;
|
||||
|
||||
if (PyObject_SetAttrString(self, "args", args))
|
||||
goto finally;
|
||||
if (!set_args_and_message(self, args)) {
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lenargs = PySequence_Size(args);
|
||||
if (lenargs >= 1) {
|
||||
|
@ -879,8 +963,9 @@ KeyError__str__(PyObject *self, PyObject *args)
|
|||
if (!PyArg_ParseTuple(args, "O:__str__", &self))
|
||||
return NULL;
|
||||
|
||||
if (!(argsattr = PyObject_GetAttrString(self, "args")))
|
||||
return NULL;
|
||||
argsattr = PyObject_GetAttrString(self, "args");
|
||||
if (!argsattr)
|
||||
return NULL;
|
||||
|
||||
/* If args is a tuple of exactly one item, apply repr to args[0].
|
||||
This is done so that e.g. the exception raised by {}[''] prints
|
||||
|
@ -889,14 +974,14 @@ KeyError__str__(PyObject *self, PyObject *args)
|
|||
KeyError
|
||||
alone. The downside is that if KeyError is raised with an explanatory
|
||||
string, that string will be displayed in quotes. Too bad.
|
||||
If args is anything else, use the default Exception__str__().
|
||||
If args is anything else, use the default BaseException__str__().
|
||||
*/
|
||||
if (PyTuple_Check(argsattr) && PyTuple_GET_SIZE(argsattr) == 1) {
|
||||
PyObject *key = PyTuple_GET_ITEM(argsattr, 0);
|
||||
result = PyObject_Repr(key);
|
||||
}
|
||||
else
|
||||
result = Exception__str__(self, args);
|
||||
result = BaseException__str__(self, args);
|
||||
|
||||
Py_DECREF(argsattr);
|
||||
return result;
|
||||
|
@ -1193,6 +1278,11 @@ UnicodeError__init__(PyObject *self, PyObject *args, PyTypeObject *objecttype)
|
|||
if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
|
||||
return NULL;
|
||||
|
||||
if (!set_args_and_message(self, args)) {
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!O!O!O!O!",
|
||||
&PyString_Type, &encoding,
|
||||
objecttype, &object,
|
||||
|
@ -1201,9 +1291,6 @@ UnicodeError__init__(PyObject *self, PyObject *args, PyTypeObject *objecttype)
|
|||
&PyString_Type, &reason))
|
||||
goto finally;
|
||||
|
||||
if (PyObject_SetAttrString(self, "args", args))
|
||||
goto finally;
|
||||
|
||||
if (PyObject_SetAttrString(self, "encoding", encoding))
|
||||
goto finally;
|
||||
if (PyObject_SetAttrString(self, "object", object))
|
||||
|
@ -1405,6 +1492,11 @@ UnicodeTranslateError__init__(PyObject *self, PyObject *args)
|
|||
if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
|
||||
return NULL;
|
||||
|
||||
if (!set_args_and_message(self, args)) {
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!O!O!O!",
|
||||
&PyUnicode_Type, &object,
|
||||
&PyInt_Type, &start,
|
||||
|
@ -1412,9 +1504,6 @@ UnicodeTranslateError__init__(PyObject *self, PyObject *args)
|
|||
&PyString_Type, &reason))
|
||||
goto finally;
|
||||
|
||||
if (PyObject_SetAttrString(self, "args", args))
|
||||
goto finally;
|
||||
|
||||
if (PyObject_SetAttrString(self, "object", object))
|
||||
goto finally;
|
||||
if (PyObject_SetAttrString(self, "start", start))
|
||||
|
@ -1424,8 +1513,8 @@ UnicodeTranslateError__init__(PyObject *self, PyObject *args)
|
|||
if (PyObject_SetAttrString(self, "reason", reason))
|
||||
goto finally;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
rtnval = Py_None;
|
||||
Py_INCREF(rtnval);
|
||||
|
||||
finally:
|
||||
Py_DECREF(args);
|
||||
|
@ -1591,6 +1680,7 @@ static PyMethodDef functions[] = {
|
|||
|
||||
/* Global C API defined exceptions */
|
||||
|
||||
PyObject *PyExc_BaseException;
|
||||
PyObject *PyExc_Exception;
|
||||
PyObject *PyExc_StopIteration;
|
||||
PyObject *PyExc_GeneratorExit;
|
||||
|
@ -1636,7 +1726,7 @@ PyObject *PyExc_VMSError;
|
|||
#endif
|
||||
|
||||
/* Pre-computed MemoryError instance. Best to create this as early as
|
||||
* possibly and not wait until a MemoryError is actually raised!
|
||||
* possible and not wait until a MemoryError is actually raised!
|
||||
*/
|
||||
PyObject *PyExc_MemoryErrorInst;
|
||||
|
||||
|
@ -1663,9 +1753,10 @@ static struct {
|
|||
int (*classinit)(PyObject *);
|
||||
} exctable[] = {
|
||||
/*
|
||||
* The first three classes MUST appear in exactly this order
|
||||
* The first four classes MUST appear in exactly this order
|
||||
*/
|
||||
{"Exception", &PyExc_Exception},
|
||||
{"BaseException", &PyExc_BaseException},
|
||||
{"Exception", &PyExc_Exception, &PyExc_BaseException, Exception__doc__},
|
||||
{"StopIteration", &PyExc_StopIteration, &PyExc_Exception,
|
||||
StopIteration__doc__},
|
||||
{"GeneratorExit", &PyExc_GeneratorExit, &PyExc_Exception,
|
||||
|
@ -1676,9 +1767,10 @@ static struct {
|
|||
/*
|
||||
* The rest appear in depth-first order of the hierarchy
|
||||
*/
|
||||
{"SystemExit", &PyExc_SystemExit, &PyExc_Exception, SystemExit__doc__,
|
||||
{"SystemExit", &PyExc_SystemExit, &PyExc_BaseException, SystemExit__doc__,
|
||||
SystemExit_methods},
|
||||
{"KeyboardInterrupt", &PyExc_KeyboardInterrupt, 0, KeyboardInterrupt__doc__},
|
||||
{"KeyboardInterrupt", &PyExc_KeyboardInterrupt, &PyExc_BaseException,
|
||||
KeyboardInterrupt__doc__},
|
||||
{"ImportError", &PyExc_ImportError, 0, ImportError__doc__},
|
||||
{"EnvironmentError", &PyExc_EnvironmentError, 0, EnvironmentError__doc__,
|
||||
EnvironmentError_methods},
|
||||
|
@ -1786,11 +1878,11 @@ _PyExc_Init(void)
|
|||
}
|
||||
|
||||
/* This is the base class of all exceptions, so make it first. */
|
||||
if (make_Exception(modulename) ||
|
||||
PyDict_SetItemString(mydict, "Exception", PyExc_Exception) ||
|
||||
PyDict_SetItemString(bdict, "Exception", PyExc_Exception))
|
||||
if (make_BaseException(modulename) ||
|
||||
PyDict_SetItemString(mydict, "BaseException", PyExc_BaseException) ||
|
||||
PyDict_SetItemString(bdict, "BaseException", PyExc_BaseException))
|
||||
{
|
||||
Py_FatalError("Base class `Exception' could not be created.");
|
||||
Py_FatalError("Base class `BaseException' could not be created.");
|
||||
}
|
||||
|
||||
/* Now we can programmatically create all the remaining exceptions.
|
||||
|
|
|
@ -976,7 +976,7 @@ handle_system_exit(void)
|
|||
fflush(stdout);
|
||||
if (value == NULL || value == Py_None)
|
||||
goto done;
|
||||
if (PyInstance_Check(value)) {
|
||||
if (PyExceptionInstance_Check(value)) {
|
||||
/* The error code should be in the `code' attribute. */
|
||||
PyObject *code = PyObject_GetAttrString(value, "code");
|
||||
if (code) {
|
||||
|
@ -1106,11 +1106,10 @@ void PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
|
|||
if (err) {
|
||||
/* Don't do anything else */
|
||||
}
|
||||
else if (PyClass_Check(exception)) {
|
||||
PyClassObject* exc = (PyClassObject*)exception;
|
||||
PyObject* className = exc->cl_name;
|
||||
else if (PyExceptionClass_Check(exception)) {
|
||||
char* className = PyExceptionClass_Name(exception);
|
||||
PyObject* moduleName =
|
||||
PyDict_GetItemString(exc->cl_dict, "__module__");
|
||||
PyObject_GetAttrString(exception, "__module__");
|
||||
|
||||
if (moduleName == NULL)
|
||||
err = PyFile_WriteString("<unknown>", f);
|
||||
|
@ -1126,8 +1125,7 @@ void PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
|
|||
if (className == NULL)
|
||||
err = PyFile_WriteString("<unknown>", f);
|
||||
else
|
||||
err = PyFile_WriteObject(className, f,
|
||||
Py_PRINT_RAW);
|
||||
err = PyFile_WriteString(className, f);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue