From 1339099e7b7d43ecfee6af2fc213b08547222fa9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 21 Mar 2011 13:23:42 +0100 Subject: _elementtree.c: remove trailing spaces --- Modules/_elementtree.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 3061d8eaf3..5983a3b87b 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -226,7 +226,7 @@ typedef struct { PyObject* *children; PyObject* _children[STATIC_CHILDREN]; - + } ElementObjectExtra; typedef struct { @@ -354,14 +354,14 @@ element_resize(ElementObject* self, int extra) /* use Python 2.4's list growth strategy */ size = (size >> 3) + (size < 9 ? 3 : 6) + size; /* Coverity CID #182 size_error: Allocating 1 bytes to pointer "children" - * which needs at least 4 bytes. - * Although it's a false alarm always assume at least one child to + * which needs at least 4 bytes. + * Although it's a false alarm always assume at least one child to * be safe. */ size = size ? size : 1; if (self->extra->children != self->extra->_children) { /* Coverity CID #182 size_error: Allocating 1 bytes to pointer - * "children", which needs at least 4 bytes. Although it's a + * "children", which needs at least 4 bytes. Although it's a * false alarm always assume at least one child to be safe. */ children = PyObject_Realloc(self->extra->children, @@ -606,7 +606,7 @@ element_copy(ElementObject* self, PyObject* args) Py_INCREF(JOIN_OBJ(element->tail)); if (self->extra) { - + if (element_resize(element, self->extra->length) < 0) { Py_DECREF(element); return NULL; @@ -618,7 +618,7 @@ element_copy(ElementObject* self, PyObject* args) } element->extra->length = self->extra->length; - + } return (PyObject*) element; @@ -661,7 +661,7 @@ element_deepcopy(ElementObject* self, PyObject* args) if (!element) return NULL; - + text = deepcopy(JOIN_OBJ(self->text), memo); if (!text) goto error; @@ -675,7 +675,7 @@ element_deepcopy(ElementObject* self, PyObject* args) element->tail = JOIN_SET(tail, JOIN_GET(self->tail)); if (self->extra) { - + if (element_resize(element, self->extra->length) < 0) goto error; @@ -689,7 +689,7 @@ element_deepcopy(ElementObject* self, PyObject* args) } element->extra->length = self->extra->length; - + } /* add object to memo dictionary (so deepcopy won't visit it again) */ @@ -800,7 +800,7 @@ element_find(ElementObject* self, PyObject* args) if (!self->extra) Py_RETURN_NONE; - + for (i = 0; i < self->extra->length; i++) { PyObject* item = self->extra->children[i]; if (Element_CheckExact(item) && @@ -953,7 +953,7 @@ static PyObject* element_iter(ElementObject* self, PyObject* args) { PyObject* result; - + PyObject* tag = Py_None; if (!PyArg_ParseTuple(args, "|O:iter", &tag)) return NULL; @@ -985,7 +985,7 @@ static PyObject* element_itertext(ElementObject* self, PyObject* args) { PyObject* result; - + if (!PyArg_ParseTuple(args, ":itertext")) return NULL; @@ -1483,7 +1483,7 @@ element_getattro(ElementObject* self, PyObject* nameobj) if (PyUnicode_Check(nameobj)) name = _PyUnicode_AsString(nameobj); - + if (name == NULL) return NULL; @@ -2113,7 +2113,7 @@ makeuniversal(XMLParserObject* self, const char* string) Py_INCREF(key); tag = key; } - + /* decode universal name */ p = PyBytes_AS_STRING(tag); value = PyUnicode_DecodeUTF8(p, size, "strict"); @@ -2407,7 +2407,7 @@ expat_unknown_encoding_handler(XMLParserObject *self, const XML_Char *name, for (i = 0; i < 256; i++) s[i] = i; - + u = PyUnicode_Decode((char*) s, 256, name, "replace"); if (!u) return XML_STATUS_ERROR; @@ -2466,7 +2466,7 @@ xmlparser(PyObject* self_, PyObject* args, PyObject* kw) PyObject_Del(self); return NULL; } - + self->names = PyDict_New(); if (!self->names) { PyObject_Del(self->entity); @@ -2645,7 +2645,7 @@ xmlparser_parse(XMLParserObject* self, PyObject* args) reader = PyObject_GetAttrString(fileobj, "read"); if (!reader) return NULL; - + /* read from open file object */ for (;;) { @@ -2796,7 +2796,7 @@ static PyMethodDef xmlparser_methods[] = { {NULL, NULL} }; -static PyObject* +static PyObject* xmlparser_getattro(XMLParserObject* self, PyObject* nameobj) { if (PyUnicode_Check(nameobj)) { @@ -2957,7 +2957,7 @@ PyInit__elementtree(void) " break\n" " parser.feed(data)\n" " self._root = parser.close()\n" - " else:\n" + " else:\n" " parser = cElementTree.XMLParser()\n" " self._root = parser._parse(source)\n" " return self._root\n" -- cgit v1.2.1 From 758975ac24d240747b3e4f3bc7fa682cc94d6ebc Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 21 Mar 2011 13:26:24 +0100 Subject: Issue #10833: Use PyUnicode_FromFormat() and PyErr_Format() instead of PyOS_snprintf(). --- Modules/_elementtree.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 5983a3b87b..6373c4848f 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2138,13 +2138,15 @@ makeuniversal(XMLParserObject* self, const char* string) static void expat_set_error(const char* message, int line, int column) { - PyObject *error; - PyObject *position; - char buffer[256]; + PyObject *errmsg, *error, *position; - sprintf(buffer, "%.100s: line %d, column %d", message, line, column); + errmsg = PyUnicode_FromFormat("%s: line %d, column %d", + message, line, column); + if (errmsg == NULL) + return; - error = PyObject_CallFunction(elementtree_parseerror_obj, "s", buffer); + error = PyObject_CallFunction(elementtree_parseerror_obj, "O", errmsg); + Py_DECREF(errmsg); if (!error) return; -- cgit v1.2.1 From d1d013c01c268d869597b35cbcd8b5d7c5baf2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Wed, 28 Sep 2011 07:41:54 +0200 Subject: Implement PEP 393. --- Modules/_elementtree.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 6373c4848f..0c64dd5d4b 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -723,13 +723,16 @@ checkpath(PyObject* tag) (ch == '/' || ch == '*' || ch == '[' || ch == '@' || ch == '.') if (PyUnicode_Check(tag)) { - Py_UNICODE *p = PyUnicode_AS_UNICODE(tag); - for (i = 0; i < PyUnicode_GET_SIZE(tag); i++) { - if (p[i] == '{') + const Py_ssize_t len = PyUnicode_GET_LENGTH(tag); + void *data = PyUnicode_DATA(tag); + unsigned int kind = PyUnicode_KIND(tag); + for (i = 0; i < len; i++) { + Py_UCS4 ch = PyUnicode_READ(kind, data, i); + if (ch == '{') check = 0; - else if (p[i] == '}') + else if (ch == '}') check = 1; - else if (check && PATHCHAR(p[i])) + else if (check && PATHCHAR(ch)) return 1; } return 0; @@ -2401,9 +2404,10 @@ expat_unknown_encoding_handler(XMLParserObject *self, const XML_Char *name, XML_Encoding *info) { PyObject* u; - Py_UNICODE* p; unsigned char s[256]; int i; + void *data; + unsigned int kind; memset(info, 0, sizeof(XML_Encoding)); @@ -2413,17 +2417,20 @@ expat_unknown_encoding_handler(XMLParserObject *self, const XML_Char *name, u = PyUnicode_Decode((char*) s, 256, name, "replace"); if (!u) return XML_STATUS_ERROR; + if (PyUnicode_READY(u)) + return XML_STATUS_ERROR; - if (PyUnicode_GET_SIZE(u) != 256) { + if (PyUnicode_GET_LENGTH(u) != 256) { Py_DECREF(u); return XML_STATUS_ERROR; } - p = PyUnicode_AS_UNICODE(u); - + kind = PyUnicode_KIND(u); + data = PyUnicode_DATA(u); for (i = 0; i < 256; i++) { - if (p[i] != Py_UNICODE_REPLACEMENT_CHARACTER) - info->map[i] = p[i]; + Py_UCS4 ch = PyUnicode_READ(kind, data, i); + if (ch != Py_UNICODE_REPLACEMENT_CHARACTER) + info->map[i] = ch; else info->map[i] = -1; } -- cgit v1.2.1 From dcacb24f386ae1b107462181af42b6826ec15fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 9 Oct 2011 10:38:36 +0200 Subject: =?UTF-8?q?Add=20API=20for=20static=20strings,=20primarily=20good?= =?UTF-8?q?=20for=20identifiers.=20Thanks=20to=20Konrad=20Sch=C3=B6bel=20a?= =?UTF-8?q?nd=20Jasper=20Schulz=20for=20helping=20with=20the=20mass-editin?= =?UTF-8?q?g.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modules/_elementtree.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 0c64dd5d4b..fcd12716e3 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -790,16 +790,18 @@ static PyObject* element_find(ElementObject* self, PyObject* args) { int i; - PyObject* tag; PyObject* namespaces = Py_None; + if (!PyArg_ParseTuple(args, "O|O:find", &tag, &namespaces)) return NULL; - if (checkpath(tag) || namespaces != Py_None) - return PyObject_CallMethod( - elementpath_obj, "find", "OOO", self, tag, namespaces + if (checkpath(tag) || namespaces != Py_None) { + _Py_identifier(find); + return _PyObject_CallMethodId( + elementpath_obj, &PyId_find, "OOO", self, tag, namespaces ); + } if (!self->extra) Py_RETURN_NONE; @@ -820,16 +822,17 @@ static PyObject* element_findtext(ElementObject* self, PyObject* args) { int i; - PyObject* tag; PyObject* default_value = Py_None; PyObject* namespaces = Py_None; + _Py_identifier(findtext); + if (!PyArg_ParseTuple(args, "O|OO:findtext", &tag, &default_value, &namespaces)) return NULL; if (checkpath(tag) || namespaces != Py_None) - return PyObject_CallMethod( - elementpath_obj, "findtext", "OOOO", self, tag, default_value, namespaces + return _PyObject_CallMethodId( + elementpath_obj, &PyId_findtext, "OOOO", self, tag, default_value, namespaces ); if (!self->extra) { @@ -858,16 +861,18 @@ element_findall(ElementObject* self, PyObject* args) { int i; PyObject* out; - PyObject* tag; PyObject* namespaces = Py_None; + if (!PyArg_ParseTuple(args, "O|O:findall", &tag, &namespaces)) return NULL; - if (checkpath(tag) || namespaces != Py_None) - return PyObject_CallMethod( - elementpath_obj, "findall", "OOO", self, tag, namespaces + if (checkpath(tag) || namespaces != Py_None) { + _Py_identifier(findall); + return _PyObject_CallMethodId( + elementpath_obj, &PyId_findall, "OOO", self, tag, namespaces ); + } out = PyList_New(0); if (!out) @@ -895,11 +900,13 @@ element_iterfind(ElementObject* self, PyObject* args) { PyObject* tag; PyObject* namespaces = Py_None; + _Py_identifier(iterfind); + if (!PyArg_ParseTuple(args, "O|O:iterfind", &tag, &namespaces)) return NULL; - return PyObject_CallMethod( - elementpath_obj, "iterfind", "OOO", self, tag, namespaces + return _PyObject_CallMethodId( + elementpath_obj, &PyId_iterfind, "OOO", self, tag, namespaces ); } -- cgit v1.2.1 From f5ad3b280b43227eb0e3fa63d89490a58ba9c28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 14 Oct 2011 10:20:37 +0200 Subject: Rename _Py_identifier to _Py_IDENTIFIER. --- Modules/_elementtree.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index fcd12716e3..1fb603807f 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -797,7 +797,7 @@ element_find(ElementObject* self, PyObject* args) return NULL; if (checkpath(tag) || namespaces != Py_None) { - _Py_identifier(find); + _Py_IDENTIFIER(find); return _PyObject_CallMethodId( elementpath_obj, &PyId_find, "OOO", self, tag, namespaces ); @@ -825,7 +825,7 @@ element_findtext(ElementObject* self, PyObject* args) PyObject* tag; PyObject* default_value = Py_None; PyObject* namespaces = Py_None; - _Py_identifier(findtext); + _Py_IDENTIFIER(findtext); if (!PyArg_ParseTuple(args, "O|OO:findtext", &tag, &default_value, &namespaces)) return NULL; @@ -868,7 +868,7 @@ element_findall(ElementObject* self, PyObject* args) return NULL; if (checkpath(tag) || namespaces != Py_None) { - _Py_identifier(findall); + _Py_IDENTIFIER(findall); return _PyObject_CallMethodId( elementpath_obj, &PyId_findall, "OOO", self, tag, namespaces ); @@ -900,7 +900,7 @@ element_iterfind(ElementObject* self, PyObject* args) { PyObject* tag; PyObject* namespaces = Py_None; - _Py_identifier(iterfind); + _Py_IDENTIFIER(iterfind); if (!PyArg_ParseTuple(args, "O|O:iterfind", &tag, &namespaces)) return NULL; -- cgit v1.2.1 From b9dfe4f74a5f128d9820c36f8e8dc9f1e27e04c9 Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Sat, 11 Feb 2012 11:28:16 +0100 Subject: Issue #13988: move the python bootstrap code to cElementTree.py, and remove obsolete code for Python 2.4 and 2.5. --- Modules/_elementtree.c | 234 +------------------------------------------------ 1 file changed, 2 insertions(+), 232 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 884e50d077..af7661eb0c 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -94,25 +94,6 @@ do { memory -= size; printf("%8d - %s\n", memory, comment); } while (0) #define LOCAL(type) static type #endif -/* compatibility macros */ -#if (PY_VERSION_HEX < 0x02060000) -#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) -#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) -#endif - -#if (PY_VERSION_HEX < 0x02050000) -typedef int Py_ssize_t; -#define lenfunc inquiry -#endif - -#if (PY_VERSION_HEX < 0x02040000) -#define PyDict_CheckExact PyDict_Check - -#if !defined(Py_RETURN_NONE) -#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None -#endif -#endif - /* macros used to store 'join' flags in string object pointers. note that all use of text and tail as object pointers must be wrapped in JOIN_OBJ. see comments in the ElementObject definition for more @@ -123,7 +104,6 @@ typedef int Py_ssize_t; /* glue functions (see the init function for details) */ static PyObject* elementtree_parseerror_obj; -static PyObject* elementtree_copyelement_obj; static PyObject* elementtree_deepcopy_obj; static PyObject* elementtree_iter_obj; static PyObject* elementtree_itertext_obj; @@ -1127,31 +1107,6 @@ element_makeelement(PyObject* self, PyObject* args, PyObject* kw) return elem; } -static PyObject* -element_reduce(ElementObject* self, PyObject* args) -{ - if (!PyArg_ParseTuple(args, ":__reduce__")) - return NULL; - - /* Hack alert: This method is used to work around a __copy__ - problem on certain 2.3 and 2.4 versions. To save time and - simplify the code, we create the copy in here, and use a dummy - copyelement helper to trick the copy module into doing the - right thing. */ - - if (!elementtree_copyelement_obj) { - PyErr_SetString( - PyExc_RuntimeError, - "copyelement helper not found" - ); - return NULL; - } - - return Py_BuildValue( - "O(N)", elementtree_copyelement_obj, element_copy(self, args) - ); -} - static PyObject* element_remove(ElementObject* self, PyObject* args) { @@ -1260,13 +1215,8 @@ element_subscr(PyObject* self_, PyObject* item) { ElementObject* self = (ElementObject*) self_; -#if (PY_VERSION_HEX < 0x02050000) - if (PyInt_Check(item) || PyLong_Check(item)) { - long i = PyInt_AsLong(item); -#else if (PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); -#endif if (i == -1 && PyErr_Occurred()) { return NULL; @@ -1317,13 +1267,8 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) { ElementObject* self = (ElementObject*) self_; -#if (PY_VERSION_HEX < 0x02050000) - if (PyInt_Check(item) || PyLong_Check(item)) { - long i = PyInt_AsLong(item); -#else if (PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); -#endif if (i == -1 && PyErr_Occurred()) { return -1; @@ -1364,13 +1309,8 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) if (step != 1 && newlen != slicelen) { PyErr_Format(PyExc_ValueError, -#if (PY_VERSION_HEX < 0x02050000) - "attempt to assign sequence of size %d " - "to extended slice of size %d", -#else "attempt to assign sequence of size %zd " "to extended slice of size %zd", -#endif newlen, slicelen ); return -1; @@ -1470,18 +1410,6 @@ static PyMethodDef element_methods[] = { {"__copy__", (PyCFunction) element_copy, METH_VARARGS}, {"__deepcopy__", (PyCFunction) element_deepcopy, METH_VARARGS}, - /* Some 2.3 and 2.4 versions do not handle the __copy__ method on - C objects correctly, so we have to fake it using a __reduce__- - based hack (see the element_reduce implementation above for - details). */ - - /* The behaviour has been changed in 2.3.5 and 2.4.1, so we're - using a runtime test to figure out if we need to fake things - or now (see the init code below). The following entry is - enabled only if the hack is needed. */ - - {"!__reduce__", (PyCFunction) element_reduce, METH_VARARGS}, - {NULL, NULL} }; @@ -2878,7 +2806,6 @@ static PyMethodDef _functions[] = { {"TreeBuilder", (PyCFunction) treebuilder, METH_VARARGS}, #if defined(USE_EXPAT) {"XMLParser", (PyCFunction) xmlparser, METH_VARARGS|METH_KEYWORDS}, - {"XMLTreeBuilder", (PyCFunction) xmlparser, METH_VARARGS|METH_KEYWORDS}, #endif {NULL, NULL} }; @@ -2933,54 +2860,8 @@ PyInit__elementtree(void) bootstrap = ( - "from copy import copy, deepcopy\n" - - "try:\n" - " from xml.etree import ElementTree\n" - "except ImportError:\n" - " import ElementTree\n" - "ET = ElementTree\n" - "del ElementTree\n" - - "import _elementtree as cElementTree\n" - - "try:\n" /* check if copy works as is */ - " copy(cElementTree.Element('x'))\n" - "except:\n" - " def copyelement(elem):\n" - " return elem\n" - - "class CommentProxy:\n" - " def __call__(self, text=None):\n" - " element = cElementTree.Element(ET.Comment)\n" - " element.text = text\n" - " return element\n" - " def __eq__(self, other):\n" - " return ET.Comment == other\n" - "cElementTree.Comment = CommentProxy()\n" - - "class ElementTree(ET.ElementTree):\n" /* public */ - " def parse(self, source, parser=None):\n" - " close_source = False\n" - " if not hasattr(source, 'read'):\n" - " source = open(source, 'rb')\n" - " close_source = True\n" - " try:\n" - " if parser is not None:\n" - " while 1:\n" - " data = source.read(65536)\n" - " if not data:\n" - " break\n" - " parser.feed(data)\n" - " self._root = parser.close()\n" - " else:\n" - " parser = cElementTree.XMLParser()\n" - " self._root = parser._parse(source)\n" - " return self._root\n" - " finally:\n" - " if close_source:\n" - " source.close()\n" - "cElementTree.ElementTree = ElementTree\n" + "from copy import deepcopy\n" + "from xml.etree import ElementPath\n" "def iter(node, tag=None):\n" /* helper */ " if tag == '*':\n" @@ -3000,123 +2881,12 @@ PyInit__elementtree(void) " if e.tail:\n" " yield e.tail\n" - "def parse(source, parser=None):\n" /* public */ - " tree = ElementTree()\n" - " tree.parse(source, parser)\n" - " return tree\n" - "cElementTree.parse = parse\n" - - "class iterparse:\n" - " root = None\n" - " def __init__(self, file, events=None):\n" - " self._close_file = False\n" - " if not hasattr(file, 'read'):\n" - " file = open(file, 'rb')\n" - " self._close_file = True\n" - " self._file = file\n" - " self._events = []\n" - " self._index = 0\n" - " self._error = None\n" - " self.root = self._root = None\n" - " b = cElementTree.TreeBuilder()\n" - " self._parser = cElementTree.XMLParser(b)\n" - " self._parser._setevents(self._events, events)\n" - " def __next__(self):\n" - " while 1:\n" - " try:\n" - " item = self._events[self._index]\n" - " self._index += 1\n" - " return item\n" - " except IndexError:\n" - " pass\n" - " if self._error:\n" - " e = self._error\n" - " self._error = None\n" - " raise e\n" - " if self._parser is None:\n" - " self.root = self._root\n" - " if self._close_file:\n" - " self._file.close()\n" - " raise StopIteration\n" - " # load event buffer\n" - " del self._events[:]\n" - " self._index = 0\n" - " data = self._file.read(16384)\n" - " if data:\n" - " try:\n" - " self._parser.feed(data)\n" - " except SyntaxError as exc:\n" - " self._error = exc\n" - " else:\n" - " self._root = self._parser.close()\n" - " self._parser = None\n" - " def __iter__(self):\n" - " return self\n" - "cElementTree.iterparse = iterparse\n" - - "class PIProxy:\n" - " def __call__(self, target, text=None):\n" - " element = cElementTree.Element(ET.PI)\n" - " element.text = target\n" - " if text:\n" - " element.text = element.text + ' ' + text\n" - " return element\n" - " def __eq__(self, other):\n" - " return ET.PI == other\n" - "cElementTree.PI = cElementTree.ProcessingInstruction = PIProxy()\n" - - "def XML(text):\n" /* public */ - " parser = cElementTree.XMLParser()\n" - " parser.feed(text)\n" - " return parser.close()\n" - "cElementTree.XML = cElementTree.fromstring = XML\n" - - "def XMLID(text):\n" /* public */ - " tree = XML(text)\n" - " ids = {}\n" - " for elem in tree.iter():\n" - " id = elem.get('id')\n" - " if id:\n" - " ids[id] = elem\n" - " return tree, ids\n" - "cElementTree.XMLID = XMLID\n" - - "try:\n" - " register_namespace = ET.register_namespace\n" - "except AttributeError:\n" - " def register_namespace(prefix, uri):\n" - " ET._namespace_map[uri] = prefix\n" - "cElementTree.register_namespace = register_namespace\n" - - "cElementTree.dump = ET.dump\n" - "cElementTree.ElementPath = ElementPath = ET.ElementPath\n" - "cElementTree.iselement = ET.iselement\n" - "cElementTree.QName = ET.QName\n" - "cElementTree.tostring = ET.tostring\n" - "cElementTree.fromstringlist = ET.fromstringlist\n" - "cElementTree.tostringlist = ET.tostringlist\n" - "cElementTree.VERSION = '" VERSION "'\n" - "cElementTree.__version__ = '" VERSION "'\n" - ); if (!PyRun_String(bootstrap, Py_file_input, g, NULL)) return NULL; elementpath_obj = PyDict_GetItemString(g, "ElementPath"); - - elementtree_copyelement_obj = PyDict_GetItemString(g, "copyelement"); - if (elementtree_copyelement_obj) { - /* reduce hack needed; enable reduce method */ - PyMethodDef* mp; - for (mp = element_methods; mp->ml_name; mp++) - if (mp->ml_meth == (PyCFunction) element_reduce) { - mp->ml_name = "__reduce__"; - break; - } - } else - PyErr_Clear(); - elementtree_deepcopy_obj = PyDict_GetItemString(g, "deepcopy"); elementtree_iter_obj = PyDict_GetItemString(g, "iter"); elementtree_itertext_obj = PyDict_GetItemString(g, "itertext"); -- cgit v1.2.1 From dac572d93a0ae78bc4b1fb471c2280cdac850ddf Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Mon, 13 Feb 2012 11:03:30 +0100 Subject: Issue #13988: cElementTree is deprecated and the _elementtree accelerator is automatically used whenever available. --- Modules/_elementtree.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index af7661eb0c..78d8177d68 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -70,7 +70,7 @@ helps if you have lots of leaf nodes with attributes). */ /* Also note that pymalloc always allocates blocks in multiples of - eight bytes. For the current version of cElementTree, this means + eight bytes. For the current C version of ElementTree, this means that the number of children should be an even number, at least on 32-bit platforms. */ @@ -2649,7 +2649,7 @@ xmlparser_setevents(XMLParserObject* self, PyObject* args) if (!TreeBuilder_CheckExact(self->target)) { PyErr_SetString( PyExc_TypeError, - "event handling only supported for cElementTree.Treebuilder " + "event handling only supported for ElementTree.TreeBuilder " "targets" ); return NULL; @@ -2906,7 +2906,7 @@ PyInit__elementtree(void) #endif elementtree_parseerror_obj = PyErr_NewException( - "cElementTree.ParseError", PyExc_SyntaxError, NULL + "xml.etree.ElementTree.ParseError", PyExc_SyntaxError, NULL ); Py_INCREF(elementtree_parseerror_obj); PyModule_AddObject(m, "ParseError", elementtree_parseerror_obj); -- cgit v1.2.1 From f69c84221263d4c5f993a396f530b28ac65caf3b Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sun, 4 Mar 2012 07:14:03 +0200 Subject: Issue #14128: Exposing Element as an actual type from _elementtree, rather than a factory function. This makes the C implementation more aligned with the Python implementation. Also added some tests to ensure that Element is now a type and that it can be subclassed. --- Modules/_elementtree.c | 227 +++++++++++++++++++++++++++++++------------------ 1 file changed, 145 insertions(+), 82 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 78d8177d68..179cadc5f5 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -191,7 +191,7 @@ list_join(PyObject* list) } /* -------------------------------------------------------------------- */ -/* the element type */ +/* the Element type */ typedef struct { @@ -236,10 +236,10 @@ static PyTypeObject Element_Type; #define Element_CheckExact(op) (Py_TYPE(op) == &Element_Type) /* -------------------------------------------------------------------- */ -/* element constructor and destructor */ +/* Element constructors and destructor */ LOCAL(int) -element_new_extra(ElementObject* self, PyObject* attrib) +create_extra(ElementObject* self, PyObject* attrib) { self->extra = PyObject_Malloc(sizeof(ElementObjectExtra)); if (!self->extra) @@ -259,7 +259,7 @@ element_new_extra(ElementObject* self, PyObject* attrib) } LOCAL(void) -element_dealloc_extra(ElementObject* self) +dealloc_extra(ElementObject* self) { int i; @@ -274,8 +274,11 @@ element_dealloc_extra(ElementObject* self) PyObject_Free(self->extra); } +/* Convenience internal function to create new Element objects with the given + * tag and attributes. +*/ LOCAL(PyObject*) -element_new(PyObject* tag, PyObject* attrib) +create_new_element(PyObject* tag, PyObject* attrib) { ElementObject* self; @@ -290,16 +293,10 @@ element_new(PyObject* tag, PyObject* attrib) self->extra = NULL; if (attrib != Py_None) { - - if (element_new_extra(self, attrib) < 0) { + if (create_extra(self, attrib) < 0) { PyObject_Del(self); return NULL; } - - self->extra->length = 0; - self->extra->allocated = STATIC_CHILDREN; - self->extra->children = self->extra->_children; - } Py_INCREF(tag); @@ -316,6 +313,86 @@ element_new(PyObject* tag, PyObject* attrib) return (PyObject*) self; } +static PyObject * +element_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + ElementObject *e = (ElementObject *)type->tp_alloc(type, 0); + if (e != NULL) { + Py_INCREF(Py_None); + e->tag = Py_None; + + Py_INCREF(Py_None); + e->text = Py_None; + + Py_INCREF(Py_None); + e->tail = Py_None; + + e->extra = NULL; + } + return (PyObject *)e; +} + +static int +element_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *tag; + PyObject *tmp; + PyObject *attrib = NULL; + ElementObject *self_elem; + + if (!PyArg_ParseTuple(args, "O|O!:Element", &tag, &PyDict_Type, &attrib)) + return -1; + + if (attrib || kwds) { + attrib = (attrib) ? PyDict_Copy(attrib) : PyDict_New(); + if (!attrib) + return -1; + if (kwds) + PyDict_Update(attrib, kwds); + } else { + Py_INCREF(Py_None); + attrib = Py_None; + } + + self_elem = (ElementObject *)self; + + /* Use None for empty dictionaries */ + if (PyDict_CheckExact(attrib) && PyDict_Size(attrib) == 0) { + Py_INCREF(Py_None); + attrib = Py_None; + } + + if (attrib != Py_None) { + if (create_extra(self_elem, attrib) < 0) { + PyObject_Del(self_elem); + return -1; + } + } + + /* If create_extra needed attrib, it took a reference to it, so we can + * release ours anyway. + */ + Py_DECREF(attrib); + + /* Replace the objects already pointed to by tag, text and tail. */ + tmp = self_elem->tag; + self_elem->tag = tag; + Py_INCREF(tag); + Py_DECREF(tmp); + + tmp = self_elem->text; + self_elem->text = Py_None; + Py_INCREF(Py_None); + Py_DECREF(JOIN_OBJ(tmp)); + + tmp = self_elem->tail; + self_elem->tail = Py_None; + Py_INCREF(Py_None); + Py_DECREF(JOIN_OBJ(tmp)); + + return 0; +} + LOCAL(int) element_resize(ElementObject* self, int extra) { @@ -326,7 +403,7 @@ element_resize(ElementObject* self, int extra) elements. set an exception and return -1 if allocation failed */ if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); size = self->extra->length + extra; @@ -443,35 +520,6 @@ element_get_tail(ElementObject* self) return res; } -static PyObject* -element(PyObject* self, PyObject* args, PyObject* kw) -{ - PyObject* elem; - - PyObject* tag; - PyObject* attrib = NULL; - if (!PyArg_ParseTuple(args, "O|O!:Element", &tag, - &PyDict_Type, &attrib)) - return NULL; - - if (attrib || kw) { - attrib = (attrib) ? PyDict_Copy(attrib) : PyDict_New(); - if (!attrib) - return NULL; - if (kw) - PyDict_Update(attrib, kw); - } else { - Py_INCREF(Py_None); - attrib = Py_None; - } - - elem = element_new(tag, attrib); - - Py_DECREF(attrib); - - return elem; -} - static PyObject* subelement(PyObject* self, PyObject* args, PyObject* kw) { @@ -496,7 +544,7 @@ subelement(PyObject* self, PyObject* args, PyObject* kw) attrib = Py_None; } - elem = element_new(tag, attrib); + elem = create_new_element(tag, attrib); Py_DECREF(attrib); @@ -512,7 +560,7 @@ static void element_dealloc(ElementObject* self) { if (self->extra) - element_dealloc_extra(self); + dealloc_extra(self); /* discard attributes */ Py_DECREF(self->tag); @@ -521,7 +569,7 @@ element_dealloc(ElementObject* self) RELEASE(sizeof(ElementObject), "destroy element"); - PyObject_Del(self); + Py_TYPE(self)->tp_free((PyObject *)self); } /* -------------------------------------------------------------------- */ @@ -547,7 +595,7 @@ element_clear(ElementObject* self, PyObject* args) return NULL; if (self->extra) { - element_dealloc_extra(self); + dealloc_extra(self); self->extra = NULL; } @@ -571,7 +619,7 @@ element_copy(ElementObject* self, PyObject* args) if (!PyArg_ParseTuple(args, ":__copy__")) return NULL; - element = (ElementObject*) element_new( + element = (ElementObject*) create_new_element( self->tag, (self->extra) ? self->extra->attrib : Py_None ); if (!element) @@ -634,7 +682,7 @@ element_deepcopy(ElementObject* self, PyObject* args) attrib = Py_None; } - element = (ElementObject*) element_new(tag, attrib); + element = (ElementObject*) create_new_element(tag, attrib); Py_DECREF(tag); Py_DECREF(attrib); @@ -1029,7 +1077,7 @@ element_insert(ElementObject* self, PyObject* args) return NULL; if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); if (index < 0) { index += self->extra->length; @@ -1100,7 +1148,7 @@ element_makeelement(PyObject* self, PyObject* args, PyObject* kw) if (!attrib) return NULL; - elem = element_new(tag, attrib); + elem = create_new_element(tag, attrib); Py_DECREF(attrib); @@ -1154,7 +1202,10 @@ element_remove(ElementObject* self, PyObject* args) static PyObject* element_repr(ElementObject* self) { - return PyUnicode_FromFormat("", self->tag, self); + if (self->tag) + return PyUnicode_FromFormat("", self->tag, self); + else + return PyUnicode_FromFormat("", self); } static PyObject* @@ -1168,7 +1219,7 @@ element_set(ElementObject* self, PyObject* args) return NULL; if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); attrib = element_get_attrib(self); if (!attrib) @@ -1284,7 +1335,7 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) PyObject* seq = NULL; if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); if (PySlice_GetIndicesEx(item, self->extra->length, @@ -1448,7 +1499,7 @@ element_getattro(ElementObject* self, PyObject* nameobj) } else if (strcmp(name, "attrib") == 0) { PyErr_Clear(); if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); res = element_get_attrib(self); } @@ -1484,7 +1535,7 @@ element_setattr(ElementObject* self, const char* name, PyObject* value) Py_INCREF(self->tail); } else if (strcmp(name, "attrib") == 0) { if (!self->extra) - element_new_extra(self, NULL); + create_extra(self, NULL); Py_DECREF(self->extra->attrib); self->extra->attrib = value; Py_INCREF(self->extra->attrib); @@ -1516,31 +1567,41 @@ static PyTypeObject Element_Type = { PyVarObject_HEAD_INIT(NULL, 0) "Element", sizeof(ElementObject), 0, /* methods */ - (destructor)element_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - (setattrfunc)element_setattr, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)element_repr, /* tp_repr */ - 0, /* tp_as_number */ - &element_as_sequence, /* tp_as_sequence */ - &element_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - (getattrofunc)element_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 */ - element_methods, /* tp_methods */ - 0, /* tp_members */ + (destructor)element_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + (setattrfunc)element_setattr, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)element_repr, /* tp_repr */ + 0, /* tp_as_number */ + &element_as_sequence, /* tp_as_sequence */ + &element_as_mapping, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + (getattrofunc)element_getattro, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + element_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)element_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + element_new, /* tp_new */ + 0, /* tp_free */ }; /* ==================================================================== */ @@ -1666,7 +1727,7 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag, self->data = NULL; } - node = element_new(tag, attrib); + node = create_new_element(tag, attrib); if (!node) return NULL; @@ -2801,7 +2862,6 @@ static PyTypeObject XMLParser_Type = { /* python module interface */ static PyMethodDef _functions[] = { - {"Element", (PyCFunction) element, METH_VARARGS|METH_KEYWORDS}, {"SubElement", (PyCFunction) subelement, METH_VARARGS|METH_KEYWORDS}, {"TreeBuilder", (PyCFunction) treebuilder, METH_VARARGS}, #if defined(USE_EXPAT) @@ -2911,5 +2971,8 @@ PyInit__elementtree(void) Py_INCREF(elementtree_parseerror_obj); PyModule_AddObject(m, "ParseError", elementtree_parseerror_obj); + Py_INCREF((PyObject *)&Element_Type); + PyModule_AddObject(m, "Element", (PyObject *)&Element_Type); + return m; } -- cgit v1.2.1 From f566fc64bc29e7e3b3992a3ce47fde7b2a99d885 Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Mon, 5 Mar 2012 10:28:42 +0100 Subject: Issue #14007: drop unused TreeBuilder().xml. --- Modules/_elementtree.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 179cadc5f5..348fefcf52 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1698,13 +1698,6 @@ treebuilder_dealloc(TreeBuilderObject* self) /* -------------------------------------------------------------------- */ /* handlers */ -LOCAL(PyObject*) -treebuilder_handle_xml(TreeBuilderObject* self, PyObject* encoding, - PyObject* standalone) -{ - Py_RETURN_NONE; -} - LOCAL(PyObject*) treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag, PyObject* attrib) @@ -1976,22 +1969,10 @@ treebuilder_start(TreeBuilderObject* self, PyObject* args) return treebuilder_handle_start(self, tag, attrib); } -static PyObject* -treebuilder_xml(TreeBuilderObject* self, PyObject* args) -{ - PyObject* encoding; - PyObject* standalone; - if (!PyArg_ParseTuple(args, "OO:xml", &encoding, &standalone)) - return NULL; - - return treebuilder_handle_xml(self, encoding, standalone); -} - static PyMethodDef treebuilder_methods[] = { {"data", (PyCFunction) treebuilder_data, METH_VARARGS}, {"start", (PyCFunction) treebuilder_start, METH_VARARGS}, {"end", (PyCFunction) treebuilder_end, METH_VARARGS}, - {"xml", (PyCFunction) treebuilder_xml, METH_VARARGS}, {"close", (PyCFunction) treebuilder_close, METH_VARARGS}, {NULL, NULL} }; @@ -2052,8 +2033,6 @@ typedef struct { PyObject* names; - PyObject* handle_xml; - PyObject* handle_start; PyObject* handle_data; PyObject* handle_end; @@ -2506,7 +2485,6 @@ xmlparser(PyObject* self_, PyObject* args, PyObject* kw) Py_INCREF(target); self->target = target; - self->handle_xml = PyObject_GetAttrString(target, "xml"); self->handle_start = PyObject_GetAttrString(target, "start"); self->handle_data = PyObject_GetAttrString(target, "data"); self->handle_end = PyObject_GetAttrString(target, "end"); @@ -2562,7 +2540,6 @@ xmlparser_dealloc(XMLParserObject* self) Py_XDECREF(self->handle_end); Py_XDECREF(self->handle_data); Py_XDECREF(self->handle_start); - Py_XDECREF(self->handle_xml); Py_DECREF(self->target); Py_DECREF(self->entity); -- cgit v1.2.1 From e7bfd30fdd62cec6b77f0a2a24b78cd34bcddb79 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 9 Mar 2012 13:38:15 +0200 Subject: Issue #14178: Problem deleting slices with steps != +1 in the _elementtree module. Fixed the problem and added some tests. Closes #14178 --- Modules/_elementtree.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 3 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 348fefcf52..ba37cd7b7a 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1343,9 +1343,74 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) return -1; } - if (value == NULL) - newlen = 0; + if (value == NULL) { + /* Delete slice */ + size_t cur; + Py_ssize_t i; + + if (slicelen <= 0) + return 0; + + /* Since we're deleting, the direction of the range doesn't matter, + * so for simplicity make it always ascending. + */ + if (step < 0) { + stop = start + 1; + start = stop + step * (slicelen - 1) - 1; + step = -step; + } + + assert((size_t)slicelen <= PY_SIZE_MAX / sizeof(PyObject *)); + + /* recycle is a list that will contain all the children + * scheduled for removal. + */ + if (!(recycle = PyList_New(slicelen))) { + PyErr_NoMemory(); + return -1; + } + + /* This loop walks over all the children that have to be deleted, + * with cur pointing at them. num_moved is the amount of children + * until the next deleted child that have to be "shifted down" to + * occupy the deleted's places. + * Note that in the ith iteration, shifting is done i+i places down + * because i children were already removed. + */ + for (cur = start, i = 0; cur < (size_t)stop; cur += step, ++i) { + /* Compute how many children have to be moved, clipping at the + * list end. + */ + Py_ssize_t num_moved = step - 1; + if (cur + step >= (size_t)self->extra->length) { + num_moved = self->extra->length - cur - 1; + } + + PyList_SET_ITEM(recycle, i, self->extra->children[cur]); + + memmove( + self->extra->children + cur - i, + self->extra->children + cur + 1, + num_moved * sizeof(PyObject *)); + } + + /* Leftover "tail" after the last removed child */ + cur = start + (size_t)slicelen * step; + if (cur < (size_t)self->extra->length) { + memmove( + self->extra->children + cur - slicelen, + self->extra->children + cur, + (self->extra->length - cur) * sizeof(PyObject *)); + } + + self->extra->length -= slicelen; + + /* Discard the recycle list with all the deleted sub-elements */ + Py_XDECREF(recycle); + return 0; + } else { + /* A new slice is actually being assigned */ seq = PySequence_Fast(value, ""); if (!seq) { PyErr_Format( @@ -1367,7 +1432,6 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) return -1; } - /* Resize before creating the recycle bin, to prevent refleaks. */ if (newlen > slicelen) { if (element_resize(self, newlen - slicelen) < 0) { -- cgit v1.2.1 From 5fabaff437959bae74a0d995567c582fca68155a Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 16 Mar 2012 05:53:30 +0200 Subject: Closes Issue #14246: _elementtree parser will now handle io.StringIO --- Modules/_elementtree.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index ba37cd7b7a..99935b92dc 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2682,6 +2682,7 @@ xmlparser_parse(XMLParserObject* self, PyObject* args) PyObject* reader; PyObject* buffer; + PyObject* temp; PyObject* res; PyObject* fileobj; @@ -2703,7 +2704,27 @@ xmlparser_parse(XMLParserObject* self, PyObject* args) return NULL; } - if (!PyBytes_CheckExact(buffer) || PyBytes_GET_SIZE(buffer) == 0) { + if (PyUnicode_CheckExact(buffer)) { + /* A unicode object is encoded into bytes using UTF-8 */ + if (PyUnicode_GET_SIZE(buffer) == 0) { + Py_DECREF(buffer); + break; + } + temp = PyUnicode_AsEncodedString(buffer, "utf-8", "surrogatepass"); + if (!temp) { + /* Propagate exception from PyUnicode_AsEncodedString */ + Py_DECREF(buffer); + Py_DECREF(reader); + return NULL; + } + + /* Here we no longer need the original buffer since it contains + * unicode. Make it point to the encoded bytes object. + */ + Py_DECREF(buffer); + buffer = temp; + } + else if (!PyBytes_CheckExact(buffer) || PyBytes_GET_SIZE(buffer) == 0) { Py_DECREF(buffer); break; } -- cgit v1.2.1 From 04ba98f530598717a5883a8fd5ffb0d3c9fe4a17 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 16 Mar 2012 08:20:05 +0200 Subject: 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. --- Modules/_elementtree.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 99935b92dc..a50a3e7a67 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2177,13 +2177,18 @@ makeuniversal(XMLParserObject* self, const char* string) 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 @@ expat_set_error(const char* message, int line, int column) 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 @@ expat_default_handler(XMLParserObject* self, const XML_Char* data_in, 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 @@ expat_parse(XMLParserObject* self, char* data, int data_len, int final) 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; } -- cgit v1.2.1 From 01cc0764da1665cefdb4ba815ab0d31821f91d27 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 23 Mar 2012 14:24:20 +0200 Subject: Issue #13782: streamline argument type-checking in ET.Element append, extend and insert now consistently type-check their argument in both the C and Python implementations, and raise TypeError for non-Element argument. Added tests --- Modules/_elementtree.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index a50a3e7a67..e8309df299 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -803,6 +803,15 @@ element_extend(ElementObject* self, PyObject* args) seqlen = PySequence_Size(seq); for (i = 0; i < seqlen; i++) { PyObject* element = PySequence_Fast_GET_ITEM(seq, i); + if (!PyObject_IsInstance(element, (PyObject *)&Element_Type)) { + Py_DECREF(seq); + PyErr_Format( + PyExc_TypeError, + "expected an Element, not \"%.200s\"", + Py_TYPE(element)->tp_name); + return NULL; + } + if (element_add_subelement(self, element) < 0) { Py_DECREF(seq); return NULL; -- cgit v1.2.1 From a790ee3890bccd3dab9765365a4ed084925a9a27 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 30 Mar 2012 16:38:33 +0300 Subject: Issue #14065: Added cyclic GC support to ET.Element --- Modules/_elementtree.c | 63 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 15 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index e8309df299..a9da3ec181 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -282,7 +282,7 @@ create_new_element(PyObject* tag, PyObject* attrib) { ElementObject* self; - self = PyObject_New(ElementObject, &Element_Type); + self = PyObject_GC_New(ElementObject, &Element_Type); if (self == NULL) return NULL; @@ -309,7 +309,7 @@ create_new_element(PyObject* tag, PyObject* attrib) self->tail = Py_None; ALLOC(sizeof(ElementObject), "create element"); - + PyObject_GC_Track(self); return (PyObject*) self; } @@ -556,19 +556,51 @@ subelement(PyObject* self, PyObject* args, PyObject* kw) return elem; } -static void -element_dealloc(ElementObject* self) +static int +element_gc_traverse(ElementObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->tag); + Py_VISIT(JOIN_OBJ(self->text)); + Py_VISIT(JOIN_OBJ(self->tail)); + + if (self->extra) { + int i; + Py_VISIT(self->extra->attrib); + + for (i = 0; i < self->extra->length; ++i) + Py_VISIT(self->extra->children[i]); + } + return 0; +} + +static int +element_gc_clear(ElementObject *self) { - if (self->extra) + PyObject *text = JOIN_OBJ(self->text); + PyObject *tail = JOIN_OBJ(self->tail); + Py_CLEAR(self->tag); + Py_CLEAR(text); + Py_CLEAR(tail); + + /* After dropping all references from extra, it's no longer valid anyway, + ** so fully deallocate it (see also element_clearmethod) + */ + if (self->extra) { dealloc_extra(self); + self->extra = NULL; + } + return 0; +} - /* discard attributes */ - Py_DECREF(self->tag); - Py_DECREF(JOIN_OBJ(self->text)); - Py_DECREF(JOIN_OBJ(self->tail)); +static void +element_dealloc(ElementObject* self) +{ + PyObject_GC_UnTrack(self); + /* element_gc_clear clears all references and deallocates extra + */ + element_gc_clear(self); RELEASE(sizeof(ElementObject), "destroy element"); - Py_TYPE(self)->tp_free((PyObject *)self); } @@ -589,7 +621,7 @@ element_append(ElementObject* self, PyObject* args) } static PyObject* -element_clear(ElementObject* self, PyObject* args) +element_clearmethod(ElementObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, ":clear")) return NULL; @@ -1505,7 +1537,7 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) static PyMethodDef element_methods[] = { - {"clear", (PyCFunction) element_clear, METH_VARARGS}, + {"clear", (PyCFunction) element_clearmethod, METH_VARARGS}, {"get", (PyCFunction) element_get, METH_VARARGS}, {"set", (PyCFunction) element_set, METH_VARARGS}, @@ -1655,10 +1687,11 @@ static PyTypeObject Element_Type = { (getattrofunc)element_getattro, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + /* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)element_gc_traverse, /* tp_traverse */ + (inquiry)element_gc_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ -- cgit v1.2.1 From 9a6f60bb6ddda49f5b358a6a69d1c3411dfecc83 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Tue, 3 Apr 2012 22:02:37 +0300 Subject: Fixes and enhancements to _elementtree: * Fixed refleak problems when GC collection is run (see messages in issue #14065) * Added weakref support to Element objects --- Modules/_elementtree.c | 65 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 21 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index a9da3ec181..5425269c1a 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -48,6 +48,7 @@ /* See http://www.python.org/psf/license for licensing details. */ #include "Python.h" +#include "structmember.h" #define VERSION "1.0.6" @@ -229,6 +230,8 @@ typedef struct { ElementObjectExtra* extra; + PyObject *weakreflist; /* For tp_weaklistoffset */ + } ElementObject; static PyTypeObject Element_Type; @@ -261,17 +264,24 @@ create_extra(ElementObject* self, PyObject* attrib) LOCAL(void) dealloc_extra(ElementObject* self) { - int i; + if (!self->extra) + return; + + /* Avoid DECREFs calling into this code again (cycles, etc.) + */ + ElementObjectExtra *myextra = self->extra; + self->extra = NULL; - Py_DECREF(self->extra->attrib); + Py_DECREF(myextra->attrib); - for (i = 0; i < self->extra->length; i++) - Py_DECREF(self->extra->children[i]); + int i; + for (i = 0; i < myextra->length; i++) + Py_DECREF(myextra->children[i]); - if (self->extra->children != self->extra->_children) - PyObject_Free(self->extra->children); + if (myextra->children != myextra->_children) + PyObject_Free(myextra->children); - PyObject_Free(self->extra); + PyObject_Free(myextra); } /* Convenience internal function to create new Element objects with the given @@ -308,6 +318,8 @@ create_new_element(PyObject* tag, PyObject* attrib) Py_INCREF(Py_None); self->tail = Py_None; + self->weakreflist = NULL; + ALLOC(sizeof(ElementObject), "create element"); PyObject_GC_Track(self); return (PyObject*) self; @@ -328,6 +340,7 @@ element_new(PyTypeObject *type, PyObject *args, PyObject *kwds) e->tail = Py_None; e->extra = NULL; + e->weakreflist = NULL; } return (PyObject *)e; } @@ -576,19 +589,28 @@ element_gc_traverse(ElementObject *self, visitproc visit, void *arg) static int element_gc_clear(ElementObject *self) { - PyObject *text = JOIN_OBJ(self->text); - PyObject *tail = JOIN_OBJ(self->tail); Py_CLEAR(self->tag); - Py_CLEAR(text); - Py_CLEAR(tail); - /* After dropping all references from extra, it's no longer valid anyway, - ** so fully deallocate it (see also element_clearmethod) + /* The following is like Py_CLEAR for self->text and self->tail, but + * written explicitily because the real pointers hide behind access + * macros. */ - if (self->extra) { - dealloc_extra(self); - self->extra = NULL; + if (self->text) { + PyObject *tmp = JOIN_OBJ(self->text); + self->text = NULL; + Py_DECREF(tmp); + } + + if (self->tail) { + PyObject *tmp = JOIN_OBJ(self->tail); + self->tail = NULL; + Py_DECREF(tmp); } + + /* After dropping all references from extra, it's no longer valid anyway, + * so fully deallocate it. + */ + dealloc_extra(self); return 0; } @@ -596,6 +618,10 @@ static void element_dealloc(ElementObject* self) { PyObject_GC_UnTrack(self); + + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) self); + /* element_gc_clear clears all references and deallocates extra */ element_gc_clear(self); @@ -626,10 +652,7 @@ element_clearmethod(ElementObject* self, PyObject* args) if (!PyArg_ParseTuple(args, ":clear")) return NULL; - if (self->extra) { - dealloc_extra(self); - self->extra = NULL; - } + dealloc_extra(self); Py_INCREF(Py_None); Py_DECREF(JOIN_OBJ(self->text)); @@ -1693,7 +1716,7 @@ static PyTypeObject Element_Type = { (traverseproc)element_gc_traverse, /* tp_traverse */ (inquiry)element_gc_clear, /* tp_clear */ 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + offsetof(ElementObject, weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ element_methods, /* tp_methods */ -- cgit v1.2.1 From c80aa4aa2dd0be5e07d68842c961217a379921fd Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Wed, 4 Apr 2012 15:55:07 +0300 Subject: Fix Windows compilation errors --- Modules/_elementtree.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 5425269c1a..c5bbc80868 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -264,17 +264,19 @@ create_extra(ElementObject* self, PyObject* attrib) LOCAL(void) dealloc_extra(ElementObject* self) { + ElementObjectExtra *myextra; + int i; + if (!self->extra) return; /* Avoid DECREFs calling into this code again (cycles, etc.) */ - ElementObjectExtra *myextra = self->extra; + myextra = self->extra; self->extra = NULL; Py_DECREF(myextra->attrib); - int i; for (i = 0; i < myextra->length; i++) Py_DECREF(myextra->children[i]); -- cgit v1.2.1 From c120a396ad497f8d39b404dcb6c32b2655f0aed9 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Thu, 5 Apr 2012 05:40:58 +0300 Subject: Replace bootstrap imports with real C API calls. --- Modules/_elementtree.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'Modules/_elementtree.c') diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index c5bbc80868..42634977da 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -3034,8 +3034,7 @@ static struct PyModuleDef _elementtreemodule = { PyMODINIT_FUNC PyInit__elementtree(void) { - PyObject* m; - PyObject* g; + PyObject *m, *g, *temp; char* bootstrap; /* Initialize object types */ @@ -3067,10 +3066,6 @@ PyInit__elementtree(void) PyDict_SetItemString(g, "__builtins__", PyEval_GetBuiltins()); bootstrap = ( - - "from copy import deepcopy\n" - "from xml.etree import ElementPath\n" - "def iter(node, tag=None):\n" /* helper */ " if tag == '*':\n" " tag = None\n" @@ -3094,8 +3089,14 @@ PyInit__elementtree(void) if (!PyRun_String(bootstrap, Py_file_input, g, NULL)) return NULL; - elementpath_obj = PyDict_GetItemString(g, "ElementPath"); - elementtree_deepcopy_obj = PyDict_GetItemString(g, "deepcopy"); + if (!(temp = PyImport_ImportModule("copy"))) + return NULL; + elementtree_deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy"); + Py_XDECREF(temp); + + if (!(elementpath_obj = PyImport_ImportModule("xml.etree.ElementPath"))) + return NULL; + elementtree_iter_obj = PyDict_GetItemString(g, "iter"); elementtree_itertext_obj = PyDict_GetItemString(g, "itertext"); -- cgit v1.2.1