diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index dbdad23a742..952a4fd6060 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -6,6 +6,7 @@
# monkey-patched when running the "test_xml_etree_c" test suite.
import copy
+import functools
import html
import io
import operator
@@ -90,6 +91,16 @@ ENTITY_XML = """\
"""
+def checkwarnings(*filters, quiet=False):
+ def decorator(test):
+ def newtest(*args, **kwargs):
+ with support.check_warnings(*filters, quiet=quiet):
+ test(*args, **kwargs)
+ functools.update_wrapper(newtest, test)
+ return newtest
+ return decorator
+
+
class ModuleTest(unittest.TestCase):
def test_sanity(self):
# Import sanity.
@@ -690,6 +701,10 @@ class ElementTreeTest(unittest.TestCase):
])
+ # Element.getchildren() and ElementTree.getiterator() are deprecated.
+ @checkwarnings(("This method will be removed in future versions. "
+ "Use .+ instead.",
+ (DeprecationWarning, PendingDeprecationWarning)))
def test_getchildren(self):
# Test Element.getchildren()
@@ -1558,7 +1573,7 @@ class BugsTest(unittest.TestCase):
class EchoTarget:
def close(self):
return ET.Element("element") # simulate root
- parser = ET.XMLParser(EchoTarget())
+ parser = ET.XMLParser(target=EchoTarget())
parser.feed("some text")
self.assertEqual(parser.close().tag, 'element')
@@ -2225,8 +2240,12 @@ class ElementFindTest(unittest.TestCase):
self.assertEqual(summarize_list(ET.ElementTree(e).findall('tag')),
['tag'] * 2)
# this produces a warning
- self.assertEqual(summarize_list(ET.ElementTree(e).findall('//tag')),
- ['tag'] * 3)
+ msg = ("This search is broken in 1.3 and earlier, and will be fixed "
+ "in a future version. If you rely on the current behaviour, "
+ "change it to '.+'")
+ with self.assertWarnsRegex(FutureWarning, msg):
+ it = ET.ElementTree(e).findall('//tag')
+ self.assertEqual(summarize_list(it), ['tag'] * 3)
class ElementIterTest(unittest.TestCase):
@@ -2311,6 +2330,9 @@ class ElementIterTest(unittest.TestCase):
self.assertEqual(self._ilist(doc), all_tags)
self.assertEqual(self._ilist(doc, '*'), all_tags)
+ # Element.getiterator() is deprecated.
+ @checkwarnings(("This method will be removed in future versions. "
+ "Use .+ instead.", PendingDeprecationWarning))
def test_getiterator(self):
doc = ET.XML('''
@@ -2493,13 +2515,13 @@ class XMLParserTest(unittest.TestCase):
def test_constructor_args(self):
# Positional args. The first (html) is not supported, but should be
# nevertheless correctly accepted.
- parser = ET.XMLParser(None, ET.TreeBuilder(), 'utf-8')
+ with self.assertWarnsRegex(DeprecationWarning, r'\bhtml\b'):
+ parser = ET.XMLParser(None, ET.TreeBuilder(), 'utf-8')
parser.feed(self.sample1)
self._check_sample_element(parser.close())
# Now as keyword args.
parser2 = ET.XMLParser(encoding='utf-8',
- html=[{}],
target=ET.TreeBuilder())
parser2.feed(self.sample1)
self._check_sample_element(parser2.close())
@@ -3016,46 +3038,6 @@ class NoAcceleratorTest(unittest.TestCase):
# --------------------------------------------------------------------
-class CleanContext(object):
- """Provide default namespace mapping and path cache."""
- checkwarnings = None
-
- def __init__(self, quiet=False):
- if sys.flags.optimize >= 2:
- # under -OO, doctests cannot be run and therefore not all warnings
- # will be emitted
- quiet = True
- deprecations = (
- # Search behaviour is broken if search path starts with "/".
- ("This search is broken in 1.3 and earlier, and will be fixed "
- "in a future version. If you rely on the current behaviour, "
- "change it to '.+'", FutureWarning),
- # Element.getchildren() and Element.getiterator() are deprecated.
- ("This method will be removed in future versions. "
- "Use .+ instead.", DeprecationWarning),
- ("This method will be removed in future versions. "
- "Use .+ instead.", PendingDeprecationWarning))
- self.checkwarnings = support.check_warnings(*deprecations, quiet=quiet)
-
- def __enter__(self):
- from xml.etree import ElementPath
- self._nsmap = ET.register_namespace._namespace_map
- # Copy the default namespace mapping
- self._nsmap_copy = self._nsmap.copy()
- # Copy the path cache (should be empty)
- self._path_cache = ElementPath._cache
- ElementPath._cache = self._path_cache.copy()
- self.checkwarnings.__enter__()
-
- def __exit__(self, *args):
- from xml.etree import ElementPath
- # Restore mapping and path cache
- self._nsmap.clear()
- self._nsmap.update(self._nsmap_copy)
- ElementPath._cache = self._path_cache
- self.checkwarnings.__exit__(*args)
-
-
def test_main(module=None):
# When invoked without a module, runs the Python ET tests by loading pyET.
# Otherwise, uses the given module as the ET.
@@ -3095,11 +3077,22 @@ def test_main(module=None):
NoAcceleratorTest,
])
+ # Provide default namespace mapping and path cache.
+ from xml.etree import ElementPath
+ nsmap = ET.register_namespace._namespace_map
+ # Copy the default namespace mapping
+ nsmap_copy = nsmap.copy()
+ # Copy the path cache (should be empty)
+ path_cache = ElementPath._cache
+ ElementPath._cache = path_cache.copy()
try:
- # XXX the C module should give the same warnings as the Python module
- with CleanContext(quiet=(pyET is not ET)):
- support.run_unittest(*test_classes)
+ support.run_unittest(*test_classes)
finally:
+ from xml.etree import ElementPath
+ # Restore mapping and path cache
+ nsmap.clear()
+ nsmap.update(nsmap_copy)
+ ElementPath._cache = path_cache
# don't interfere with subsequent tests
ET = pyET = None
diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py
index 7c60699f912..171a3f88b9a 100644
--- a/Lib/test/test_xml_etree_c.py
+++ b/Lib/test/test_xml_etree_c.py
@@ -8,7 +8,8 @@ import unittest
cET = import_fresh_module('xml.etree.ElementTree',
fresh=['_elementtree'])
cET_alias = import_fresh_module('xml.etree.cElementTree',
- fresh=['_elementtree', 'xml.etree'])
+ fresh=['_elementtree', 'xml.etree'],
+ deprecated=True)
@unittest.skipUnless(cET, 'requires _elementtree')
diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py
index 735405681ff..7944cf100fa 100644
--- a/Lib/xml/etree/ElementTree.py
+++ b/Lib/xml/etree/ElementTree.py
@@ -1430,6 +1430,7 @@ class TreeBuilder:
self._tail = 1
return self._last
+_sentinel = ['sentinel']
# also see ElementTree and TreeBuilder
class XMLParser:
@@ -1443,7 +1444,11 @@ class XMLParser:
"""
- def __init__(self, html=0, target=None, encoding=None):
+ def __init__(self, html=_sentinel, target=None, encoding=None):
+ if html is not _sentinel:
+ warnings.warn(
+ "The html argument of XMLParser() is deprecated",
+ DeprecationWarning, stacklevel=2)
try:
from xml.parsers import expat
except ImportError:
diff --git a/Misc/NEWS b/Misc/NEWS
index 5fff581cfce..87b47829d71 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -298,6 +298,10 @@ Extension Modules
Library
-------
+- bpo-29204: Element.getiterator() and the html parameter of XMLParser() were
+ deprecated only in the documentation (since Python 3.2 and 3.4 correspondintly).
+ Now using them emits a deprecation warning.
+
- bpo-27863: Fixed multiple crashes in ElementTree caused by race conditions
and wrong types.
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 36aa391609f..4e1750f9dd0 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -1366,7 +1366,12 @@ _elementtree_Element_getchildren_impl(ElementObject *self)
Py_ssize_t i;
PyObject* list;
- /* FIXME: report as deprecated? */
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "This method will be removed in future versions. "
+ "Use 'list(elem)' or iteration over elem instead.",
+ 1) < 0) {
+ return NULL;
+ }
if (!self->extra)
return PyList_New(0);
@@ -1415,6 +1420,28 @@ _elementtree_Element_iter_impl(ElementObject *self, PyObject *tag)
}
+/*[clinic input]
+_elementtree.Element.getiterator
+
+ tag: object = None
+
+[clinic start generated code]*/
+
+static PyObject *
+_elementtree_Element_getiterator_impl(ElementObject *self, PyObject *tag)
+/*[clinic end generated code: output=cb69ff4a3742dfa1 input=500da1a03f7b9e28]*/
+{
+ /* Change for a DeprecationWarning in 1.4 */
+ if (PyErr_WarnEx(PyExc_PendingDeprecationWarning,
+ "This method will be removed in future versions. "
+ "Use 'tree.iter()' or 'list(tree.iter())' instead.",
+ 1) < 0) {
+ return NULL;
+ }
+ return _elementtree_Element_iter_impl(self, tag);
+}
+
+
/*[clinic input]
_elementtree.Element.itertext
@@ -3244,6 +3271,14 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *html,
PyObject *target, const char *encoding)
/*[clinic end generated code: output=d6a16c63dda54441 input=155bc5695baafffd]*/
{
+ if (html != NULL) {
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "The html argument of XMLParser() is deprecated",
+ 1) < 0) {
+ return -1;
+ }
+ }
+
self->entity = PyDict_New();
if (!self->entity)
return -1;
@@ -3716,7 +3751,7 @@ static PyMethodDef element_methods[] = {
_ELEMENTTREE_ELEMENT_ITERTEXT_METHODDEF
_ELEMENTTREE_ELEMENT_ITERFIND_METHODDEF
- {"getiterator", (PyCFunction)_elementtree_Element_iter, METH_FASTCALL, _elementtree_Element_iter__doc__},
+ _ELEMENTTREE_ELEMENT_GETITERATOR_METHODDEF
_ELEMENTTREE_ELEMENT_GETCHILDREN_METHODDEF
_ELEMENTTREE_ELEMENT_ITEMS_METHODDEF
diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h
index c13cb35c708..7d1fd1813ca 100644
--- a/Modules/clinic/_elementtree.c.h
+++ b/Modules/clinic/_elementtree.c.h
@@ -333,6 +333,35 @@ exit:
return return_value;
}
+PyDoc_STRVAR(_elementtree_Element_getiterator__doc__,
+"getiterator($self, /, tag=None)\n"
+"--\n"
+"\n");
+
+#define _ELEMENTTREE_ELEMENT_GETITERATOR_METHODDEF \
+ {"getiterator", (PyCFunction)_elementtree_Element_getiterator, METH_FASTCALL, _elementtree_Element_getiterator__doc__},
+
+static PyObject *
+_elementtree_Element_getiterator_impl(ElementObject *self, PyObject *tag);
+
+static PyObject *
+_elementtree_Element_getiterator(ElementObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"tag", NULL};
+ static _PyArg_Parser _parser = {"|O:getiterator", _keywords, 0};
+ PyObject *tag = Py_None;
+
+ if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
+ &tag)) {
+ goto exit;
+ }
+ return_value = _elementtree_Element_getiterator_impl(self, tag);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(_elementtree_Element_itertext__doc__,
"itertext($self, /)\n"
"--\n"
@@ -726,4 +755,4 @@ _elementtree_XMLParser__setevents(XMLParserObject *self, PyObject **args, Py_ssi
exit:
return return_value;
}
-/*[clinic end generated code: output=b69fa98c40917f58 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=fbc92d64735adec0 input=a9049054013a1b77]*/