@@ -1656,6 +1656,43 @@ def test_unknown_events(self):
16561656 del cm
16571657 gc_collect ()
16581658
1659+ class Target :
1660+ # a target which does not build a tree
1661+ def start (self , tag , attrib ):
1662+ return tag
1663+ def end (self , tag ):
1664+ return tag
1665+ def data (self , data ):
1666+ pass
1667+
1668+ def test_target (self ):
1669+ # gh-63102: a custom target reports its own objects
1670+ with open (SIMPLE_XMLFILE , 'rb' ) as f :
1671+ it = ET .iterparse (f , events = ('start' , 'end' ), target = self .Target ())
1672+ self .assertEqual (list (it ), [
1673+ ('start' , 'root' ),
1674+ ('start' , 'element' ),
1675+ ('end' , 'element' ),
1676+ ('start' , 'element' ),
1677+ ('end' , 'element' ),
1678+ ('start' , 'empty-element' ),
1679+ ('end' , 'empty-element' ),
1680+ ('end' , 'root' ),
1681+ ])
1682+ self .assertIsNone (it .root )
1683+
1684+ def test_parser_with_target (self ):
1685+ with open (SIMPLE_XMLFILE , 'rb' ) as f :
1686+ parser = ET .XMLParser (target = self .Target ())
1687+ it = ET .iterparse (f , events = ('start' ,), parser = parser )
1688+ self .assertEqual (next (it ), ('start' , 'root' ))
1689+
1690+ def test_target_and_parser (self ):
1691+ with self .assertRaisesRegex (ValueError ,
1692+ "can't specify both parser and target" ):
1693+ ET .iterparse (SIMPLE_XMLFILE , parser = ET .XMLParser (),
1694+ target = self .Target ())
1695+
16591696 def test_non_utf8 (self ):
16601697 source = io .BytesIO (
16611698 b"<?xml version='1.0' encoding='iso-8859-1'?>\n "
@@ -2067,6 +2104,76 @@ def __next__(self):
20672104 self ._feed (parser , "<foo>bar</foo>" )
20682105 self .assert_event_tags (parser , [('start' , 'foo' ), ('end' , 'foo' )])
20692106
2107+ # gh-63102: the pull parser reports events from any target
2108+ class SimpleTarget :
2109+ def start (self , tag , attrib ):
2110+ return ('start' , tag )
2111+ def end (self , tag ):
2112+ return ('end' , tag )
2113+ def data (self , data ):
2114+ pass
2115+ def comment (self , text ):
2116+ return ('comment' , text )
2117+ def pi (self , target , data = None ):
2118+ return ('pi' , target )
2119+ def close (self ):
2120+ return 'closed'
2121+
2122+ def test_custom_target (self ):
2123+ parser = ET .XMLPullParser (events = ('start' , 'end' ),
2124+ target = self .SimpleTarget ())
2125+ self ._feed (parser , "<root><element/></root>" )
2126+ self .assert_event_tuples (parser , [
2127+ ('start' , ('start' , 'root' )),
2128+ ('start' , ('start' , 'element' )),
2129+ ('end' , ('end' , 'element' )),
2130+ ('end' , ('end' , 'root' )),
2131+ ])
2132+
2133+ def test_custom_target_comment_pi (self ):
2134+ parser = ET .XMLPullParser (events = ('comment' , 'pi' ),
2135+ target = self .SimpleTarget ())
2136+ self ._feed (parser , "<root><!-- text --><?pitarget data?></root>" )
2137+ self .assert_event_tuples (parser , [
2138+ ('comment' , ('comment' , ' text ' )),
2139+ ('pi' , ('pi' , 'pitarget' )),
2140+ ])
2141+
2142+ def test_custom_target_without_method (self ):
2143+ class Target :
2144+ def close (self ):
2145+ pass
2146+ for event in ('start' , 'end' , 'comment' , 'pi' ):
2147+ with self .subTest (event = event ):
2148+ with self .assertRaisesRegex (TypeError ,
2149+ "the target does not support %r events" % event ):
2150+ ET .XMLPullParser (events = (event ,), target = Target ())
2151+ # the namespace events do not need methods of the target
2152+ parser = ET .XMLPullParser (events = ('start-ns' , 'end-ns' ),
2153+ target = Target ())
2154+ self ._feed (parser , "<root xmlns='namespace' />" )
2155+ self .assert_event_tuples (parser , [
2156+ ('start-ns' , ('' , 'namespace' )),
2157+ ('end-ns' , None ),
2158+ ])
2159+
2160+ def test_custom_target_ns_events (self ):
2161+ # the target does not implement start_ns()/end_ns(),
2162+ # so the prefix and the uri are reported
2163+ parser = ET .XMLPullParser (events = ('start-ns' , 'end-ns' ),
2164+ target = self .SimpleTarget ())
2165+ self ._feed (parser , "<root xmlns='namespace' />" )
2166+ self .assert_event_tuples (parser , [
2167+ ('start-ns' , ('' , 'namespace' )),
2168+ ('end-ns' , None ),
2169+ ])
2170+
2171+ def test_custom_target_close (self ):
2172+ parser = ET .XMLPullParser (events = ('end' ,), target = self .SimpleTarget ())
2173+ self ._feed (parser , "<root/>" )
2174+ parser .close ()
2175+ self .assert_event_tuples (parser , [('end' , ('end' , 'root' ))])
2176+
20702177 def test_unknown_event (self ):
20712178 with self .assertRaises (ValueError ):
20722179 ET .XMLPullParser (events = ('start' , 'end' , 'bogus' ))
0 commit comments