summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2010-10-15 14:46:48 (GMT)
committerGeorg Brandl <georg@python.org>2010-10-15 14:46:48 (GMT)
commitb4dac71a8768888dbe3de007780cd5467e48f0f4 (patch)
treec44b7b9544d5953a767a74a8bad038a5f99b4284
parentf668df5fa7e2048f4b17e98882f2a21405b6bdb4 (diff)
downloadcpython-b4dac71a8768888dbe3de007780cd5467e48f0f4.zip
cpython-b4dac71a8768888dbe3de007780cd5467e48f0f4.tar.gz
cpython-b4dac71a8768888dbe3de007780cd5467e48f0f4.tar.bz2
#5355: Provide mappings from Expat error numbers to string descriptions and backwards, in order to actually make it possible to analyze error codes provided by ExpatError.
-rw-r--r--Doc/library/pyexpat.rst91
-rw-r--r--Misc/NEWS4
-rw-r--r--Modules/pyexpat.c41
3 files changed, 83 insertions, 53 deletions
diff --git a/Doc/library/pyexpat.rst b/Doc/library/pyexpat.rst
index e16e45f..390c38e 100644
--- a/Doc/library/pyexpat.rst
+++ b/Doc/library/pyexpat.rst
@@ -169,7 +169,7 @@ XMLParser Objects
This method can only be called before the :meth:`Parse` or :meth:`ParseFile`
methods are called; calling it after either of those have been called causes
:exc:`ExpatError` to be raised with the :attr:`code` attribute set to
- :const:`errors.XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING`.
+ ``errors.codes[errors.XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING]``.
:class:`xmlparser` objects have the following attributes:
@@ -467,8 +467,21 @@ ExpatError Exceptions
.. attribute:: ExpatError.code
- Expat's internal error number for the specific error. This will match one of
- the constants defined in the ``errors`` object from this module.
+ Expat's internal error number for the specific error. The
+ :data:`errors.messages` dictionary maps these error numbers to Expat's error
+ messages. For example::
+
+ from xml.parsers.expat import ParserCreate, ExpatError, errors
+
+ p = ParserCreate()
+ try:
+ p.Parse(some_xml_document)
+ except ExpatError as err:
+ print("Error:", errors.messages[err.code])
+
+ The :mod:`errors` module also provides error message constants and a
+ dictionary :data:`~errors.codes` mapping these messages back to the error
+ codes, see below.
.. attribute:: ExpatError.lineno
@@ -530,15 +543,16 @@ The output from this program is::
Content Model Descriptions
--------------------------
-.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
+.. module:: xml.parsers.expat.model
+.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
Content modules are described using nested tuples. Each tuple contains four
values: the type, the quantifier, the name, and a tuple of children. Children
are simply additional content module descriptions.
-The values of the first two fields are constants defined in the ``model`` object
-of the :mod:`xml.parsers.expat` module. These constants can be collected in two
+The values of the first two fields are constants defined in the
+:mod:`xml.parsers.expat.model` module. These constants can be collected in two
groups: the model type group and the quantifier group.
The constants in the model type group are:
@@ -610,143 +624,139 @@ The constants in the quantifier group are:
Expat error constants
---------------------
-The following constants are provided in the ``errors`` object of the
-:mod:`xml.parsers.expat` module. These constants are useful in interpreting
-some of the attributes of the :exc:`ExpatError` exception objects raised when an
-error has occurred.
+.. module:: xml.parsers.expat.errors
+
+The following constants are provided in the :mod:`xml.parsers.expat.errors`
+module. These constants are useful in interpreting some of the attributes of
+the :exc:`ExpatError` exception objects raised when an error has occurred.
+Since for backwards compatibility reasons, the constants' value is the error
+*message* and not the numeric error *code*, you do this by comparing its
+:attr:`code` attribute with
+:samp:`errors.codes[errors.XML_ERROR_{CONSTANT_NAME}]`.
+
+The ``errors`` module has the following attributes:
+
+.. data:: codes
+
+ A dictionary mapping numeric error codes to their string descriptions.
+
+ .. versionadded:: 3.2
+
+
+.. data:: messages
+
+ A dictionary mapping string descriptions to their error codes.
-The ``errors`` object has the following attributes:
+ .. versionadded:: 3.2
.. data:: XML_ERROR_ASYNC_ENTITY
- :noindex:
.. data:: XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF
- :noindex:
An entity reference in an attribute value referred to an external entity instead
of an internal entity.
.. data:: XML_ERROR_BAD_CHAR_REF
- :noindex:
A character reference referred to a character which is illegal in XML (for
example, character ``0``, or '``&#0;``').
.. data:: XML_ERROR_BINARY_ENTITY_REF
- :noindex:
An entity reference referred to an entity which was declared with a notation, so
cannot be parsed.
.. data:: XML_ERROR_DUPLICATE_ATTRIBUTE
- :noindex:
An attribute was used more than once in a start tag.
.. data:: XML_ERROR_INCORRECT_ENCODING
- :noindex:
.. data:: XML_ERROR_INVALID_TOKEN
- :noindex:
Raised when an input byte could not properly be assigned to a character; for
example, a NUL byte (value ``0``) in a UTF-8 input stream.
.. data:: XML_ERROR_JUNK_AFTER_DOC_ELEMENT
- :noindex:
Something other than whitespace occurred after the document element.
.. data:: XML_ERROR_MISPLACED_XML_PI
- :noindex:
An XML declaration was found somewhere other than the start of the input data.
.. data:: XML_ERROR_NO_ELEMENTS
- :noindex:
The document contains no elements (XML requires all documents to contain exactly
one top-level element)..
.. data:: XML_ERROR_NO_MEMORY
- :noindex:
Expat was not able to allocate memory internally.
.. data:: XML_ERROR_PARAM_ENTITY_REF
- :noindex:
A parameter entity reference was found where it was not allowed.
.. data:: XML_ERROR_PARTIAL_CHAR
- :noindex:
An incomplete character was found in the input.
.. data:: XML_ERROR_RECURSIVE_ENTITY_REF
- :noindex:
An entity reference contained another reference to the same entity; possibly via
a different name, and possibly indirectly.
.. data:: XML_ERROR_SYNTAX
- :noindex:
Some unspecified syntax error was encountered.
.. data:: XML_ERROR_TAG_MISMATCH
- :noindex:
An end tag did not match the innermost open start tag.
.. data:: XML_ERROR_UNCLOSED_TOKEN
- :noindex:
Some token (such as a start tag) was not closed before the end of the stream or
the next token was encountered.
.. data:: XML_ERROR_UNDEFINED_ENTITY
- :noindex:
A reference was made to a entity which was not defined.
.. data:: XML_ERROR_UNKNOWN_ENCODING
- :noindex:
The document encoding is not supported by Expat.
.. data:: XML_ERROR_UNCLOSED_CDATA_SECTION
- :noindex:
A CDATA marked section was not closed.
.. data:: XML_ERROR_EXTERNAL_ENTITY_HANDLING
- :noindex:
.. data:: XML_ERROR_NOT_STANDALONE
- :noindex:
The parser determined that the document was not "standalone" though it declared
itself to be in the XML declaration, and the :attr:`NotStandaloneHandler` was
@@ -754,15 +764,12 @@ The ``errors`` object has the following attributes:
.. data:: XML_ERROR_UNEXPECTED_STATE
- :noindex:
.. data:: XML_ERROR_ENTITY_DECLARED_IN_PE
- :noindex:
.. data:: XML_ERROR_FEATURE_REQUIRES_XML_DTD
- :noindex:
An operation was requested that requires DTD support to be compiled in, but
Expat was configured without DTD support. This should never be reported by a
@@ -770,7 +777,6 @@ The ``errors`` object has the following attributes:
.. data:: XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING
- :noindex:
A behavioral change was requested after parsing started that can only be changed
before parsing has started. This is (currently) only raised by
@@ -778,63 +784,53 @@ The ``errors`` object has the following attributes:
.. data:: XML_ERROR_UNBOUND_PREFIX
- :noindex:
An undeclared prefix was found when namespace processing was enabled.
.. data:: XML_ERROR_UNDECLARING_PREFIX
- :noindex:
The document attempted to remove the namespace declaration associated with a
prefix.
.. data:: XML_ERROR_INCOMPLETE_PE
- :noindex:
A parameter entity contained incomplete markup.
.. data:: XML_ERROR_XML_DECL
- :noindex:
The document contained no document element at all.
.. data:: XML_ERROR_TEXT_DECL
- :noindex:
There was an error parsing a text declaration in an external entity.
.. data:: XML_ERROR_PUBLICID
- :noindex:
Characters were found in the public id that are not allowed.
.. data:: XML_ERROR_SUSPENDED
- :noindex:
The requested operation was made on a suspended parser, but isn't allowed. This
includes attempts to provide additional input or to stop the parser.
.. data:: XML_ERROR_NOT_SUSPENDED
- :noindex:
An attempt to resume the parser was made when the parser had not been suspended.
.. data:: XML_ERROR_ABORTED
- :noindex:
This should not be reported to Python applications.
.. data:: XML_ERROR_FINISHED
- :noindex:
The requested operation was made on a parser which was finished parsing input,
but isn't allowed. This includes attempts to provide additional input or to
@@ -842,7 +838,6 @@ The ``errors`` object has the following attributes:
.. data:: XML_ERROR_SUSPEND_PE
- :noindex:
.. rubric:: Footnotes
diff --git a/Misc/NEWS b/Misc/NEWS
index 4e66031..a87dacf 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -63,6 +63,10 @@ Library
Extensions
----------
+- Issue #5355: Provide mappings from Expat error numbers to string
+ descriptions and backwards, in order to actually make it possible
+ to analyze error codes provided by ExpatError.
+
- The Unicode database was updated to 6.0.0.
Tools/Demos
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
index e603984..a8b0f8f 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -1685,8 +1685,12 @@ MODULE_INITFUNC(void)
PyObject *modelmod_name;
PyObject *model_module;
PyObject *sys_modules;
+ PyObject *tmpnum, *tmpstr;
+ PyObject *codes_dict;
+ PyObject *rev_codes_dict;
+ int res;
static struct PyExpat_CAPI capi;
- PyObject* capi_object;
+ PyObject *capi_object;
if (errmod_name == NULL)
return NULL;
@@ -1789,9 +1793,29 @@ MODULE_INITFUNC(void)
}
#endif
+ codes_dict = PyDict_New();
+ rev_codes_dict = PyDict_New();
+ if (codes_dict == NULL || rev_codes_dict == NULL) {
+ Py_XDECREF(codes_dict);
+ Py_XDECREF(rev_codes_dict);
+ return NULL;
+ }
+
#define MYCONST(name) \
- PyModule_AddStringConstant(errors_module, #name, \
- (char*)XML_ErrorString(name))
+ if (PyModule_AddStringConstant(errors_module, #name, \
+ (char *)XML_ErrorString(name)) < 0) \
+ return NULL; \
+ tmpnum = PyLong_FromLong(name); \
+ if (tmpnum == NULL) return NULL; \
+ res = PyDict_SetItemString(codes_dict, \
+ XML_ErrorString(name), tmpnum); \
+ if (res < 0) return NULL; \
+ tmpstr = PyUnicode_FromString(XML_ErrorString(name)); \
+ if (tmpstr == NULL) return NULL; \
+ res = PyDict_SetItem(rev_codes_dict, tmpnum, tmpstr); \
+ Py_DECREF(tmpstr); \
+ Py_DECREF(tmpnum); \
+ if (res < 0) return NULL; \
MYCONST(XML_ERROR_NO_MEMORY);
MYCONST(XML_ERROR_SYNTAX);
@@ -1833,9 +1857,16 @@ MODULE_INITFUNC(void)
MYCONST(XML_ERROR_FINISHED);
MYCONST(XML_ERROR_SUSPEND_PE);
- PyModule_AddStringConstant(errors_module, "__doc__",
- "Constants used to describe error conditions.");
+ if (PyModule_AddStringConstant(errors_module, "__doc__",
+ "Constants used to describe "
+ "error conditions.") < 0)
+ return NULL;
+ if (PyModule_AddObject(errors_module, "codes", codes_dict) < 0)
+ return NULL;
+ if (PyModule_AddObject(errors_module, "messages", rev_codes_dict) < 0)
+ return NULL;
+
#undef MYCONST
#define MYCONST(c) PyModule_AddIntConstant(m, #c, c)