summaryrefslogtreecommitdiffstats
path: root/Modules/_elementtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_elementtree.c')
-rw-r--r--Modules/_elementtree.c234
1 files changed, 133 insertions, 101 deletions
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 8eb655c..949e3a0 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -1881,94 +1881,92 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
}
static PyObject*
-element_getattro(ElementObject* self, PyObject* nameobj)
+element_tag_getter(ElementObject *self, void *closure)
{
- PyObject* res;
- char *name = "";
+ PyObject *res = self->tag;
+ Py_INCREF(res);
+ return res;
+}
- if (PyUnicode_Check(nameobj))
- name = _PyUnicode_AsString(nameobj);
+static PyObject*
+element_text_getter(ElementObject *self, void *closure)
+{
+ PyObject *res = element_get_text(self);
+ Py_XINCREF(res);
+ return res;
+}
- if (name == NULL)
- return NULL;
+static PyObject*
+element_tail_getter(ElementObject *self, void *closure)
+{
+ PyObject *res = element_get_tail(self);
+ Py_XINCREF(res);
+ return res;
+}
- /* handle common attributes first */
- if (strcmp(name, "tag") == 0) {
- res = self->tag;
- Py_INCREF(res);
- return res;
- } else if (strcmp(name, "text") == 0) {
- res = element_get_text(self);
- Py_XINCREF(res);
- return res;
+static PyObject*
+element_attrib_getter(ElementObject *self, void *closure)
+{
+ PyObject *res;
+ if (!self->extra) {
+ if (create_extra(self, NULL) < 0)
+ return NULL;
}
+ res = element_get_attrib(self);
+ Py_XINCREF(res);
+ return res;
+}
- /* methods */
- res = PyObject_GenericGetAttr((PyObject*) self, nameobj);
- if (res)
- return res;
-
- /* less common attributes */
- if (strcmp(name, "tail") == 0) {
- PyErr_Clear();
- res = element_get_tail(self);
- } else if (strcmp(name, "attrib") == 0) {
- PyErr_Clear();
- if (!self->extra) {
- if (create_extra(self, NULL) < 0)
- return NULL;
- }
- res = element_get_attrib(self);
+/* macro for setter validation */
+#define _VALIDATE_ATTR_VALUE(V) \
+ if ((V) == NULL) { \
+ PyErr_SetString( \
+ PyExc_AttributeError, \
+ "can't delete element attribute"); \
+ return -1; \
}
- if (!res)
- return NULL;
-
- Py_INCREF(res);
- return res;
+static int
+element_tag_setter(ElementObject *self, PyObject *value, void *closure)
+{
+ _VALIDATE_ATTR_VALUE(value);
+ Py_INCREF(value);
+ Py_DECREF(self->tag);
+ self->tag = value;
+ return 0;
}
static int
-element_setattro(ElementObject* self, PyObject* nameobj, PyObject* value)
+element_text_setter(ElementObject *self, PyObject *value, void *closure)
{
- char *name = "";
+ _VALIDATE_ATTR_VALUE(value);
+ Py_INCREF(value);
+ Py_DECREF(JOIN_OBJ(self->text));
+ self->text = value;
+ return 0;
+}
- if (value == NULL) {
- PyErr_SetString(PyExc_AttributeError,
- "can't delete attribute");
- return -1;
- }
- if (PyUnicode_Check(nameobj))
- name = _PyUnicode_AsString(nameobj);
- if (name == NULL)
- return -1;
+static int
+element_tail_setter(ElementObject *self, PyObject *value, void *closure)
+{
+ _VALIDATE_ATTR_VALUE(value);
+ Py_INCREF(value);
+ Py_DECREF(JOIN_OBJ(self->tail));
+ self->tail = value;
+ return 0;
+}
- if (strcmp(name, "tag") == 0) {
- Py_DECREF(self->tag);
- self->tag = value;
- Py_INCREF(self->tag);
- } else if (strcmp(name, "text") == 0) {
- Py_DECREF(JOIN_OBJ(self->text));
- self->text = value;
- Py_INCREF(self->text);
- } else if (strcmp(name, "tail") == 0) {
- Py_DECREF(JOIN_OBJ(self->tail));
- self->tail = value;
- Py_INCREF(self->tail);
- } else if (strcmp(name, "attrib") == 0) {
- 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);
- } else {
- PyErr_SetString(PyExc_AttributeError,
- "Can't set arbitrary attributes on Element");
- return -1;
+static int
+element_attrib_setter(ElementObject *self, PyObject *value, void *closure)
+{
+ _VALIDATE_ATTR_VALUE(value);
+ if (!self->extra) {
+ if (create_extra(self, NULL) < 0)
+ return -1;
}
-
+ Py_INCREF(value);
+ Py_DECREF(self->extra->attrib);
+ self->extra->attrib = value;
return 0;
}
@@ -2317,7 +2315,7 @@ typedef struct {
PyObject *element_factory;
/* element tracing */
- PyObject *events; /* list of events, or NULL if not collecting */
+ PyObject *events_append; /* the append method of the list of events, or NULL */
PyObject *start_event_obj; /* event objects (NULL to ignore) */
PyObject *end_event_obj;
PyObject *start_ns_event_obj;
@@ -2352,7 +2350,7 @@ treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
t->index = 0;
- t->events = NULL;
+ t->events_append = NULL;
t->start_event_obj = t->end_event_obj = NULL;
t->start_ns_event_obj = t->end_ns_event_obj = NULL;
}
@@ -2402,7 +2400,7 @@ treebuilder_gc_clear(TreeBuilderObject *self)
Py_CLEAR(self->start_ns_event_obj);
Py_CLEAR(self->end_event_obj);
Py_CLEAR(self->start_event_obj);
- Py_CLEAR(self->events);
+ Py_CLEAR(self->events_append);
Py_CLEAR(self->stack);
Py_CLEAR(self->data);
Py_CLEAR(self->last);
@@ -2483,13 +2481,14 @@ treebuilder_append_event(TreeBuilderObject *self, PyObject *action,
PyObject *node)
{
if (action != NULL) {
- PyObject *res = PyTuple_Pack(2, action, node);
- if (res == NULL)
+ PyObject *res;
+ PyObject *event = PyTuple_Pack(2, action, node);
+ if (event == NULL)
return -1;
- if (PyList_Append(self->events, res) < 0) {
- Py_DECREF(res);
+ res = PyObject_CallFunctionObjArgs(self->events_append, event, NULL);
+ Py_DECREF(event);
+ if (res == NULL)
return -1;
- }
Py_DECREF(res);
}
return 0;
@@ -2518,10 +2517,17 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
self->data = NULL;
}
- if (self->element_factory && self->element_factory != Py_None) {
- node = PyObject_CallFunction(self->element_factory, "OO", tag, attrib);
- } else {
+ if (!self->element_factory || self->element_factory == Py_None) {
node = create_new_element(tag, attrib);
+ } else if (attrib == Py_None) {
+ attrib = PyDict_New();
+ if (!attrib)
+ return NULL;
+ node = PyObject_CallFunction(self->element_factory, "OO", tag, attrib);
+ Py_DECREF(attrib);
+ }
+ else {
+ node = PyObject_CallFunction(self->element_factory, "OO", tag, attrib);
}
if (!node) {
return NULL;
@@ -2986,12 +2992,8 @@ expat_start_handler(XMLParserObject* self, const XML_Char* tag_in,
attrib_in += 2;
}
} else {
- /* Pass an empty dictionary on */
- attrib = PyDict_New();
- if (!attrib) {
- Py_DECREF(tag);
- return;
- }
+ Py_INCREF(Py_None);
+ attrib = Py_None;
}
if (TreeBuilder_CheckExact(self->target)) {
@@ -3000,6 +3002,14 @@ expat_start_handler(XMLParserObject* self, const XML_Char* tag_in,
tag, attrib);
}
else if (self->handle_start) {
+ if (attrib == Py_None) {
+ Py_DECREF(attrib);
+ attrib = PyDict_New();
+ if (!attrib) {
+ Py_DECREF(tag);
+ return;
+ }
+ }
res = PyObject_CallFunction(self->handle_start, "OO", tag, attrib);
} else
res = NULL;
@@ -3073,7 +3083,7 @@ expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix,
if (PyErr_Occurred())
return;
- if (!target->events || !target->start_ns_event_obj)
+ if (!target->events_append || !target->start_ns_event_obj)
return;
if (!uri)
@@ -3096,7 +3106,7 @@ expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in)
if (PyErr_Occurred())
return;
- if (!target->events)
+ if (!target->events_append)
return;
treebuilder_append_event(target, target->end_ns_event_obj, Py_None);
@@ -3585,7 +3595,7 @@ _elementtree_XMLParser_doctype_impl(XMLParserObject *self, PyObject *name,
/*[clinic input]
_elementtree.XMLParser._setevents
- events_queue: object(subclass_of='&PyList_Type')
+ events_queue: object
events_to_report: object = None
/
@@ -3595,12 +3605,12 @@ static PyObject *
_elementtree_XMLParser__setevents_impl(XMLParserObject *self,
PyObject *events_queue,
PyObject *events_to_report)
-/*[clinic end generated code: output=1440092922b13ed1 input=59db9742910c6174]*/
+/*[clinic end generated code: output=1440092922b13ed1 input=abf90830a1c3b0fc]*/
{
/* activate element event reporting */
Py_ssize_t i, seqlen;
TreeBuilderObject *target;
- PyObject *events_seq;
+ PyObject *events_append, *events_seq;
if (!TreeBuilder_CheckExact(self->target)) {
PyErr_SetString(
@@ -3613,9 +3623,11 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self,
target = (TreeBuilderObject*) self->target;
- Py_INCREF(events_queue);
- Py_XDECREF(target->events);
- target->events = events_queue;
+ events_append = PyObject_GetAttrString(events_queue, "append");
+ if (events_append == NULL)
+ return NULL;
+ Py_XDECREF(target->events_append);
+ target->events_append = events_append;
/* clear out existing events */
Py_CLEAR(target->start_event_obj);
@@ -3753,6 +3765,26 @@ static PyMappingMethods element_as_mapping = {
(objobjargproc) element_ass_subscr,
};
+static PyGetSetDef element_getsetlist[] = {
+ {"tag",
+ (getter)element_tag_getter,
+ (setter)element_tag_setter,
+ "A string identifying what kind of data this element represents"},
+ {"text",
+ (getter)element_text_getter,
+ (setter)element_text_setter,
+ "A string of text directly after the start tag, or None"},
+ {"tail",
+ (getter)element_tail_getter,
+ (setter)element_tail_setter,
+ "A string of text directly after the end tag, or None"},
+ {"attrib",
+ (getter)element_attrib_getter,
+ (setter)element_attrib_setter,
+ "A dictionary containing the element's attributes"},
+ {NULL},
+};
+
static PyTypeObject Element_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"xml.etree.ElementTree.Element", sizeof(ElementObject), 0,
@@ -3769,8 +3801,8 @@ static PyTypeObject Element_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
- (getattrofunc)element_getattro, /* tp_getattro */
- (setattrofunc)element_setattro, /* tp_setattro */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
/* tp_flags */
@@ -3783,7 +3815,7 @@ static PyTypeObject Element_Type = {
0, /* tp_iternext */
element_methods, /* tp_methods */
0, /* tp_members */
- 0, /* tp_getset */
+ element_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */