cpython: a29ae1c2b8b2 (original) (raw)
--- a/Doc/library/xml.etree.elementtree.rst
+++ b/Doc/library/xml.etree.elementtree.rst
@@ -646,8 +646,8 @@ ElementTree Objects
Loads an external XML section into this element tree. source is a file
name or :term:file object
. parser is an optional parser instance.
If not given, the standard XMLParser parser is used. Returns the section[](#l1.7)
root element.[](#l1.8)
If not given, the standard :class:`XMLParser` parser is used. Returns the[](#l1.9)
section root element.[](#l1.10)
.. method:: write(file, encoding="us-ascii", xml_declaration=None, method="xml")
@@ -767,9 +767,9 @@ XMLParser Objects
:class:Element
structure builder for XML source data, based on the expat
parser. html are predefined HTML entities. This flag is not supported by
the current implementation. target is the target object. If omitted, the
- builder uses an instance of the standard TreeBuilder class. encoding [1]_
- is optional. If given, the value overrides the encoding specified in the
- XML file.
- builder uses an instance of the standard :class:
TreeBuilder
class. - encoding [1]_ is optional. If given, the value overrides the encoding
- specified in the XML file.
--- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -2028,6 +2028,34 @@ class TreeBuilderTest(unittest.TestCase) 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'))[](#l2.4) +class XMLParserTest(unittest.TestCase):
- def _check_sample_element(self, e):
self.assertEqual(e.tag, 'file')[](#l2.11)
self.assertEqual(e[0].tag, 'line')[](#l2.12)
self.assertEqual(e[0].text, '22')[](#l2.13)
- def test_constructor_args(self):
# Positional args. The first (html) is not supported, but should be[](#l2.16)
# nevertheless correctly accepted.[](#l2.17)
parser = ET.XMLParser(None, ET.TreeBuilder(), 'utf-8')[](#l2.18)
parser.feed(self.sample1)[](#l2.19)
self._check_sample_element(parser.close())[](#l2.20)
# Now as keyword args.[](#l2.22)
parser2 = ET.XMLParser(encoding='utf-8', html=[{}], target=ET.TreeBuilder())[](#l2.23)
parser2.feed(self.sample1)[](#l2.24)
self._check_sample_element(parser2.close())[](#l2.25)
- def test_subclass(self):
class MyParser(ET.XMLParser):[](#l2.28)
pass[](#l2.29)
parser = MyParser()[](#l2.30)
parser.feed(self.sample1)[](#l2.31)
self._check_sample_element(parser.close())[](#l2.32)
+ + class NoAcceleratorTest(unittest.TestCase): # Test that the C accelerator was not imported for pyET def test_correct_import_pyET(self): @@ -2245,6 +2273,7 @@ def test_main(module=pyET): ElementTreeTest, NamespaceParseTest, TreeBuilderTest,
if module is pyET: # Run the tests specific to the Python implementationXMLParserTest,[](#l2.42) KeywordArgsTest][](#l2.43)
--- a/Modules/_elementtree.c +++ b/Modules/elementtree.c @@ -2257,6 +2257,9 @@ static struct PyExpat_CAPI* expat_capi; #define EXPAT(func) (XML##func) #endif +static XML_Memory_Handling_Suite ExpatMemoryHandler = {
+ typedef struct { PyObject_HEAD @@ -2671,121 +2674,125 @@ expat_unknown_encoding_handler(XMLParser } /* -------------------------------------------------------------------- / -/ constructor and destructor / - -static PyObject -xmlparser(PyObject* self_, PyObject* args, PyObject* kw) + +static PyObject * +xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- XMLParserObject* self;
- /* FIXME: does this need to be static? */
- static XML_Memory_Handling_Suite memory_handler;
- PyObject* target = NULL;
- char* encoding = NULL;
- static char* kwlist[] = { "target", "encoding", NULL };
- if (!PyArg_ParseTupleAndKeywords(args, kw, "|Oz:XMLParser", kwlist,
&target, &encoding))[](#l3.33)
return NULL;[](#l3.34)
- -#if defined(USE_PYEXPAT_CAPI)
- if (!expat_capi) {
PyErr_SetString([](#l3.38)
PyExc_RuntimeError, "cannot load dispatch table from pyexpat"[](#l3.39)
);[](#l3.40)
return NULL;[](#l3.41)
- XMLParserObject *self = (XMLParserObject *)type->tp_alloc(type, 0);
- if (self) {
self->parser = NULL;[](#l3.44)
self->target = self->entity = self->names = NULL;[](#l3.45)
self->handle_start = self->handle_data = self->handle_end = NULL;[](#l3.46)
} -#endif -self->handle_comment = self->handle_pi = self->handle_close = NULL;[](#l3.47)
- self->entity = PyDict_New();
- if (!self->entity) {
PyObject_Del(self);[](#l3.57)
return NULL;[](#l3.58)
+} + +static int +xmlparser_init(PyObject *self, PyObject *args, PyObject *kwds) +{
- XMLParserObject *self_xp = (XMLParserObject *)self;
- PyObject *target = NULL, *html = NULL;
- char *encoding = NULL;
- static char *kwlist[] = {"html", "target", "encoding"};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOz:XMLParser", kwlist,
&html, &target, &encoding)) {[](#l3.71)
}return -1;[](#l3.72)
- self->names = PyDict_New();
- if (!self->names) {
PyObject_Del(self->entity);[](#l3.77)
PyObject_Del(self);[](#l3.78)
return NULL;[](#l3.79)
- self_xp->names = PyDict_New();
- if (!self_xp->names) {
Py_XDECREF(self_xp->entity);[](#l3.86)
}return -1;[](#l3.87)
- memory_handler.malloc_fcn = PyObject_Malloc;
- memory_handler.realloc_fcn = PyObject_Realloc;
- memory_handler.free_fcn = PyObject_Free;
- self->parser = EXPAT(ParserCreate_MM)(encoding, &memory_handler, "}");
- if (!self->parser) {
PyObject_Del(self->names);[](#l3.96)
PyObject_Del(self->entity);[](#l3.97)
PyObject_Del(self);[](#l3.98)
- self_xp->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}");
- if (!self_xp->parser) {
Py_XDECREF(self_xp->entity);[](#l3.101)
Py_XDECREF(self_xp->names);[](#l3.102) PyErr_NoMemory();[](#l3.103)
return NULL;[](#l3.104)
- if (target) {
Py_INCREF(target);[](#l3.111)
- } else { target = treebuilder_new(&TreeBuilder_Type, NULL, NULL); if (!target) {
EXPAT(ParserFree)(self->parser);[](#l3.115)
PyObject_Del(self->names);[](#l3.116)
PyObject_Del(self->entity);[](#l3.117)
PyObject_Del(self);[](#l3.118)
return NULL;[](#l3.119)
Py_XDECREF(self_xp->entity);[](#l3.120)
Py_XDECREF(self_xp->names);[](#l3.121)
EXPAT(ParserFree)(self_xp->parser);[](#l3.122)
return -1;[](#l3.123) }[](#l3.124)
- self->handle_start = PyObject_GetAttrString(target, "start");
- self->handle_data = PyObject_GetAttrString(target, "data");
- self->handle_end = PyObject_GetAttrString(target, "end");
- self->handle_comment = PyObject_GetAttrString(target, "comment");
- self->handle_pi = PyObject_GetAttrString(target, "pi");
- self->handle_close = PyObject_GetAttrString(target, "close");
- self_xp->handle_start = PyObject_GetAttrString(target, "start");
- self_xp->handle_data = PyObject_GetAttrString(target, "data");
- self_xp->handle_end = PyObject_GetAttrString(target, "end");
- self_xp->handle_comment = PyObject_GetAttrString(target, "comment");
- self_xp->handle_pi = PyObject_GetAttrString(target, "pi");
- self_xp->handle_close = PyObject_GetAttrString(target, "close");
self->parser,[](#l3.152)
EXPAT(SetDefaultHandlerExpand)(self_xp->parser,[](#l3.153) (XML_StartElementHandler) expat_start_handler,[](#l3.154) (XML_EndElementHandler) expat_end_handler[](#l3.155) );[](#l3.156)
self->parser,[](#l3.158)
EXPAT(SetCharacterDataHandler)(self_xp->parser,[](#l3.159) (XML_DefaultHandler) expat_default_handler[](#l3.160) );[](#l3.161)
self->parser,[](#l3.163)
self_xp->parser,[](#l3.164) (XML_CharacterDataHandler) expat_data_handler[](#l3.165) );[](#l3.166)
self->parser,[](#l3.170)
self_xp->parser,[](#l3.171) (XML_CommentHandler) expat_comment_handler[](#l3.172) );[](#l3.173)
self->parser,[](#l3.177)
EXPAT(SetUnknownEncodingHandler)(self_xp->parser,[](#l3.178) (XML_ProcessingInstructionHandler) expat_pi_handler[](#l3.179) );[](#l3.180)
self->parser,[](#l3.182)
self_xp->parser,[](#l3.183) (XML_UnknownEncodingHandler) expat_unknown_encoding_handler, NULL[](#l3.184) );[](#l3.185)
} -static void -xmlparser_dealloc(XMLParserObject* self) +static int +xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg) +{
- Py_VISIT(self->handle_close);
- Py_VISIT(self->handle_pi);
- Py_VISIT(self->handle_comment);
- Py_VISIT(self->handle_end);
- Py_VISIT(self->handle_data);
- Py_VISIT(self->handle_start);
+} + +static int +xmlparser_gc_clear(XMLParserObject self) { EXPAT(ParserFree)(self->parser); @@ -2796,17 +2803,20 @@ xmlparser_dealloc(XMLParserObject self) Py_XDECREF(self->handle_data); Py_XDECREF(self->handle_start);
} -/* -------------------------------------------------------------------- / -/ methods (in alphabetical order) / +static void +xmlparser_dealloc(XMLParserObject self) +{
+} LOCAL(PyObject*) expat_parse(XMLParserObject* self, char* data, int data_len, int final) @@ -3083,31 +3093,42 @@ static PyTypeObject XMLParser_Type = { PyVarObject_HEAD_INIT(NULL, 0) "XMLParser", sizeof(XMLParserObject), 0, /* methods */
- (destructor)xmlparser_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- (getattrofunc)xmlparser_getattro, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- xmlparser_methods, /* tp_methods */
- 0, /* tp_members */
- (destructor)xmlparser_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- (getattrofunc)xmlparser_getattro, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
/* tp_flags */[](#l3.292)
- 0, /* tp_doc */
- (traverseproc)xmlparser_gc_traverse, /* tp_traverse */
- (inquiry)xmlparser_gc_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- xmlparser_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)xmlparser_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- xmlparser_new, /* tp_new */
- 0, /* tp_free */
}; #endif @@ -3117,9 +3138,6 @@ static PyTypeObject XMLParser_Type = { static PyMethodDef _functions[] = { {"SubElement", (PyCFunction) subelement, METH_VARARGS|METH_KEYWORDS}, -#if defined(USE_EXPAT)
-#endif {NULL, NULL} }; @@ -3214,8 +3232,15 @@ PyInit__elementtree(void) expat_capi->size < sizeof(struct PyExpat_CAPI) || expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION || expat_capi->MINOR_VERSION != XML_MINOR_VERSION ||
expat_capi->MICRO_VERSION != XML_MICRO_VERSION)[](#l3.329)
expat_capi->MICRO_VERSION != XML_MICRO_VERSION) {[](#l3.330) expat_capi = NULL;[](#l3.331)
}[](#l3.332)
- }
- if (!expat_capi) {
PyErr_SetString([](#l3.335)
PyExc_RuntimeError, "cannot load dispatch table from pyexpat"[](#l3.336)
);[](#l3.337)
}return NULL;[](#l3.338)
#endif @@ -3231,5 +3256,10 @@ PyInit__elementtree(void) Py_INCREF((PyObject *)&TreeBuilder_Type); PyModule_AddObject(m, "TreeBuilder", (PyObject *)&TreeBuilder_Type); +#if defined(USE_EXPAT)