From 7b9558d37dc7f2c6ae984cf25d16b9bf5e532b77 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Sat, 27 May 2006 12:29:24 +0000 Subject: Conversion of exceptions over from faked-up classes to new-style C types. --- Doc/tut/tut.tex | 2 +- Include/pyerrors.h | 68 +- Lib/codeop.py | 10 +- Lib/ctypes/test/test_structures.py | 8 +- Lib/test/exception_hierarchy.txt | 2 +- Lib/test/output/test_logging | 6 +- Lib/test/test_codeccallbacks.py | 73 -- Lib/test/test_exceptions.py | 93 +- Lib/warnings.py | 2 - Makefile.pre.in | 2 +- Modules/cPickle.c | 2 - Objects/exceptions.c | 2130 ++++++++++++++++++++++++++++++++++++ PCbuild/pythoncore.vcproj | 2 +- Python/errors.c | 35 +- Python/exceptions.c | 2032 ---------------------------------- Python/pythonrun.c | 12 +- 16 files changed, 2316 insertions(+), 2163 deletions(-) create mode 100644 Objects/exceptions.c delete mode 100644 Python/exceptions.c diff --git a/Doc/tut/tut.tex b/Doc/tut/tut.tex index f6cdb1e..88fb58b 100644 --- a/Doc/tut/tut.tex +++ b/Doc/tut/tut.tex @@ -2711,7 +2711,7 @@ standard module \module{__builtin__}\refbimodindex{__builtin__}: 'FloatingPointError', 'FutureWarning', 'IOError', 'ImportError', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', - 'NotImplementedError', 'OSError', 'OverflowError', 'OverflowWarning', + 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', diff --git a/Include/pyerrors.h b/Include/pyerrors.h index edf3efd..6fa6ed7 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -4,6 +4,72 @@ extern "C" { #endif +/* Error objects */ + +typedef struct { + PyObject_HEAD + PyObject *dict; + PyObject *args; + PyObject *message; +} PyBaseExceptionObject; + +typedef struct { + PyObject_HEAD + PyObject *dict; + PyObject *args; + PyObject *message; + PyObject *msg; + PyObject *filename; + PyObject *lineno; + PyObject *offset; + PyObject *text; + PyObject *print_file_and_line; +} PySyntaxErrorObject; + +#ifdef Py_USING_UNICODE +typedef struct { + PyObject_HEAD + PyObject *dict; + PyObject *args; + PyObject *message; + PyObject *encoding; + PyObject *object; + PyObject *start; + PyObject *end; + PyObject *reason; +} PyUnicodeErrorObject; +#endif + +typedef struct { + PyObject_HEAD + PyObject *dict; + PyObject *args; + PyObject *message; + PyObject *code; +} PySystemExitObject; + +typedef struct { + PyObject_HEAD + PyObject *dict; + PyObject *args; + PyObject *message; + PyObject *myerrno; + PyObject *strerror; + PyObject *filename; +} PyEnvironmentErrorObject; + +#ifdef MS_WINDOWS +typedef struct { + PyObject_HEAD + PyObject *dict; + PyObject *args; + PyObject *message; + PyObject *myerrno; + PyObject *strerror; + PyObject *filename; + PyObject *winerror; +} PyWindowsErrorObject; +#endif /* Error handling definitions */ @@ -104,8 +170,6 @@ PyAPI_DATA(PyObject *) PyExc_UserWarning; PyAPI_DATA(PyObject *) PyExc_DeprecationWarning; PyAPI_DATA(PyObject *) PyExc_PendingDeprecationWarning; PyAPI_DATA(PyObject *) PyExc_SyntaxWarning; -/* PyExc_OverflowWarning will go away for Python 2.5 */ -PyAPI_DATA(PyObject *) PyExc_OverflowWarning; PyAPI_DATA(PyObject *) PyExc_RuntimeWarning; PyAPI_DATA(PyObject *) PyExc_FutureWarning; PyAPI_DATA(PyObject *) PyExc_ImportWarning; diff --git a/Lib/codeop.py b/Lib/codeop.py index daa7eb8..5616d92 100644 --- a/Lib/codeop.py +++ b/Lib/codeop.py @@ -95,15 +95,7 @@ def _maybe_compile(compiler, source, filename, symbol): if code: return code - try: - e1 = err1.__dict__ - except AttributeError: - e1 = err1 - try: - e2 = err2.__dict__ - except AttributeError: - e2 = err2 - if not code1 and e1 == e2: + if not code1 and repr(err1) == repr(err2): raise SyntaxError, err1 def _compile(source, filename, symbol): diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py index b6eaac4..5340f79 100644 --- a/Lib/ctypes/test/test_structures.py +++ b/Lib/ctypes/test/test_structures.py @@ -294,20 +294,20 @@ class StructureTestCase(unittest.TestCase): # In Python 2.5, Exception is a new-style class, and the repr changed if issubclass(Exception, object): self.failUnlessEqual(msg, - "(Phone) : " + "(Phone) : " "expected string or Unicode object, int found") else: self.failUnlessEqual(msg, - "(Phone) exceptions.TypeError: " + "(Phone) TypeError: " "expected string or Unicode object, int found") cls, msg = self.get_except(Person, "Someone", ("a", "b", "c")) self.failUnlessEqual(cls, RuntimeError) if issubclass(Exception, object): self.failUnlessEqual(msg, - "(Phone) : too many initializers") + "(Phone) : too many initializers") else: - self.failUnlessEqual(msg, "(Phone) exceptions.ValueError: too many initializers") + self.failUnlessEqual(msg, "(Phone) ValueError: too many initializers") def get_except(self, func, *args): diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt index 5fff7d9..58131d7 100644 --- a/Lib/test/exception_hierarchy.txt +++ b/Lib/test/exception_hierarchy.txt @@ -15,6 +15,7 @@ BaseException | | +-- IOError | | +-- OSError | | +-- WindowsError (Windows) + | | +-- VMSError (VMS) | +-- EOFError | +-- ImportError | +-- LookupError @@ -43,5 +44,4 @@ BaseException +-- SyntaxWarning +-- UserWarning +-- FutureWarning - +-- OverflowWarning [not generated by the interpreter] +-- ImportWarning diff --git a/Lib/test/output/test_logging b/Lib/test/output/test_logging index 7be3a3e..c0d6e06 100644 --- a/Lib/test/output/test_logging +++ b/Lib/test/output/test_logging @@ -488,12 +488,12 @@ INFO:a.b.c.d:Info 5 -- log_test4 begin --------------------------------------------------- config0: ok. config1: ok. -config2: -config3: +config2: +config3: -- log_test4 end --------------------------------------------------- -- log_test5 begin --------------------------------------------------- ERROR:root:just testing -... Don't panic! +... Don't panic! -- log_test5 end --------------------------------------------------- -- logrecv output begin --------------------------------------------------- ERR -> CRITICAL: Message 0 (via logrecv.tcp.ERR) diff --git a/Lib/test/test_codeccallbacks.py b/Lib/test/test_codeccallbacks.py index c6e56c9..159c86d 100644 --- a/Lib/test/test_codeccallbacks.py +++ b/Lib/test/test_codeccallbacks.py @@ -18,30 +18,12 @@ class PosReturn: self.pos = len(exc.object) return (u"", oldpos) -# A UnicodeEncodeError object without a start attribute -class NoStartUnicodeEncodeError(UnicodeEncodeError): - def __init__(self): - UnicodeEncodeError.__init__(self, "ascii", u"", 0, 1, "bad") - del self.start - # A UnicodeEncodeError object with a bad start attribute class BadStartUnicodeEncodeError(UnicodeEncodeError): def __init__(self): UnicodeEncodeError.__init__(self, "ascii", u"", 0, 1, "bad") self.start = [] -# A UnicodeEncodeError object without an end attribute -class NoEndUnicodeEncodeError(UnicodeEncodeError): - def __init__(self): - UnicodeEncodeError.__init__(self, "ascii", u"", 0, 1, "bad") - del self.end - -# A UnicodeEncodeError object without an object attribute -class NoObjectUnicodeEncodeError(UnicodeEncodeError): - def __init__(self): - UnicodeEncodeError.__init__(self, "ascii", u"", 0, 1, "bad") - del self.object - # A UnicodeEncodeError object with a bad object attribute class BadObjectUnicodeEncodeError(UnicodeEncodeError): def __init__(self): @@ -478,55 +460,15 @@ class CodecCallbackTest(unittest.TestCase): UnicodeError("ouch") ) self.assertRaises( - AttributeError, - codecs.replace_errors, - NoStartUnicodeEncodeError() - ) - self.assertRaises( - TypeError, - codecs.replace_errors, - BadStartUnicodeEncodeError() - ) - self.assertRaises( - AttributeError, - codecs.replace_errors, - NoEndUnicodeEncodeError() - ) - self.assertRaises( - AttributeError, - codecs.replace_errors, - NoObjectUnicodeEncodeError() - ) - self.assertRaises( TypeError, codecs.replace_errors, BadObjectUnicodeEncodeError() ) self.assertRaises( - AttributeError, - codecs.replace_errors, - NoEndUnicodeDecodeError() - ) - self.assertRaises( TypeError, codecs.replace_errors, BadObjectUnicodeDecodeError() ) - self.assertRaises( - AttributeError, - codecs.replace_errors, - NoStartUnicodeTranslateError() - ) - self.assertRaises( - AttributeError, - codecs.replace_errors, - NoEndUnicodeTranslateError() - ) - self.assertRaises( - AttributeError, - codecs.replace_errors, - NoObjectUnicodeTranslateError() - ) # With the correct exception, "replace" returns an "?" or u"\ufffd" replacement self.assertEquals( codecs.replace_errors(UnicodeEncodeError("ascii", u"\u3042", 0, 1, "ouch")), @@ -565,21 +507,6 @@ class CodecCallbackTest(unittest.TestCase): codecs.xmlcharrefreplace_errors, UnicodeTranslateError(u"\u3042", 0, 1, "ouch") ) - self.assertRaises( - AttributeError, - codecs.xmlcharrefreplace_errors, - NoStartUnicodeEncodeError() - ) - self.assertRaises( - AttributeError, - codecs.xmlcharrefreplace_errors, - NoEndUnicodeEncodeError() - ) - self.assertRaises( - AttributeError, - codecs.xmlcharrefreplace_errors, - NoObjectUnicodeEncodeError() - ) # Use the correct exception cs = (0, 1, 9, 10, 99, 100, 999, 1000, 9999, 10000, 0x3042) s = "".join(unichr(c) for c in cs) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index fdef876..076d84d 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -81,14 +81,6 @@ try: x = undefined_variable except NameError: pass r(OverflowError) -# XXX -# Obscure: in 2.2 and 2.3, this test relied on changing OverflowWarning -# into an error, in order to trigger OverflowError. In 2.4, OverflowWarning -# should no longer be generated, so the focus of the test shifts to showing -# that OverflowError *isn't* generated. OverflowWarning should be gone -# in Python 2.5, and then the filterwarnings() call, and this comment, -# should go away. -warnings.filterwarnings("error", "", OverflowWarning, __name__) x = 1 for dummy in range(128): x += x # this simply shouldn't blow up @@ -206,3 +198,88 @@ if not sys.platform.startswith('java'): test_capi2() unlink(TESTFN) + +# test that exception attributes are happy. +try: str(u'Hello \u00E1') +except Exception, e: sampleUnicodeEncodeError = e +try: unicode('\xff') +except Exception, e: sampleUnicodeDecodeError = e +exceptionList = [ + ( BaseException, (), { 'message' : '', 'args' : () }), + ( BaseException, (1, ), { 'message' : 1, 'args' : ( 1, ) }), + ( BaseException, ('foo', ), { 'message' : 'foo', 'args' : ( 'foo', ) }), + ( BaseException, ('foo', 1), { 'message' : '', 'args' : ( 'foo', 1 ) }), + ( SystemExit, ('foo',), { 'message' : 'foo', 'args' : ( 'foo', ), + 'code' : 'foo' }), + ( IOError, ('foo',), { 'message' : 'foo', 'args' : ( 'foo', ), }), + ( IOError, ('foo', 'bar'), { 'message' : '', + 'args' : ('foo', 'bar'), }), + ( IOError, ('foo', 'bar', 'baz'), + { 'message' : '', 'args' : ('foo', 'bar'), }), + ( EnvironmentError, ('errnoStr', 'strErrorStr', 'filenameStr'), + { 'message' : '', 'args' : ('errnoStr', 'strErrorStr'), + 'strerror' : 'strErrorStr', + 'errno' : 'errnoStr', 'filename' : 'filenameStr' }), + ( EnvironmentError, (1, 'strErrorStr', 'filenameStr'), + { 'message' : '', 'args' : (1, 'strErrorStr'), + 'strerror' : 'strErrorStr', 'errno' : 1, + 'filename' : 'filenameStr' }), + ( SyntaxError, ('msgStr',), + { 'message' : 'msgStr', 'args' : ('msgStr', ), + 'print_file_and_line' : None, 'msg' : 'msgStr', + 'filename' : None, 'lineno' : None, 'offset' : None, + 'text' : None }), + ( SyntaxError, ('msgStr', ('filenameStr', 'linenoStr', 'offsetStr', + 'textStr')), + { 'message' : '', 'args' : ('msgStr', ('filenameStr', + 'linenoStr', 'offsetStr', 'textStr' )), + 'print_file_and_line' : None, 'msg' : 'msgStr', + 'filename' : 'filenameStr', 'lineno' : 'linenoStr', + 'offset' : 'offsetStr', 'text' : 'textStr' }), + ( SyntaxError, ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr', + 'textStr', 'print_file_and_lineStr'), + { 'message' : '', 'args' : ('msgStr', 'filenameStr', + 'linenoStr', 'offsetStr', 'textStr', + 'print_file_and_lineStr'), + 'print_file_and_line' : None, 'msg' : 'msgStr', + 'filename' : None, 'lineno' : None, 'offset' : None, + 'text' : None }), + ( UnicodeError, (), + { 'message' : '', 'args' : (), }), + ( sampleUnicodeEncodeError, + { 'message' : '', 'args' : ('ascii', u'Hello \xe1', 6, 7, + 'ordinal not in range(128)'), + 'encoding' : 'ascii', 'object' : u'Hello \xe1', + 'start' : 6, 'reason' : 'ordinal not in range(128)' }), + ( sampleUnicodeDecodeError, + { 'message' : '', 'args' : ('ascii', '\xff', 0, 1, + 'ordinal not in range(128)'), + 'encoding' : 'ascii', 'object' : '\xff', + 'start' : 0, 'reason' : 'ordinal not in range(128)' }), + ( UnicodeTranslateError, (u"\u3042", 0, 1, "ouch"), + { 'message' : '', 'args' : (u'\u3042', 0, 1, 'ouch'), + 'object' : u'\u3042', 'reason' : 'ouch', + 'start' : 0, 'end' : 1 }), + ] +try: + exceptionList.append( + ( WindowsError, (1, 'strErrorStr', 'filenameStr'), + { 'message' : '', 'args' : (1, 'strErrorStr'), + 'strerror' : 'strErrorStr', + 'errno' : 22, 'filename' : 'filenameStr', + 'winerror' : 1 })) +except NameError: pass + +for args in exceptionList: + expected = args[-1] + try: + if len(args) == 2: raise args[0] + else: raise apply(args[0], args[1]) + except BaseException, e: + for checkArgName in expected.keys(): + if repr(getattr(e, checkArgName)) != repr(expected[checkArgName]): + raise TestFailed('Checking exception arguments, exception ' + '"%s", attribute "%s" expected %s got %s.' % + ( repr(e), checkArgName, + repr(expected[checkArgName]), + repr(getattr(e, checkArgName)) )) diff --git a/Lib/warnings.py b/Lib/warnings.py index bc0b818..b5d75e4 100644 --- a/Lib/warnings.py +++ b/Lib/warnings.py @@ -261,6 +261,4 @@ def _getcategory(category): # Module initialization _processoptions(sys.warnoptions) -# XXX OverflowWarning should go away for Python 2.5. -simplefilter("ignore", category=OverflowWarning, append=1) simplefilter("ignore", category=PendingDeprecationWarning, append=1) diff --git a/Makefile.pre.in b/Makefile.pre.in index a41ded3..566e5d4 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -240,7 +240,6 @@ PYTHON_OBJS= \ Python/asdl.o \ Python/ast.o \ Python/bltinmodule.o \ - Python/exceptions.o \ Python/ceval.o \ Python/compile.o \ Python/codecs.o \ @@ -289,6 +288,7 @@ OBJECT_OBJS= \ Objects/complexobject.o \ Objects/descrobject.o \ Objects/enumobject.o \ + Objects/exceptions.o \ Objects/genobject.o \ Objects/fileobject.o \ Objects/floatobject.o \ diff --git a/Modules/cPickle.c b/Modules/cPickle.c index 4c630bb..85fd459 100644 --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -5625,7 +5625,6 @@ init_stuff(PyObject *module_dict) if (!( t=PyDict_New())) return -1; if (!( r=PyRun_String( - "def __init__(self, *args): self.args=args\n\n" "def __str__(self):\n" " return self.args and ('%s' % self.args[0]) or '(what)'\n", Py_file_input, @@ -5645,7 +5644,6 @@ init_stuff(PyObject *module_dict) if (!( t=PyDict_New())) return -1; if (!( r=PyRun_String( - "def __init__(self, *args): self.args=args\n\n" "def __str__(self):\n" " a=self.args\n" " a=a and type(a[0]) or '(what)'\n" diff --git a/Objects/exceptions.c b/Objects/exceptions.c new file mode 100644 index 0000000..4c88d68 --- /dev/null +++ b/Objects/exceptions.c @@ -0,0 +1,2130 @@ +#define PY_SSIZE_T_CLEAN +#include +#include "structmember.h" +#include "osdefs.h" + +#define MAKE_IT_NONE(x) (x) = Py_None; Py_INCREF(Py_None); +#define EXC_MODULE_NAME "exceptions." + +/* + * BaseException + */ +static PyObject * +BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyBaseExceptionObject *self; + + self = (PyBaseExceptionObject *)type->tp_alloc(type, 0); + /* the dict is created on the fly in PyObject_GenericSetAttr */ + self->message = self->dict = NULL; + + self->args = PyTuple_New(0); + if (!self->args) { + Py_DECREF(self); + return NULL; + } + + self->message = PyString_FromString(""); + if (!self->message) { + Py_DECREF(self); + return NULL; + } + + return (PyObject *)self; +} + +static int +BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds) +{ + Py_DECREF(self->args); + self->args = args; + Py_INCREF(self->args); + + if (PyTuple_GET_SIZE(self->args) == 1) { + Py_DECREF(self->message); + self->message = PyTuple_GET_ITEM(self->args, 0); + Py_INCREF(self->message); + } + return 0; +} + +int +BaseException_clear(PyBaseExceptionObject *self) +{ + Py_CLEAR(self->dict); + Py_CLEAR(self->args); + Py_CLEAR(self->message); + return 0; +} + +static void +BaseException_dealloc(PyBaseExceptionObject *self) +{ + BaseException_clear(self); + self->ob_type->tp_free((PyObject *)self); +} + +int +BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg) +{ + if (self->dict) + Py_VISIT(self->dict); + Py_VISIT(self->args); + Py_VISIT(self->message); + return 0; +} + +static PyObject * +BaseException_str(PyBaseExceptionObject *self) +{ + PyObject *out; + + switch (PySequence_Length(self->args)) { + case 0: + out = PyString_FromString(""); + break; + case 1: + { + PyObject *tmp = PySequence_GetItem(self->args, 0); + if (tmp) { + out = PyObject_Str(tmp); + Py_DECREF(tmp); + } + else + out = NULL; + break; + } + case -1: + PyErr_Clear(); + /* Fall through */ + default: + out = PyObject_Str(self->args); + break; + } + + return out; +} + +static PyObject * +BaseException_repr(PyBaseExceptionObject *self) +{ + Py_ssize_t args_len; + PyObject *repr_suffix; + PyObject *repr; + char *name; + char *dot; + + args_len = PySequence_Length(self->args); + if (args_len < 0) { + return NULL; + } + + if (args_len == 0) { + repr_suffix = PyString_FromString("()"); + if (!repr_suffix) + return NULL; + } + else { + PyObject *args_repr = PyObject_Repr(self->args); + if (!args_repr) + return NULL; + repr_suffix = args_repr; + } + + name = (char *)self->ob_type->tp_name; + dot = strrchr(name, '.'); + if (dot != NULL) name = dot+1; + + repr = PyString_FromString(name); + if (!repr) { + Py_DECREF(repr_suffix); + return NULL; + } + + PyString_ConcatAndDel(&repr, repr_suffix); + return repr; +} + +/* Pickling support */ +static PyObject * +BaseException_reduce(PyBaseExceptionObject *self) +{ + return PyTuple_Pack(3, self->ob_type, self->args, self->dict); +} + + +#ifdef Py_USING_UNICODE +/* while this method generates fairly uninspired output, it a least + * guarantees that we can display exceptions that have unicode attributes + */ +static PyObject * +BaseException_unicode(PyBaseExceptionObject *self) +{ + if (PySequence_Length(self->args) == 0) + return PyUnicode_FromUnicode(NULL, 0); + if (PySequence_Length(self->args) == 1) { + PyObject *temp = PySequence_GetItem(self->args, 0); + PyObject *unicode_obj; + if (!temp) { + return NULL; + } + unicode_obj = PyObject_Unicode(temp); + Py_DECREF(temp); + return unicode_obj; + } + return PyObject_Unicode(self->args); +} +#endif /* Py_USING_UNICODE */ + +static PyMethodDef BaseException_methods[] = { + {"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS }, +#ifdef Py_USING_UNICODE + {"__unicode__", (PyCFunction)BaseException_unicode, METH_NOARGS }, +#endif + {NULL, NULL, 0, NULL}, +}; + + + +static PyObject * +BaseException_getitem(PyBaseExceptionObject *self, Py_ssize_t index) +{ + return PySequence_GetItem(self->args, index); +} + +static PySequenceMethods BaseException_as_sequence = { + 0, /* sq_length; */ + 0, /* sq_concat; */ + 0, /* sq_repeat; */ + (ssizeargfunc)BaseException_getitem, /* sq_item; */ + 0, /* sq_slice; */ + 0, /* sq_ass_item; */ + 0, /* sq_ass_slice; */ + 0, /* sq_contains; */ + 0, /* sq_inplace_concat; */ + 0 /* sq_inplace_repeat; */ +}; + +static PyMemberDef BaseException_members[] = { + {"message", T_OBJECT, offsetof(PyBaseExceptionObject, message), 0, + PyDoc_STR("exception message")}, + {NULL} /* Sentinel */ +}; + + +static PyObject * +BaseException_get_dict(PyBaseExceptionObject *self) +{ + if (self->dict == NULL) { + self->dict = PyDict_New(); + if (!self->dict) + return NULL; + } + Py_INCREF(self->dict); + return self->dict; +} + +static int +BaseException_set_dict(PyBaseExceptionObject *self, PyObject *val) +{ + if (val == NULL) { + PyErr_SetString(PyExc_TypeError, "__dict__ may not be deleted"); + return -1; + } + if (!PyDict_Check(val)) { + PyErr_SetString(PyExc_TypeError, "__dict__ must be a dictionary"); + return -1; + } + Py_CLEAR(self->dict); + Py_INCREF(val); + self->dict = val; + return 0; +} + +static PyObject * +BaseException_get_args(PyBaseExceptionObject *self) +{ + if (self->args == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + Py_INCREF(self->args); + return self->args; +} + +static int +BaseException_set_args(PyBaseExceptionObject *self, PyObject *val) +{ + PyObject *seq; + if (val == NULL) { + PyErr_SetString(PyExc_TypeError, "args may not be deleted"); + return -1; + } + seq = PySequence_Tuple(val); + if (!seq) return -1; + self->args = seq; + return 0; +} + +static PyGetSetDef BaseException_getset[] = { + {"__dict__", (getter)BaseException_get_dict, (setter)BaseException_set_dict}, + {"args", (getter)BaseException_get_args, (setter)BaseException_set_args}, + {NULL}, +}; + + +static PyTypeObject _PyExc_BaseException = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + EXC_MODULE_NAME "BaseException", /*tp_name*/ + sizeof(PyBaseExceptionObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)BaseException_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /* tp_compare; */ + (reprfunc)BaseException_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + &BaseException_as_sequence, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + (reprfunc)BaseException_str, /*tp_str*/ + PyObject_GenericGetAttr, /*tp_getattro*/ + PyObject_GenericSetAttr, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + PyDoc_STR("Common base class for all exceptions"), /* tp_doc */ + (traverseproc)BaseException_traverse, /* tp_traverse */ + (inquiry)BaseException_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BaseException_methods, /* tp_methods */ + BaseException_members, /* tp_members */ + BaseException_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(PyBaseExceptionObject, dict), /* tp_dictoffset */ + (initproc)BaseException_init, /* tp_init */ + 0, /* tp_alloc */ + BaseException_new, /* tp_new */ +}; +/* the CPython API expects exceptions to be (PyObject *) - both a hold-over +from the previous implmentation and also allowing Python objects to be used +in the API */ +PyObject *PyExc_BaseException = (PyObject *)&_PyExc_BaseException; + +#define SimpleExtendsException(EXCBASE, EXCNAME, EXCDOC) \ +static PyTypeObject _PyExc_ ## EXCNAME = { \ + PyObject_HEAD_INIT(NULL) \ + 0, \ + EXC_MODULE_NAME # EXCNAME, \ + sizeof(PyBaseExceptionObject), \ + 0, (destructor)BaseException_dealloc, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, \ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \ + PyDoc_STR(EXCDOC), (traverseproc)BaseException_traverse, \ + (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \ + 0, 0, 0, offsetof(PyBaseExceptionObject, dict), \ + (initproc)BaseException_init, 0, BaseException_new,\ +}; \ +PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME; + +#define MiddlingExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDOC) \ +static PyTypeObject _PyExc_ ## EXCNAME = { \ + PyObject_HEAD_INIT(NULL) \ + 0, \ + EXC_MODULE_NAME # EXCNAME, \ + sizeof(Py ## EXCSTORE ## Object), \ + 0, (destructor)BaseException_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, \ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \ + PyDoc_STR(EXCDOC), (traverseproc)BaseException_traverse, \ + (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \ + 0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \ + (initproc)EXCSTORE ## _init, 0, EXCSTORE ## _new,\ +}; \ +PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME; + +#define ComplexExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDEALLOC, EXCMETHODS, EXCMEMBERS, EXCSTR, EXCDOC) \ +static PyTypeObject _PyExc_ ## EXCNAME = { \ + PyObject_HEAD_INIT(NULL) \ + 0, \ + EXC_MODULE_NAME # EXCNAME, \ + sizeof(Py ## EXCSTORE ## Object), 0, \ + (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + (reprfunc)EXCSTR, 0, 0, 0, \ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \ + PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \ + (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, EXCMETHODS, \ + EXCMEMBERS, 0, &_ ## EXCBASE, \ + 0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \ + (initproc)EXCSTORE ## _init, 0, EXCSTORE ## _new,\ +}; \ +PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME; + + +/* + * Exception extends BaseException + */ +SimpleExtendsException(PyExc_BaseException, Exception, + "Common base class for all non-exit exceptions.") + + +/* + * StandardError extends Exception + */ +SimpleExtendsException(PyExc_Exception, StandardError, + "Base class for all standard Python exceptions that do not represent\n" + "interpreter exiting."); + + +/* + * TypeError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, TypeError, + "Inappropriate argument type."); + + +/* + * StopIteration extends Exception + */ +SimpleExtendsException(PyExc_Exception, StopIteration, + "Signal the end from iterator.next()."); + + +/* + * GeneratorExit extends Exception + */ +SimpleExtendsException(PyExc_Exception, GeneratorExit, + "Request that a generator exit."); + + +/* + * SystemExit extends BaseException + */ +static PyObject * +SystemExit_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PySystemExitObject *self; + + self = (PySystemExitObject *)BaseException_new(type, args, kwds); + if (!self) + return NULL; + + MAKE_IT_NONE(self->code); + + return (PyObject *)self; +} + +static int +SystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds) +{ + Py_ssize_t size = PyTuple_GET_SIZE(args); + + if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) + return -1; + + Py_DECREF(self->code); + if (size == 1) + self->code = PyTuple_GET_ITEM(args, 0); + else if (size > 1) + self->code = args; + Py_INCREF(self->code); + return 0; +} + +int +SystemExit_clear(PySystemExitObject *self) +{ + Py_CLEAR(self->code); + return BaseException_clear((PyBaseExceptionObject *)self); +} + +static void +SystemExit_dealloc(PySystemExitObject *self) +{ + SystemExit_clear(self); + self->ob_type->tp_free((PyObject *)self); +} + +int +SystemExit_traverse(PySystemExitObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->code); + return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); +} + +static PyMemberDef SystemExit_members[] = { + {"message", T_OBJECT, offsetof(PySystemExitObject, message), 0, + PyDoc_STR("exception message")}, + {"code", T_OBJECT, offsetof(PySystemExitObject, code), 0, + PyDoc_STR("exception code")}, + {NULL} /* Sentinel */ +}; + +ComplexExtendsException(PyExc_BaseException, SystemExit, SystemExit, + SystemExit_dealloc, 0, SystemExit_members, 0, + "Request to exit from the interpreter."); + +/* + * KeyboardInterrupt extends BaseException + */ +SimpleExtendsException(PyExc_BaseException, KeyboardInterrupt, + "Program interrupted by user."); + + +/* + * ImportError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, ImportError, + "Import can't find module, or can't find name in module."); + + +/* + * EnvironmentError extends StandardError + */ + +static PyObject * +EnvironmentError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyEnvironmentErrorObject *self = NULL; + + self = (PyEnvironmentErrorObject *)BaseException_new(type, args, kwds); + if (!self) + return NULL; + + self->myerrno = Py_None; + Py_INCREF(Py_None); + self->strerror = Py_None; + Py_INCREF(Py_None); + self->filename = Py_None; + Py_INCREF(Py_None); + + return (PyObject *)self; +} + +/* Where a function has a single filename, such as open() or some + * of the os module functions, PyErr_SetFromErrnoWithFilename() is + * called, giving a third argument which is the filename. But, so + * that old code using in-place unpacking doesn't break, e.g.: + * + * except IOError, (errno, strerror): + * + * we hack args so that it only contains two items. This also + * means we need our own __str__() which prints out the filename + * when it was supplied. + */ +static int +EnvironmentError_init(PyEnvironmentErrorObject *self, PyObject *args, + PyObject *kwds) +{ + PyObject *myerrno = NULL, *strerror = NULL, *filename = NULL; + PyObject *subslice = NULL; + + if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) + return -1; + + if (PyTuple_GET_SIZE(args) <= 1) { + return 0; + } + + if (!PyArg_UnpackTuple(args, "EnvironmentError", 2, 3, + &myerrno, &strerror, &filename)) { + return -1; + } + Py_DECREF(self->myerrno); /* replacing */ + self->myerrno = myerrno; + Py_INCREF(self->myerrno); + + Py_DECREF(self->strerror); /* replacing */ + self->strerror = strerror; + Py_INCREF(self->strerror); + + /* self->filename will remain Py_None otherwise */ + if (filename != NULL) { + Py_DECREF(self->filename); /* replacing */ + self->filename = filename; + Py_INCREF(self->filename); + + subslice = PyTuple_GetSlice(args, 0, 2); + if (!subslice) + return -1; + + Py_DECREF(self->args); /* replacing args */ + self->args = subslice; + } + return 0; +} + +int +EnvironmentError_clear(PyEnvironmentErrorObject *self) +{ + Py_CLEAR(self->myerrno); + Py_CLEAR(self->strerror); + Py_CLEAR(self->filename); + return BaseException_clear((PyBaseExceptionObject *)self); +} + +static void +EnvironmentError_dealloc(PyEnvironmentErrorObject *self) +{ + EnvironmentError_clear(self); + self->ob_type->tp_free((PyObject *)self); +} + +int +EnvironmentError_traverse(PyEnvironmentErrorObject *self, visitproc visit, + void *arg) +{ + Py_VISIT(self->myerrno); + Py_VISIT(self->strerror); + Py_VISIT(self->filename); + return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); +} + +static PyObject * +EnvironmentError_str(PyEnvironmentErrorObject *self) +{ + PyObject *rtnval = NULL; + + if (self->filename != Py_None) { + PyObject *fmt = PyString_FromString("[Errno %s] %s: %s"); + PyObject *repr = PyObject_Repr(self->filename); + PyObject *tuple = PyTuple_New(3); + + if (!fmt || !repr || !tuple) { + Py_XDECREF(fmt); + Py_XDECREF(repr); + Py_XDECREF(tuple); + return NULL; + } + Py_INCREF(self->myerrno); + PyTuple_SET_ITEM(tuple, 0, self->myerrno); + Py_INCREF(self->strerror); + PyTuple_SET_ITEM(tuple, 1, self->strerror); + Py_INCREF(repr); + PyTuple_SET_ITEM(tuple, 2, repr); + + rtnval = PyString_Format(fmt, tuple); + + Py_DECREF(fmt); + Py_DECREF(tuple); + } + else if (PyObject_IsTrue(self->myerrno) && + PyObject_IsTrue(self->strerror)) { + PyObject *fmt = PyString_FromString("[Errno %s] %s"); + PyObject *tuple = PyTuple_New(2); + + if (!fmt || !tuple) { + Py_XDECREF(fmt); + Py_XDECREF(tuple); + return NULL; + } + Py_INCREF(self->myerrno); + PyTuple_SET_ITEM(tuple, 0, self->myerrno); + Py_INCREF(self->strerror); + PyTuple_SET_ITEM(tuple, 1, self->strerror); + + rtnval = PyString_Format(fmt, tuple); + + Py_DECREF(fmt); + Py_DECREF(tuple); + } + else + rtnval = BaseException_str((PyBaseExceptionObject *)self); + + return rtnval; +} + +static PyMemberDef EnvironmentError_members[] = { + {"message", T_OBJECT, offsetof(PyEnvironmentErrorObject, message), 0, + PyDoc_STR("exception message")}, + {"errno", T_OBJECT, offsetof(PyEnvironmentErrorObject, myerrno), 0, + PyDoc_STR("exception code")}, + {"strerror", T_OBJECT, offsetof(PyEnvironmentErrorObject, strerror), 0, + PyDoc_STR("exception code")}, + {"filename", T_OBJECT, offsetof(PyEnvironmentErrorObject, filename), 0, + PyDoc_STR("exception code")}, + {NULL} /* Sentinel */ +}; + + +static PyObject * +EnvironmentError_reduce(PyEnvironmentErrorObject *self) +{ + PyObject *args = self->args; + PyObject *res = NULL, *tmp; + /* self->args is only the first two real arguments if there was a + * file name given to EnvironmentError. */ + if (PyTuple_Check(args) && + PyTuple_GET_SIZE(args) == 2 && + self->filename != Py_None) { + + args = PyTuple_New(3); + if (!args) return NULL; + + tmp = PyTuple_GetItem(self->args, 0); + if (!tmp) goto finish; + Py_INCREF(tmp); + PyTuple_SET_ITEM(args, 0, tmp); + + tmp = PyTuple_GetItem(self->args, 1); + if (!tmp) goto finish; + Py_INCREF(tmp); + PyTuple_SET_ITEM(args, 1, tmp); + + Py_INCREF(self->filename); + PyTuple_SET_ITEM(args, 2, self->filename); + } else { + Py_INCREF(args); + } + res = PyTuple_Pack(3, self->ob_type, args, self->dict); + finish: + Py_DECREF(args); + return res; +} + + +static PyMethodDef EnvironmentError_methods[] = { + {"__reduce__", (PyCFunction)EnvironmentError_reduce, METH_NOARGS}, + {NULL} +}; + +ComplexExtendsException(PyExc_StandardError, EnvironmentError, + EnvironmentError, EnvironmentError_dealloc, + EnvironmentError_methods, EnvironmentError_members, + EnvironmentError_str, + "Base class for I/O related errors."); + + +/* + * IOError extends EnvironmentError + */ +MiddlingExtendsException(PyExc_EnvironmentError, IOError, + EnvironmentError, "I/O operation failed."); + + +/* + * OSError extends EnvironmentError + */ +MiddlingExtendsException(PyExc_EnvironmentError, OSError, + EnvironmentError, "OS system call failed."); + + +/* + * WindowsError extends OSError + */ +#ifdef MS_WINDOWS +#include "errmap.h" + +int +WindowsError_clear(PyWindowsErrorObject *self) +{ + Py_CLEAR(self->myerrno); + Py_CLEAR(self->strerror); + Py_CLEAR(self->filename); + Py_CLEAR(self->winerror); + return BaseException_clear((PyBaseExceptionObject *)self); +} + +static void +WindowsError_dealloc(PyWindowsErrorObject *self) +{ + WindowsError_clear(self); + self->ob_type->tp_free((PyObject *)self); +} + +int +WindowsError_traverse(PyWindowsErrorObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->myerrno); + Py_VISIT(self->strerror); + Py_VISIT(self->filename); + Py_VISIT(self->winerror); + return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); +} + +static PyObject * +WindowsError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *o_errcode = NULL; + long errcode; + PyWindowsErrorObject *self; + long posix_errno; + + self = (PyWindowsErrorObject *)EnvironmentError_new(type, args, kwds); + if (!self) + return NULL; + + if (self->myerrno == Py_None) { + self->winerror = self->myerrno; + Py_INCREF(self->winerror); + return (PyObject *)self; + } + + /* Set errno to the POSIX errno, and winerror to the Win32 + error code. */ + errcode = PyInt_AsLong(self->myerrno); + if (errcode == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) + /* give a clearer error message */ + PyErr_SetString(PyExc_TypeError, "errno has to be an integer"); + goto failed; + } + posix_errno = winerror_to_errno(errcode); + + self->winerror = self->myerrno; + + o_errcode = PyInt_FromLong(posix_errno); + if (!o_errcode) + goto failed; + + self->myerrno = o_errcode; + + return (PyObject *)self; +failed: + /* Could not set errno. */ + Py_DECREF(self); + return NULL; +} + +static int +WindowsError_init(PyWindowsErrorObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *o_errcode = NULL; + long errcode; + long posix_errno; + + if (EnvironmentError_init((PyEnvironmentErrorObject *)self, args, kwds) + == -1) + return -1; + + if (self->myerrno == Py_None) { + Py_DECREF(self->winerror); + self->winerror = self->myerrno; + Py_INCREF(self->winerror); + return 0; + } + + /* Set errno to the POSIX errno, and winerror to the Win32 + error code. */ + errcode = PyInt_AsLong(self->myerrno); + if (errcode == -1 && PyErr_Occurred()) + return -1; + posix_errno = winerror_to_errno(errcode); + + Py_DECREF(self->winerror); + self->winerror = self->myerrno; + + o_errcode = PyInt_FromLong(posix_errno); + if (!o_errcode) + return -1; + + self->myerrno = o_errcode; + + return 0; +} + + +static PyObject * +WindowsError_str(PyWindowsErrorObject *self) +{ + PyObject *repr = NULL; + PyObject *fmt = NULL; + PyObject *tuple = NULL; + PyObject *rtnval = NULL; + + if (self->filename != Py_None) { + fmt = PyString_FromString("[Error %s] %s: %s"); + repr = PyObject_Repr(self->filename); + if (!fmt || !repr) + goto finally; + + tuple = PyTuple_Pack(3, self->myerrno, self->strerror, repr); + if (!tuple) + goto finally; + + rtnval = PyString_Format(fmt, tuple); + Py_DECREF(tuple); + } + else if (PyObject_IsTrue(self->myerrno) && + PyObject_IsTrue(self->strerror)) { + fmt = PyString_FromString("[Error %s] %s"); + if (!fmt) + goto finally; + + tuple = PyTuple_Pack(2, self->myerrno, self->strerror); + if (!tuple) + goto finally; + + rtnval = PyString_Format(fmt, tuple); + Py_DECREF(tuple); + } + else + rtnval = EnvironmentError_str((PyEnvironmentErrorObject *)self); + + finally: + Py_XDECREF(repr); + Py_XDECREF(fmt); + Py_XDECREF(tuple); + return rtnval; +} + +static PyMemberDef WindowsError_members[] = { + {"message", T_OBJECT, offsetof(PyWindowsErrorObject, message), 0, + PyDoc_STR("exception message")}, + {"errno", T_OBJECT, offsetof(PyWindowsErrorObject, myerrno), 0, + PyDoc_STR("exception code")}, + {"strerror", T_OBJECT, offsetof(PyWindowsErrorObject, strerror), 0, + PyDoc_STR("exception code")}, + {"filename", T_OBJECT, offsetof(PyWindowsErrorObject, filename), 0, + PyDoc_STR("exception code")}, + {"winerror", T_OBJECT, offsetof(PyWindowsErrorObject, winerror), 0, + PyDoc_STR("windows exception code")}, + {NULL} /* Sentinel */ +}; + +ComplexExtendsException(PyExc_OSError, + WindowsError, + WindowsError, + WindowsError_dealloc, + 0, + WindowsError_members, + WindowsError_str, + "MS-Windows OS system call failed."); + +#endif /* MS_WINDOWS */ + + +/* + * VMSError extends OSError (I think) + */ +#ifdef __VMS +MiddlingExtendsException(PyExc_OSError, VMSError, EnvironmentError, + "OpenVMS OS system call failed."); +#endif + + +/* + * EOFError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, EOFError, + "Read beyond end of file."); + + +/* + * RuntimeError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, RuntimeError, + "Unspecified run-time error."); + + +/* + * NotImplementedError extends RuntimeError + */ +SimpleExtendsException(PyExc_RuntimeError, NotImplementedError, + "Method or function hasn't been implemented yet."); + +/* + * NameError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, NameError, + "Name not found globally."); + +/* + * UnboundLocalError extends NameError + */ +SimpleExtendsException(PyExc_NameError, UnboundLocalError, + "Local name referenced but not bound to a value."); + +/* + * AttributeError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, AttributeError, + "Attribute not found."); + + +/* + * SyntaxError extends StandardError + */ +static PyObject * +SyntaxError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PySyntaxErrorObject *self = NULL; + + self = (PySyntaxErrorObject *)BaseException_new(type, args, kwds); + if (!self) + return NULL; + + MAKE_IT_NONE(self->msg) + MAKE_IT_NONE(self->filename) + MAKE_IT_NONE(self->lineno) + MAKE_IT_NONE(self->offset) + MAKE_IT_NONE(self->text) + + /* this is always None - yes, I know it doesn't seem to be used + anywhere, but it was in the previous implementation */ + MAKE_IT_NONE(self->print_file_and_line) + + return (PyObject *)self; +} + +static int +SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *info = NULL; + Py_ssize_t lenargs = PyTuple_GET_SIZE(args); + + if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) + return -1; + + if (lenargs >= 1) { + Py_DECREF(self->msg); + self->msg = PyTuple_GET_ITEM(args, 0); + Py_INCREF(self->msg); + } + if (lenargs == 2) { + info = PyTuple_GET_ITEM(args, 1); + info = PySequence_Tuple(info); + if (!info) return -1; + + Py_DECREF(self->filename); + self->filename = PyTuple_GET_ITEM(info, 0); + Py_INCREF(self->filename); + + Py_DECREF(self->lineno); + self->lineno = PyTuple_GET_ITEM(info, 1); + Py_INCREF(self->lineno); + + Py_DECREF(self->offset); + self->offset = PyTuple_GET_ITEM(info, 2); + Py_INCREF(self->offset); + + Py_DECREF(self->text); + self->text = PyTuple_GET_ITEM(info, 3); + Py_INCREF(self->text); + } + return 0; +} + +int +SyntaxError_clear(PySyntaxErrorObject *self) +{ + Py_CLEAR(self->msg); + Py_CLEAR(self->filename); + Py_CLEAR(self->lineno); + Py_CLEAR(self->offset); + Py_CLEAR(self->text); + Py_CLEAR(self->print_file_and_line); + return BaseException_clear((PyBaseExceptionObject *)self); +} + +static void +SyntaxError_dealloc(PySyntaxErrorObject *self) +{ + SyntaxError_clear(self); + self->ob_type->tp_free((PyObject *)self); +} + +int +SyntaxError_traverse(PySyntaxErrorObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->msg); + Py_VISIT(self->filename); + Py_VISIT(self->lineno); + Py_VISIT(self->offset); + Py_VISIT(self->text); + Py_VISIT(self->print_file_and_line); + return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); +} + +/* This is called "my_basename" instead of just "basename" to avoid name + conflicts with glibc; basename is already prototyped if _GNU_SOURCE is + defined, and Python does define that. */ +static char * +my_basename(char *name) +{ + char *cp = name; + char *result = name; + + if (name == NULL) + return "???"; + while (*cp != '\0') { + if (*cp == SEP) + result = cp + 1; + ++cp; + } + return result; +} + + +static PyObject * +SyntaxError_str(PySyntaxErrorObject *self) +{ + PyObject *str; + PyObject *result; + + str = PyObject_Str(self->msg); + result = str; + + /* XXX -- do all the additional formatting with filename and + lineno here */ + + if (str != NULL && PyString_Check(str)) { + int have_filename = 0; + int have_lineno = 0; + char *buffer = NULL; + + have_filename = (self->filename != NULL) && + PyString_Check(self->filename); + have_lineno = (self->lineno != NULL) && PyInt_Check(self->lineno); + + if (have_filename || have_lineno) { + Py_ssize_t bufsize = PyString_GET_SIZE(str) + 64; + if (have_filename) + bufsize += PyString_GET_SIZE(self->filename); + + buffer = (char *)PyMem_MALLOC(bufsize); + if (buffer != NULL) { + if (have_filename && have_lineno) + PyOS_snprintf(buffer, bufsize, "%s (%s, line %ld)", + PyString_AS_STRING(str), + my_basename(PyString_AS_STRING(self->filename)), + PyInt_AsLong(self->lineno)); + else if (have_filename) + PyOS_snprintf(buffer, bufsize, "%s (%s)", + PyString_AS_STRING(str), + my_basename(PyString_AS_STRING(self->filename))); + else if (have_lineno) + PyOS_snprintf(buffer, bufsize, "%s (line %ld)", + PyString_AS_STRING(str), + PyInt_AsLong(self->lineno)); + + result = PyString_FromString(buffer); + PyMem_FREE(buffer); + + if (result == NULL) + result = str; + else + Py_DECREF(str); + } + } + } + return result; +} + +static PyMemberDef SyntaxError_members[] = { + {"message", T_OBJECT, offsetof(PySyntaxErrorObject, message), 0, + PyDoc_STR("exception message")}, + {"msg", T_OBJECT, offsetof(PySyntaxErrorObject, msg), 0, + PyDoc_STR("exception msg")}, + {"filename", T_OBJECT, offsetof(PySyntaxErrorObject, filename), 0, + PyDoc_STR("exception filename")}, + {"lineno", T_OBJECT, offsetof(PySyntaxErrorObject, lineno), 0, + PyDoc_STR("exception lineno")}, + {"offset", T_OBJECT, offsetof(PySyntaxErrorObject, offset), 0, + PyDoc_STR("exception offset")}, + {"text", T_OBJECT, offsetof(PySyntaxErrorObject, text), 0, + PyDoc_STR("exception text")}, + {"print_file_and_line", T_OBJECT, + offsetof(PySyntaxErrorObject, print_file_and_line), 0, + PyDoc_STR("exception print_file_and_line")}, + {NULL} /* Sentinel */ +}; + +ComplexExtendsException(PyExc_StandardError, SyntaxError, SyntaxError, + SyntaxError_dealloc, 0, SyntaxError_members, + SyntaxError_str, "Invalid syntax."); + + +/* + * IndentationError extends SyntaxError + */ +MiddlingExtendsException(PyExc_SyntaxError, IndentationError, SyntaxError, + "Improper indentation."); + + +/* + * TabError extends IndentationError + */ +MiddlingExtendsException(PyExc_IndentationError, TabError, SyntaxError, + "Improper mixture of spaces and tabs."); + + +/* + * LookupError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, LookupError, + "Base class for lookup errors."); + + +/* + * IndexError extends LookupError + */ +SimpleExtendsException(PyExc_LookupError, IndexError, + "Sequence index out of range."); + + +/* + * KeyError extends LookupError + */ +static PyObject * +KeyError_str(PyBaseExceptionObject *self) +{ + /* 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 + KeyError: '' + rather than the confusing + 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 BaseException__str__(). + */ + if (PyTuple_Check(self->args) && PyTuple_GET_SIZE(self->args) == 1) { + PyObject *key = PyTuple_GET_ITEM(self->args, 0); + return PyObject_Repr(key); + } + return BaseException_str(self); +} + +ComplexExtendsException(PyExc_LookupError, KeyError, BaseException, + 0, 0, 0, KeyError_str, "Mapping key not found."); + + +/* + * ValueError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, ValueError, + "Inappropriate argument value (of correct type)."); + +/* + * UnicodeError extends ValueError + */ + +SimpleExtendsException(PyExc_ValueError, UnicodeError, + "Unicode related error."); + +#ifdef Py_USING_UNICODE +static int +get_int(PyObject *attr, Py_ssize_t *value, const char *name) +{ + if (!attr) { + PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name); + return -1; + } + + if (PyInt_Check(attr)) { + *value = PyInt_AS_LONG(attr); + } else if (PyLong_Check(attr)) { + *value = _PyLong_AsSsize_t(attr); + if (*value == -1 && PyErr_Occurred()) + return -1; + } else { + PyErr_Format(PyExc_TypeError, "%.200s attribute must be int", name); + return -1; + } + return 0; +} + +static int +set_ssize_t(PyObject **attr, Py_ssize_t value) +{ + PyObject *obj = PyInt_FromSsize_t(value); + if (!obj) + return -1; + Py_XDECREF(*attr); + *attr = obj; + return 0; +} + +static PyObject * +get_string(PyObject *attr, const char *name) +{ + if (!attr) { + PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name); + return NULL; + } + + if (!PyString_Check(attr)) { + PyErr_Format(PyExc_TypeError, "%.200s attribute must be str", name); + return NULL; + } + Py_INCREF(attr); + return attr; +} + + +static int +set_string(PyObject **attr, const char *value) +{ + PyObject *obj = PyString_FromString(value); + if (!obj) + return -1; + Py_XDECREF(*attr); + *attr = obj; + return 0; +} + + +static PyObject * +get_unicode(PyObject *attr, const char *name) +{ + if (!attr) { + PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name); + return NULL; + } + + if (!PyUnicode_Check(attr)) { + PyErr_Format(PyExc_TypeError, + "%.200s attribute must be unicode", name); + return NULL; + } + Py_INCREF(attr); + return attr; +} + +PyObject * +PyUnicodeEncodeError_GetEncoding(PyObject *exc) +{ + return get_string(((PyUnicodeErrorObject *)exc)->encoding, "encoding"); +} + +PyObject * +PyUnicodeDecodeError_GetEncoding(PyObject *exc) +{ + return get_string(((PyUnicodeErrorObject *)exc)->encoding, "encoding"); +} + +PyObject * +PyUnicodeEncodeError_GetObject(PyObject *exc) +{ + return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object"); +} + +PyObject * +PyUnicodeDecodeError_GetObject(PyObject *exc) +{ + return get_string(((PyUnicodeErrorObject *)exc)->object, "object"); +} + +PyObject * +PyUnicodeTranslateError_GetObject(PyObject *exc) +{ + return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object"); +} + +int +PyUnicodeEncodeError_GetStart(PyObject *exc, Py_ssize_t *start) +{ + if (!get_int(((PyUnicodeErrorObject *)exc)->start, start, "start")) { + Py_ssize_t size; + PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object, + "object"); + if (!obj) return -1; + size = PyUnicode_GET_SIZE(obj); + if (*start<0) + *start = 0; /*XXX check for values <0*/ + if (*start>=size) + *start = size-1; + return 0; + } + return -1; +} + + +int +PyUnicodeDecodeError_GetStart(PyObject *exc, Py_ssize_t *start) +{ + if (!get_int(((PyUnicodeErrorObject *)exc)->start, start, "start")) { + Py_ssize_t size; + PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object, + "object"); + if (!obj) return -1; + size = PyString_GET_SIZE(obj); + if (*start<0) + *start = 0; + if (*start>=size) + *start = size-1; + return 0; + } + return -1; +} + + +int +PyUnicodeTranslateError_GetStart(PyObject *exc, Py_ssize_t *start) +{ + return PyUnicodeEncodeError_GetStart(exc, start); +} + + +int +PyUnicodeEncodeError_SetStart(PyObject *exc, Py_ssize_t start) +{ + return set_ssize_t(&((PyUnicodeErrorObject *)exc)->start, start); +} + + +int +PyUnicodeDecodeError_SetStart(PyObject *exc, Py_ssize_t start) +{ + return set_ssize_t(&((PyUnicodeErrorObject *)exc)->start, start); +} + + +int +PyUnicodeTranslateError_SetStart(PyObject *exc, Py_ssize_t start) +{ + return set_ssize_t(&((PyUnicodeErrorObject *)exc)->start, start); +} + + +int +PyUnicodeEncodeError_GetEnd(PyObject *exc, Py_ssize_t *end) +{ + if (!get_int(((PyUnicodeErrorObject *)exc)->end, end, "end")) { + Py_ssize_t size; + PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object, + "object"); + if (!obj) return -1; + size = PyUnicode_GET_SIZE(obj); + if (*end<1) + *end = 1; + if (*end>size) + *end = size; + return 0; + } + return -1; +} + + +int +PyUnicodeDecodeError_GetEnd(PyObject *exc, Py_ssize_t *end) +{ + if (!get_int(((PyUnicodeErrorObject *)exc)->end, end, "end")) { + Py_ssize_t size; + PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object, + "object"); + if (!obj) return -1; + size = PyString_GET_SIZE(obj); + if (*end<1) + *end = 1; + if (*end>size) + *end = size; + return 0; + } + return -1; +} + + +int +PyUnicodeTranslateError_GetEnd(PyObject *exc, Py_ssize_t *start) +{ + return PyUnicodeEncodeError_GetEnd(exc, start); +} + + +int +PyUnicodeEncodeError_SetEnd(PyObject *exc, Py_ssize_t end) +{ + return set_ssize_t(&((PyUnicodeErrorObject *)exc)->end, end); +} + + +int +PyUnicodeDecodeError_SetEnd(PyObject *exc, Py_ssize_t end) +{ + return set_ssize_t(&((PyUnicodeErrorObject *)exc)->end, end); +} + + +int +PyUnicodeTranslateError_SetEnd(PyObject *exc, Py_ssize_t end) +{ + return set_ssize_t(&((PyUnicodeErrorObject *)exc)->end, end); +} + +PyObject * +PyUnicodeEncodeError_GetReason(PyObject *exc) +{ + return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason"); +} + + +PyObject * +PyUnicodeDecodeError_GetReason(PyObject *exc) +{ + return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason"); +} + + +PyObject * +PyUnicodeTranslateError_GetReason(PyObject *exc) +{ + return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason"); +} + + +int +PyUnicodeEncodeError_SetReason(PyObject *exc, const char *reason) +{ + return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason); +} + + +int +PyUnicodeDecodeError_SetReason(PyObject *exc, const char *reason) +{ + return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason); +} + + +int +PyUnicodeTranslateError_SetReason(PyObject *exc, const char *reason) +{ + return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason); +} + + +static PyObject * +UnicodeError_new(PyTypeObject *type, PyObject *args, PyObject *kwds, + PyTypeObject *objecttype) +{ + PyUnicodeErrorObject *self; + + self = (PyUnicodeErrorObject *)BaseException_new(type, args, kwds); + if (!self) + return NULL; + + MAKE_IT_NONE(self->encoding); + MAKE_IT_NONE(self->object); + MAKE_IT_NONE(self->start); + MAKE_IT_NONE(self->end); + MAKE_IT_NONE(self->reason); + + return (PyObject *)self; +} + +static int +UnicodeError_init(PyUnicodeErrorObject *self, PyObject *args, PyObject *kwds, + PyTypeObject *objecttype) +{ + if (!PyArg_ParseTuple(args, "O!O!O!O!O!", + &PyString_Type, &self->encoding, + objecttype, &self->object, + &PyInt_Type, &self->start, + &PyInt_Type, &self->end, + &PyString_Type, &self->reason)) { + self->encoding = self->object = self->start = self->end = + self->reason = NULL; + return -1; + } + + Py_INCREF(self->encoding); + Py_INCREF(self->object); + Py_INCREF(self->start); + Py_INCREF(self->end); + Py_INCREF(self->reason); + + return 0; +} + +int +UnicodeError_clear(PyUnicodeErrorObject *self) +{ + Py_CLEAR(self->encoding); + Py_CLEAR(self->object); + Py_CLEAR(self->start); + Py_CLEAR(self->end); + Py_CLEAR(self->reason); + return BaseException_clear((PyBaseExceptionObject *)self); +} + +static void +UnicodeError_dealloc(PyUnicodeErrorObject *self) +{ + UnicodeError_clear(self); + self->ob_type->tp_free((PyObject *)self); +} + +int +UnicodeError_traverse(PyUnicodeErrorObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->encoding); + Py_VISIT(self->object); + Py_VISIT(self->start); + Py_VISIT(self->end); + Py_VISIT(self->reason); + return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); +} + +static PyMemberDef UnicodeError_members[] = { + {"message", T_OBJECT, offsetof(PyUnicodeErrorObject, message), 0, + PyDoc_STR("exception message")}, + {"encoding", T_OBJECT, offsetof(PyUnicodeErrorObject, encoding), 0, + PyDoc_STR("exception encoding")}, + {"object", T_OBJECT, offsetof(PyUnicodeErrorObject, object), 0, + PyDoc_STR("exception object")}, + {"start", T_OBJECT, offsetof(PyUnicodeErrorObject, start), 0, + PyDoc_STR("exception start")}, + {"end", T_OBJECT, offsetof(PyUnicodeErrorObject, end), 0, + PyDoc_STR("exception end")}, + {"reason", T_OBJECT, offsetof(PyUnicodeErrorObject, reason), 0, + PyDoc_STR("exception reason")}, + {NULL} /* Sentinel */ +}; + + +/* + * UnicodeEncodeError extends UnicodeError + */ +static PyObject * +UnicodeEncodeError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + return UnicodeError_new(type, args, kwds, &PyUnicode_Type); +} + +static int +UnicodeEncodeError_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) + return -1; + return UnicodeError_init((PyUnicodeErrorObject *)self, args, + kwds, &PyUnicode_Type); +} + +static PyObject * +UnicodeEncodeError_str(PyObject *self) +{ + Py_ssize_t start; + Py_ssize_t end; + + if (PyUnicodeEncodeError_GetStart(self, &start)) + return NULL; + + if (PyUnicodeEncodeError_GetEnd(self, &end)) + return NULL; + + if (end==start+1) { + int badchar = (int)PyUnicode_AS_UNICODE(((PyUnicodeErrorObject *)self)->object)[start]; + char badchar_str[20]; + if (badchar <= 0xff) + PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar); + else if (badchar <= 0xffff) + PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar); + else + PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar); + return PyString_FromFormat( + "'%.400s' codec can't encode character u'\\%s' in position %zd: %.400s", + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding), + badchar_str, + start, + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) + ); + } + return PyString_FromFormat( + "'%.400s' codec can't encode characters in position %zd-%zd: %.400s", + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding), + start, + (end-1), + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) + ); +} + +static PyTypeObject _PyExc_UnicodeEncodeError = { + PyObject_HEAD_INIT(NULL) + 0, + "UnicodeEncodeError", + sizeof(PyUnicodeErrorObject), 0, + (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + (reprfunc)UnicodeEncodeError_str, 0, 0, 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + PyDoc_STR("Unicode encoding error."), (traverseproc)BaseException_traverse, + (inquiry)BaseException_clear, 0, 0, 0, 0, 0, UnicodeError_members, + 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict), + (initproc)UnicodeEncodeError_init, 0, UnicodeEncodeError_new, +}; +PyObject *PyExc_UnicodeEncodeError = (PyObject *)&_PyExc_UnicodeEncodeError; + +PyObject * +PyUnicodeEncodeError_Create( + const char *encoding, const Py_UNICODE *object, Py_ssize_t length, + Py_ssize_t start, Py_ssize_t end, const char *reason) +{ + return PyObject_CallFunction(PyExc_UnicodeEncodeError, "su#nns", + encoding, object, length, start, end, reason); +} + + +/* + * UnicodeDecodeError extends UnicodeError + */ +static PyObject * +UnicodeDecodeError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + return UnicodeError_new(type, args, kwds, &PyString_Type); +} + +static int +UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) + return -1; + return UnicodeError_init((PyUnicodeErrorObject *)self, args, + kwds, &PyString_Type); +} + +static PyObject * +UnicodeDecodeError_str(PyObject *self) +{ + Py_ssize_t start; + Py_ssize_t end; + + if (PyUnicodeDecodeError_GetStart(self, &start)) + return NULL; + + if (PyUnicodeDecodeError_GetEnd(self, &end)) + return NULL; + + if (end==start+1) { + /* FromFormat does not support %02x, so format that separately */ + char byte[4]; + PyOS_snprintf(byte, sizeof(byte), "%02x", + ((int)PyString_AS_STRING(((PyUnicodeErrorObject *)self)->object)[start])&0xff); + return PyString_FromFormat( + "'%.400s' codec can't decode byte 0x%s in position %zd: %.400s", + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding), + byte, + start, + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) + ); + } + return PyString_FromFormat( + "'%.400s' codec can't decode bytes in position %zd-%zd: %.400s", + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding), + start, + (end-1), + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) + ); +} + +static PyTypeObject _PyExc_UnicodeDecodeError = { + PyObject_HEAD_INIT(NULL) + 0, + EXC_MODULE_NAME "UnicodeDecodeError", + sizeof(PyUnicodeErrorObject), 0, + (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + (reprfunc)UnicodeDecodeError_str, 0, 0, 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + PyDoc_STR("Unicode decoding error."), (traverseproc)BaseException_traverse, + (inquiry)BaseException_clear, 0, 0, 0, 0, 0, UnicodeError_members, + 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict), + (initproc)UnicodeDecodeError_init, 0, UnicodeDecodeError_new, +}; +PyObject *PyExc_UnicodeDecodeError = (PyObject *)&_PyExc_UnicodeDecodeError; + +PyObject * +PyUnicodeDecodeError_Create( + const char *encoding, const char *object, Py_ssize_t length, + Py_ssize_t start, Py_ssize_t end, const char *reason) +{ + assert(length < INT_MAX); + assert(start < INT_MAX); + assert(end < INT_MAX); + return PyObject_CallFunction(PyExc_UnicodeDecodeError, "ss#nns", + encoding, object, length, start, end, reason); +} + + +/* + * UnicodeTranslateError extends UnicodeError + */ +static PyObject * +UnicodeTranslateError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyUnicodeErrorObject *self = NULL; + + self = (PyUnicodeErrorObject *)BaseException_new(type, args, kwds); + if (!self) + return NULL; + + MAKE_IT_NONE(self->encoding); + MAKE_IT_NONE(self->object); + MAKE_IT_NONE(self->start); + MAKE_IT_NONE(self->end); + MAKE_IT_NONE(self->reason); + + return (PyObject *)self; +} + +static int +UnicodeTranslateError_init(PyUnicodeErrorObject *self, PyObject *args, + PyObject *kwds) +{ + if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) + return -1; + + Py_CLEAR(self->object); + Py_CLEAR(self->start); + Py_CLEAR(self->end); + Py_CLEAR(self->reason); + + if (!PyArg_ParseTuple(args, "O!O!O!O!", + &PyUnicode_Type, &self->object, + &PyInt_Type, &self->start, + &PyInt_Type, &self->end, + &PyString_Type, &self->reason)) { + self->object = self->start = self->end = self->reason = NULL; + return -1; + } + + Py_INCREF(self->object); + Py_INCREF(self->start); + Py_INCREF(self->end); + Py_INCREF(self->reason); + + return 0; +} + + +static PyObject * +UnicodeTranslateError_str(PyObject *self) +{ + Py_ssize_t start; + Py_ssize_t end; + + if (PyUnicodeTranslateError_GetStart(self, &start)) + return NULL; + + if (PyUnicodeTranslateError_GetEnd(self, &end)) + return NULL; + + if (end==start+1) { + int badchar = (int)PyUnicode_AS_UNICODE(((PyUnicodeErrorObject *)self)->object)[start]; + char badchar_str[20]; + if (badchar <= 0xff) + PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar); + else if (badchar <= 0xffff) + PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar); + else + PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar); + return PyString_FromFormat( + "can't translate character u'\\%s' in position %zd: %.400s", + badchar_str, + start, + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) + ); + } + return PyString_FromFormat( + "can't translate characters in position %zd-%zd: %.400s", + start, + (end-1), + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) + ); +} + +static PyTypeObject _PyExc_UnicodeTranslateError = { + PyObject_HEAD_INIT(NULL) + 0, + EXC_MODULE_NAME "UnicodeTranslateError", + sizeof(PyUnicodeErrorObject), 0, + (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + (reprfunc)UnicodeTranslateError_str, 0, 0, 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + PyDoc_STR("Unicode decoding error."), (traverseproc)UnicodeError_traverse, + (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members, + 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict), + (initproc)UnicodeTranslateError_init, 0, UnicodeTranslateError_new, +}; +PyObject *PyExc_UnicodeTranslateError = (PyObject *)&_PyExc_UnicodeTranslateError; + +PyObject * +PyUnicodeTranslateError_Create( + const Py_UNICODE *object, Py_ssize_t length, + Py_ssize_t start, Py_ssize_t end, const char *reason) +{ + return PyObject_CallFunction(PyExc_UnicodeTranslateError, "u#nns", + object, length, start, end, reason); +} +#endif + + +/* + * AssertionError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, AssertionError, + "Assertion failed."); + + +/* + * ArithmeticError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, ArithmeticError, + "Base class for arithmetic errors."); + + +/* + * FloatingPointError extends ArithmeticError + */ +SimpleExtendsException(PyExc_ArithmeticError, FloatingPointError, + "Floating point operation failed."); + + +/* + * OverflowError extends ArithmeticError + */ +SimpleExtendsException(PyExc_ArithmeticError, OverflowError, + "Result too large to be represented."); + + +/* + * ZeroDivisionError extends ArithmeticError + */ +SimpleExtendsException(PyExc_ArithmeticError, ZeroDivisionError, + "Second argument to a division or modulo operation was zero."); + + +/* + * SystemError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, SystemError, + "Internal error in the Python interpreter.\n" + "\n" + "Please report this to the Python maintainer, along with the traceback,\n" + "the Python version, and the hardware/OS platform and version."); + + +/* + * ReferenceError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, ReferenceError, + "Weak ref proxy used after referent went away."); + + +/* + * MemoryError extends StandardError + */ +SimpleExtendsException(PyExc_StandardError, MemoryError, "Out of memory."); + + +/* Warning category docstrings */ + +/* + * Warning extends Exception + */ +SimpleExtendsException(PyExc_Exception, Warning, + "Base class for warning categories."); + + +/* + * UserWarning extends Warning + */ +SimpleExtendsException(PyExc_Warning, UserWarning, + "Base class for warnings generated by user code."); + + +/* + * DeprecationWarning extends Warning + */ +SimpleExtendsException(PyExc_Warning, DeprecationWarning, + "Base class for warnings about deprecated features."); + + +/* + * PendingDeprecationWarning extends Warning + */ +SimpleExtendsException(PyExc_Warning, PendingDeprecationWarning, + "Base class for warnings about features which will be deprecated\n" + "in the future."); + + +/* + * SyntaxWarning extends Warning + */ +SimpleExtendsException(PyExc_Warning, SyntaxWarning, + "Base class for warnings about dubious syntax."); + + +/* + * RuntimeWarning extends Warning + */ +SimpleExtendsException(PyExc_Warning, RuntimeWarning, + "Base class for warnings about dubious runtime behavior."); + + +/* + * FutureWarning extends Warning + */ +SimpleExtendsException(PyExc_Warning, FutureWarning, + "Base class for warnings about constructs that will change semantically\n" + "in the future."); + + +/* + * ImportWarning extends Warning + */ +SimpleExtendsException(PyExc_Warning, ImportWarning, + "Base class for warnings about probable mistakes in module imports"); + + +/* Pre-computed MemoryError instance. Best to create this as early as + * possible and not wait until a MemoryError is actually raised! + */ +PyObject *PyExc_MemoryErrorInst=NULL; + +/* module global functions */ +static PyMethodDef functions[] = { + /* Sentinel */ + {NULL, NULL} +}; + +#define PRE_INIT(TYPE) if (PyType_Ready(&_PyExc_ ## TYPE) < 0) \ + Py_FatalError("exceptions bootstrapping error."); + +#define POST_INIT(TYPE) Py_INCREF(PyExc_ ## TYPE); \ + PyModule_AddObject(m, # TYPE, PyExc_ ## TYPE); \ + if (PyDict_SetItemString(bdict, # TYPE, PyExc_ ## TYPE)) \ + Py_FatalError("Module dictionary insertion problem."); + +PyMODINIT_FUNC +_PyExc_Init(void) +{ + PyObject *m, *bltinmod, *bdict; + + PRE_INIT(BaseException) + PRE_INIT(Exception) + PRE_INIT(StandardError) + PRE_INIT(TypeError) + PRE_INIT(StopIteration) + PRE_INIT(GeneratorExit) + PRE_INIT(SystemExit) + PRE_INIT(KeyboardInterrupt) + PRE_INIT(ImportError) + PRE_INIT(EnvironmentError) + PRE_INIT(IOError) + PRE_INIT(OSError) +#ifdef MS_WINDOWS + PRE_INIT(WindowsError) +#endif +#ifdef __VMS + PRE_INIT(VMSError) +#endif + PRE_INIT(EOFError) + PRE_INIT(RuntimeError) + PRE_INIT(NotImplementedError) + PRE_INIT(NameError) + PRE_INIT(UnboundLocalError) + PRE_INIT(AttributeError) + PRE_INIT(SyntaxError) + PRE_INIT(IndentationError) + PRE_INIT(TabError) + PRE_INIT(LookupError) + PRE_INIT(IndexError) + PRE_INIT(KeyError) + PRE_INIT(ValueError) + PRE_INIT(UnicodeError) +#ifdef Py_USING_UNICODE + PRE_INIT(UnicodeEncodeError) + PRE_INIT(UnicodeDecodeError) + PRE_INIT(UnicodeTranslateError) +#endif + PRE_INIT(AssertionError) + PRE_INIT(ArithmeticError) + PRE_INIT(FloatingPointError) + PRE_INIT(OverflowError) + PRE_INIT(ZeroDivisionError) + PRE_INIT(SystemError) + PRE_INIT(ReferenceError) + PRE_INIT(MemoryError) + PRE_INIT(Warning) + PRE_INIT(UserWarning) + PRE_INIT(DeprecationWarning) + PRE_INIT(PendingDeprecationWarning) + PRE_INIT(SyntaxWarning) + PRE_INIT(RuntimeWarning) + PRE_INIT(FutureWarning) + PRE_INIT(ImportWarning) + + m = Py_InitModule("exceptions", functions); + if (m == NULL) return; + + bltinmod = PyImport_ImportModule("__builtin__"); + if (bltinmod == NULL) + Py_FatalError("exceptions bootstrapping error."); + bdict = PyModule_GetDict(bltinmod); + if (bdict == NULL) + Py_FatalError("exceptions bootstrapping error."); + + POST_INIT(BaseException) + POST_INIT(Exception) + POST_INIT(StandardError) + POST_INIT(TypeError) + POST_INIT(StopIteration) + POST_INIT(GeneratorExit) + POST_INIT(SystemExit) + POST_INIT(KeyboardInterrupt) + POST_INIT(ImportError) + POST_INIT(EnvironmentError) + POST_INIT(IOError) + POST_INIT(OSError) +#ifdef MS_WINDOWS + POST_INIT(WindowsError) +#endif +#ifdef __VMS + POST_INIT(VMSError) +#endif + POST_INIT(EOFError) + POST_INIT(RuntimeError) + POST_INIT(NotImplementedError) + POST_INIT(NameError) + POST_INIT(UnboundLocalError) + POST_INIT(AttributeError) + POST_INIT(SyntaxError) + POST_INIT(IndentationError) + POST_INIT(TabError) + POST_INIT(LookupError) + POST_INIT(IndexError) + POST_INIT(KeyError) + POST_INIT(ValueError) + POST_INIT(UnicodeError) +#ifdef Py_USING_UNICODE + POST_INIT(UnicodeEncodeError) + POST_INIT(UnicodeDecodeError) + POST_INIT(UnicodeTranslateError) +#endif + POST_INIT(AssertionError) + POST_INIT(ArithmeticError) + POST_INIT(FloatingPointError) + POST_INIT(OverflowError) + POST_INIT(ZeroDivisionError) + POST_INIT(SystemError) + POST_INIT(ReferenceError) + POST_INIT(MemoryError) + POST_INIT(Warning) + POST_INIT(UserWarning) + POST_INIT(DeprecationWarning) + POST_INIT(PendingDeprecationWarning) + POST_INIT(SyntaxWarning) + POST_INIT(RuntimeWarning) + POST_INIT(FutureWarning) + POST_INIT(ImportWarning) + + PyExc_MemoryErrorInst = BaseException_new(&_PyExc_MemoryError, NULL, NULL); + if (!PyExc_MemoryErrorInst) + Py_FatalError("Cannot pre-allocate MemoryError instance\n"); + + Py_DECREF(bltinmod); +} + +void +_PyExc_Fini(void) +{ + Py_XDECREF(PyExc_MemoryErrorInst); + PyExc_MemoryErrorInst = NULL; +} diff --git a/PCbuild/pythoncore.vcproj b/PCbuild/pythoncore.vcproj index 21e8d83..c37e9b9 100644 --- a/PCbuild/pythoncore.vcproj +++ b/PCbuild/pythoncore.vcproj @@ -494,7 +494,7 @@ RelativePath="..\Python\errors.c"> + RelativePath="..\Objects\exceptions.c"> diff --git a/Python/errors.c b/Python/errors.c index e0ce833..f7a1c08 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -557,9 +557,6 @@ PyErr_NewException(char *name, PyObject *base, PyObject *dict) if (PyDict_SetItemString(dict, "__module__", modulename) != 0) goto failure; } - classname = PyString_FromString(dot+1); - if (classname == NULL) - goto failure; if (PyTuple_Check(base)) { bases = base; /* INCREF as we create a new ref in the else branch */ @@ -569,7 +566,9 @@ PyErr_NewException(char *name, PyObject *base, PyObject *dict) if (bases == NULL) goto failure; } - result = PyClass_New(bases, dict, classname); + /* Create a real new-style class. */ + result = PyObject_CallFunction((PyObject *)&PyType_Type, "sOO", + dot+1, bases, dict); failure: Py_XDECREF(bases); Py_XDECREF(mydict); @@ -590,8 +589,11 @@ PyErr_WriteUnraisable(PyObject *obj) PyFile_WriteString("Exception ", f); if (t) { char* className = PyExceptionClass_Name(t); - PyObject* moduleName = - PyObject_GetAttrString(t, "__module__"); + PyObject* moduleName; + char *dot = strrchr(className, '.'); + if (dot != NULL) + className = dot+1; + moduleName = PyObject_GetAttrString(t, "__module__"); if (moduleName == NULL) PyFile_WriteString("", f); @@ -641,15 +643,11 @@ PyErr_Warn(PyObject *category, char *message) return 0; } else { - PyObject *args, *res; + PyObject *res; if (category == NULL) category = PyExc_RuntimeWarning; - args = Py_BuildValue("(sO)", message, category); - if (args == NULL) - return -1; - res = PyEval_CallObject(func, args); - Py_DECREF(args); + res = PyObject_CallFunction(func, "sO", message, category); if (res == NULL) return -1; Py_DECREF(res); @@ -677,18 +675,14 @@ PyErr_WarnExplicit(PyObject *category, const char *message, return 0; } else { - PyObject *args, *res; + PyObject *res; if (category == NULL) category = PyExc_RuntimeWarning; if (registry == NULL) registry = Py_None; - args = Py_BuildValue("(sOsizO)", message, category, - filename, lineno, module, registry); - if (args == NULL) - return -1; - res = PyEval_CallObject(func, args); - Py_DECREF(args); + res = PyObject_CallFunction(func, "sOsizO", message, category, + filename, lineno, module, registry); if (res == NULL) return -1; Py_DECREF(res); @@ -709,7 +703,8 @@ PyErr_SyntaxLocation(const char *filename, int lineno) /* add attributes for the line number and filename for the error */ PyErr_Fetch(&exc, &v, &tb); PyErr_NormalizeException(&exc, &v, &tb); - /* XXX check that it is, indeed, a syntax error */ + /* XXX check that it is, indeed, a syntax error. It might not + * be, though. */ tmp = PyInt_FromLong(lineno); if (tmp == NULL) PyErr_Clear(); diff --git a/Python/exceptions.c b/Python/exceptions.c deleted file mode 100644 index 7cf1580..0000000 --- a/Python/exceptions.c +++ /dev/null @@ -1,2032 +0,0 @@ -/* This module provides the suite of standard class-based exceptions for - * Python's builtin module. This is a complete C implementation of what, - * in Python 1.5.2, was contained in the exceptions.py module. The problem - * there was that if exceptions.py could not be imported for some reason, - * the entire interpreter would abort. - * - * By moving the exceptions into C and statically linking, we can guarantee - * that the standard exceptions will always be available. - * - * - * written by Fredrik Lundh - * modifications, additions, cleanups, and proofreading by Barry Warsaw - * - * Copyright (c) 1998-2000 by Secret Labs AB. All rights reserved. - */ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "osdefs.h" - -/* Caution: MS Visual C++ 6 errors if a single string literal exceeds - * 2Kb. So the module docstring has been broken roughly in half, using - * compile-time literal concatenation. - */ - -/* NOTE: If the exception class hierarchy changes, don't forget to update - * Doc/lib/libexcs.tex! - */ - -PyDoc_STRVAR(module__doc__, -"Python's standard exception class hierarchy.\n\ -\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. See the documentation for the exception inheritance hierarchy.\n\ -" - - /* keep string pieces "small" */ -/* XXX(bcannon): exception hierarchy in Lib/test/exception_hierarchy.txt */ -); - - -/* Helper function for populating a dictionary with method wrappers. */ -static int -populate_methods(PyObject *klass, PyMethodDef *methods) -{ - PyObject *module; - int status = -1; - - if (!methods) - return 0; - - module = PyString_FromString("exceptions"); - if (!module) - return 0; - while (methods->ml_name) { - /* get a wrapper for the built-in function */ - PyObject *func = PyCFunction_NewEx(methods, NULL, module); - PyObject *meth; - - if (!func) - goto status; - - /* turn the function into an unbound method */ - if (!(meth = PyMethod_New(func, NULL, klass))) { - Py_DECREF(func); - goto status; - } - - /* add method to dictionary */ - status = PyObject_SetAttrString(klass, methods->ml_name, meth); - Py_DECREF(meth); - Py_DECREF(func); - - /* stop now if an error occurred, otherwise do the next method */ - if (status) - goto status; - - methods++; - } - status = 0; - status: - Py_DECREF(module); - return status; -} - - - -/* This function is used to create all subsequent exception classes. */ -static int -make_class(PyObject **klass, PyObject *base, - char *name, PyMethodDef *methods, - char *docstr) -{ - PyObject *dict = PyDict_New(); - PyObject *str = NULL; - int status = -1; - - if (!dict) - return -1; - - /* If an error occurs from here on, goto finally instead of explicitly - * returning NULL. - */ - - if (docstr) { - if (!(str = PyString_FromString(docstr))) - goto finally; - if (PyDict_SetItemString(dict, "__doc__", str)) - goto finally; - } - - if (!(*klass = PyErr_NewException(name, base, dict))) - goto finally; - - if (populate_methods(*klass, methods)) { - Py_DECREF(*klass); - *klass = NULL; - goto finally; - } - - status = 0; - - finally: - Py_XDECREF(dict); - Py_XDECREF(str); - return status; -} - - -/* Use this for *args signatures, otherwise just use PyArg_ParseTuple() */ -static PyObject * -get_self(PyObject *args) -{ - PyObject *self = PyTuple_GetItem(args, 0); - if (!self) { - /* Watch out for being called to early in the bootstrapping process */ - if (PyExc_TypeError) { - PyErr_SetString(PyExc_TypeError, - "unbound method must be called with instance as first argument"); - } - return NULL; - } - return self; -} - - - -/* Notes on bootstrapping the exception classes. - * - * First thing we create is the base class for all exceptions, called - * 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, 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 BaseException can be created using PyErr_NewException(). - */ - -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 * -BaseException__init__(PyObject *self, PyObject *args) -{ - if (!(self = get_self(args))) - return NULL; - - /* set args and message attribute */ - args = PySequence_GetSlice(args, 1, PySequence_Length(args)); - if (!args) - return NULL; - - if (!set_args_and_message(self, args)) { - Py_DECREF(args); - return NULL; - } - - Py_DECREF(args); - Py_RETURN_NONE; -} - - -static PyObject * -BaseException__str__(PyObject *_self, PyObject *self) -{ - PyObject *out, *args; - - args = PyObject_GetAttrString(self, "args"); - if (!args) - return NULL; - - switch (PySequence_Size(args)) { - case 0: - out = PyString_FromString(""); - break; - case 1: - { - PyObject *tmp = PySequence_GetItem(args, 0); - if (tmp) { - out = PyObject_Str(tmp); - Py_DECREF(tmp); - } - else - out = NULL; - break; - } - case -1: - PyErr_Clear(); - /* Fall through */ - default: - out = PyObject_Str(args); - break; - } - - Py_DECREF(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); - PyObject *unicode_obj; - - if (!temp) { - Py_DECREF(args); - return NULL; - } - Py_DECREF(args); - unicode_obj = PyObject_Unicode(temp); - Py_DECREF(temp); - return unicode_obj; - } - else { - PyObject *unicode_obj = PyObject_Unicode(args); - - Py_DECREF(args); - return unicode_obj; - } -} -#endif /* Py_USING_UNICODE */ - -static PyObject * -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_Repr(args_attr); - Py_DECREF(args_attr); - if (!args_repr) - return NULL; - - repr_suffix = args_repr; - } - - 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; - - if (!PyArg_ParseTuple(args, "OO:__getitem__", &self, &index)) - return NULL; - - args = PyObject_GetAttrString(self, "args"); - if (!args) - return NULL; - - out = PyObject_GetItem(args, index); - Py_DECREF(args); - return out; -} - - -static PyMethodDef -BaseException_methods[] = { - /* methods for the BaseException class */ - {"__getitem__", BaseException__getitem__, METH_VARARGS}, - {"__repr__", BaseException__repr__, METH_VARARGS}, - {"__str__", BaseException__str__, METH_O}, -#ifdef Py_USING_UNICODE - {"__unicode__", BaseException__unicode__, METH_VARARGS}, -#endif /* Py_USING_UNICODE */ - {"__init__", BaseException__init__, METH_VARARGS}, - {NULL, NULL } -}; - - -static int -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) - return -1; - - /* If an error occurs from here on, goto finally instead of explicitly - * returning NULL. - */ - - if (!(str = PyString_FromString(modulename))) - goto finally; - if (PyDict_SetItemString(dict, "__module__", str)) - goto finally; - Py_DECREF(str); - - if (!(str = PyString_FromString(BaseException__doc__))) - goto finally; - if (PyDict_SetItemString(dict, "__doc__", str)) - goto finally; - - if (!(name = PyString_FromString("BaseException"))) - goto finally; - - 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_BaseException, BaseException_methods)) - /* Don't need to reclaim PyExc_BaseException here because that'll - * happen during interpreter shutdown. - */ - goto finally; - - status = 0; - - finally: - 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 that do not represent" -"interpreter exiting."); - -PyDoc_STRVAR(TypeError__doc__, "Inappropriate argument type."); - -PyDoc_STRVAR(StopIteration__doc__, "Signal the end from iterator.next()."); -PyDoc_STRVAR(GeneratorExit__doc__, "Request that a generator exit."); - - - -PyDoc_STRVAR(SystemExit__doc__, "Request to exit from the interpreter."); - - -static PyObject * -SystemExit__init__(PyObject *self, PyObject *args) -{ - PyObject *code; - int status; - - if (!(self = get_self(args))) - return NULL; - - if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args)))) - return NULL; - - if (!set_args_and_message(self, args)) { - Py_DECREF(args); - return NULL; - } - - /* set code attribute */ - switch (PySequence_Size(args)) { - case 0: - Py_INCREF(Py_None); - code = Py_None; - break; - case 1: - code = PySequence_GetItem(args, 0); - break; - case -1: - PyErr_Clear(); - /* Fall through */ - default: - Py_INCREF(args); - code = args; - break; - } - - status = PyObject_SetAttrString(self, "code", code); - Py_DECREF(code); - Py_DECREF(args); - if (status < 0) - return NULL; - - Py_RETURN_NONE; -} - - -static PyMethodDef SystemExit_methods[] = { - { "__init__", SystemExit__init__, METH_VARARGS}, - {NULL, NULL} -}; - - - -PyDoc_STRVAR(KeyboardInterrupt__doc__, "Program interrupted by user."); - -PyDoc_STRVAR(ImportError__doc__, -"Import can't find module, or can't find name in module."); - - - -PyDoc_STRVAR(EnvironmentError__doc__, "Base class for I/O related errors."); - - -static PyObject * -EnvironmentError__init__(PyObject *self, PyObject *args) -{ - PyObject *item0 = NULL; - PyObject *item1 = NULL; - PyObject *item2 = NULL; - PyObject *subslice = NULL; - PyObject *rtnval = NULL; - - if (!(self = get_self(args))) - return NULL; - - if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args)))) - return NULL; - - 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)) - { - goto finally; - } - - switch (PySequence_Size(args)) { - case 3: - /* Where a function has a single filename, such as open() or some - * of the os module functions, PyErr_SetFromErrnoWithFilename() is - * called, giving a third argument which is the filename. But, so - * that old code using in-place unpacking doesn't break, e.g.: - * - * except IOError, (errno, strerror): - * - * we hack args so that it only contains two items. This also - * means we need our own __str__() which prints out the filename - * when it was supplied. - */ - item0 = PySequence_GetItem(args, 0); - item1 = PySequence_GetItem(args, 1); - item2 = PySequence_GetItem(args, 2); - if (!item0 || !item1 || !item2) - goto finally; - - if (PyObject_SetAttrString(self, "errno", item0) || - PyObject_SetAttrString(self, "strerror", item1) || - PyObject_SetAttrString(self, "filename", item2)) - { - goto finally; - } - - subslice = PySequence_GetSlice(args, 0, 2); - if (!subslice || PyObject_SetAttrString(self, "args", subslice)) - goto finally; - break; - - case 2: - /* Used when PyErr_SetFromErrno() is called and no filename - * argument is given. - */ - item0 = PySequence_GetItem(args, 0); - item1 = PySequence_GetItem(args, 1); - if (!item0 || !item1) - goto finally; - - if (PyObject_SetAttrString(self, "errno", item0) || - PyObject_SetAttrString(self, "strerror", item1)) - { - goto finally; - } - break; - - case -1: - PyErr_Clear(); - break; - } - - Py_INCREF(Py_None); - rtnval = Py_None; - - finally: - Py_DECREF(args); - Py_XDECREF(item0); - Py_XDECREF(item1); - Py_XDECREF(item2); - Py_XDECREF(subslice); - return rtnval; -} - - -static PyObject * -EnvironmentError__str__(PyObject *originalself, PyObject *self) -{ - PyObject *filename; - PyObject *serrno; - PyObject *strerror; - PyObject *rtnval = NULL; - - filename = PyObject_GetAttrString(self, "filename"); - serrno = PyObject_GetAttrString(self, "errno"); - strerror = PyObject_GetAttrString(self, "strerror"); - if (!filename || !serrno || !strerror) - goto finally; - - if (filename != Py_None) { - PyObject *fmt = PyString_FromString("[Errno %s] %s: %s"); - PyObject *repr = PyObject_Repr(filename); - PyObject *tuple = PyTuple_New(3); - - if (!fmt || !repr || !tuple) { - Py_XDECREF(fmt); - Py_XDECREF(repr); - Py_XDECREF(tuple); - goto finally; - } - - PyTuple_SET_ITEM(tuple, 0, serrno); - PyTuple_SET_ITEM(tuple, 1, strerror); - PyTuple_SET_ITEM(tuple, 2, repr); - - rtnval = PyString_Format(fmt, tuple); - - Py_DECREF(fmt); - Py_DECREF(tuple); - /* already freed because tuple owned only reference */ - serrno = NULL; - strerror = NULL; - } - else if (PyObject_IsTrue(serrno) && PyObject_IsTrue(strerror)) { - PyObject *fmt = PyString_FromString("[Errno %s] %s"); - PyObject *tuple = PyTuple_New(2); - - if (!fmt || !tuple) { - Py_XDECREF(fmt); - Py_XDECREF(tuple); - goto finally; - } - - PyTuple_SET_ITEM(tuple, 0, serrno); - PyTuple_SET_ITEM(tuple, 1, strerror); - - rtnval = PyString_Format(fmt, tuple); - - Py_DECREF(fmt); - Py_DECREF(tuple); - /* already freed because tuple owned only reference */ - serrno = NULL; - strerror = NULL; - } - else - /* The original Python code said: - * - * return StandardError.__str__(self) - * - * but there is no StandardError__str__() function; we happen to - * know that's just a pass through to BaseException__str__(). - */ - rtnval = BaseException__str__(originalself, self); - - finally: - Py_XDECREF(filename); - Py_XDECREF(serrno); - Py_XDECREF(strerror); - return rtnval; -} - - -static -PyMethodDef EnvironmentError_methods[] = { - {"__init__", EnvironmentError__init__, METH_VARARGS}, - {"__str__", EnvironmentError__str__, METH_O}, - {NULL, NULL} -}; - -PyDoc_STRVAR(IOError__doc__, "I/O operation failed."); - -PyDoc_STRVAR(OSError__doc__, "OS system call failed."); - -#ifdef MS_WINDOWS -#include "errmap.h" - -PyDoc_STRVAR(WindowsError__doc__, "MS-Windows OS system call failed."); - -static PyObject * -WindowsError__init__(PyObject *self, PyObject *args) -{ - PyObject *o_errcode, *result; - long errcode, posix_errno; - result = EnvironmentError__init__(self, args); - if (!result) - return NULL; - self = get_self(args); - if (!self) - goto failed; - /* Set errno to the POSIX errno, and winerror to the Win32 - error code. */ - o_errcode = PyObject_GetAttrString(self, "errno"); - if (!o_errcode) - goto failed; - errcode = PyInt_AsLong(o_errcode); - if (!errcode == -1 && PyErr_Occurred()) - goto failed; - posix_errno = winerror_to_errno(errcode); - if (PyObject_SetAttrString(self, "winerror", o_errcode) < 0) - goto failed; - Py_DECREF(o_errcode); - o_errcode = PyInt_FromLong(posix_errno); - if (!o_errcode) - goto failed; - if (PyObject_SetAttrString(self, "errno", o_errcode) < 0) - goto failed; - Py_DECREF(o_errcode); - return result; -failed: - /* Could not set errno. */ - Py_XDECREF(o_errcode); - Py_DECREF(result); - return NULL; -} - -static PyObject * -WindowsError__str__(PyObject *originalself, PyObject *self) -{ - PyObject *filename; - PyObject *serrno; - PyObject *strerror; - PyObject *repr = NULL; - PyObject *fmt = NULL; - PyObject *tuple = NULL; - PyObject *rtnval = NULL; - - filename = PyObject_GetAttrString(self, "filename"); - serrno = PyObject_GetAttrString(self, "winerror"); - strerror = PyObject_GetAttrString(self, "strerror"); - if (!filename || !serrno || !strerror) - goto finally; - - if (filename != Py_None) { - fmt = PyString_FromString("[Error %s] %s: %s"); - repr = PyObject_Repr(filename); - if (!fmt || !repr) - goto finally; - - - tuple = PyTuple_Pack(3, serrno, strerror, repr); - if (!tuple) - goto finally; - - rtnval = PyString_Format(fmt, tuple); - } - else if (PyObject_IsTrue(serrno) && PyObject_IsTrue(strerror)) { - fmt = PyString_FromString("[Error %s] %s"); - if (!fmt) - goto finally; - - tuple = PyTuple_Pack(2, serrno, strerror); - if (!tuple) - goto finally; - - rtnval = PyString_Format(fmt, tuple); - } - else - rtnval = EnvironmentError__str__(originalself, self); - - finally: - Py_XDECREF(filename); - Py_XDECREF(serrno); - Py_XDECREF(strerror); - Py_XDECREF(repr); - Py_XDECREF(fmt); - Py_XDECREF(tuple); - return rtnval; -} - -static -PyMethodDef WindowsError_methods[] = { - {"__init__", WindowsError__init__, METH_VARARGS}, - {"__str__", WindowsError__str__, METH_O}, - {NULL, NULL} -}; -#endif /* MS_WINDOWS */ - -#ifdef __VMS -static char -VMSError__doc__[] = "OpenVMS OS system call failed."; -#endif - -PyDoc_STRVAR(EOFError__doc__, "Read beyond end of file."); - -PyDoc_STRVAR(RuntimeError__doc__, "Unspecified run-time error."); - -PyDoc_STRVAR(NotImplementedError__doc__, -"Method or function hasn't been implemented yet."); - -PyDoc_STRVAR(NameError__doc__, "Name not found globally."); - -PyDoc_STRVAR(UnboundLocalError__doc__, -"Local name referenced but not bound to a value."); - -PyDoc_STRVAR(AttributeError__doc__, "Attribute not found."); - - - -PyDoc_STRVAR(SyntaxError__doc__, "Invalid syntax."); - - -static int -SyntaxError__classinit__(PyObject *klass) -{ - int retval = 0; - PyObject *emptystring = PyString_FromString(""); - - /* Additional class-creation time initializations */ - if (!emptystring || - PyObject_SetAttrString(klass, "msg", emptystring) || - PyObject_SetAttrString(klass, "filename", Py_None) || - PyObject_SetAttrString(klass, "lineno", Py_None) || - PyObject_SetAttrString(klass, "offset", Py_None) || - PyObject_SetAttrString(klass, "text", Py_None) || - PyObject_SetAttrString(klass, "print_file_and_line", Py_None)) - { - retval = -1; - } - Py_XDECREF(emptystring); - return retval; -} - - -static PyObject * -SyntaxError__init__(PyObject *self, PyObject *args) -{ - PyObject *rtnval = NULL; - Py_ssize_t lenargs; - - if (!(self = get_self(args))) - return NULL; - - if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args)))) - return NULL; - - if (!set_args_and_message(self, args)) { - Py_DECREF(args); - return NULL; - } - - lenargs = PySequence_Size(args); - if (lenargs >= 1) { - PyObject *item0 = PySequence_GetItem(args, 0); - int status; - - if (!item0) - goto finally; - status = PyObject_SetAttrString(self, "msg", item0); - Py_DECREF(item0); - if (status) - goto finally; - } - if (lenargs == 2) { - PyObject *info = PySequence_GetItem(args, 1); - PyObject *filename = NULL, *lineno = NULL; - PyObject *offset = NULL, *text = NULL; - int status = 1; - - if (!info) - goto finally; - - filename = PySequence_GetItem(info, 0); - if (filename != NULL) { - lineno = PySequence_GetItem(info, 1); - if (lineno != NULL) { - offset = PySequence_GetItem(info, 2); - if (offset != NULL) { - text = PySequence_GetItem(info, 3); - if (text != NULL) { - status = - PyObject_SetAttrString(self, "filename", filename) - || PyObject_SetAttrString(self, "lineno", lineno) - || PyObject_SetAttrString(self, "offset", offset) - || PyObject_SetAttrString(self, "text", text); - Py_DECREF(text); - } - Py_DECREF(offset); - } - Py_DECREF(lineno); - } - Py_DECREF(filename); - } - Py_DECREF(info); - - if (status) - goto finally; - } - Py_INCREF(Py_None); - rtnval = Py_None; - - finally: - Py_DECREF(args); - return rtnval; -} - - -/* This is called "my_basename" instead of just "basename" to avoid name - conflicts with glibc; basename is already prototyped if _GNU_SOURCE is - defined, and Python does define that. */ -static char * -my_basename(char *name) -{ - char *cp = name; - char *result = name; - - if (name == NULL) - return "???"; - while (*cp != '\0') { - if (*cp == SEP) - result = cp + 1; - ++cp; - } - return result; -} - - -static PyObject * -SyntaxError__str__(PyObject *_self, PyObject *self) -{ - PyObject *msg; - PyObject *str; - PyObject *filename, *lineno, *result; - - if (!(msg = PyObject_GetAttrString(self, "msg"))) - return NULL; - - str = PyObject_Str(msg); - Py_DECREF(msg); - result = str; - - /* XXX -- do all the additional formatting with filename and - lineno here */ - - if (str != NULL && PyString_Check(str)) { - int have_filename = 0; - int have_lineno = 0; - char *buffer = NULL; - - if ((filename = PyObject_GetAttrString(self, "filename")) != NULL) - have_filename = PyString_Check(filename); - else - PyErr_Clear(); - - if ((lineno = PyObject_GetAttrString(self, "lineno")) != NULL) - have_lineno = PyInt_Check(lineno); - else - PyErr_Clear(); - - if (have_filename || have_lineno) { - Py_ssize_t bufsize = PyString_GET_SIZE(str) + 64; - if (have_filename) - bufsize += PyString_GET_SIZE(filename); - - buffer = (char *)PyMem_MALLOC(bufsize); - if (buffer != NULL) { - if (have_filename && have_lineno) - PyOS_snprintf(buffer, bufsize, "%s (%s, line %ld)", - PyString_AS_STRING(str), - my_basename(PyString_AS_STRING(filename)), - PyInt_AsLong(lineno)); - else if (have_filename) - PyOS_snprintf(buffer, bufsize, "%s (%s)", - PyString_AS_STRING(str), - my_basename(PyString_AS_STRING(filename))); - else if (have_lineno) - PyOS_snprintf(buffer, bufsize, "%s (line %ld)", - PyString_AS_STRING(str), - PyInt_AsLong(lineno)); - - result = PyString_FromString(buffer); - PyMem_FREE(buffer); - - if (result == NULL) - result = str; - else - Py_DECREF(str); - } - } - Py_XDECREF(filename); - Py_XDECREF(lineno); - } - return result; -} - - -static PyMethodDef SyntaxError_methods[] = { - {"__init__", SyntaxError__init__, METH_VARARGS}, - {"__str__", SyntaxError__str__, METH_O}, - {NULL, NULL} -}; - - -static PyObject * -KeyError__str__(PyObject *_self, PyObject *self) -{ - PyObject *argsattr; - PyObject *result; - - 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 - KeyError: '' - rather than the confusing - 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 BaseException__str__(). - */ - if (PyTuple_Check(argsattr) && PyTuple_GET_SIZE(argsattr) == 1) { - PyObject *key = PyTuple_GET_ITEM(argsattr, 0); - result = PyObject_Repr(key); - } - else - result = BaseException__str__(_self, self); - - Py_DECREF(argsattr); - return result; -} - -static PyMethodDef KeyError_methods[] = { - {"__str__", KeyError__str__, METH_O}, - {NULL, NULL} -}; - - -#ifdef Py_USING_UNICODE -static -int get_int(PyObject *exc, const char *name, Py_ssize_t *value) -{ - PyObject *attr = PyObject_GetAttrString(exc, (char *)name); - - if (!attr) - return -1; - if (PyInt_Check(attr)) { - *value = PyInt_AS_LONG(attr); - } else if (PyLong_Check(attr)) { - *value = (size_t)PyLong_AsLongLong(attr); - if (*value == -1) { - Py_DECREF(attr); - return -1; - } - } else { - PyErr_Format(PyExc_TypeError, "%.200s attribute must be int", name); - Py_DECREF(attr); - return -1; - } - Py_DECREF(attr); - return 0; -} - - -static -int set_ssize_t(PyObject *exc, const char *name, Py_ssize_t value) -{ - PyObject *obj = PyInt_FromSsize_t(value); - int result; - - if (!obj) - return -1; - result = PyObject_SetAttrString(exc, (char *)name, obj); - Py_DECREF(obj); - return result; -} - -static -PyObject *get_string(PyObject *exc, const char *name) -{ - PyObject *attr = PyObject_GetAttrString(exc, (char *)name); - - if (!attr) - return NULL; - if (!PyString_Check(attr)) { - PyErr_Format(PyExc_TypeError, "%.200s attribute must be str", name); - Py_DECREF(attr); - return NULL; - } - return attr; -} - - -static -int set_string(PyObject *exc, const char *name, const char *value) -{ - PyObject *obj = PyString_FromString(value); - int result; - - if (!obj) - return -1; - result = PyObject_SetAttrString(exc, (char *)name, obj); - Py_DECREF(obj); - return result; -} - - -static -PyObject *get_unicode(PyObject *exc, const char *name) -{ - PyObject *attr = PyObject_GetAttrString(exc, (char *)name); - - if (!attr) - return NULL; - if (!PyUnicode_Check(attr)) { - PyErr_Format(PyExc_TypeError, "%.200s attribute must be unicode", name); - Py_DECREF(attr); - return NULL; - } - return attr; -} - -PyObject * PyUnicodeEncodeError_GetEncoding(PyObject *exc) -{ - return get_string(exc, "encoding"); -} - -PyObject * PyUnicodeDecodeError_GetEncoding(PyObject *exc) -{ - return get_string(exc, "encoding"); -} - -PyObject *PyUnicodeEncodeError_GetObject(PyObject *exc) -{ - return get_unicode(exc, "object"); -} - -PyObject *PyUnicodeDecodeError_GetObject(PyObject *exc) -{ - return get_string(exc, "object"); -} - -PyObject *PyUnicodeTranslateError_GetObject(PyObject *exc) -{ - return get_unicode(exc, "object"); -} - -int PyUnicodeEncodeError_GetStart(PyObject *exc, Py_ssize_t *start) -{ - if (!get_int(exc, "start", start)) { - PyObject *object = PyUnicodeEncodeError_GetObject(exc); - Py_ssize_t size; - if (!object) - return -1; - size = PyUnicode_GET_SIZE(object); - if (*start<0) - *start = 0; /*XXX check for values <0*/ - if (*start>=size) - *start = size-1; - Py_DECREF(object); - return 0; - } - return -1; -} - - -int PyUnicodeDecodeError_GetStart(PyObject *exc, Py_ssize_t *start) -{ - if (!get_int(exc, "start", start)) { - PyObject *object = PyUnicodeDecodeError_GetObject(exc); - Py_ssize_t size; - if (!object) - return -1; - size = PyString_GET_SIZE(object); - if (*start<0) - *start = 0; - if (*start>=size) - *start = size-1; - Py_DECREF(object); - return 0; - } - return -1; -} - - -int PyUnicodeTranslateError_GetStart(PyObject *exc, Py_ssize_t *start) -{ - return PyUnicodeEncodeError_GetStart(exc, start); -} - - -int PyUnicodeEncodeError_SetStart(PyObject *exc, Py_ssize_t start) -{ - return set_ssize_t(exc, "start", start); -} - - -int PyUnicodeDecodeError_SetStart(PyObject *exc, Py_ssize_t start) -{ - return set_ssize_t(exc, "start", start); -} - - -int PyUnicodeTranslateError_SetStart(PyObject *exc, Py_ssize_t start) -{ - return set_ssize_t(exc, "start", start); -} - - -int PyUnicodeEncodeError_GetEnd(PyObject *exc, Py_ssize_t *end) -{ - if (!get_int(exc, "end", end)) { - PyObject *object = PyUnicodeEncodeError_GetObject(exc); - Py_ssize_t size; - if (!object) - return -1; - size = PyUnicode_GET_SIZE(object); - if (*end<1) - *end = 1; - if (*end>size) - *end = size; - Py_DECREF(object); - return 0; - } - return -1; -} - - -int PyUnicodeDecodeError_GetEnd(PyObject *exc, Py_ssize_t *end) -{ - if (!get_int(exc, "end", end)) { - PyObject *object = PyUnicodeDecodeError_GetObject(exc); - Py_ssize_t size; - if (!object) - return -1; - size = PyString_GET_SIZE(object); - if (*end<1) - *end = 1; - if (*end>size) - *end = size; - Py_DECREF(object); - return 0; - } - return -1; -} - - -int PyUnicodeTranslateError_GetEnd(PyObject *exc, Py_ssize_t *start) -{ - return PyUnicodeEncodeError_GetEnd(exc, start); -} - - -int PyUnicodeEncodeError_SetEnd(PyObject *exc, Py_ssize_t end) -{ - return set_ssize_t(exc, "end", end); -} - - -int PyUnicodeDecodeError_SetEnd(PyObject *exc, Py_ssize_t end) -{ - return set_ssize_t(exc, "end", end); -} - - -int PyUnicodeTranslateError_SetEnd(PyObject *exc, Py_ssize_t end) -{ - return set_ssize_t(exc, "end", end); -} - - -PyObject *PyUnicodeEncodeError_GetReason(PyObject *exc) -{ - return get_string(exc, "reason"); -} - - -PyObject *PyUnicodeDecodeError_GetReason(PyObject *exc) -{ - return get_string(exc, "reason"); -} - - -PyObject *PyUnicodeTranslateError_GetReason(PyObject *exc) -{ - return get_string(exc, "reason"); -} - - -int PyUnicodeEncodeError_SetReason(PyObject *exc, const char *reason) -{ - return set_string(exc, "reason", reason); -} - - -int PyUnicodeDecodeError_SetReason(PyObject *exc, const char *reason) -{ - return set_string(exc, "reason", reason); -} - - -int PyUnicodeTranslateError_SetReason(PyObject *exc, const char *reason) -{ - return set_string(exc, "reason", reason); -} - - -static PyObject * -UnicodeError__init__(PyObject *self, PyObject *args, PyTypeObject *objecttype) -{ - PyObject *rtnval = NULL; - PyObject *encoding; - PyObject *object; - PyObject *start; - PyObject *end; - PyObject *reason; - - if (!(self = get_self(args))) - return NULL; - - 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, - &PyInt_Type, &start, - &PyInt_Type, &end, - &PyString_Type, &reason)) - goto finally; - - if (PyObject_SetAttrString(self, "encoding", encoding)) - goto finally; - if (PyObject_SetAttrString(self, "object", object)) - goto finally; - if (PyObject_SetAttrString(self, "start", start)) - goto finally; - if (PyObject_SetAttrString(self, "end", end)) - goto finally; - if (PyObject_SetAttrString(self, "reason", reason)) - goto finally; - - Py_INCREF(Py_None); - rtnval = Py_None; - - finally: - Py_DECREF(args); - return rtnval; -} - - -static PyObject * -UnicodeEncodeError__init__(PyObject *self, PyObject *args) -{ - return UnicodeError__init__(self, args, &PyUnicode_Type); -} - -static PyObject * -UnicodeEncodeError__str__(PyObject *self, PyObject *arg) -{ - PyObject *encodingObj = NULL; - PyObject *objectObj = NULL; - Py_ssize_t start; - Py_ssize_t end; - PyObject *reasonObj = NULL; - PyObject *result = NULL; - - self = arg; - - if (!(encodingObj = PyUnicodeEncodeError_GetEncoding(self))) - goto error; - - if (!(objectObj = PyUnicodeEncodeError_GetObject(self))) - goto error; - - if (PyUnicodeEncodeError_GetStart(self, &start)) - goto error; - - if (PyUnicodeEncodeError_GetEnd(self, &end)) - goto error; - - if (!(reasonObj = PyUnicodeEncodeError_GetReason(self))) - goto error; - - if (end==start+1) { - int badchar = (int)PyUnicode_AS_UNICODE(objectObj)[start]; - char badchar_str[20]; - if (badchar <= 0xff) - PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar); - else if (badchar <= 0xffff) - PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar); - else - PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar); - result = PyString_FromFormat( - "'%.400s' codec can't encode character u'\\%s' in position %zd: %.400s", - PyString_AS_STRING(encodingObj), - badchar_str, - start, - PyString_AS_STRING(reasonObj) - ); - } - else { - result = PyString_FromFormat( - "'%.400s' codec can't encode characters in position %zd-%zd: %.400s", - PyString_AS_STRING(encodingObj), - start, - (end-1), - PyString_AS_STRING(reasonObj) - ); - } - -error: - Py_XDECREF(reasonObj); - Py_XDECREF(objectObj); - Py_XDECREF(encodingObj); - return result; -} - -static PyMethodDef UnicodeEncodeError_methods[] = { - {"__init__", UnicodeEncodeError__init__, METH_VARARGS}, - {"__str__", UnicodeEncodeError__str__, METH_O}, - {NULL, NULL} -}; - - -PyObject * PyUnicodeEncodeError_Create( - const char *encoding, const Py_UNICODE *object, Py_ssize_t length, - Py_ssize_t start, Py_ssize_t end, const char *reason) -{ - return PyObject_CallFunction(PyExc_UnicodeEncodeError, "su#nns", - encoding, object, length, start, end, reason); -} - - -static PyObject * -UnicodeDecodeError__init__(PyObject *self, PyObject *args) -{ - return UnicodeError__init__(self, args, &PyString_Type); -} - -static PyObject * -UnicodeDecodeError__str__(PyObject *self, PyObject *arg) -{ - PyObject *encodingObj = NULL; - PyObject *objectObj = NULL; - Py_ssize_t start; - Py_ssize_t end; - PyObject *reasonObj = NULL; - PyObject *result = NULL; - - self = arg; - - if (!(encodingObj = PyUnicodeDecodeError_GetEncoding(self))) - goto error; - - if (!(objectObj = PyUnicodeDecodeError_GetObject(self))) - goto error; - - if (PyUnicodeDecodeError_GetStart(self, &start)) - goto error; - - if (PyUnicodeDecodeError_GetEnd(self, &end)) - goto error; - - if (!(reasonObj = PyUnicodeDecodeError_GetReason(self))) - goto error; - - if (end==start+1) { - /* FromFormat does not support %02x, so format that separately */ - char byte[4]; - PyOS_snprintf(byte, sizeof(byte), "%02x", - ((int)PyString_AS_STRING(objectObj)[start])&0xff); - result = PyString_FromFormat( - "'%.400s' codec can't decode byte 0x%s in position %zd: %.400s", - PyString_AS_STRING(encodingObj), - byte, - start, - PyString_AS_STRING(reasonObj) - ); - } - else { - result = PyString_FromFormat( - "'%.400s' codec can't decode bytes in position %zd-%zd: %.400s", - PyString_AS_STRING(encodingObj), - start, - (end-1), - PyString_AS_STRING(reasonObj) - ); - } - - -error: - Py_XDECREF(reasonObj); - Py_XDECREF(objectObj); - Py_XDECREF(encodingObj); - return result; -} - -static PyMethodDef UnicodeDecodeError_methods[] = { - {"__init__", UnicodeDecodeError__init__, METH_VARARGS}, - {"__str__", UnicodeDecodeError__str__, METH_O}, - {NULL, NULL} -}; - - -PyObject * PyUnicodeDecodeError_Create( - const char *encoding, const char *object, Py_ssize_t length, - Py_ssize_t start, Py_ssize_t end, const char *reason) -{ - assert(length < INT_MAX); - assert(start < INT_MAX); - assert(end < INT_MAX); - return PyObject_CallFunction(PyExc_UnicodeDecodeError, "ss#nns", - encoding, object, length, start, end, reason); -} - - -static PyObject * -UnicodeTranslateError__init__(PyObject *self, PyObject *args) -{ - PyObject *rtnval = NULL; - PyObject *object; - PyObject *start; - PyObject *end; - PyObject *reason; - - if (!(self = get_self(args))) - return NULL; - - 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, - &PyInt_Type, &end, - &PyString_Type, &reason)) - goto finally; - - if (PyObject_SetAttrString(self, "object", object)) - goto finally; - if (PyObject_SetAttrString(self, "start", start)) - goto finally; - if (PyObject_SetAttrString(self, "end", end)) - goto finally; - if (PyObject_SetAttrString(self, "reason", reason)) - goto finally; - - rtnval = Py_None; - Py_INCREF(rtnval); - - finally: - Py_DECREF(args); - return rtnval; -} - - -static PyObject * -UnicodeTranslateError__str__(PyObject *self, PyObject *arg) -{ - PyObject *objectObj = NULL; - Py_ssize_t start; - Py_ssize_t end; - PyObject *reasonObj = NULL; - PyObject *result = NULL; - - self = arg; - - if (!(objectObj = PyUnicodeTranslateError_GetObject(self))) - goto error; - - if (PyUnicodeTranslateError_GetStart(self, &start)) - goto error; - - if (PyUnicodeTranslateError_GetEnd(self, &end)) - goto error; - - if (!(reasonObj = PyUnicodeTranslateError_GetReason(self))) - goto error; - - if (end==start+1) { - int badchar = (int)PyUnicode_AS_UNICODE(objectObj)[start]; - char badchar_str[20]; - if (badchar <= 0xff) - PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar); - else if (badchar <= 0xffff) - PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar); - else - PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar); - result = PyString_FromFormat( - "can't translate character u'\\%s' in position %zd: %.400s", - badchar_str, - start, - PyString_AS_STRING(reasonObj) - ); - } - else { - result = PyString_FromFormat( - "can't translate characters in position %zd-%zd: %.400s", - start, - (end-1), - PyString_AS_STRING(reasonObj) - ); - } - -error: - Py_XDECREF(reasonObj); - Py_XDECREF(objectObj); - return result; -} - -static PyMethodDef UnicodeTranslateError_methods[] = { - {"__init__", UnicodeTranslateError__init__, METH_VARARGS}, - {"__str__", UnicodeTranslateError__str__, METH_O}, - {NULL, NULL} -}; - - -PyObject * PyUnicodeTranslateError_Create( - const Py_UNICODE *object, Py_ssize_t length, - Py_ssize_t start, Py_ssize_t end, const char *reason) -{ - return PyObject_CallFunction(PyExc_UnicodeTranslateError, "u#nns", - object, length, start, end, reason); -} -#endif - - - -/* Exception doc strings */ - -PyDoc_STRVAR(AssertionError__doc__, "Assertion failed."); - -PyDoc_STRVAR(LookupError__doc__, "Base class for lookup errors."); - -PyDoc_STRVAR(IndexError__doc__, "Sequence index out of range."); - -PyDoc_STRVAR(KeyError__doc__, "Mapping key not found."); - -PyDoc_STRVAR(ArithmeticError__doc__, "Base class for arithmetic errors."); - -PyDoc_STRVAR(OverflowError__doc__, "Result too large to be represented."); - -PyDoc_STRVAR(ZeroDivisionError__doc__, -"Second argument to a division or modulo operation was zero."); - -PyDoc_STRVAR(FloatingPointError__doc__, "Floating point operation failed."); - -PyDoc_STRVAR(ValueError__doc__, -"Inappropriate argument value (of correct type)."); - -PyDoc_STRVAR(UnicodeError__doc__, "Unicode related error."); - -#ifdef Py_USING_UNICODE -PyDoc_STRVAR(UnicodeEncodeError__doc__, "Unicode encoding error."); - -PyDoc_STRVAR(UnicodeDecodeError__doc__, "Unicode decoding error."); - -PyDoc_STRVAR(UnicodeTranslateError__doc__, "Unicode translation error."); -#endif - -PyDoc_STRVAR(SystemError__doc__, -"Internal error in the Python interpreter.\n\ -\n\ -Please report this to the Python maintainer, along with the traceback,\n\ -the Python version, and the hardware/OS platform and version."); - -PyDoc_STRVAR(ReferenceError__doc__, -"Weak ref proxy used after referent went away."); - -PyDoc_STRVAR(MemoryError__doc__, "Out of memory."); - -PyDoc_STRVAR(IndentationError__doc__, "Improper indentation."); - -PyDoc_STRVAR(TabError__doc__, "Improper mixture of spaces and tabs."); - -/* Warning category docstrings */ - -PyDoc_STRVAR(Warning__doc__, "Base class for warning categories."); - -PyDoc_STRVAR(UserWarning__doc__, -"Base class for warnings generated by user code."); - -PyDoc_STRVAR(DeprecationWarning__doc__, -"Base class for warnings about deprecated features."); - -PyDoc_STRVAR(PendingDeprecationWarning__doc__, -"Base class for warnings about features which will be deprecated " -"in the future."); - -PyDoc_STRVAR(SyntaxWarning__doc__, -"Base class for warnings about dubious syntax."); - -PyDoc_STRVAR(OverflowWarning__doc__, -"Base class for warnings about numeric overflow. Won't exist in Python 2.5."); - -PyDoc_STRVAR(RuntimeWarning__doc__, -"Base class for warnings about dubious runtime behavior."); - -PyDoc_STRVAR(FutureWarning__doc__, -"Base class for warnings about constructs that will change semantically " -"in the future."); - -PyDoc_STRVAR(ImportWarning__doc__, -"Base class for warnings about probable mistakes in module imports"); - - -/* module global functions */ -static PyMethodDef functions[] = { - /* Sentinel */ - {NULL, NULL} -}; - - - -/* Global C API defined exceptions */ - -PyObject *PyExc_BaseException; -PyObject *PyExc_Exception; -PyObject *PyExc_StopIteration; -PyObject *PyExc_GeneratorExit; -PyObject *PyExc_StandardError; -PyObject *PyExc_ArithmeticError; -PyObject *PyExc_LookupError; - -PyObject *PyExc_AssertionError; -PyObject *PyExc_AttributeError; -PyObject *PyExc_EOFError; -PyObject *PyExc_FloatingPointError; -PyObject *PyExc_EnvironmentError; -PyObject *PyExc_IOError; -PyObject *PyExc_OSError; -PyObject *PyExc_ImportError; -PyObject *PyExc_IndexError; -PyObject *PyExc_KeyError; -PyObject *PyExc_KeyboardInterrupt; -PyObject *PyExc_MemoryError; -PyObject *PyExc_NameError; -PyObject *PyExc_OverflowError; -PyObject *PyExc_RuntimeError; -PyObject *PyExc_NotImplementedError; -PyObject *PyExc_SyntaxError; -PyObject *PyExc_IndentationError; -PyObject *PyExc_TabError; -PyObject *PyExc_ReferenceError; -PyObject *PyExc_SystemError; -PyObject *PyExc_SystemExit; -PyObject *PyExc_UnboundLocalError; -PyObject *PyExc_UnicodeError; -PyObject *PyExc_UnicodeEncodeError; -PyObject *PyExc_UnicodeDecodeError; -PyObject *PyExc_UnicodeTranslateError; -PyObject *PyExc_TypeError; -PyObject *PyExc_ValueError; -PyObject *PyExc_ZeroDivisionError; -#ifdef MS_WINDOWS -PyObject *PyExc_WindowsError; -#endif -#ifdef __VMS -PyObject *PyExc_VMSError; -#endif - -/* Pre-computed MemoryError instance. Best to create this as early as - * possible and not wait until a MemoryError is actually raised! - */ -PyObject *PyExc_MemoryErrorInst; - -/* Predefined warning categories */ -PyObject *PyExc_Warning; -PyObject *PyExc_UserWarning; -PyObject *PyExc_DeprecationWarning; -PyObject *PyExc_PendingDeprecationWarning; -PyObject *PyExc_SyntaxWarning; -/* PyExc_OverflowWarning should be removed for Python 2.5 */ -PyObject *PyExc_OverflowWarning; -PyObject *PyExc_RuntimeWarning; -PyObject *PyExc_FutureWarning; -PyObject *PyExc_ImportWarning; - - - -/* mapping between exception names and their PyObject ** */ -static struct { - char *name; - PyObject **exc; - PyObject **base; /* NULL == PyExc_StandardError */ - char *docstr; - PyMethodDef *methods; - int (*classinit)(PyObject *); -} exctable[] = { - /* - * The first four classes MUST appear in exactly this order - */ - {"BaseException", &PyExc_BaseException}, - {"Exception", &PyExc_Exception, &PyExc_BaseException, Exception__doc__}, - {"StopIteration", &PyExc_StopIteration, &PyExc_Exception, - StopIteration__doc__}, - {"GeneratorExit", &PyExc_GeneratorExit, &PyExc_Exception, - GeneratorExit__doc__}, - {"StandardError", &PyExc_StandardError, &PyExc_Exception, - StandardError__doc__}, - {"TypeError", &PyExc_TypeError, 0, TypeError__doc__}, - /* - * The rest appear in depth-first order of the hierarchy - */ - {"SystemExit", &PyExc_SystemExit, &PyExc_BaseException, SystemExit__doc__, - SystemExit_methods}, - {"KeyboardInterrupt", &PyExc_KeyboardInterrupt, &PyExc_BaseException, - KeyboardInterrupt__doc__}, - {"ImportError", &PyExc_ImportError, 0, ImportError__doc__}, - {"EnvironmentError", &PyExc_EnvironmentError, 0, EnvironmentError__doc__, - EnvironmentError_methods}, - {"IOError", &PyExc_IOError, &PyExc_EnvironmentError, IOError__doc__}, - {"OSError", &PyExc_OSError, &PyExc_EnvironmentError, OSError__doc__}, -#ifdef MS_WINDOWS - {"WindowsError", &PyExc_WindowsError, &PyExc_OSError, -WindowsError__doc__, WindowsError_methods}, -#endif /* MS_WINDOWS */ -#ifdef __VMS - {"VMSError", &PyExc_VMSError, &PyExc_OSError, - VMSError__doc__}, -#endif - {"EOFError", &PyExc_EOFError, 0, EOFError__doc__}, - {"RuntimeError", &PyExc_RuntimeError, 0, RuntimeError__doc__}, - {"NotImplementedError", &PyExc_NotImplementedError, - &PyExc_RuntimeError, NotImplementedError__doc__}, - {"NameError", &PyExc_NameError, 0, NameError__doc__}, - {"UnboundLocalError", &PyExc_UnboundLocalError, &PyExc_NameError, - UnboundLocalError__doc__}, - {"AttributeError", &PyExc_AttributeError, 0, AttributeError__doc__}, - {"SyntaxError", &PyExc_SyntaxError, 0, SyntaxError__doc__, - SyntaxError_methods, SyntaxError__classinit__}, - {"IndentationError", &PyExc_IndentationError, &PyExc_SyntaxError, - IndentationError__doc__}, - {"TabError", &PyExc_TabError, &PyExc_IndentationError, - TabError__doc__}, - {"AssertionError", &PyExc_AssertionError, 0, AssertionError__doc__}, - {"LookupError", &PyExc_LookupError, 0, LookupError__doc__}, - {"IndexError", &PyExc_IndexError, &PyExc_LookupError, - IndexError__doc__}, - {"KeyError", &PyExc_KeyError, &PyExc_LookupError, - KeyError__doc__, KeyError_methods}, - {"ArithmeticError", &PyExc_ArithmeticError, 0, ArithmeticError__doc__}, - {"OverflowError", &PyExc_OverflowError, &PyExc_ArithmeticError, - OverflowError__doc__}, - {"ZeroDivisionError", &PyExc_ZeroDivisionError, &PyExc_ArithmeticError, - ZeroDivisionError__doc__}, - {"FloatingPointError", &PyExc_FloatingPointError, &PyExc_ArithmeticError, - FloatingPointError__doc__}, - {"ValueError", &PyExc_ValueError, 0, ValueError__doc__}, - {"UnicodeError", &PyExc_UnicodeError, &PyExc_ValueError, UnicodeError__doc__}, -#ifdef Py_USING_UNICODE - {"UnicodeEncodeError", &PyExc_UnicodeEncodeError, &PyExc_UnicodeError, - UnicodeEncodeError__doc__, UnicodeEncodeError_methods}, - {"UnicodeDecodeError", &PyExc_UnicodeDecodeError, &PyExc_UnicodeError, - UnicodeDecodeError__doc__, UnicodeDecodeError_methods}, - {"UnicodeTranslateError", &PyExc_UnicodeTranslateError, &PyExc_UnicodeError, - UnicodeTranslateError__doc__, UnicodeTranslateError_methods}, -#endif - {"ReferenceError", &PyExc_ReferenceError, 0, ReferenceError__doc__}, - {"SystemError", &PyExc_SystemError, 0, SystemError__doc__}, - {"MemoryError", &PyExc_MemoryError, 0, MemoryError__doc__}, - /* Warning categories */ - {"Warning", &PyExc_Warning, &PyExc_Exception, Warning__doc__}, - {"UserWarning", &PyExc_UserWarning, &PyExc_Warning, UserWarning__doc__}, - {"DeprecationWarning", &PyExc_DeprecationWarning, &PyExc_Warning, - DeprecationWarning__doc__}, - {"PendingDeprecationWarning", &PyExc_PendingDeprecationWarning, &PyExc_Warning, - PendingDeprecationWarning__doc__}, - {"SyntaxWarning", &PyExc_SyntaxWarning, &PyExc_Warning, SyntaxWarning__doc__}, - /* OverflowWarning should be removed for Python 2.5 */ - {"OverflowWarning", &PyExc_OverflowWarning, &PyExc_Warning, - OverflowWarning__doc__}, - {"RuntimeWarning", &PyExc_RuntimeWarning, &PyExc_Warning, - RuntimeWarning__doc__}, - {"FutureWarning", &PyExc_FutureWarning, &PyExc_Warning, - FutureWarning__doc__}, - {"ImportWarning", &PyExc_ImportWarning, &PyExc_Warning, - ImportWarning__doc__}, - /* Sentinel */ - {NULL} -}; - - - -void -_PyExc_Init(void) -{ - char *modulename = "exceptions"; - Py_ssize_t modnamesz = strlen(modulename); - int i; - PyObject *me, *mydict, *bltinmod, *bdict, *doc, *args; - - me = Py_InitModule(modulename, functions); - if (me == NULL) - goto err; - mydict = PyModule_GetDict(me); - if (mydict == NULL) - goto err; - bltinmod = PyImport_ImportModule("__builtin__"); - if (bltinmod == NULL) - goto err; - bdict = PyModule_GetDict(bltinmod); - if (bdict == NULL) - goto err; - doc = PyString_FromString(module__doc__); - if (doc == NULL) - goto err; - - i = PyDict_SetItemString(mydict, "__doc__", doc); - Py_DECREF(doc); - if (i < 0) { - err: - Py_FatalError("exceptions bootstrapping error."); - return; - } - - /* This is the base class of all exceptions, so make it first. */ - if (make_BaseException(modulename) || - PyDict_SetItemString(mydict, "BaseException", PyExc_BaseException) || - PyDict_SetItemString(bdict, "BaseException", PyExc_BaseException)) - { - Py_FatalError("Base class `BaseException' could not be created."); - } - - /* Now we can programmatically create all the remaining exceptions. - * Remember to start the loop at 1 to skip Exceptions. - */ - for (i=1; exctable[i].name; i++) { - int status; - char *cname = PyMem_NEW(char, modnamesz+strlen(exctable[i].name)+2); - PyObject *base; - - (void)strcpy(cname, modulename); - (void)strcat(cname, "."); - (void)strcat(cname, exctable[i].name); - - if (exctable[i].base == 0) - base = PyExc_StandardError; - else - base = *exctable[i].base; - - status = make_class(exctable[i].exc, base, cname, - exctable[i].methods, - exctable[i].docstr); - - PyMem_DEL(cname); - - if (status) - Py_FatalError("Standard exception classes could not be created."); - - if (exctable[i].classinit) { - status = (*exctable[i].classinit)(*exctable[i].exc); - if (status) - Py_FatalError("An exception class could not be initialized."); - } - - /* Now insert the class into both this module and the __builtin__ - * module. - */ - if (PyDict_SetItemString(mydict, exctable[i].name, *exctable[i].exc) || - PyDict_SetItemString(bdict, exctable[i].name, *exctable[i].exc)) - { - Py_FatalError("Module dictionary insertion problem."); - } - } - - /* Now we need to pre-allocate a MemoryError instance */ - args = PyTuple_New(0); - if (!args || - !(PyExc_MemoryErrorInst = PyEval_CallObject(PyExc_MemoryError, args))) - { - Py_FatalError("Cannot pre-allocate MemoryError instance\n"); - } - Py_DECREF(args); - - /* We're done with __builtin__ */ - Py_DECREF(bltinmod); -} - - -void -_PyExc_Fini(void) -{ - int i; - - Py_XDECREF(PyExc_MemoryErrorInst); - PyExc_MemoryErrorInst = NULL; - - for (i=0; exctable[i].name; i++) { - /* clear the class's dictionary, freeing up circular references - * between the class and its methods. - */ - PyObject* cdict = PyObject_GetAttrString(*exctable[i].exc, "__dict__"); - PyDict_Clear(cdict); - Py_DECREF(cdict); - - /* Now decref the exception class */ - Py_XDECREF(*exctable[i].exc); - *exctable[i].exc = NULL; - } -} diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 1dc4f28..6f3ff6f 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1084,7 +1084,8 @@ PyErr_PrintEx(int set_sys_last_vars) Py_XDECREF(tb); } -void PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) +void +PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) { int err = 0; PyObject *f = PySys_GetObject("stderr"); @@ -1132,19 +1133,22 @@ void PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) } else if (PyExceptionClass_Check(exception)) { char* className = PyExceptionClass_Name(exception); - PyObject* moduleName = - PyObject_GetAttrString(exception, "__module__"); + char *dot = strrchr(className, '.'); + PyObject* moduleName; + if (dot != NULL) + className = dot+1; + moduleName = PyObject_GetAttrString(exception, "__module__"); if (moduleName == NULL) err = PyFile_WriteString("", f); else { char* modstr = PyString_AsString(moduleName); - Py_DECREF(moduleName); if (modstr && strcmp(modstr, "exceptions")) { err = PyFile_WriteString(modstr, f); err += PyFile_WriteString(".", f); } + Py_DECREF(moduleName); } if (err == 0) { if (className == NULL) -- cgit v0.12