changeset: 75722:b76fa310e73d user: Eli Bendersky date: Fri Mar 16 08:20:05 2012 +0200 files: Doc/library/xml.etree.elementtree.rst Lib/test/test_xml_etree.py Modules/_elementtree.c description: 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. diff -r 7bdf5c96fdc0 -r b76fa310e73d Doc/library/xml.etree.elementtree.rst --- a/Doc/library/xml.etree.elementtree.rst Fri Mar 16 05:53:30 2012 +0200 +++ b/Doc/library/xml.etree.elementtree.rst Fri Mar 16 08:20:05 2012 +0200 @@ -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 -r 7bdf5c96fdc0 -r b76fa310e73d Lib/test/test_xml_etree.py --- a/Lib/test/test_xml_etree.py Fri Mar 16 05:53:30 2012 +0200 +++ b/Lib/test/test_xml_etree.py Fri Mar 16 08:20:05 2012 +0200 @@ -1055,26 +1055,6 @@ 'text' """ -def error(xml): - """ - - Test error handling. - ->>> issubclass(ET.ParseError, SyntaxError) - True ->>> error("foo").position - (1, 0) ->>> error("&foo;").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('&foo;').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 -r 7bdf5c96fdc0 -r b76fa310e73d Modules/_elementtree.c --- a/Modules/_elementtree.c Fri Mar 16 05:53:30 2012 +0200 +++ b/Modules/_elementtree.c Fri Mar 16 08:20:05 2012 +0200 @@ -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; }

AltStyle によって変換されたページ (->オリジナル) /