mirror of
https://github.com/python/cpython.git
synced 2025-11-02 03:01:58 +00:00
bpo-36673: Implement comment/PI parsing support for the TreeBuilder in ElementTree. (#12883)
* bpo-36673: Implement comment/PI parsing support for the TreeBuilder in ElementTree. * bpo-36673: Rewrite the comment/PI factory handling for the TreeBuilder in "_elementtree" to make it use the same factories as the ElementTree module, and to make it explicit when the comments/PIs are inserted into the tree and when they are not (which is the default).
This commit is contained in:
parent
3d37ea25dc
commit
43851a202c
6 changed files with 630 additions and 54 deletions
|
|
@ -1194,6 +1194,12 @@ class XMLPullParserTest(unittest.TestCase):
|
|||
for i in range(0, len(data), chunk_size):
|
||||
parser.feed(data[i:i+chunk_size])
|
||||
|
||||
def assert_events(self, parser, expected):
|
||||
self.assertEqual(
|
||||
[(event, (elem.tag, elem.text))
|
||||
for event, elem in parser.read_events()],
|
||||
expected)
|
||||
|
||||
def assert_event_tags(self, parser, expected):
|
||||
events = parser.read_events()
|
||||
self.assertEqual([(action, elem.tag) for action, elem in events],
|
||||
|
|
@ -1276,8 +1282,10 @@ class XMLPullParserTest(unittest.TestCase):
|
|||
self.assert_event_tags(parser, [])
|
||||
|
||||
parser = ET.XMLPullParser(events=('start', 'end'))
|
||||
self._feed(parser, "<!-- comment -->\n")
|
||||
self.assert_event_tags(parser, [])
|
||||
self._feed(parser, "<!-- text here -->\n")
|
||||
self.assert_events(parser, [])
|
||||
|
||||
parser = ET.XMLPullParser(events=('start', 'end'))
|
||||
self._feed(parser, "<root>\n")
|
||||
self.assert_event_tags(parser, [('start', 'root')])
|
||||
self._feed(parser, "<element key='value'>text</element")
|
||||
|
|
@ -1314,6 +1322,33 @@ class XMLPullParserTest(unittest.TestCase):
|
|||
self._feed(parser, "</root>")
|
||||
self.assertIsNone(parser.close())
|
||||
|
||||
def test_events_comment(self):
|
||||
parser = ET.XMLPullParser(events=('start', 'comment', 'end'))
|
||||
self._feed(parser, "<!-- text here -->\n")
|
||||
self.assert_events(parser, [('comment', (ET.Comment, ' text here '))])
|
||||
self._feed(parser, "<!-- more text here -->\n")
|
||||
self.assert_events(parser, [('comment', (ET.Comment, ' more text here '))])
|
||||
self._feed(parser, "<root-tag>text")
|
||||
self.assert_event_tags(parser, [('start', 'root-tag')])
|
||||
self._feed(parser, "<!-- inner comment-->\n")
|
||||
self.assert_events(parser, [('comment', (ET.Comment, ' inner comment'))])
|
||||
self._feed(parser, "</root-tag>\n")
|
||||
self.assert_event_tags(parser, [('end', 'root-tag')])
|
||||
self._feed(parser, "<!-- outer comment -->\n")
|
||||
self.assert_events(parser, [('comment', (ET.Comment, ' outer comment '))])
|
||||
|
||||
parser = ET.XMLPullParser(events=('comment',))
|
||||
self._feed(parser, "<!-- text here -->\n")
|
||||
self.assert_events(parser, [('comment', (ET.Comment, ' text here '))])
|
||||
|
||||
def test_events_pi(self):
|
||||
parser = ET.XMLPullParser(events=('start', 'pi', 'end'))
|
||||
self._feed(parser, "<?pitarget?>\n")
|
||||
self.assert_events(parser, [('pi', (ET.PI, 'pitarget'))])
|
||||
parser = ET.XMLPullParser(events=('pi',))
|
||||
self._feed(parser, "<?pitarget some text ?>\n")
|
||||
self.assert_events(parser, [('pi', (ET.PI, 'pitarget some text '))])
|
||||
|
||||
def test_events_sequence(self):
|
||||
# Test that events can be some sequence that's not just a tuple or list
|
||||
eventset = {'end', 'start'}
|
||||
|
|
@ -1333,7 +1368,6 @@ class XMLPullParserTest(unittest.TestCase):
|
|||
self._feed(parser, "<foo>bar</foo>")
|
||||
self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')])
|
||||
|
||||
|
||||
def test_unknown_event(self):
|
||||
with self.assertRaises(ValueError):
|
||||
ET.XMLPullParser(events=('start', 'end', 'bogus'))
|
||||
|
|
@ -2741,6 +2775,33 @@ class TreeBuilderTest(unittest.TestCase):
|
|||
parser.feed(self.sample1)
|
||||
self.assertIsNone(parser.close())
|
||||
|
||||
def test_treebuilder_comment(self):
|
||||
b = ET.TreeBuilder()
|
||||
self.assertEqual(b.comment('ctext').tag, ET.Comment)
|
||||
self.assertEqual(b.comment('ctext').text, 'ctext')
|
||||
|
||||
b = ET.TreeBuilder(comment_factory=ET.Comment)
|
||||
self.assertEqual(b.comment('ctext').tag, ET.Comment)
|
||||
self.assertEqual(b.comment('ctext').text, 'ctext')
|
||||
|
||||
b = ET.TreeBuilder(comment_factory=len)
|
||||
self.assertEqual(b.comment('ctext'), len('ctext'))
|
||||
|
||||
def test_treebuilder_pi(self):
|
||||
b = ET.TreeBuilder()
|
||||
self.assertEqual(b.pi('target', None).tag, ET.PI)
|
||||
self.assertEqual(b.pi('target', None).text, 'target')
|
||||
|
||||
b = ET.TreeBuilder(pi_factory=ET.PI)
|
||||
self.assertEqual(b.pi('target').tag, ET.PI)
|
||||
self.assertEqual(b.pi('target').text, "target")
|
||||
self.assertEqual(b.pi('pitarget', ' text ').tag, ET.PI)
|
||||
self.assertEqual(b.pi('pitarget', ' text ').text, "pitarget text ")
|
||||
|
||||
b = ET.TreeBuilder(pi_factory=lambda target, text: (len(target), text))
|
||||
self.assertEqual(b.pi('target'), (len('target'), None))
|
||||
self.assertEqual(b.pi('pitarget', ' text '), (len('pitarget'), ' text '))
|
||||
|
||||
def test_treebuilder_elementfactory_none(self):
|
||||
parser = ET.XMLParser(target=ET.TreeBuilder(element_factory=None))
|
||||
parser.feed(self.sample1)
|
||||
|
|
@ -2761,6 +2822,21 @@ class TreeBuilderTest(unittest.TestCase):
|
|||
e = parser.close()
|
||||
self._check_sample1_element(e)
|
||||
|
||||
def test_subclass_comment_pi(self):
|
||||
class MyTreeBuilder(ET.TreeBuilder):
|
||||
def foobar(self, x):
|
||||
return x * 2
|
||||
|
||||
tb = MyTreeBuilder(comment_factory=ET.Comment, pi_factory=ET.PI)
|
||||
self.assertEqual(tb.foobar(10), 20)
|
||||
|
||||
parser = ET.XMLParser(target=tb)
|
||||
parser.feed(self.sample1)
|
||||
parser.feed('<!-- a comment--><?and a pi?>')
|
||||
|
||||
e = parser.close()
|
||||
self._check_sample1_element(e)
|
||||
|
||||
def test_element_factory(self):
|
||||
lst = []
|
||||
def myfactory(tag, attrib):
|
||||
|
|
@ -3418,6 +3494,12 @@ def test_main(module=None):
|
|||
# Copy the path cache (should be empty)
|
||||
path_cache = ElementPath._cache
|
||||
ElementPath._cache = path_cache.copy()
|
||||
# Align the Comment/PI factories.
|
||||
if hasattr(ET, '_set_factories'):
|
||||
old_factories = ET._set_factories(ET.Comment, ET.PI)
|
||||
else:
|
||||
old_factories = None
|
||||
|
||||
try:
|
||||
support.run_unittest(*test_classes)
|
||||
finally:
|
||||
|
|
@ -3426,6 +3508,8 @@ def test_main(module=None):
|
|||
nsmap.clear()
|
||||
nsmap.update(nsmap_copy)
|
||||
ElementPath._cache = path_cache
|
||||
if old_factories is not None:
|
||||
ET._set_factories(*old_factories)
|
||||
# don't interfere with subsequent tests
|
||||
ET = pyET = None
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue