diff options
author | Florent Xicluna <florent.xicluna@gmail.com> | 2012-02-11 10:28:16 (GMT) |
---|---|---|
committer | Florent Xicluna <florent.xicluna@gmail.com> | 2012-02-11 10:28:16 (GMT) |
commit | f4bdf4e478adc3f7c0ec54e60bb3359f51058722 (patch) | |
tree | 90798a7497fa0f406fe6885b7b8c9950a890790b | |
parent | 44fb613816f2e0e9fc4388ef80603fa9ae35de4f (diff) | |
download | cpython-f4bdf4e478adc3f7c0ec54e60bb3359f51058722.zip cpython-f4bdf4e478adc3f7c0ec54e60bb3359f51058722.tar.gz cpython-f4bdf4e478adc3f7c0ec54e60bb3359f51058722.tar.bz2 |
Issue #13988: move the python bootstrap code to cElementTree.py, and remove obsolete code for Python 2.4 and 2.5.
-rw-r--r-- | Lib/xml/etree/cElementTree.py | 150 | ||||
-rw-r--r-- | Modules/_elementtree.c | 234 |
2 files changed, 152 insertions, 232 deletions
diff --git a/Lib/xml/etree/cElementTree.py b/Lib/xml/etree/cElementTree.py index a6f127a..aaef59e 100644 --- a/Lib/xml/etree/cElementTree.py +++ b/Lib/xml/etree/cElementTree.py @@ -1,3 +1,153 @@ # Wrapper module for _elementtree +from xml.etree.ElementTree import (ElementTree, dump, iselement, QName, + fromstringlist, + tostring, tostringlist, VERSION) +# These ones are not in ElementTree.__all__ +from xml.etree.ElementTree import ElementPath, register_namespace + +# Import the C accelerators: +# Element, SubElement, TreeBuilder, XMLParser, ParseError from _elementtree import * + + +class ElementTree(ElementTree): + + def parse(self, source, parser=None): + close_source = False + if not hasattr(source, 'read'): + source = open(source, 'rb') + close_source = True + try: + if parser is not None: + while True: + data = source.read(65536) + if not data: + break + parser.feed(data) + self._root = parser.close() + else: + parser = XMLParser() + self._root = parser._parse(source) + return self._root + finally: + if close_source: + source.close() + + +class iterparse: + root = None + + def __init__(self, file, events=None): + self._close_file = False + if not hasattr(file, 'read'): + file = open(file, 'rb') + self._close_file = True + self._file = file + self._events = [] + self._index = 0 + self._error = None + self.root = self._root = None + b = TreeBuilder() + self._parser = XMLParser(b) + self._parser._setevents(self._events, events) + + def __next__(self): + while True: + try: + item = self._events[self._index] + self._index += 1 + return item + except IndexError: + pass + if self._error: + e = self._error + self._error = None + raise e + if self._parser is None: + self.root = self._root + if self._close_file: + self._file.close() + raise StopIteration + # load event buffer + del self._events[:] + self._index = 0 + data = self._file.read(16384) + if data: + try: + self._parser.feed(data) + except SyntaxError as exc: + self._error = exc + else: + self._root = self._parser.close() + self._parser = None + + def __iter__(self): + return self + + +# ============================================================================= +# +# Everything below this line can be removed +# after cElementTree is folded behind ElementTree. +# +# ============================================================================= + +from xml.etree.ElementTree import Comment as _Comment, PI as _PI + + +def parse(source, parser=None): + tree = ElementTree() + tree.parse(source, parser) + return tree + + +def XML(text, parser=None): + if not parser: + parser = XMLParser() + parser = XMLParser() + parser.feed(text) + return parser.close() + + +def XMLID(text, parser=None): + tree = XML(text, parser=parser) + ids = {} + for elem in tree.iter(): + id = elem.get('id') + if id: + ids[id] = elem + return tree, ids + + +class CommentProxy: + + def __call__(self, text=None): + element = Element(_Comment) + element.text = text + return element + + def __eq__(self, other): + return _Comment == other + + +class PIProxy: + + def __call__(self, target, text=None): + element = Element(_PI) + element.text = target + if text: + element.text = element.text + ' ' + text + return element + + def __eq__(self, other): + return _PI == other + + +Comment = CommentProxy() +PI = ProcessingInstruction = PIProxy() +del CommentProxy, PIProxy + +# Aliases +fromstring = XML +XMLTreeBuilder = XMLParser diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 884e50d..af7661e 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; @@ -1128,31 +1108,6 @@ element_makeelement(PyObject* self, PyObject* args, PyObject* kw) } 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) { int i; @@ -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"); |