[pypy-commit] pypy py3.5: Fix inconsistencies in the xml.etree.ElementTree.Element class, which on

arigo pypy.commits at gmail.com
Tue Mar 28 09:40:10 EDT 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r90841:0939e3a8a08d
Date: 2017-03-28 15:39 +0200
http://bitbucket.org/pypy/pypy/changeset/0939e3a8a08d/

Log:	Fix inconsistencies in the xml.etree.ElementTree.Element class,
	which on CPython is hidden by the C version from '_elementree'. Add
	test.

diff --git a/lib-python/3/test/test_xml_etree.py b/lib-python/3/test/test_xml_etree.py
--- a/lib-python/3/test/test_xml_etree.py
+++ b/lib-python/3/test/test_xml_etree.py
@@ -1878,6 +1878,17 @@
             with self.assertRaises(RuntimeError):
                 repr(e)  # Should not crash
 
+    def test_bad_find_returns_none(self):
+        # This behavior is the one we get historically when the C
+        # extension module is enabled.  With the Python version, it
+        # raised a TypeError instead.  There are projects out there
+        # that depend on the non-raising behavior, of course.
+        e = ET.Element('foo')
+        assert e.find('') is None
+        assert e.findall('') == []
+        assert e.findtext('') is None
+        assert e.findtext('', default="default.") == "default."
+
 class MutatingElementPath(str):
     def __new__(cls, elem, *args):
         self = str.__new__(cls, *args)
diff --git a/lib-python/3/xml/etree/ElementTree.py b/lib-python/3/xml/etree/ElementTree.py
--- a/lib-python/3/xml/etree/ElementTree.py
+++ b/lib-python/3/xml/etree/ElementTree.py
@@ -294,7 +294,14 @@
         Return the first matching element, or None if no element was found.
 
         """
-        return ElementPath.find(self, path, namespaces)
+        # Used to be:  return ElementPath.find(self, path, namespaces)
+        # but there are projects out there that rely on it getting None
+        # instead of an internal TypeError.  This is what the C version
+        # of this class does.
+        result = ElementPath.iterfind(self, path, namespaces)
+        if result is None:
+            return None
+        return next(result, None)
 
     def findtext(self, path, default=None, namespaces=None):
         """Find text for first matching element by tag name or path.
@@ -308,7 +315,17 @@
         content, the empty string is returned.
 
         """
-        return ElementPath.findtext(self, path, default, namespaces)
+        # Used to be:
+        #     return ElementPath.findtext(self, path, default, namespaces)
+        # See find().
+        result = ElementPath.iterfind(self, path, namespaces)
+        if result is None:
+            return default
+        try:
+            elem = next(result)
+            return elem.text or ""
+        except StopIteration:
+            return default
 
     def findall(self, path, namespaces=None):
         """Find all matching subelements by tag name or path.
@@ -319,7 +336,12 @@
         Returns list containing all matching elements in document order.
 
         """
-        return ElementPath.findall(self, path, namespaces)
+        # Used to be:  return ElementPath.findall(self, path, namespaces)
+        # See find().
+        result = ElementPath.iterfind(self, path, namespaces)
+        if result is None:
+            return []
+        return list(result)
 
     def iterfind(self, path, namespaces=None):
         """Find all matching subelements by tag name or path.


More information about the pypy-commit mailing list