summaryrefslogtreecommitdiff
path: root/Modules/_elementtree.c
diff options
context:
space:
mode:
authorRonald Oussoren <ronaldoussoren@mac.com>2013-07-19 11:14:05 +0200
committerRonald Oussoren <ronaldoussoren@mac.com>2013-07-19 11:14:05 +0200
commit248da793d9e1d2117618c2225b5c7bb82d93f7eb (patch)
tree63420e56f25bd1ab51686c36f7352bf417f66937 /Modules/_elementtree.c
parent063f8b0a2ecb6a4711c342f044df7551de97fc7e (diff)
parent1a133f78b8ac46c1f929462bd15e61e747bd5cc2 (diff)
downloadcpython-248da793d9e1d2117618c2225b5c7bb82d93f7eb.tar.gz
(3.3->default): #18480: Add missing PyType_Ready call to _elementtree extension
Diffstat (limited to 'Modules/_elementtree.c')
-rw-r--r--Modules/_elementtree.c279
1 files changed, 138 insertions, 141 deletions
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 9789527c39..28bdf1effe 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -1,63 +1,22 @@
-/*
- * ElementTree
- * $Id: _elementtree.c 3473 2009-01-11 22:53:55Z fredrik $
- *
- * elementtree accelerator
- *
- * History:
- * 1999-06-20 fl created (as part of sgmlop)
- * 2001-05-29 fl effdom edition
- * 2003-02-27 fl elementtree edition (alpha)
- * 2004-06-03 fl updates for elementtree 1.2
- * 2005-01-05 fl major optimization effort
- * 2005-01-11 fl first public release (cElementTree 0.8)
- * 2005-01-12 fl split element object into base and extras
- * 2005-01-13 fl use tagged pointers for tail/text (cElementTree 0.9)
- * 2005-01-17 fl added treebuilder close method
- * 2005-01-17 fl fixed crash in getchildren
- * 2005-01-18 fl removed observer api, added iterparse (cElementTree 0.9.3)
- * 2005-01-23 fl revised iterparse api; added namespace event support (0.9.8)
- * 2005-01-26 fl added VERSION module property (cElementTree 1.0)
- * 2005-01-28 fl added remove method (1.0.1)
- * 2005-03-01 fl added iselement function; fixed makeelement aliasing (1.0.2)
- * 2005-03-13 fl export Comment and ProcessingInstruction/PI helpers
- * 2005-03-26 fl added Comment and PI support to XMLParser
- * 2005-03-27 fl event optimizations; complain about bogus events
- * 2005-08-08 fl fixed read error handling in parse
- * 2005-08-11 fl added runtime test for copy workaround (1.0.3)
- * 2005-12-13 fl added expat_capi support (for xml.etree) (1.0.4)
- * 2005-12-16 fl added support for non-standard encodings
- * 2006-03-08 fl fixed a couple of potential null-refs and leaks
- * 2006-03-12 fl merge in 2.5 ssize_t changes
- * 2007-08-25 fl call custom builder's close method from XMLParser
- * 2007-08-31 fl added iter, extend from ET 1.3
- * 2007-09-01 fl fixed ParseError exception, setslice source type, etc
- * 2007-09-03 fl fixed handling of negative insert indexes
- * 2007-09-04 fl added itertext from ET 1.3
- * 2007-09-06 fl added position attribute to ParseError exception
- * 2008-06-06 fl delay error reporting in iterparse (from Hrvoje Niksic)
+/*--------------------------------------------------------------------
+ * Licensed to PSF under a Contributor Agreement.
+ * See http://www.python.org/psf/license for licensing details.
*
+ * _elementtree - C accelerator for xml.etree.ElementTree
* Copyright (c) 1999-2009 by Secret Labs AB. All rights reserved.
* Copyright (c) 1999-2009 by Fredrik Lundh.
*
* info@pythonware.com
* http://www.pythonware.com
+ *--------------------------------------------------------------------
*/
-/* Licensed to PSF under a Contributor Agreement. */
-/* See http://www.python.org/psf/license for licensing details. */
-
#include "Python.h"
#include "structmember.h"
-#define VERSION "1.0.6"
-
/* -------------------------------------------------------------------- */
/* configuration */
-/* Leave defined to include the expat-based XMLParser type */
-#define USE_EXPAT
-
/* An element can hold this many children without extra memory
allocations. */
#define STATIC_CHILDREN 4
@@ -217,8 +176,10 @@ LOCAL(int)
create_extra(ElementObject* self, PyObject* attrib)
{
self->extra = PyObject_Malloc(sizeof(ElementObjectExtra));
- if (!self->extra)
+ if (!self->extra) {
+ PyErr_NoMemory();
return -1;
+ }
if (!attrib)
attrib = Py_None;
@@ -271,13 +232,6 @@ create_new_element(PyObject* tag, PyObject* attrib)
return NULL;
self->extra = NULL;
- if (attrib != Py_None && !is_empty_dict(attrib)) {
- if (create_extra(self, attrib) < 0) {
- PyObject_Del(self);
- return NULL;
- }
- }
-
Py_INCREF(tag);
self->tag = tag;
@@ -291,6 +245,14 @@ create_new_element(PyObject* tag, PyObject* attrib)
ALLOC(sizeof(ElementObject), "create element");
PyObject_GC_Track(self);
+
+ if (attrib != Py_None && !is_empty_dict(attrib)) {
+ if (create_extra(self, attrib) < 0) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+
return (PyObject*) self;
}
@@ -346,6 +308,7 @@ get_attrib_from_keywords(PyObject *kwds)
Py_DECREF(attrib_str);
+ /* attrib can be NULL if PyDict_New failed */
if (attrib)
PyDict_Update(attrib, kwds);
return attrib;
@@ -420,8 +383,10 @@ element_resize(ElementObject* self, int extra)
/* make sure self->children can hold the given number of extra
elements. set an exception and return -1 if allocation failed */
- if (!self->extra)
- create_extra(self, NULL);
+ if (!self->extra) {
+ if (create_extra(self, NULL) < 0)
+ return -1;
+ }
size = self->extra->length + extra;
@@ -573,8 +538,9 @@ subelement(PyObject *self, PyObject *args, PyObject *kwds)
}
elem = create_new_element(tag, attrib);
-
Py_DECREF(attrib);
+ if (elem == NULL)
+ return NULL;
if (element_add_subelement(parent, elem) < 0) {
Py_DECREF(elem);
@@ -1313,8 +1279,10 @@ element_insert(ElementObject* self, PyObject* args)
&Element_Type, &element))
return NULL;
- if (!self->extra)
- create_extra(self, NULL);
+ if (!self->extra) {
+ if (create_extra(self, NULL) < 0)
+ return NULL;
+ }
if (index < 0) {
index += self->extra->length;
@@ -1455,8 +1423,10 @@ element_set(ElementObject* self, PyObject* args)
if (!PyArg_ParseTuple(args, "OO:set", &key, &value))
return NULL;
- if (!self->extra)
- create_extra(self, NULL);
+ if (!self->extra) {
+ if (create_extra(self, NULL) < 0)
+ return NULL;
+ }
attrib = element_get_attrib(self);
if (!attrib)
@@ -1571,8 +1541,10 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
PyObject* recycle = NULL;
PyObject* seq = NULL;
- if (!self->extra)
- create_extra(self, NULL);
+ if (!self->extra) {
+ if (create_extra(self, NULL) < 0)
+ return -1;
+ }
if (PySlice_GetIndicesEx(item,
self->extra->length,
@@ -1787,7 +1759,7 @@ element_getattro(ElementObject* self, PyObject* nameobj)
return res;
} else if (strcmp(name, "text") == 0) {
res = element_get_text(self);
- Py_INCREF(res);
+ Py_XINCREF(res);
return res;
}
@@ -1802,8 +1774,10 @@ element_getattro(ElementObject* self, PyObject* nameobj)
res = element_get_tail(self);
} else if (strcmp(name, "attrib") == 0) {
PyErr_Clear();
- if (!self->extra)
- create_extra(self, NULL);
+ if (!self->extra) {
+ if (create_extra(self, NULL) < 0)
+ return NULL;
+ }
res = element_get_attrib(self);
}
@@ -1820,10 +1794,10 @@ element_setattro(ElementObject* self, PyObject* nameobj, PyObject* value)
char *name = "";
if (PyUnicode_Check(nameobj))
name = _PyUnicode_AsString(nameobj);
-
- if (name == NULL) {
+ if (name == NULL)
return -1;
- } else if (strcmp(name, "tag") == 0) {
+
+ if (strcmp(name, "tag") == 0) {
Py_DECREF(self->tag);
self->tag = value;
Py_INCREF(self->tag);
@@ -1836,8 +1810,10 @@ element_setattro(ElementObject* self, PyObject* nameobj, PyObject* value)
self->tail = value;
Py_INCREF(self->tail);
} else if (strcmp(name, "attrib") == 0) {
- if (!self->extra)
- create_extra(self, NULL);
+ if (!self->extra) {
+ if (create_extra(self, NULL) < 0)
+ return -1;
+ }
Py_DECREF(self->extra->attrib);
self->extra->attrib = value;
Py_INCREF(self->extra->attrib);
@@ -2153,14 +2129,6 @@ create_elementiter(ElementObject *self, PyObject *tag, int gettext)
it = PyObject_GC_New(ElementIterObject, &ElementIter_Type);
if (!it)
return NULL;
- if (!(it->parent_stack = PyObject_Malloc(sizeof(ParentLocator)))) {
- PyObject_GC_Del(it);
- return NULL;
- }
-
- it->parent_stack->parent = NULL;
- it->parent_stack->child_index = 0;
- it->parent_stack->next = NULL;
if (PyUnicode_Check(tag))
star = PyUnicode_FromString("*");
@@ -2169,17 +2137,27 @@ create_elementiter(ElementObject *self, PyObject *tag, int gettext)
if (star && PyObject_RichCompareBool(tag, star, Py_EQ) == 1)
tag = Py_None;
-
Py_XDECREF(star);
+
+ Py_INCREF(tag);
it->sought_tag = tag;
it->root_done = 0;
it->gettext = gettext;
- it->root_element = self;
-
Py_INCREF(self);
- Py_INCREF(tag);
+ it->root_element = self;
PyObject_GC_Track(it);
+
+ it->parent_stack = PyObject_Malloc(sizeof(ParentLocator));
+ if (it->parent_stack == NULL) {
+ Py_DECREF(it);
+ PyErr_NoMemory();
+ return NULL;
+ }
+ it->parent_stack->parent = NULL;
+ it->parent_stack->child_index = 0;
+ it->parent_stack->next = NULL;
+
return (PyObject *)it;
}
@@ -2689,8 +2667,6 @@ static PyTypeObject TreeBuilder_Type = {
/* ==================================================================== */
/* the expat interface */
-#if defined(USE_EXPAT)
-
#include "expat.h"
#include "pyexpat.h"
static struct PyExpat_CAPI *expat_capi;
@@ -2759,6 +2735,10 @@ makeuniversal(XMLParserObject* self, const char* string)
if (i != size) {
/* convert to universal name */
tag = PyBytes_FromStringAndSize(NULL, size+1);
+ if (tag == NULL) {
+ Py_DECREF(key);
+ return NULL;
+ }
p = PyBytes_AS_STRING(tag);
p[0] = '{';
memcpy(p+1, string, size);
@@ -2853,6 +2833,9 @@ expat_default_handler(XMLParserObject* self, const XML_Char* data_in,
if (data_len < 2 || data_in[0] != '&')
return;
+ if (PyErr_Occurred())
+ return;
+
key = PyUnicode_DecodeUTF8(data_in + 1, data_len - 2, "strict");
if (!key)
return;
@@ -2893,6 +2876,9 @@ expat_start_handler(XMLParserObject* self, const XML_Char* tag_in,
PyObject* attrib;
int ok;
+ if (PyErr_Occurred())
+ return;
+
/* tag name */
tag = makeuniversal(self, tag_in);
if (!tag)
@@ -2951,6 +2937,9 @@ expat_data_handler(XMLParserObject* self, const XML_Char* data_in,
PyObject* data;
PyObject* res;
+ if (PyErr_Occurred())
+ return;
+
data = PyUnicode_DecodeUTF8(data_in, data_len, "strict");
if (!data)
return; /* parser will look for errors */
@@ -2974,6 +2963,9 @@ expat_end_handler(XMLParserObject* self, const XML_Char* tag_in)
PyObject* tag;
PyObject* res = NULL;
+ if (PyErr_Occurred())
+ return;
+
if (TreeBuilder_CheckExact(self->target))
/* shortcut */
/* the standard tree builder doesn't look at the end tag */
@@ -2998,6 +2990,9 @@ expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix,
PyObject* sprefix = NULL;
PyObject* suri = NULL;
+ if (PyErr_Occurred())
+ return;
+
suri = PyUnicode_DecodeUTF8(uri, strlen(uri), "strict");
if (!suri)
return;
@@ -3022,6 +3017,9 @@ expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix,
static void
expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in)
{
+ if (PyErr_Occurred())
+ return;
+
treebuilder_handle_namespace(
(TreeBuilderObject*) self->target, 0, NULL, NULL
);
@@ -3033,6 +3031,9 @@ expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in)
PyObject* comment;
PyObject* res;
+ if (PyErr_Occurred())
+ return;
+
if (self->handle_comment) {
comment = PyUnicode_DecodeUTF8(comment_in, strlen(comment_in), "strict");
if (comment) {
@@ -3055,6 +3056,9 @@ expat_start_doctype_handler(XMLParserObject *self,
PyObject *parser_doctype = NULL;
PyObject *res = NULL;
+ if (PyErr_Occurred())
+ return;
+
doctype_name_obj = makeuniversal(self, doctype_name);
if (!doctype_name_obj)
return;
@@ -3123,6 +3127,9 @@ expat_pi_handler(XMLParserObject* self, const XML_Char* target_in,
PyObject* data;
PyObject* res;
+ if (PyErr_Occurred())
+ return;
+
if (self->handle_pi) {
target = PyUnicode_DecodeUTF8(target_in, strlen(target_in), "strict");
data = PyUnicode_DecodeUTF8(data_in, strlen(data_in), "strict");
@@ -3295,6 +3302,7 @@ expat_parse(XMLParserObject* self, const char* data, int data_len, int final)
{
int ok;
+ assert(!PyErr_Occurred());
ok = EXPAT(Parse)(self->parser, data, data_len, final);
if (PyErr_Occurred())
@@ -3371,10 +3379,9 @@ xmlparser_feed(XMLParserObject* self, PyObject* arg)
}
static PyObject*
-xmlparser_parse(XMLParserObject* self, PyObject* args)
+xmlparser_parse_whole(XMLParserObject* self, PyObject* args)
{
- /* (internal) parse until end of input stream */
-
+ /* (internal) parse the whole input, until end of stream */
PyObject* reader;
PyObject* buffer;
PyObject* temp;
@@ -3455,14 +3462,14 @@ static PyObject*
xmlparser_setevents(XMLParserObject *self, PyObject* args)
{
/* activate element event reporting */
+ Py_ssize_t i, seqlen;
+ TreeBuilderObject *target;
- Py_ssize_t i;
- TreeBuilderObject* target;
-
- PyObject* events; /* event collector */
- PyObject* event_set = Py_None;
- if (!PyArg_ParseTuple(args, "O!|O:_setevents", &PyList_Type, &events,
- &event_set))
+ PyObject *events_queue;
+ PyObject *events_to_report = Py_None;
+ PyObject *events_seq;
+ if (!PyArg_ParseTuple(args, "O!|O:_setevents", &PyList_Type, &events_queue,
+ &events_to_report))
return NULL;
if (!TreeBuilder_CheckExact(self->target)) {
@@ -3476,9 +3483,9 @@ xmlparser_setevents(XMLParserObject *self, PyObject* args)
target = (TreeBuilderObject*) self->target;
- Py_INCREF(events);
+ Py_INCREF(events_queue);
Py_XDECREF(target->events);
- target->events = events;
+ target->events = events_queue;
/* clear out existing events */
Py_CLEAR(target->start_event_obj);
@@ -3486,75 +3493,71 @@ xmlparser_setevents(XMLParserObject *self, PyObject* args)
Py_CLEAR(target->start_ns_event_obj);
Py_CLEAR(target->end_ns_event_obj);
- if (event_set == Py_None) {
+ if (events_to_report == Py_None) {
/* default is "end" only */
target->end_event_obj = PyUnicode_FromString("end");
Py_RETURN_NONE;
}
- if (!PyTuple_Check(event_set)) /* FIXME: handle arbitrary sequences */
- goto error;
+ if (!(events_seq = PySequence_Fast(events_to_report,
+ "events must be a sequence"))) {
+ return NULL;
+ }
- for (i = 0; i < PyTuple_GET_SIZE(event_set); i++) {
- PyObject* item = PyTuple_GET_ITEM(event_set, i);
- char* event;
- if (PyUnicode_Check(item)) {
- event = _PyUnicode_AsString(item);
- if (event == NULL)
- goto error;
- } else if (PyBytes_Check(item))
- event = PyBytes_AS_STRING(item);
- else {
- goto error;
+ seqlen = PySequence_Size(events_seq);
+ for (i = 0; i < seqlen; ++i) {
+ PyObject *event_name_obj = PySequence_Fast_GET_ITEM(events_seq, i);
+ char *event_name = NULL;
+ if (PyUnicode_Check(event_name_obj)) {
+ event_name = _PyUnicode_AsString(event_name_obj);
+ } else if (PyBytes_Check(event_name_obj)) {
+ event_name = PyBytes_AS_STRING(event_name_obj);
}
- if (strcmp(event, "start") == 0) {
- Py_INCREF(item);
- target->start_event_obj = item;
- } else if (strcmp(event, "end") == 0) {
- Py_INCREF(item);
+
+ if (event_name == NULL) {
+ Py_DECREF(events_seq);
+ PyErr_Format(PyExc_ValueError, "invalid events sequence");
+ return NULL;
+ } else if (strcmp(event_name, "start") == 0) {
+ Py_INCREF(event_name_obj);
+ target->start_event_obj = event_name_obj;
+ } else if (strcmp(event_name, "end") == 0) {
+ Py_INCREF(event_name_obj);
Py_XDECREF(target->end_event_obj);
- target->end_event_obj = item;
- } else if (strcmp(event, "start-ns") == 0) {
- Py_INCREF(item);
+ target->end_event_obj = event_name_obj;
+ } else if (strcmp(event_name, "start-ns") == 0) {
+ Py_INCREF(event_name_obj);
Py_XDECREF(target->start_ns_event_obj);
- target->start_ns_event_obj = item;
+ target->start_ns_event_obj = event_name_obj;
EXPAT(SetNamespaceDeclHandler)(
self->parser,
(XML_StartNamespaceDeclHandler) expat_start_ns_handler,
(XML_EndNamespaceDeclHandler) expat_end_ns_handler
);
- } else if (strcmp(event, "end-ns") == 0) {
- Py_INCREF(item);
+ } else if (strcmp(event_name, "end-ns") == 0) {
+ Py_INCREF(event_name_obj);
Py_XDECREF(target->end_ns_event_obj);
- target->end_ns_event_obj = item;
+ target->end_ns_event_obj = event_name_obj;
EXPAT(SetNamespaceDeclHandler)(
self->parser,
(XML_StartNamespaceDeclHandler) expat_start_ns_handler,
(XML_EndNamespaceDeclHandler) expat_end_ns_handler
);
} else {
- PyErr_Format(
- PyExc_ValueError,
- "unknown event '%s'", event
- );
+ Py_DECREF(events_seq);
+ PyErr_Format(PyExc_ValueError, "unknown event '%s'", event_name);
return NULL;
}
}
+ Py_DECREF(events_seq);
Py_RETURN_NONE;
-
- error:
- PyErr_SetString(
- PyExc_TypeError,
- "invalid event tuple"
- );
- return NULL;
}
static PyMethodDef xmlparser_methods[] = {
{"feed", (PyCFunction) xmlparser_feed, METH_O},
{"close", (PyCFunction) xmlparser_close, METH_VARARGS},
- {"_parse", (PyCFunction) xmlparser_parse, METH_VARARGS},
+ {"_parse_whole", (PyCFunction) xmlparser_parse_whole, METH_VARARGS},
{"_setevents", (PyCFunction) xmlparser_setevents, METH_VARARGS},
{"doctype", (PyCFunction) xmlparser_doctype, METH_VARARGS},
{NULL, NULL}
@@ -3626,8 +3629,6 @@ static PyTypeObject XMLParser_Type = {
0, /* tp_free */
};
-#endif
-
/* ==================================================================== */
/* python module interface */
@@ -3661,10 +3662,8 @@ PyInit__elementtree(void)
return NULL;
if (PyType_Ready(&Element_Type) < 0)
return NULL;
-#if defined(USE_EXPAT)
if (PyType_Ready(&XMLParser_Type) < 0)
return NULL;
-#endif
m = PyModule_Create(&_elementtreemodule);
if (!m)
@@ -3707,10 +3706,8 @@ PyInit__elementtree(void)
Py_INCREF((PyObject *)&TreeBuilder_Type);
PyModule_AddObject(m, "TreeBuilder", (PyObject *)&TreeBuilder_Type);
-#if defined(USE_EXPAT)
Py_INCREF((PyObject *)&XMLParser_Type);
PyModule_AddObject(m, "XMLParser", (PyObject *)&XMLParser_Type);
-#endif
return m;
}