Author: Armin Rigo <ar...@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. _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit