mirror of
https://github.com/python/cpython.git
synced 2026-05-07 02:51:00 +00:00
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
16 changed files with 570 additions and 232 deletions
|
|
@ -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)
|
||||
|
|
@ -282,7 +285,7 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
|
|||
{
|
||||
/* Note that the Win32 errors do not lineup with the
|
||||
errno error. So if the error is in the MSVC error
|
||||
table, we use it, otherwise we assume it really _is_
|
||||
table, we use it, otherwise we assume it really _is_
|
||||
a Win32 error code
|
||||
*/
|
||||
if (i > 0 && i < _sys_nerr) {
|
||||
|
|
@ -302,7 +305,7 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
|
|||
0, /* size not used */
|
||||
NULL); /* no args */
|
||||
if (len==0) {
|
||||
/* Only ever seen this in out-of-mem
|
||||
/* Only ever seen this in out-of-mem
|
||||
situations */
|
||||
sprintf(s_small_buf, "Windows Error 0x%X", i);
|
||||
s = s_small_buf;
|
||||
|
|
@ -345,8 +348,8 @@ PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename)
|
|||
PyObject *
|
||||
PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, Py_UNICODE *filename)
|
||||
{
|
||||
PyObject *name = filename ?
|
||||
PyUnicode_FromUnicode(filename, wcslen(filename)) :
|
||||
PyObject *name = filename ?
|
||||
PyUnicode_FromUnicode(filename, wcslen(filename)) :
|
||||
NULL;
|
||||
PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
|
||||
Py_XDECREF(name);
|
||||
|
|
@ -360,7 +363,7 @@ PyErr_SetFromErrno(PyObject *exc)
|
|||
return PyErr_SetFromErrnoWithFilenameObject(exc, NULL);
|
||||
}
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
#ifdef MS_WINDOWS
|
||||
/* Windows specific error code handling */
|
||||
PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
|
||||
PyObject *exc,
|
||||
|
|
@ -415,8 +418,8 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilename(
|
|||
const char *filename)
|
||||
{
|
||||
PyObject *name = filename ? PyString_FromString(filename) : NULL;
|
||||
PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
|
||||
ierr,
|
||||
PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
|
||||
ierr,
|
||||
name);
|
||||
Py_XDECREF(name);
|
||||
return ret;
|
||||
|
|
@ -428,11 +431,11 @@ PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename(
|
|||
int ierr,
|
||||
const Py_UNICODE *filename)
|
||||
{
|
||||
PyObject *name = filename ?
|
||||
PyUnicode_FromUnicode(filename, wcslen(filename)) :
|
||||
PyObject *name = filename ?
|
||||
PyUnicode_FromUnicode(filename, wcslen(filename)) :
|
||||
NULL;
|
||||
PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
|
||||
ierr,
|
||||
PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
|
||||
ierr,
|
||||
name);
|
||||
Py_XDECREF(name);
|
||||
return ret;
|
||||
|
|
@ -466,8 +469,8 @@ PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename(
|
|||
int ierr,
|
||||
const Py_UNICODE *filename)
|
||||
{
|
||||
PyObject *name = filename ?
|
||||
PyUnicode_FromUnicode(filename, wcslen(filename)) :
|
||||
PyObject *name = filename ?
|
||||
PyUnicode_FromUnicode(filename, wcslen(filename)) :
|
||||
NULL;
|
||||
PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(
|
||||
PyExc_WindowsError,
|
||||
|
|
@ -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);
|
||||
|
|
@ -726,7 +746,7 @@ PyErr_SyntaxLocation(const char *filename, int lineno)
|
|||
|
||||
/* com_fetch_program_text will attempt to load the line of text that
|
||||
the exception refers to. If it fails, it will return NULL but will
|
||||
not set an exception.
|
||||
not set an exception.
|
||||
|
||||
XXX The functionality of this function is quite similar to the
|
||||
functionality in tb_displayline() in traceback.c.
|
||||
|
|
|
|||
|
|
@ -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…
Add table
Add a link
Reference in a new issue