summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2015-12-21 09:09:48 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2015-12-21 09:09:48 (GMT)
commit66c08d90f6d7e5889a19891a0ef994354b14f172 (patch)
tree53ef527e4ce8cba37f0f0d753f666cafdbfd0cdf /Lib
parent0744641668ebf975fa41707ed7eb467c9cac2f67 (diff)
downloadcpython-66c08d90f6d7e5889a19891a0ef994354b14f172.zip
cpython-66c08d90f6d7e5889a19891a0ef994354b14f172.tar.gz
cpython-66c08d90f6d7e5889a19891a0ef994354b14f172.tar.bz2
Issue #25902: Fixed various refcount issues in ElementTree iteration.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_xml_etree.py51
-rw-r--r--Lib/xml/etree/ElementTree.py10
2 files changed, 57 insertions, 4 deletions
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index 57d8e4d..358484d 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -1666,6 +1666,57 @@ class BugsTest(unittest.TestCase):
ET.register_namespace('test10777', 'http://myuri/')
ET.register_namespace('test10777', 'http://myuri/')
+ def test_lost_text(self):
+ # Issue #25902: Borrowed text can disappear
+ class Text:
+ def __bool__(self):
+ e.text = 'changed'
+ return True
+
+ e = ET.Element('tag')
+ e.text = Text()
+ i = e.itertext()
+ t = next(i)
+ self.assertIsInstance(t, Text)
+ self.assertIsInstance(e.text, str)
+ self.assertEqual(e.text, 'changed')
+
+ def test_lost_tail(self):
+ # Issue #25902: Borrowed tail can disappear
+ class Text:
+ def __bool__(self):
+ e[0].tail = 'changed'
+ return True
+
+ e = ET.Element('root')
+ e.append(ET.Element('tag'))
+ e[0].tail = Text()
+ i = e.itertext()
+ t = next(i)
+ self.assertIsInstance(t, Text)
+ self.assertIsInstance(e[0].tail, str)
+ self.assertEqual(e[0].tail, 'changed')
+
+ def test_lost_elem(self):
+ # Issue #25902: Borrowed element can disappear
+ class Tag:
+ def __eq__(self, other):
+ e[0] = ET.Element('changed')
+ next(i)
+ return True
+
+ e = ET.Element('root')
+ e.append(ET.Element(Tag()))
+ e.append(ET.Element('tag'))
+ i = e.iter('tag')
+ try:
+ t = next(i)
+ except ValueError:
+ self.skipTest('generators are not reentrant')
+ self.assertIsInstance(t.tag, Tag)
+ self.assertIsInstance(e[0].tag, str)
+ self.assertEqual(e[0].tag, 'changed')
+
# --------------------------------------------------------------------
diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py
index 62b5d3a..b4e110d 100644
--- a/Lib/xml/etree/ElementTree.py
+++ b/Lib/xml/etree/ElementTree.py
@@ -428,12 +428,14 @@ class Element:
tag = self.tag
if not isinstance(tag, str) and tag is not None:
return
- if self.text:
- yield self.text
+ t = self.text
+ if t:
+ yield t
for e in self:
yield from e.itertext()
- if e.tail:
- yield e.tail
+ t = e.tail
+ if t:
+ yield t
def SubElement(parent, tag, attrib={}, **extra):