[Python-checkins] cpython: Issue #14207: the ParseError exception raised by _elementtree was made

eli.bendersky python-checkins at python.org
Fri Mar 16 07:21:49 CET 2012


http://hg.python.org/cpython/rev/b76fa310e73d
changeset:   75722:b76fa310e73d
user:        Eli Bendersky <eliben at gmail.com>
date:        Fri Mar 16 08:20:05 2012 +0200
summary:
  Issue #14207: the ParseError exception raised by _elementtree was made
consistent to the one raised by the Python module (the 'code' attribute
was added).

In addition, the exception is now documented.

Added a test to check that ParseError has the required attributes, and
threw away the equivalent doctest which is no longer required.

files:
  Doc/library/xml.etree.elementtree.rst |  19 ++++++-
  Lib/test/test_xml_etree.py            |  42 +++++++-------
  Modules/_elementtree.c                |  35 +++++++++--
  3 files changed, 67 insertions(+), 29 deletions(-)


diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst
--- a/Doc/library/xml.etree.elementtree.rst
+++ b/Doc/library/xml.etree.elementtree.rst
@@ -198,7 +198,6 @@
 Element Objects
 ---------------
 
-
 .. class:: Element(tag, attrib={}, **extra)
 
    Element class.  This class defines the Element interface, and provides a
@@ -643,6 +642,24 @@
     >>> parser.close()
     4
 
+Exceptions
+----------
+
+.. class:: ParseError
+
+   XML parse error, raised by the various parsing methods in this module when
+   parsing fails.  The string representation of an instance of this exception
+   will contain a user-friendly error message.  In addition, it will have
+   the following attributes available:
+
+   .. attribute:: code
+
+      A numeric error code from the expat parser. See the documentation of
+      :mod:`xml.parsers.expat` for the list of error codes and their meanings.
+
+   .. attribute:: position
+
+      A tuple of *line*, *column* numbers, specifying where the error occurred.
 
 .. rubric:: Footnotes
 
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -1055,26 +1055,6 @@
     '<document>text</document>'
     """
 
-def error(xml):
-    """
-
-    Test error handling.
-
-    >>> issubclass(ET.ParseError, SyntaxError)
-    True
-    >>> error("foo").position
-    (1, 0)
-    >>> error("<tag>&foo;</tag>").position
-    (1, 5)
-    >>> error("foobar<").position
-    (1, 6)
-
-    """
-    try:
-        ET.XML(xml)
-    except ET.ParseError:
-        return sys.exc_info()[1]
-
 def namespace():
     """
     Test namespace issues.
@@ -2039,6 +2019,27 @@
         self.assertEqual(tree.getroot().tag, 'site')
 
 
+class ParseErrorTest(unittest.TestCase):
+    def test_subclass(self):
+        self.assertIsInstance(ET.ParseError(), SyntaxError)
+
+    def _get_error(self, s):
+        try:
+            ET.fromstring(s)
+        except ET.ParseError as e:
+            return e
+
+    def test_error_position(self):
+        self.assertEqual(self._get_error('foo').position, (1, 0))
+        self.assertEqual(self._get_error('<tag>&foo;</tag>').position, (1, 5))
+        self.assertEqual(self._get_error('foobar<').position, (1, 6))
+
+    def test_error_code(self):
+        import xml.parsers.expat.errors as ERRORS
+        self.assertEqual(self._get_error('foo').code,
+                ERRORS.codes[ERRORS.XML_ERROR_SYNTAX])
+
+
 # --------------------------------------------------------------------
 
 
@@ -2091,6 +2092,7 @@
     test_classes = [
         ElementSlicingTest,
         StringIOTest,
+        ParseErrorTest,
         ElementTreeTest,
         TreeBuilderTest]
     if module is pyET:
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -2177,13 +2177,18 @@
     return value;
 }
 
+/* Set the ParseError exception with the given parameters.
+ * If message is not NULL, it's used as the error string. Otherwise, the
+ * message string is the default for the given error_code.
+*/
 static void
-expat_set_error(const char* message, int line, int column)
+expat_set_error(enum XML_Error error_code, int line, int column, char *message)
 {
-    PyObject *errmsg, *error, *position;
+    PyObject *errmsg, *error, *position, *code;
 
     errmsg = PyUnicode_FromFormat("%s: line %d, column %d",
-                                  message, line, column);
+                message ? message : EXPAT(ErrorString)(error_code),
+                line, column);
     if (errmsg == NULL)
         return;
 
@@ -2192,7 +2197,19 @@
     if (!error)
         return;
 
-    /* add position attribute */
+    /* Add code and position attributes */
+    code = PyLong_FromLong((long)error_code);
+    if (!code) {
+        Py_DECREF(error);
+        return;
+    }
+    if (PyObject_SetAttrString(error, "code", code) == -1) {
+        Py_DECREF(error);
+        Py_DECREF(code);
+        return;
+    }
+    Py_DECREF(code);
+
     position = Py_BuildValue("(ii)", line, column);
     if (!position) {
         Py_DECREF(error);
@@ -2244,9 +2261,10 @@
         char message[128] = "undefined entity ";
         strncat(message, data_in, data_len < 100?data_len:100);
         expat_set_error(
-            message,
+            XML_ERROR_UNDEFINED_ENTITY,
             EXPAT(GetErrorLineNumber)(self->parser),
-            EXPAT(GetErrorColumnNumber)(self->parser)
+            EXPAT(GetErrorColumnNumber)(self->parser),
+            message
             );
     }
 
@@ -2629,9 +2647,10 @@
 
     if (!ok) {
         expat_set_error(
-            EXPAT(ErrorString)(EXPAT(GetErrorCode)(self->parser)),
+            EXPAT(GetErrorCode)(self->parser),
             EXPAT(GetErrorLineNumber)(self->parser),
-            EXPAT(GetErrorColumnNumber)(self->parser)
+            EXPAT(GetErrorColumnNumber)(self->parser),
+            NULL
             );
         return NULL;
     }

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list