[Python-checkins] r77089 - in python/branches/py3k: Doc/c-api/exceptions.rst Doc/data/refcounts.dat Include/pyerrors.h Lib/test/test_exceptions.py Misc/NEWS Modules/_testcapimodule.c Python/errors.c

georg.brandl python-checkins at python.org
Mon Dec 28 09:41:02 CET 2009


Author: georg.brandl
Date: Mon Dec 28 09:41:01 2009
New Revision: 77089

Log:
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.
........


Modified:
   python/branches/py3k/   (props changed)
   python/branches/py3k/Doc/c-api/exceptions.rst
   python/branches/py3k/Doc/data/refcounts.dat
   python/branches/py3k/Include/pyerrors.h
   python/branches/py3k/Lib/test/test_exceptions.py
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Modules/_testcapimodule.c
   python/branches/py3k/Python/errors.c

Modified: python/branches/py3k/Doc/c-api/exceptions.rst
==============================================================================
--- python/branches/py3k/Doc/c-api/exceptions.rst	(original)
+++ python/branches/py3k/Doc/c-api/exceptions.rst	Mon Dec 28 09:41:01 2009
@@ -404,6 +404,15 @@
    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)
 
    This utility function prints a warning message to ``sys.stderr`` when an

Modified: python/branches/py3k/Doc/data/refcounts.dat
==============================================================================
--- python/branches/py3k/Doc/data/refcounts.dat	(original)
+++ python/branches/py3k/Doc/data/refcounts.dat	Mon Dec 28 09:41:01 2009
@@ -281,6 +281,12 @@
 PyErr_NewException:PyObject*:base: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_NormalizeException:void:::

Modified: python/branches/py3k/Include/pyerrors.h
==============================================================================
--- python/branches/py3k/Include/pyerrors.h	(original)
+++ python/branches/py3k/Include/pyerrors.h	Mon Dec 28 09:41:01 2009
@@ -210,8 +210,10 @@
 #define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__)
 
 /* Function to create a new exception */
-PyAPI_FUNC(PyObject *) PyErr_NewException(const char *name, PyObject *base,
-                                         PyObject *dict);
+PyAPI_FUNC(PyObject *) PyErr_NewException(
+	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 *);
 
 /* In sigcheck.c or signalmodule.c */

Modified: python/branches/py3k/Lib/test/test_exceptions.py
==============================================================================
--- python/branches/py3k/Lib/test/test_exceptions.py	(original)
+++ python/branches/py3k/Lib/test/test_exceptions.py	Mon Dec 28 09:41:01 2009
@@ -618,6 +618,46 @@
         tb2 = raiseMemError()
         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():
     run_unittest(ExceptionTests)
 

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Mon Dec 28 09:41:01 2009
@@ -136,6 +136,8 @@
 C-API
 -----
 
+- Issue #7033: function ``PyErr_NewExceptionWithDoc()`` added.
+
 - Issue #7414: 'C' code wasn't being skipped properly (for keyword arguments)
   in PyArg_ParseTupleAndKeywords.
 

Modified: python/branches/py3k/Modules/_testcapimodule.c
==============================================================================
--- python/branches/py3k/Modules/_testcapimodule.c	(original)
+++ python/branches/py3k/Modules/_testcapimodule.c	Mon Dec 28 09:41:01 2009
@@ -1716,6 +1716,26 @@
 	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[] = {
 	{"raise_exception",	raise_exception,		 METH_VARARGS},
 	{"raise_memoryerror",   (PyCFunction)raise_memoryerror,  METH_NOARGS},
@@ -1774,6 +1794,8 @@
 	{"exception_print", exception_print, 	         METH_VARARGS},
 	{"argparsing",     argparsing, METH_VARARGS},
 	{"code_newempty", code_newempty, 	         METH_VARARGS},
+	{"make_exception_with_doc", (PyCFunction)make_exception_with_doc,
+	 METH_VARARGS | METH_KEYWORDS},
 	{NULL, NULL} /* sentinel */
 };
 

Modified: python/branches/py3k/Python/errors.c
==============================================================================
--- python/branches/py3k/Python/errors.c	(original)
+++ python/branches/py3k/Python/errors.c	Mon Dec 28 09:41:01 2009
@@ -693,6 +693,41 @@
 	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
    to handle it.  Examples: exception in __del__ or during GC. */
 void


More information about the Python-checkins mailing list