Merged revisions 77088 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r77088 | georg.brandl | 2009-12-28 09:34:58 +0100 (Mo, 28 Dez 2009) | 1 line #7033: add new API function PyErr_NewExceptionWithDoc, for easily giving new exceptions a docstring. ........
This commit is contained in:
parent
127d47092a
commit
1e28a27f84
|
@ -404,6 +404,15 @@ in various ways. There is a separate error indicator for each thread.
|
||||||
argument can be used to specify a dictionary of class variables and methods.
|
argument can be used to specify a dictionary of class variables and methods.
|
||||||
|
|
||||||
|
|
||||||
|
.. cfunction:: PyObject* PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict)
|
||||||
|
|
||||||
|
Same as :cfunc:`PyErr_NewException`, except that the new exception class can
|
||||||
|
easily be given a docstring: If *doc* is non-*NULL*, it will be used as the
|
||||||
|
docstring for the exception class.
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
|
|
||||||
.. cfunction:: void PyErr_WriteUnraisable(PyObject *obj)
|
.. cfunction:: void PyErr_WriteUnraisable(PyObject *obj)
|
||||||
|
|
||||||
This utility function prints a warning message to ``sys.stderr`` when an
|
This utility function prints a warning message to ``sys.stderr`` when an
|
||||||
|
|
|
@ -281,6 +281,12 @@ PyErr_NewException:char*:name::
|
||||||
PyErr_NewException:PyObject*:base:0:
|
PyErr_NewException:PyObject*:base:0:
|
||||||
PyErr_NewException:PyObject*:dict:0:
|
PyErr_NewException:PyObject*:dict:0:
|
||||||
|
|
||||||
|
PyErr_NewExceptionWithDoc:PyObject*::+1:
|
||||||
|
PyErr_NewExceptionWithDoc:char*:name::
|
||||||
|
PyErr_NewExceptionWithDoc:char*:doc::
|
||||||
|
PyErr_NewExceptionWithDoc:PyObject*:base:0:
|
||||||
|
PyErr_NewExceptionWithDoc:PyObject*:dict:0:
|
||||||
|
|
||||||
PyErr_NoMemory:PyObject*::null:
|
PyErr_NoMemory:PyObject*::null:
|
||||||
|
|
||||||
PyErr_NormalizeException:void:::
|
PyErr_NormalizeException:void:::
|
||||||
|
|
|
@ -210,8 +210,10 @@ PyAPI_FUNC(void) _PyErr_BadInternalCall(const char *filename, int lineno);
|
||||||
#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__)
|
#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__)
|
||||||
|
|
||||||
/* Function to create a new exception */
|
/* Function to create a new exception */
|
||||||
PyAPI_FUNC(PyObject *) PyErr_NewException(const char *name, PyObject *base,
|
PyAPI_FUNC(PyObject *) PyErr_NewException(
|
||||||
PyObject *dict);
|
const char *name, PyObject *base, PyObject *dict);
|
||||||
|
PyAPI_FUNC(PyObject *) PyErr_NewExceptionWithDoc(
|
||||||
|
const char *name, const char *doc, PyObject *base, PyObject *dict);
|
||||||
PyAPI_FUNC(void) PyErr_WriteUnraisable(PyObject *);
|
PyAPI_FUNC(void) PyErr_WriteUnraisable(PyObject *);
|
||||||
|
|
||||||
/* In sigcheck.c or signalmodule.c */
|
/* In sigcheck.c or signalmodule.c */
|
||||||
|
|
|
@ -618,6 +618,46 @@ class ExceptionTests(unittest.TestCase):
|
||||||
tb2 = raiseMemError()
|
tb2 = raiseMemError()
|
||||||
self.assertEqual(tb1, tb2)
|
self.assertEqual(tb1, tb2)
|
||||||
|
|
||||||
|
def test_exception_with_doc(self):
|
||||||
|
import _testcapi
|
||||||
|
doc2 = "This is a test docstring."
|
||||||
|
doc4 = "This is another test docstring."
|
||||||
|
|
||||||
|
self.assertRaises(SystemError, _testcapi.make_exception_with_doc,
|
||||||
|
"error1")
|
||||||
|
|
||||||
|
# test basic usage of PyErr_NewException
|
||||||
|
error1 = _testcapi.make_exception_with_doc("_testcapi.error1")
|
||||||
|
self.assertIs(type(error1), type)
|
||||||
|
self.assertTrue(issubclass(error1, Exception))
|
||||||
|
self.assertIsNone(error1.__doc__)
|
||||||
|
|
||||||
|
# test with given docstring
|
||||||
|
error2 = _testcapi.make_exception_with_doc("_testcapi.error2", doc2)
|
||||||
|
self.assertEqual(error2.__doc__, doc2)
|
||||||
|
|
||||||
|
# test with explicit base (without docstring)
|
||||||
|
error3 = _testcapi.make_exception_with_doc("_testcapi.error3",
|
||||||
|
base=error2)
|
||||||
|
self.assertTrue(issubclass(error3, error2))
|
||||||
|
|
||||||
|
# test with explicit base tuple
|
||||||
|
class C(object):
|
||||||
|
pass
|
||||||
|
error4 = _testcapi.make_exception_with_doc("_testcapi.error4", doc4,
|
||||||
|
(error3, C))
|
||||||
|
self.assertTrue(issubclass(error4, error3))
|
||||||
|
self.assertTrue(issubclass(error4, C))
|
||||||
|
self.assertEqual(error4.__doc__, doc4)
|
||||||
|
|
||||||
|
# test with explicit dictionary
|
||||||
|
error5 = _testcapi.make_exception_with_doc("_testcapi.error5", "",
|
||||||
|
error4, {'a': 1})
|
||||||
|
self.assertTrue(issubclass(error5, error4))
|
||||||
|
self.assertEqual(error5.a, 1)
|
||||||
|
self.assertEqual(error5.__doc__, "")
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
run_unittest(ExceptionTests)
|
run_unittest(ExceptionTests)
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,8 @@ Core and Builtins
|
||||||
C-API
|
C-API
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- Issue #7033: function ``PyErr_NewExceptionWithDoc()`` added.
|
||||||
|
|
||||||
- Issue #7414: 'C' code wasn't being skipped properly (for keyword arguments)
|
- Issue #7414: 'C' code wasn't being skipped properly (for keyword arguments)
|
||||||
in PyArg_ParseTupleAndKeywords.
|
in PyArg_ParseTupleAndKeywords.
|
||||||
|
|
||||||
|
|
|
@ -1716,6 +1716,26 @@ code_newempty(PyObject *self, PyObject *args)
|
||||||
return (PyObject *)PyCode_NewEmpty(filename, funcname, firstlineno);
|
return (PyObject *)PyCode_NewEmpty(filename, funcname, firstlineno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test PyErr_NewExceptionWithDoc (also exercise PyErr_NewException).
|
||||||
|
Run via Lib/test/test_exceptions.py */
|
||||||
|
static PyObject *
|
||||||
|
make_exception_with_doc(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
const char *doc = NULL;
|
||||||
|
PyObject *base = NULL;
|
||||||
|
PyObject *dict = NULL;
|
||||||
|
|
||||||
|
static char *kwlist[] = {"name", "doc", "base", "dict", NULL};
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
||||||
|
"s|sOO:make_exception_with_doc", kwlist,
|
||||||
|
&name, &doc, &base, &dict))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return PyErr_NewExceptionWithDoc(name, doc, base, dict);
|
||||||
|
}
|
||||||
|
|
||||||
static PyMethodDef TestMethods[] = {
|
static PyMethodDef TestMethods[] = {
|
||||||
{"raise_exception", raise_exception, METH_VARARGS},
|
{"raise_exception", raise_exception, METH_VARARGS},
|
||||||
{"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS},
|
{"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS},
|
||||||
|
@ -1774,6 +1794,8 @@ static PyMethodDef TestMethods[] = {
|
||||||
{"exception_print", exception_print, METH_VARARGS},
|
{"exception_print", exception_print, METH_VARARGS},
|
||||||
{"argparsing", argparsing, METH_VARARGS},
|
{"argparsing", argparsing, METH_VARARGS},
|
||||||
{"code_newempty", code_newempty, METH_VARARGS},
|
{"code_newempty", code_newempty, METH_VARARGS},
|
||||||
|
{"make_exception_with_doc", (PyCFunction)make_exception_with_doc,
|
||||||
|
METH_VARARGS | METH_KEYWORDS},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -693,6 +693,41 @@ PyErr_NewException(const char *name, PyObject *base, PyObject *dict)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Create an exception with docstring */
|
||||||
|
PyObject *
|
||||||
|
PyErr_NewExceptionWithDoc(const char *name, const char *doc,
|
||||||
|
PyObject *base, PyObject *dict)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
PyObject *ret = NULL;
|
||||||
|
PyObject *mydict = NULL; /* points to the dict only if we create it */
|
||||||
|
PyObject *docobj;
|
||||||
|
|
||||||
|
if (dict == NULL) {
|
||||||
|
dict = mydict = PyDict_New();
|
||||||
|
if (dict == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc != NULL) {
|
||||||
|
docobj = PyUnicode_FromString(doc);
|
||||||
|
if (docobj == NULL)
|
||||||
|
goto failure;
|
||||||
|
result = PyDict_SetItemString(dict, "__doc__", docobj);
|
||||||
|
Py_DECREF(docobj);
|
||||||
|
if (result < 0)
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = PyErr_NewException(name, base, dict);
|
||||||
|
failure:
|
||||||
|
Py_XDECREF(mydict);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Call when an exception has occurred but there is no way for Python
|
/* Call when an exception has occurred but there is no way for Python
|
||||||
to handle it. Examples: exception in __del__ or during GC. */
|
to handle it. Examples: exception in __del__ or during GC. */
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue