Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a72a98f

Browse files
committed
Issue #13988: cElementTree is deprecated and the _elementtree accelerator is automatically used whenever available.
1 parent d1c7b1a commit a72a98f

8 files changed

Lines changed: 133 additions & 203 deletions

File tree

Doc/library/xml.etree.elementtree.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,18 @@ To create an element instance, use the :class:`Element` constructor or the
3232
The :class:`ElementTree` class can be used to wrap an element structure, and
3333
convert it from and to XML.
3434

35-
A C implementation of this API is available as :mod:`xml.etree.cElementTree`.
36-
3735
See http://effbot.org/zone/element-index.htm for tutorials and links to other
38-
docs. Fredrik Lundh's page is also the location of the development version of
39-
the xml.etree.ElementTree.
36+
docs.
4037

4138
.. versionchanged:: 3.2
4239
The ElementTree API is updated to 1.3. For more information, see
4340
`Introducing ElementTree 1.3
4441
<http://effbot.org/zone/elementtree-13-intro.htm>`_.
4542

43+
.. versionchanged:: 3.3
44+
This module will use a fast implementation whenever available.
45+
The :mod:`xml.etree.cElementTree` module is deprecated.
46+
4647

4748
.. _elementtree-functions:
4849

Doc/whatsnew/3.3.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,8 @@ Deprecated Python modules, functions and methods
842842
* :issue:`13374`: The Windows bytes API has been deprecated in the :mod:`os`
843843
module. Use Unicode filenames, instead of bytes filenames, to not depend on
844844
the ANSI code page anymore and to support any filename.
845+
* :issue:`13988`: The :mod:`xml.etree.cElementTree` module is deprecated. The
846+
accelerator is used automatically whenever available.
845847

846848

847849
Deprecated functions and types of the C API

Lib/test/test_xml_etree.py

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
import unittest
1717

1818
from test import support
19-
from test.support import findfile
19+
from test.support import findfile, import_fresh_module
2020

21-
from xml.etree import ElementTree as ET
21+
pyET = import_fresh_module('xml.etree.ElementTree', blocked=['_elementtree'])
2222

2323
SIMPLE_XMLFILE = findfile("simple.xml", subdir="xmltestdata")
2424
try:
@@ -275,7 +275,7 @@ def simplefind():
275275
"""
276276
Test find methods using the elementpath fallback.
277277
278-
>>> from xml.etree import ElementTree
278+
>>> ElementTree = pyET
279279
280280
>>> CurrentElementPath = ElementTree.ElementPath
281281
>>> ElementTree.ElementPath = ElementTree._SimpleElementPath()
@@ -460,17 +460,19 @@ def path_cache():
460460
"""
461461
Check that the path cache behaves sanely.
462462
463+
>>> from xml.etree import ElementPath
464+
463465
>>> elem = ET.XML(SAMPLE_XML)
464466
>>> for i in range(10): ET.ElementTree(elem).find('./'+str(i))
465-
>>> cache_len_10 = len(ET.ElementPath._cache)
467+
>>> cache_len_10 = len(ElementPath._cache)
466468
>>> for i in range(10): ET.ElementTree(elem).find('./'+str(i))
467-
>>> len(ET.ElementPath._cache) == cache_len_10
469+
>>> len(ElementPath._cache) == cache_len_10
468470
True
469471
>>> for i in range(20): ET.ElementTree(elem).find('./'+str(i))
470-
>>> len(ET.ElementPath._cache) > cache_len_10
472+
>>> len(ElementPath._cache) > cache_len_10
471473
True
472474
>>> for i in range(600): ET.ElementTree(elem).find('./'+str(i))
473-
>>> len(ET.ElementPath._cache) < 500
475+
>>> len(ElementPath._cache) < 500
474476
True
475477
"""
476478

@@ -1879,37 +1881,38 @@ def __init__(self, quiet=False):
18791881
self.checkwarnings = support.check_warnings(*deprecations, quiet=quiet)
18801882

18811883
def __enter__(self):
1882-
from xml.etree import ElementTree
1883-
self._nsmap = ElementTree._namespace_map
1884-
self._path_cache = ElementTree.ElementPath._cache
1884+
from xml.etree import ElementPath
1885+
if hasattr(ET, '_namespace_map'):
1886+
self._nsmap = ET._namespace_map
1887+
else:
1888+
# when testing the cElementTree alias
1889+
from xml.etree.ElementTree import _namespace_map
1890+
self._nsmap = _namespace_map
18851891
# Copy the default namespace mapping
1886-
ElementTree._namespace_map = self._nsmap.copy()
1892+
self._nsmap_copy = self._nsmap.copy()
18871893
# Copy the path cache (should be empty)
1888-
ElementTree.ElementPath._cache = self._path_cache.copy()
1894+
self._path_cache = ElementPath._cache
1895+
ElementPath._cache = self._path_cache.copy()
18891896
self.checkwarnings.__enter__()
18901897

18911898
def __exit__(self, *args):
1892-
from xml.etree import ElementTree
1899+
from xml.etree import ElementPath
18931900
# Restore mapping and path cache
1894-
ElementTree._namespace_map = self._nsmap
1895-
ElementTree.ElementPath._cache = self._path_cache
1901+
self._nsmap.clear()
1902+
self._nsmap.update(self._nsmap_copy)
1903+
ElementPath._cache = self._path_cache
18961904
self.checkwarnings.__exit__(*args)
18971905

18981906

1899-
def test_main(module_name='xml.etree.ElementTree'):
1907+
def test_main(module=pyET):
19001908
from test import test_xml_etree
19011909

1902-
use_py_module = (module_name == 'xml.etree.ElementTree')
1903-
19041910
# The same doctests are used for both the Python and the C implementations
1905-
assert test_xml_etree.ET.__name__ == module_name
1911+
test_xml_etree.ET = module
19061912

19071913
# XXX the C module should give the same warnings as the Python module
1908-
with CleanContext(quiet=not use_py_module):
1914+
with CleanContext(quiet=(module is not pyET)):
19091915
support.run_doctest(test_xml_etree, verbosity=True)
19101916

1911-
# The module should not be changed by the tests
1912-
assert test_xml_etree.ET.__name__ == module_name
1913-
19141917
if __name__ == '__main__':
19151918
test_main()

Lib/test/test_xml_etree_c.py

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
# xml.etree test for cElementTree
22

33
from test import support
4-
from test.support import bigmemtest, _2G
54
import unittest
65

7-
cET = support.import_module('xml.etree.cElementTree')
6+
from xml.etree import ElementTree as cET, cElementTree as cET_alias
87

98

109
# cElementTree specific tests
@@ -13,10 +12,9 @@ def sanity():
1312
r"""
1413
Import sanity.
1514
16-
>>> from xml.etree import cElementTree
17-
1815
Issue #6697.
1916
17+
>>> cElementTree = cET
2018
>>> e = cElementTree.Element('a')
2119
>>> getattr(e, '\uD800') # doctest: +ELLIPSIS
2220
Traceback (most recent call last):
@@ -55,19 +53,10 @@ def test_main():
5553

5654
support.run_unittest(MiscTests)
5755

58-
# Assign the C implementation before running the doctests
59-
# Patch the __name__, to prevent confusion with the pure Python test
60-
pyET = test_xml_etree.ET
61-
py__name__ = test_xml_etree.__name__
62-
test_xml_etree.ET = cET
63-
if __name__ != '__main__':
64-
test_xml_etree.__name__ = __name__
65-
try:
66-
# Run the same test suite as xml.etree.ElementTree
67-
test_xml_etree.test_main(module_name='xml.etree.cElementTree')
68-
finally:
69-
test_xml_etree.ET = pyET
70-
test_xml_etree.__name__ = py__name__
56+
# Run the same test suite as the Python module
57+
test_xml_etree.test_main(module=cET)
58+
# Exercise the deprecated alias
59+
test_xml_etree.test_main(module=cET_alias)
7160

7261
if __name__ == '__main__':
7362
test_main()

Lib/xml/etree/ElementTree.py

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,9 @@
6868
"tostring", "tostringlist",
6969
"TreeBuilder",
7070
"VERSION",
71-
"XML",
71+
"XML", "XMLID",
7272
"XMLParser", "XMLTreeBuilder",
73+
"register_namespace",
7374
]
7475

7576
VERSION = "1.3.0"
@@ -148,9 +149,9 @@ class ParseError(SyntaxError):
148149
# @defreturn flag
149150

150151
def iselement(element):
151-
# FIXME: not sure about this; might be a better idea to look
152-
# for tag/attrib/text attributes
153-
return isinstance(element, Element) or hasattr(element, "tag")
152+
# FIXME: not sure about this;
153+
# isinstance(element, Element) or look for tag/attrib/text attributes
154+
return hasattr(element, 'tag')
154155

155156
##
156157
# Element class. This class defines the Element interface, and
@@ -1684,6 +1685,87 @@ def close(self):
16841685
del self.target, self._parser # get rid of circular references
16851686
return tree
16861687

1688+
1689+
# Import the C accelerators
1690+
try:
1691+
# Element, SubElement, ParseError, TreeBuilder, XMLParser
1692+
from _elementtree import *
1693+
except ImportError:
1694+
pass
1695+
else:
1696+
# Overwrite 'ElementTree.parse' and 'iterparse' to use the C XMLParser
1697+
1698+
class ElementTree(ElementTree):
1699+
def parse(self, source, parser=None):
1700+
close_source = False
1701+
if not hasattr(source, 'read'):
1702+
source = open(source, 'rb')
1703+
close_source = True
1704+
try:
1705+
if parser is not None:
1706+
while True:
1707+
data = source.read(65536)
1708+
if not data:
1709+
break
1710+
parser.feed(data)
1711+
self._root = parser.close()
1712+
else:
1713+
parser = XMLParser()
1714+
self._root = parser._parse(source)
1715+
return self._root
1716+
finally:
1717+
if close_source:
1718+
source.close()
1719+
1720+
class iterparse:
1721+
root = None
1722+
def __init__(self, file, events=None):
1723+
self._close_file = False
1724+
if not hasattr(file, 'read'):
1725+
file = open(file, 'rb')
1726+
self._close_file = True
1727+
self._file = file
1728+
self._events = []
1729+
self._index = 0
1730+
self._error = None
1731+
self.root = self._root = None
1732+
b = TreeBuilder()
1733+
self._parser = XMLParser(b)
1734+
self._parser._setevents(self._events, events)
1735+
1736+
def __next__(self):
1737+
while True:
1738+
try:
1739+
item = self._events[self._index]
1740+
self._index += 1
1741+
return item
1742+
except IndexError:
1743+
pass
1744+
if self._error:
1745+
e = self._error
1746+
self._error = None
1747+
raise e
1748+
if self._parser is None:
1749+
self.root = self._root
1750+
if self._close_file:
1751+
self._file.close()
1752+
raise StopIteration
1753+
# load event buffer
1754+
del self._events[:]
1755+
self._index = 0
1756+
data = self._file.read(16384)
1757+
if data:
1758+
try:
1759+
self._parser.feed(data)
1760+
except SyntaxError as exc:
1761+
self._error = exc
1762+
else:
1763+
self._root = self._parser.close()
1764+
self._parser = None
1765+
1766+
def __iter__(self):
1767+
return self
1768+
16871769
# compatibility
16881770
XMLTreeBuilder = XMLParser
16891771

0 commit comments

Comments
 (0)