17db96d56Sopenharmony_ci# IMPORTANT: the same tests are run from "test_xml_etree_c" in order 27db96d56Sopenharmony_ci# to ensure consistency between the C implementation and the Python 37db96d56Sopenharmony_ci# implementation. 47db96d56Sopenharmony_ci# 57db96d56Sopenharmony_ci# For this purpose, the module-level "ET" symbol is temporarily 67db96d56Sopenharmony_ci# monkey-patched when running the "test_xml_etree_c" test suite. 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ciimport copy 97db96d56Sopenharmony_ciimport functools 107db96d56Sopenharmony_ciimport html 117db96d56Sopenharmony_ciimport io 127db96d56Sopenharmony_ciimport itertools 137db96d56Sopenharmony_ciimport operator 147db96d56Sopenharmony_ciimport os 157db96d56Sopenharmony_ciimport pickle 167db96d56Sopenharmony_ciimport sys 177db96d56Sopenharmony_ciimport textwrap 187db96d56Sopenharmony_ciimport types 197db96d56Sopenharmony_ciimport unittest 207db96d56Sopenharmony_ciimport warnings 217db96d56Sopenharmony_ciimport weakref 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_cifrom functools import partial 247db96d56Sopenharmony_cifrom itertools import product, islice 257db96d56Sopenharmony_cifrom test import support 267db96d56Sopenharmony_cifrom test.support import os_helper 277db96d56Sopenharmony_cifrom test.support import warnings_helper 287db96d56Sopenharmony_cifrom test.support import findfile, gc_collect, swap_attr, swap_item 297db96d56Sopenharmony_cifrom test.support.import_helper import import_fresh_module 307db96d56Sopenharmony_cifrom test.support.os_helper import TESTFN 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci# pyET is the pure-Python implementation. 347db96d56Sopenharmony_ci# 357db96d56Sopenharmony_ci# ET is pyET in test_xml_etree and is the C accelerated version in 367db96d56Sopenharmony_ci# test_xml_etree_c. 377db96d56Sopenharmony_cipyET = None 387db96d56Sopenharmony_ciET = None 397db96d56Sopenharmony_ci 407db96d56Sopenharmony_ciSIMPLE_XMLFILE = findfile("simple.xml", subdir="xmltestdata") 417db96d56Sopenharmony_citry: 427db96d56Sopenharmony_ci SIMPLE_XMLFILE.encode("utf-8") 437db96d56Sopenharmony_ciexcept UnicodeEncodeError: 447db96d56Sopenharmony_ci raise unittest.SkipTest("filename is not encodable to utf8") 457db96d56Sopenharmony_ciSIMPLE_NS_XMLFILE = findfile("simple-ns.xml", subdir="xmltestdata") 467db96d56Sopenharmony_ciUTF8_BUG_XMLFILE = findfile("expat224_utf8_bug.xml", subdir="xmltestdata") 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ciSAMPLE_XML = """\ 497db96d56Sopenharmony_ci<body> 507db96d56Sopenharmony_ci <tag class='a'>text</tag> 517db96d56Sopenharmony_ci <tag class='b' /> 527db96d56Sopenharmony_ci <section> 537db96d56Sopenharmony_ci <tag class='b' id='inner'>subtext</tag> 547db96d56Sopenharmony_ci </section> 557db96d56Sopenharmony_ci</body> 567db96d56Sopenharmony_ci""" 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_ciSAMPLE_SECTION = """\ 597db96d56Sopenharmony_ci<section> 607db96d56Sopenharmony_ci <tag class='b' id='inner'>subtext</tag> 617db96d56Sopenharmony_ci <nexttag /> 627db96d56Sopenharmony_ci <nextsection> 637db96d56Sopenharmony_ci <tag /> 647db96d56Sopenharmony_ci </nextsection> 657db96d56Sopenharmony_ci</section> 667db96d56Sopenharmony_ci""" 677db96d56Sopenharmony_ci 687db96d56Sopenharmony_ciSAMPLE_XML_NS = """ 697db96d56Sopenharmony_ci<body xmlns="http://effbot.org/ns"> 707db96d56Sopenharmony_ci <tag>text</tag> 717db96d56Sopenharmony_ci <tag /> 727db96d56Sopenharmony_ci <section> 737db96d56Sopenharmony_ci <tag>subtext</tag> 747db96d56Sopenharmony_ci </section> 757db96d56Sopenharmony_ci</body> 767db96d56Sopenharmony_ci""" 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ciSAMPLE_XML_NS_ELEMS = """ 797db96d56Sopenharmony_ci<root> 807db96d56Sopenharmony_ci<h:table xmlns:h="hello"> 817db96d56Sopenharmony_ci <h:tr> 827db96d56Sopenharmony_ci <h:td>Apples</h:td> 837db96d56Sopenharmony_ci <h:td>Bananas</h:td> 847db96d56Sopenharmony_ci </h:tr> 857db96d56Sopenharmony_ci</h:table> 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci<f:table xmlns:f="foo"> 887db96d56Sopenharmony_ci <f:name>African Coffee Table</f:name> 897db96d56Sopenharmony_ci <f:width>80</f:width> 907db96d56Sopenharmony_ci <f:length>120</f:length> 917db96d56Sopenharmony_ci</f:table> 927db96d56Sopenharmony_ci</root> 937db96d56Sopenharmony_ci""" 947db96d56Sopenharmony_ci 957db96d56Sopenharmony_ciENTITY_XML = """\ 967db96d56Sopenharmony_ci<!DOCTYPE points [ 977db96d56Sopenharmony_ci<!ENTITY % user-entities SYSTEM 'user-entities.xml'> 987db96d56Sopenharmony_ci%user-entities; 997db96d56Sopenharmony_ci]> 1007db96d56Sopenharmony_ci<document>&entity;</document> 1017db96d56Sopenharmony_ci""" 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ciEXTERNAL_ENTITY_XML = """\ 1047db96d56Sopenharmony_ci<!DOCTYPE points [ 1057db96d56Sopenharmony_ci<!ENTITY entity SYSTEM "file:///non-existing-file.xml"> 1067db96d56Sopenharmony_ci]> 1077db96d56Sopenharmony_ci<document>&entity;</document> 1087db96d56Sopenharmony_ci""" 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ciATTLIST_XML = """\ 1117db96d56Sopenharmony_ci<?xml version="1.0" encoding="UTF-8"?> 1127db96d56Sopenharmony_ci<!DOCTYPE Foo [ 1137db96d56Sopenharmony_ci<!ELEMENT foo (bar*)> 1147db96d56Sopenharmony_ci<!ELEMENT bar (#PCDATA)*> 1157db96d56Sopenharmony_ci<!ATTLIST bar xml:lang CDATA "eng"> 1167db96d56Sopenharmony_ci<!ENTITY qux "quux"> 1177db96d56Sopenharmony_ci]> 1187db96d56Sopenharmony_ci<foo> 1197db96d56Sopenharmony_ci<bar>&qux;</bar> 1207db96d56Sopenharmony_ci</foo> 1217db96d56Sopenharmony_ci""" 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_cidef checkwarnings(*filters, quiet=False): 1247db96d56Sopenharmony_ci def decorator(test): 1257db96d56Sopenharmony_ci def newtest(*args, **kwargs): 1267db96d56Sopenharmony_ci with warnings_helper.check_warnings(*filters, quiet=quiet): 1277db96d56Sopenharmony_ci test(*args, **kwargs) 1287db96d56Sopenharmony_ci functools.update_wrapper(newtest, test) 1297db96d56Sopenharmony_ci return newtest 1307db96d56Sopenharmony_ci return decorator 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_cidef convlinesep(data): 1337db96d56Sopenharmony_ci return data.replace(b'\n', os.linesep.encode()) 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci 1367db96d56Sopenharmony_ciclass ModuleTest(unittest.TestCase): 1377db96d56Sopenharmony_ci def test_sanity(self): 1387db96d56Sopenharmony_ci # Import sanity. 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_ci from xml.etree import ElementTree 1417db96d56Sopenharmony_ci from xml.etree import ElementInclude 1427db96d56Sopenharmony_ci from xml.etree import ElementPath 1437db96d56Sopenharmony_ci 1447db96d56Sopenharmony_ci def test_all(self): 1457db96d56Sopenharmony_ci names = ("xml.etree.ElementTree", "_elementtree") 1467db96d56Sopenharmony_ci support.check__all__(self, ET, names, not_exported=("HTML_EMPTY",)) 1477db96d56Sopenharmony_ci 1487db96d56Sopenharmony_ci 1497db96d56Sopenharmony_cidef serialize(elem, to_string=True, encoding='unicode', **options): 1507db96d56Sopenharmony_ci if encoding != 'unicode': 1517db96d56Sopenharmony_ci file = io.BytesIO() 1527db96d56Sopenharmony_ci else: 1537db96d56Sopenharmony_ci file = io.StringIO() 1547db96d56Sopenharmony_ci tree = ET.ElementTree(elem) 1557db96d56Sopenharmony_ci tree.write(file, encoding=encoding, **options) 1567db96d56Sopenharmony_ci if to_string: 1577db96d56Sopenharmony_ci return file.getvalue() 1587db96d56Sopenharmony_ci else: 1597db96d56Sopenharmony_ci file.seek(0) 1607db96d56Sopenharmony_ci return file 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_cidef summarize_list(seq): 1637db96d56Sopenharmony_ci return [elem.tag for elem in seq] 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ci 1667db96d56Sopenharmony_ciclass ElementTestCase: 1677db96d56Sopenharmony_ci @classmethod 1687db96d56Sopenharmony_ci def setUpClass(cls): 1697db96d56Sopenharmony_ci cls.modules = {pyET, ET} 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_ci def pickleRoundTrip(self, obj, name, dumper, loader, proto): 1727db96d56Sopenharmony_ci try: 1737db96d56Sopenharmony_ci with swap_item(sys.modules, name, dumper): 1747db96d56Sopenharmony_ci temp = pickle.dumps(obj, proto) 1757db96d56Sopenharmony_ci with swap_item(sys.modules, name, loader): 1767db96d56Sopenharmony_ci result = pickle.loads(temp) 1777db96d56Sopenharmony_ci except pickle.PicklingError as pe: 1787db96d56Sopenharmony_ci # pyET must be second, because pyET may be (equal to) ET. 1797db96d56Sopenharmony_ci human = dict([(ET, "cET"), (pyET, "pyET")]) 1807db96d56Sopenharmony_ci raise support.TestFailed("Failed to round-trip %r from %r to %r" 1817db96d56Sopenharmony_ci % (obj, 1827db96d56Sopenharmony_ci human.get(dumper, dumper), 1837db96d56Sopenharmony_ci human.get(loader, loader))) from pe 1847db96d56Sopenharmony_ci return result 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_ci def assertEqualElements(self, alice, bob): 1877db96d56Sopenharmony_ci self.assertIsInstance(alice, (ET.Element, pyET.Element)) 1887db96d56Sopenharmony_ci self.assertIsInstance(bob, (ET.Element, pyET.Element)) 1897db96d56Sopenharmony_ci self.assertEqual(len(list(alice)), len(list(bob))) 1907db96d56Sopenharmony_ci for x, y in zip(alice, bob): 1917db96d56Sopenharmony_ci self.assertEqualElements(x, y) 1927db96d56Sopenharmony_ci properties = operator.attrgetter('tag', 'tail', 'text', 'attrib') 1937db96d56Sopenharmony_ci self.assertEqual(properties(alice), properties(bob)) 1947db96d56Sopenharmony_ci 1957db96d56Sopenharmony_ci# -------------------------------------------------------------------- 1967db96d56Sopenharmony_ci# element tree tests 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_ciclass ElementTreeTest(unittest.TestCase): 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_ci def serialize_check(self, elem, expected): 2017db96d56Sopenharmony_ci self.assertEqual(serialize(elem), expected) 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci def test_interface(self): 2047db96d56Sopenharmony_ci # Test element tree interface. 2057db96d56Sopenharmony_ci 2067db96d56Sopenharmony_ci def check_element(element): 2077db96d56Sopenharmony_ci self.assertTrue(ET.iselement(element), msg="not an element") 2087db96d56Sopenharmony_ci direlem = dir(element) 2097db96d56Sopenharmony_ci for attr in 'tag', 'attrib', 'text', 'tail': 2107db96d56Sopenharmony_ci self.assertTrue(hasattr(element, attr), 2117db96d56Sopenharmony_ci msg='no %s member' % attr) 2127db96d56Sopenharmony_ci self.assertIn(attr, direlem, 2137db96d56Sopenharmony_ci msg='no %s visible by dir' % attr) 2147db96d56Sopenharmony_ci 2157db96d56Sopenharmony_ci self.assertIsInstance(element.tag, str) 2167db96d56Sopenharmony_ci self.assertIsInstance(element.attrib, dict) 2177db96d56Sopenharmony_ci if element.text is not None: 2187db96d56Sopenharmony_ci self.assertIsInstance(element.text, str) 2197db96d56Sopenharmony_ci if element.tail is not None: 2207db96d56Sopenharmony_ci self.assertIsInstance(element.tail, str) 2217db96d56Sopenharmony_ci for elem in element: 2227db96d56Sopenharmony_ci check_element(elem) 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_ci element = ET.Element("tag") 2257db96d56Sopenharmony_ci check_element(element) 2267db96d56Sopenharmony_ci tree = ET.ElementTree(element) 2277db96d56Sopenharmony_ci check_element(tree.getroot()) 2287db96d56Sopenharmony_ci element = ET.Element("t\xe4g", key="value") 2297db96d56Sopenharmony_ci tree = ET.ElementTree(element) 2307db96d56Sopenharmony_ci self.assertRegex(repr(element), r"^<Element 't\xe4g' at 0x.*>$") 2317db96d56Sopenharmony_ci element = ET.Element("tag", key="value") 2327db96d56Sopenharmony_ci 2337db96d56Sopenharmony_ci # Make sure all standard element methods exist. 2347db96d56Sopenharmony_ci 2357db96d56Sopenharmony_ci def check_method(method): 2367db96d56Sopenharmony_ci self.assertTrue(hasattr(method, '__call__'), 2377db96d56Sopenharmony_ci msg="%s not callable" % method) 2387db96d56Sopenharmony_ci 2397db96d56Sopenharmony_ci check_method(element.append) 2407db96d56Sopenharmony_ci check_method(element.extend) 2417db96d56Sopenharmony_ci check_method(element.insert) 2427db96d56Sopenharmony_ci check_method(element.remove) 2437db96d56Sopenharmony_ci check_method(element.find) 2447db96d56Sopenharmony_ci check_method(element.iterfind) 2457db96d56Sopenharmony_ci check_method(element.findall) 2467db96d56Sopenharmony_ci check_method(element.findtext) 2477db96d56Sopenharmony_ci check_method(element.clear) 2487db96d56Sopenharmony_ci check_method(element.get) 2497db96d56Sopenharmony_ci check_method(element.set) 2507db96d56Sopenharmony_ci check_method(element.keys) 2517db96d56Sopenharmony_ci check_method(element.items) 2527db96d56Sopenharmony_ci check_method(element.iter) 2537db96d56Sopenharmony_ci check_method(element.itertext) 2547db96d56Sopenharmony_ci 2557db96d56Sopenharmony_ci # These methods return an iterable. See bug 6472. 2567db96d56Sopenharmony_ci 2577db96d56Sopenharmony_ci def check_iter(it): 2587db96d56Sopenharmony_ci check_method(it.__next__) 2597db96d56Sopenharmony_ci 2607db96d56Sopenharmony_ci check_iter(element.iterfind("tag")) 2617db96d56Sopenharmony_ci check_iter(element.iterfind("*")) 2627db96d56Sopenharmony_ci check_iter(tree.iterfind("tag")) 2637db96d56Sopenharmony_ci check_iter(tree.iterfind("*")) 2647db96d56Sopenharmony_ci 2657db96d56Sopenharmony_ci # These aliases are provided: 2667db96d56Sopenharmony_ci 2677db96d56Sopenharmony_ci self.assertEqual(ET.XML, ET.fromstring) 2687db96d56Sopenharmony_ci self.assertEqual(ET.PI, ET.ProcessingInstruction) 2697db96d56Sopenharmony_ci 2707db96d56Sopenharmony_ci def test_set_attribute(self): 2717db96d56Sopenharmony_ci element = ET.Element('tag') 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_ci self.assertEqual(element.tag, 'tag') 2747db96d56Sopenharmony_ci element.tag = 'Tag' 2757db96d56Sopenharmony_ci self.assertEqual(element.tag, 'Tag') 2767db96d56Sopenharmony_ci element.tag = 'TAG' 2777db96d56Sopenharmony_ci self.assertEqual(element.tag, 'TAG') 2787db96d56Sopenharmony_ci 2797db96d56Sopenharmony_ci self.assertIsNone(element.text) 2807db96d56Sopenharmony_ci element.text = 'Text' 2817db96d56Sopenharmony_ci self.assertEqual(element.text, 'Text') 2827db96d56Sopenharmony_ci element.text = 'TEXT' 2837db96d56Sopenharmony_ci self.assertEqual(element.text, 'TEXT') 2847db96d56Sopenharmony_ci 2857db96d56Sopenharmony_ci self.assertIsNone(element.tail) 2867db96d56Sopenharmony_ci element.tail = 'Tail' 2877db96d56Sopenharmony_ci self.assertEqual(element.tail, 'Tail') 2887db96d56Sopenharmony_ci element.tail = 'TAIL' 2897db96d56Sopenharmony_ci self.assertEqual(element.tail, 'TAIL') 2907db96d56Sopenharmony_ci 2917db96d56Sopenharmony_ci self.assertEqual(element.attrib, {}) 2927db96d56Sopenharmony_ci element.attrib = {'a': 'b', 'c': 'd'} 2937db96d56Sopenharmony_ci self.assertEqual(element.attrib, {'a': 'b', 'c': 'd'}) 2947db96d56Sopenharmony_ci element.attrib = {'A': 'B', 'C': 'D'} 2957db96d56Sopenharmony_ci self.assertEqual(element.attrib, {'A': 'B', 'C': 'D'}) 2967db96d56Sopenharmony_ci 2977db96d56Sopenharmony_ci def test_simpleops(self): 2987db96d56Sopenharmony_ci # Basic method sanity checks. 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci elem = ET.XML("<body><tag/></body>") 3017db96d56Sopenharmony_ci self.serialize_check(elem, '<body><tag /></body>') 3027db96d56Sopenharmony_ci e = ET.Element("tag2") 3037db96d56Sopenharmony_ci elem.append(e) 3047db96d56Sopenharmony_ci self.serialize_check(elem, '<body><tag /><tag2 /></body>') 3057db96d56Sopenharmony_ci elem.remove(e) 3067db96d56Sopenharmony_ci self.serialize_check(elem, '<body><tag /></body>') 3077db96d56Sopenharmony_ci elem.insert(0, e) 3087db96d56Sopenharmony_ci self.serialize_check(elem, '<body><tag2 /><tag /></body>') 3097db96d56Sopenharmony_ci elem.remove(e) 3107db96d56Sopenharmony_ci elem.extend([e]) 3117db96d56Sopenharmony_ci self.serialize_check(elem, '<body><tag /><tag2 /></body>') 3127db96d56Sopenharmony_ci elem.remove(e) 3137db96d56Sopenharmony_ci elem.extend(iter([e])) 3147db96d56Sopenharmony_ci self.serialize_check(elem, '<body><tag /><tag2 /></body>') 3157db96d56Sopenharmony_ci elem.remove(e) 3167db96d56Sopenharmony_ci 3177db96d56Sopenharmony_ci element = ET.Element("tag", key="value") 3187db96d56Sopenharmony_ci self.serialize_check(element, '<tag key="value" />') # 1 3197db96d56Sopenharmony_ci subelement = ET.Element("subtag") 3207db96d56Sopenharmony_ci element.append(subelement) 3217db96d56Sopenharmony_ci self.serialize_check(element, '<tag key="value"><subtag /></tag>') # 2 3227db96d56Sopenharmony_ci element.insert(0, subelement) 3237db96d56Sopenharmony_ci self.serialize_check(element, 3247db96d56Sopenharmony_ci '<tag key="value"><subtag /><subtag /></tag>') # 3 3257db96d56Sopenharmony_ci element.remove(subelement) 3267db96d56Sopenharmony_ci self.serialize_check(element, '<tag key="value"><subtag /></tag>') # 4 3277db96d56Sopenharmony_ci element.remove(subelement) 3287db96d56Sopenharmony_ci self.serialize_check(element, '<tag key="value" />') # 5 3297db96d56Sopenharmony_ci with self.assertRaises(ValueError) as cm: 3307db96d56Sopenharmony_ci element.remove(subelement) 3317db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 'list.remove(x): x not in list') 3327db96d56Sopenharmony_ci self.serialize_check(element, '<tag key="value" />') # 6 3337db96d56Sopenharmony_ci element[0:0] = [subelement, subelement, subelement] 3347db96d56Sopenharmony_ci self.serialize_check(element[1], '<subtag />') 3357db96d56Sopenharmony_ci self.assertEqual(element[1:9], [element[1], element[2]]) 3367db96d56Sopenharmony_ci self.assertEqual(element[:9:2], [element[0], element[2]]) 3377db96d56Sopenharmony_ci del element[1:2] 3387db96d56Sopenharmony_ci self.serialize_check(element, 3397db96d56Sopenharmony_ci '<tag key="value"><subtag /><subtag /></tag>') 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci def test_cdata(self): 3427db96d56Sopenharmony_ci # Test CDATA handling (etc). 3437db96d56Sopenharmony_ci 3447db96d56Sopenharmony_ci self.serialize_check(ET.XML("<tag>hello</tag>"), 3457db96d56Sopenharmony_ci '<tag>hello</tag>') 3467db96d56Sopenharmony_ci self.serialize_check(ET.XML("<tag>hello</tag>"), 3477db96d56Sopenharmony_ci '<tag>hello</tag>') 3487db96d56Sopenharmony_ci self.serialize_check(ET.XML("<tag><![CDATA[hello]]></tag>"), 3497db96d56Sopenharmony_ci '<tag>hello</tag>') 3507db96d56Sopenharmony_ci 3517db96d56Sopenharmony_ci def test_file_init(self): 3527db96d56Sopenharmony_ci stringfile = io.BytesIO(SAMPLE_XML.encode("utf-8")) 3537db96d56Sopenharmony_ci tree = ET.ElementTree(file=stringfile) 3547db96d56Sopenharmony_ci self.assertEqual(tree.find("tag").tag, 'tag') 3557db96d56Sopenharmony_ci self.assertEqual(tree.find("section/tag").tag, 'tag') 3567db96d56Sopenharmony_ci 3577db96d56Sopenharmony_ci tree = ET.ElementTree(file=SIMPLE_XMLFILE) 3587db96d56Sopenharmony_ci self.assertEqual(tree.find("element").tag, 'element') 3597db96d56Sopenharmony_ci self.assertEqual(tree.find("element/../empty-element").tag, 3607db96d56Sopenharmony_ci 'empty-element') 3617db96d56Sopenharmony_ci 3627db96d56Sopenharmony_ci def test_path_cache(self): 3637db96d56Sopenharmony_ci # Check that the path cache behaves sanely. 3647db96d56Sopenharmony_ci 3657db96d56Sopenharmony_ci from xml.etree import ElementPath 3667db96d56Sopenharmony_ci 3677db96d56Sopenharmony_ci elem = ET.XML(SAMPLE_XML) 3687db96d56Sopenharmony_ci for i in range(10): ET.ElementTree(elem).find('./'+str(i)) 3697db96d56Sopenharmony_ci cache_len_10 = len(ElementPath._cache) 3707db96d56Sopenharmony_ci for i in range(10): ET.ElementTree(elem).find('./'+str(i)) 3717db96d56Sopenharmony_ci self.assertEqual(len(ElementPath._cache), cache_len_10) 3727db96d56Sopenharmony_ci for i in range(20): ET.ElementTree(elem).find('./'+str(i)) 3737db96d56Sopenharmony_ci self.assertGreater(len(ElementPath._cache), cache_len_10) 3747db96d56Sopenharmony_ci for i in range(600): ET.ElementTree(elem).find('./'+str(i)) 3757db96d56Sopenharmony_ci self.assertLess(len(ElementPath._cache), 500) 3767db96d56Sopenharmony_ci 3777db96d56Sopenharmony_ci def test_copy(self): 3787db96d56Sopenharmony_ci # Test copy handling (etc). 3797db96d56Sopenharmony_ci 3807db96d56Sopenharmony_ci import copy 3817db96d56Sopenharmony_ci e1 = ET.XML("<tag>hello<foo/></tag>") 3827db96d56Sopenharmony_ci e2 = copy.copy(e1) 3837db96d56Sopenharmony_ci e3 = copy.deepcopy(e1) 3847db96d56Sopenharmony_ci e1.find("foo").tag = "bar" 3857db96d56Sopenharmony_ci self.serialize_check(e1, '<tag>hello<bar /></tag>') 3867db96d56Sopenharmony_ci self.serialize_check(e2, '<tag>hello<bar /></tag>') 3877db96d56Sopenharmony_ci self.serialize_check(e3, '<tag>hello<foo /></tag>') 3887db96d56Sopenharmony_ci 3897db96d56Sopenharmony_ci def test_attrib(self): 3907db96d56Sopenharmony_ci # Test attribute handling. 3917db96d56Sopenharmony_ci 3927db96d56Sopenharmony_ci elem = ET.Element("tag") 3937db96d56Sopenharmony_ci elem.get("key") # 1.1 3947db96d56Sopenharmony_ci self.assertEqual(elem.get("key", "default"), 'default') # 1.2 3957db96d56Sopenharmony_ci 3967db96d56Sopenharmony_ci elem.set("key", "value") 3977db96d56Sopenharmony_ci self.assertEqual(elem.get("key"), 'value') # 1.3 3987db96d56Sopenharmony_ci 3997db96d56Sopenharmony_ci elem = ET.Element("tag", key="value") 4007db96d56Sopenharmony_ci self.assertEqual(elem.get("key"), 'value') # 2.1 4017db96d56Sopenharmony_ci self.assertEqual(elem.attrib, {'key': 'value'}) # 2.2 4027db96d56Sopenharmony_ci 4037db96d56Sopenharmony_ci attrib = {"key": "value"} 4047db96d56Sopenharmony_ci elem = ET.Element("tag", attrib) 4057db96d56Sopenharmony_ci attrib.clear() # check for aliasing issues 4067db96d56Sopenharmony_ci self.assertEqual(elem.get("key"), 'value') # 3.1 4077db96d56Sopenharmony_ci self.assertEqual(elem.attrib, {'key': 'value'}) # 3.2 4087db96d56Sopenharmony_ci 4097db96d56Sopenharmony_ci attrib = {"key": "value"} 4107db96d56Sopenharmony_ci elem = ET.Element("tag", **attrib) 4117db96d56Sopenharmony_ci attrib.clear() # check for aliasing issues 4127db96d56Sopenharmony_ci self.assertEqual(elem.get("key"), 'value') # 4.1 4137db96d56Sopenharmony_ci self.assertEqual(elem.attrib, {'key': 'value'}) # 4.2 4147db96d56Sopenharmony_ci 4157db96d56Sopenharmony_ci elem = ET.Element("tag", {"key": "other"}, key="value") 4167db96d56Sopenharmony_ci self.assertEqual(elem.get("key"), 'value') # 5.1 4177db96d56Sopenharmony_ci self.assertEqual(elem.attrib, {'key': 'value'}) # 5.2 4187db96d56Sopenharmony_ci 4197db96d56Sopenharmony_ci elem = ET.Element('test') 4207db96d56Sopenharmony_ci elem.text = "aa" 4217db96d56Sopenharmony_ci elem.set('testa', 'testval') 4227db96d56Sopenharmony_ci elem.set('testb', 'test2') 4237db96d56Sopenharmony_ci self.assertEqual(ET.tostring(elem), 4247db96d56Sopenharmony_ci b'<test testa="testval" testb="test2">aa</test>') 4257db96d56Sopenharmony_ci self.assertEqual(sorted(elem.keys()), ['testa', 'testb']) 4267db96d56Sopenharmony_ci self.assertEqual(sorted(elem.items()), 4277db96d56Sopenharmony_ci [('testa', 'testval'), ('testb', 'test2')]) 4287db96d56Sopenharmony_ci self.assertEqual(elem.attrib['testb'], 'test2') 4297db96d56Sopenharmony_ci elem.attrib['testb'] = 'test1' 4307db96d56Sopenharmony_ci elem.attrib['testc'] = 'test2' 4317db96d56Sopenharmony_ci self.assertEqual(ET.tostring(elem), 4327db96d56Sopenharmony_ci b'<test testa="testval" testb="test1" testc="test2">aa</test>') 4337db96d56Sopenharmony_ci 4347db96d56Sopenharmony_ci # Test preserving white space chars in attributes 4357db96d56Sopenharmony_ci elem = ET.Element('test') 4367db96d56Sopenharmony_ci elem.set('a', '\r') 4377db96d56Sopenharmony_ci elem.set('b', '\r\n') 4387db96d56Sopenharmony_ci elem.set('c', '\t\n\r ') 4397db96d56Sopenharmony_ci elem.set('d', '\n\n\r\r\t\t ') 4407db96d56Sopenharmony_ci self.assertEqual(ET.tostring(elem), 4417db96d56Sopenharmony_ci b'<test a=" " b=" " c="	 " d=" 		 " />') 4427db96d56Sopenharmony_ci 4437db96d56Sopenharmony_ci def test_makeelement(self): 4447db96d56Sopenharmony_ci # Test makeelement handling. 4457db96d56Sopenharmony_ci 4467db96d56Sopenharmony_ci elem = ET.Element("tag") 4477db96d56Sopenharmony_ci attrib = {"key": "value"} 4487db96d56Sopenharmony_ci subelem = elem.makeelement("subtag", attrib) 4497db96d56Sopenharmony_ci self.assertIsNot(subelem.attrib, attrib, msg="attrib aliasing") 4507db96d56Sopenharmony_ci elem.append(subelem) 4517db96d56Sopenharmony_ci self.serialize_check(elem, '<tag><subtag key="value" /></tag>') 4527db96d56Sopenharmony_ci 4537db96d56Sopenharmony_ci elem.clear() 4547db96d56Sopenharmony_ci self.serialize_check(elem, '<tag />') 4557db96d56Sopenharmony_ci elem.append(subelem) 4567db96d56Sopenharmony_ci self.serialize_check(elem, '<tag><subtag key="value" /></tag>') 4577db96d56Sopenharmony_ci elem.extend([subelem, subelem]) 4587db96d56Sopenharmony_ci self.serialize_check(elem, 4597db96d56Sopenharmony_ci '<tag><subtag key="value" /><subtag key="value" /><subtag key="value" /></tag>') 4607db96d56Sopenharmony_ci elem[:] = [subelem] 4617db96d56Sopenharmony_ci self.serialize_check(elem, '<tag><subtag key="value" /></tag>') 4627db96d56Sopenharmony_ci elem[:] = tuple([subelem]) 4637db96d56Sopenharmony_ci self.serialize_check(elem, '<tag><subtag key="value" /></tag>') 4647db96d56Sopenharmony_ci 4657db96d56Sopenharmony_ci def test_parsefile(self): 4667db96d56Sopenharmony_ci # Test parsing from file. 4677db96d56Sopenharmony_ci 4687db96d56Sopenharmony_ci tree = ET.parse(SIMPLE_XMLFILE) 4697db96d56Sopenharmony_ci stream = io.StringIO() 4707db96d56Sopenharmony_ci tree.write(stream, encoding='unicode') 4717db96d56Sopenharmony_ci self.assertEqual(stream.getvalue(), 4727db96d56Sopenharmony_ci '<root>\n' 4737db96d56Sopenharmony_ci ' <element key="value">text</element>\n' 4747db96d56Sopenharmony_ci ' <element>text</element>tail\n' 4757db96d56Sopenharmony_ci ' <empty-element />\n' 4767db96d56Sopenharmony_ci '</root>') 4777db96d56Sopenharmony_ci tree = ET.parse(SIMPLE_NS_XMLFILE) 4787db96d56Sopenharmony_ci stream = io.StringIO() 4797db96d56Sopenharmony_ci tree.write(stream, encoding='unicode') 4807db96d56Sopenharmony_ci self.assertEqual(stream.getvalue(), 4817db96d56Sopenharmony_ci '<ns0:root xmlns:ns0="namespace">\n' 4827db96d56Sopenharmony_ci ' <ns0:element key="value">text</ns0:element>\n' 4837db96d56Sopenharmony_ci ' <ns0:element>text</ns0:element>tail\n' 4847db96d56Sopenharmony_ci ' <ns0:empty-element />\n' 4857db96d56Sopenharmony_ci '</ns0:root>') 4867db96d56Sopenharmony_ci 4877db96d56Sopenharmony_ci with open(SIMPLE_XMLFILE) as f: 4887db96d56Sopenharmony_ci data = f.read() 4897db96d56Sopenharmony_ci 4907db96d56Sopenharmony_ci parser = ET.XMLParser() 4917db96d56Sopenharmony_ci self.assertRegex(parser.version, r'^Expat ') 4927db96d56Sopenharmony_ci parser.feed(data) 4937db96d56Sopenharmony_ci self.serialize_check(parser.close(), 4947db96d56Sopenharmony_ci '<root>\n' 4957db96d56Sopenharmony_ci ' <element key="value">text</element>\n' 4967db96d56Sopenharmony_ci ' <element>text</element>tail\n' 4977db96d56Sopenharmony_ci ' <empty-element />\n' 4987db96d56Sopenharmony_ci '</root>') 4997db96d56Sopenharmony_ci 5007db96d56Sopenharmony_ci target = ET.TreeBuilder() 5017db96d56Sopenharmony_ci parser = ET.XMLParser(target=target) 5027db96d56Sopenharmony_ci parser.feed(data) 5037db96d56Sopenharmony_ci self.serialize_check(parser.close(), 5047db96d56Sopenharmony_ci '<root>\n' 5057db96d56Sopenharmony_ci ' <element key="value">text</element>\n' 5067db96d56Sopenharmony_ci ' <element>text</element>tail\n' 5077db96d56Sopenharmony_ci ' <empty-element />\n' 5087db96d56Sopenharmony_ci '</root>') 5097db96d56Sopenharmony_ci 5107db96d56Sopenharmony_ci def test_parseliteral(self): 5117db96d56Sopenharmony_ci element = ET.XML("<html><body>text</body></html>") 5127db96d56Sopenharmony_ci self.assertEqual(ET.tostring(element, encoding='unicode'), 5137db96d56Sopenharmony_ci '<html><body>text</body></html>') 5147db96d56Sopenharmony_ci element = ET.fromstring("<html><body>text</body></html>") 5157db96d56Sopenharmony_ci self.assertEqual(ET.tostring(element, encoding='unicode'), 5167db96d56Sopenharmony_ci '<html><body>text</body></html>') 5177db96d56Sopenharmony_ci sequence = ["<html><body>", "text</bo", "dy></html>"] 5187db96d56Sopenharmony_ci element = ET.fromstringlist(sequence) 5197db96d56Sopenharmony_ci self.assertEqual(ET.tostring(element), 5207db96d56Sopenharmony_ci b'<html><body>text</body></html>') 5217db96d56Sopenharmony_ci self.assertEqual(b"".join(ET.tostringlist(element)), 5227db96d56Sopenharmony_ci b'<html><body>text</body></html>') 5237db96d56Sopenharmony_ci self.assertEqual(ET.tostring(element, "ascii"), 5247db96d56Sopenharmony_ci b"<?xml version='1.0' encoding='ascii'?>\n" 5257db96d56Sopenharmony_ci b"<html><body>text</body></html>") 5267db96d56Sopenharmony_ci _, ids = ET.XMLID("<html><body>text</body></html>") 5277db96d56Sopenharmony_ci self.assertEqual(len(ids), 0) 5287db96d56Sopenharmony_ci _, ids = ET.XMLID("<html><body id='body'>text</body></html>") 5297db96d56Sopenharmony_ci self.assertEqual(len(ids), 1) 5307db96d56Sopenharmony_ci self.assertEqual(ids["body"].tag, 'body') 5317db96d56Sopenharmony_ci 5327db96d56Sopenharmony_ci def test_iterparse(self): 5337db96d56Sopenharmony_ci # Test iterparse interface. 5347db96d56Sopenharmony_ci 5357db96d56Sopenharmony_ci iterparse = ET.iterparse 5367db96d56Sopenharmony_ci 5377db96d56Sopenharmony_ci context = iterparse(SIMPLE_XMLFILE) 5387db96d56Sopenharmony_ci action, elem = next(context) 5397db96d56Sopenharmony_ci self.assertEqual((action, elem.tag), ('end', 'element')) 5407db96d56Sopenharmony_ci self.assertEqual([(action, elem.tag) for action, elem in context], [ 5417db96d56Sopenharmony_ci ('end', 'element'), 5427db96d56Sopenharmony_ci ('end', 'empty-element'), 5437db96d56Sopenharmony_ci ('end', 'root'), 5447db96d56Sopenharmony_ci ]) 5457db96d56Sopenharmony_ci self.assertEqual(context.root.tag, 'root') 5467db96d56Sopenharmony_ci 5477db96d56Sopenharmony_ci context = iterparse(SIMPLE_NS_XMLFILE) 5487db96d56Sopenharmony_ci self.assertEqual([(action, elem.tag) for action, elem in context], [ 5497db96d56Sopenharmony_ci ('end', '{namespace}element'), 5507db96d56Sopenharmony_ci ('end', '{namespace}element'), 5517db96d56Sopenharmony_ci ('end', '{namespace}empty-element'), 5527db96d56Sopenharmony_ci ('end', '{namespace}root'), 5537db96d56Sopenharmony_ci ]) 5547db96d56Sopenharmony_ci 5557db96d56Sopenharmony_ci events = () 5567db96d56Sopenharmony_ci context = iterparse(SIMPLE_XMLFILE, events) 5577db96d56Sopenharmony_ci self.assertEqual([(action, elem.tag) for action, elem in context], []) 5587db96d56Sopenharmony_ci 5597db96d56Sopenharmony_ci events = () 5607db96d56Sopenharmony_ci context = iterparse(SIMPLE_XMLFILE, events=events) 5617db96d56Sopenharmony_ci self.assertEqual([(action, elem.tag) for action, elem in context], []) 5627db96d56Sopenharmony_ci 5637db96d56Sopenharmony_ci events = ("start", "end") 5647db96d56Sopenharmony_ci context = iterparse(SIMPLE_XMLFILE, events) 5657db96d56Sopenharmony_ci self.assertEqual([(action, elem.tag) for action, elem in context], [ 5667db96d56Sopenharmony_ci ('start', 'root'), 5677db96d56Sopenharmony_ci ('start', 'element'), 5687db96d56Sopenharmony_ci ('end', 'element'), 5697db96d56Sopenharmony_ci ('start', 'element'), 5707db96d56Sopenharmony_ci ('end', 'element'), 5717db96d56Sopenharmony_ci ('start', 'empty-element'), 5727db96d56Sopenharmony_ci ('end', 'empty-element'), 5737db96d56Sopenharmony_ci ('end', 'root'), 5747db96d56Sopenharmony_ci ]) 5757db96d56Sopenharmony_ci 5767db96d56Sopenharmony_ci events = ("start", "end", "start-ns", "end-ns") 5777db96d56Sopenharmony_ci context = iterparse(SIMPLE_NS_XMLFILE, events) 5787db96d56Sopenharmony_ci self.assertEqual([(action, elem.tag) if action in ("start", "end") 5797db96d56Sopenharmony_ci else (action, elem) 5807db96d56Sopenharmony_ci for action, elem in context], [ 5817db96d56Sopenharmony_ci ('start-ns', ('', 'namespace')), 5827db96d56Sopenharmony_ci ('start', '{namespace}root'), 5837db96d56Sopenharmony_ci ('start', '{namespace}element'), 5847db96d56Sopenharmony_ci ('end', '{namespace}element'), 5857db96d56Sopenharmony_ci ('start', '{namespace}element'), 5867db96d56Sopenharmony_ci ('end', '{namespace}element'), 5877db96d56Sopenharmony_ci ('start', '{namespace}empty-element'), 5887db96d56Sopenharmony_ci ('end', '{namespace}empty-element'), 5897db96d56Sopenharmony_ci ('end', '{namespace}root'), 5907db96d56Sopenharmony_ci ('end-ns', None), 5917db96d56Sopenharmony_ci ]) 5927db96d56Sopenharmony_ci 5937db96d56Sopenharmony_ci events = ('start-ns', 'end-ns') 5947db96d56Sopenharmony_ci context = iterparse(io.StringIO(r"<root xmlns=''/>"), events) 5957db96d56Sopenharmony_ci res = [action for action, elem in context] 5967db96d56Sopenharmony_ci self.assertEqual(res, ['start-ns', 'end-ns']) 5977db96d56Sopenharmony_ci 5987db96d56Sopenharmony_ci events = ("start", "end", "bogus") 5997db96d56Sopenharmony_ci with open(SIMPLE_XMLFILE, "rb") as f: 6007db96d56Sopenharmony_ci with self.assertRaises(ValueError) as cm: 6017db96d56Sopenharmony_ci iterparse(f, events) 6027db96d56Sopenharmony_ci self.assertFalse(f.closed) 6037db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), "unknown event 'bogus'") 6047db96d56Sopenharmony_ci 6057db96d56Sopenharmony_ci with warnings_helper.check_no_resource_warning(self): 6067db96d56Sopenharmony_ci with self.assertRaises(ValueError) as cm: 6077db96d56Sopenharmony_ci iterparse(SIMPLE_XMLFILE, events) 6087db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), "unknown event 'bogus'") 6097db96d56Sopenharmony_ci del cm 6107db96d56Sopenharmony_ci 6117db96d56Sopenharmony_ci source = io.BytesIO( 6127db96d56Sopenharmony_ci b"<?xml version='1.0' encoding='iso-8859-1'?>\n" 6137db96d56Sopenharmony_ci b"<body xmlns='http://éffbot.org/ns'\n" 6147db96d56Sopenharmony_ci b" xmlns:cl\xe9='http://effbot.org/ns'>text</body>\n") 6157db96d56Sopenharmony_ci events = ("start-ns",) 6167db96d56Sopenharmony_ci context = iterparse(source, events) 6177db96d56Sopenharmony_ci self.assertEqual([(action, elem) for action, elem in context], [ 6187db96d56Sopenharmony_ci ('start-ns', ('', 'http://\xe9ffbot.org/ns')), 6197db96d56Sopenharmony_ci ('start-ns', ('cl\xe9', 'http://effbot.org/ns')), 6207db96d56Sopenharmony_ci ]) 6217db96d56Sopenharmony_ci 6227db96d56Sopenharmony_ci source = io.StringIO("<document />junk") 6237db96d56Sopenharmony_ci it = iterparse(source) 6247db96d56Sopenharmony_ci action, elem = next(it) 6257db96d56Sopenharmony_ci self.assertEqual((action, elem.tag), ('end', 'document')) 6267db96d56Sopenharmony_ci with self.assertRaises(ET.ParseError) as cm: 6277db96d56Sopenharmony_ci next(it) 6287db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 6297db96d56Sopenharmony_ci 'junk after document element: line 1, column 12') 6307db96d56Sopenharmony_ci 6317db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN) 6327db96d56Sopenharmony_ci with open(TESTFN, "wb") as f: 6337db96d56Sopenharmony_ci f.write(b"<document />junk") 6347db96d56Sopenharmony_ci it = iterparse(TESTFN) 6357db96d56Sopenharmony_ci action, elem = next(it) 6367db96d56Sopenharmony_ci self.assertEqual((action, elem.tag), ('end', 'document')) 6377db96d56Sopenharmony_ci with warnings_helper.check_no_resource_warning(self): 6387db96d56Sopenharmony_ci with self.assertRaises(ET.ParseError) as cm: 6397db96d56Sopenharmony_ci next(it) 6407db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 6417db96d56Sopenharmony_ci 'junk after document element: line 1, column 12') 6427db96d56Sopenharmony_ci del cm, it 6437db96d56Sopenharmony_ci 6447db96d56Sopenharmony_ci # Not exhausting the iterator still closes the resource (bpo-43292) 6457db96d56Sopenharmony_ci with warnings_helper.check_no_resource_warning(self): 6467db96d56Sopenharmony_ci it = iterparse(TESTFN) 6477db96d56Sopenharmony_ci del it 6487db96d56Sopenharmony_ci 6497db96d56Sopenharmony_ci with self.assertRaises(FileNotFoundError): 6507db96d56Sopenharmony_ci iterparse("nonexistent") 6517db96d56Sopenharmony_ci 6527db96d56Sopenharmony_ci def test_writefile(self): 6537db96d56Sopenharmony_ci elem = ET.Element("tag") 6547db96d56Sopenharmony_ci elem.text = "text" 6557db96d56Sopenharmony_ci self.serialize_check(elem, '<tag>text</tag>') 6567db96d56Sopenharmony_ci ET.SubElement(elem, "subtag").text = "subtext" 6577db96d56Sopenharmony_ci self.serialize_check(elem, '<tag>text<subtag>subtext</subtag></tag>') 6587db96d56Sopenharmony_ci 6597db96d56Sopenharmony_ci # Test tag suppression 6607db96d56Sopenharmony_ci elem.tag = None 6617db96d56Sopenharmony_ci self.serialize_check(elem, 'text<subtag>subtext</subtag>') 6627db96d56Sopenharmony_ci elem.insert(0, ET.Comment("comment")) 6637db96d56Sopenharmony_ci self.serialize_check(elem, 6647db96d56Sopenharmony_ci 'text<!--comment--><subtag>subtext</subtag>') # assumes 1.3 6657db96d56Sopenharmony_ci 6667db96d56Sopenharmony_ci elem[0] = ET.PI("key", "value") 6677db96d56Sopenharmony_ci self.serialize_check(elem, 'text<?key value?><subtag>subtext</subtag>') 6687db96d56Sopenharmony_ci 6697db96d56Sopenharmony_ci def test_custom_builder(self): 6707db96d56Sopenharmony_ci # Test parser w. custom builder. 6717db96d56Sopenharmony_ci 6727db96d56Sopenharmony_ci with open(SIMPLE_XMLFILE) as f: 6737db96d56Sopenharmony_ci data = f.read() 6747db96d56Sopenharmony_ci class Builder(list): 6757db96d56Sopenharmony_ci def start(self, tag, attrib): 6767db96d56Sopenharmony_ci self.append(("start", tag)) 6777db96d56Sopenharmony_ci def end(self, tag): 6787db96d56Sopenharmony_ci self.append(("end", tag)) 6797db96d56Sopenharmony_ci def data(self, text): 6807db96d56Sopenharmony_ci pass 6817db96d56Sopenharmony_ci builder = Builder() 6827db96d56Sopenharmony_ci parser = ET.XMLParser(target=builder) 6837db96d56Sopenharmony_ci parser.feed(data) 6847db96d56Sopenharmony_ci self.assertEqual(builder, [ 6857db96d56Sopenharmony_ci ('start', 'root'), 6867db96d56Sopenharmony_ci ('start', 'element'), 6877db96d56Sopenharmony_ci ('end', 'element'), 6887db96d56Sopenharmony_ci ('start', 'element'), 6897db96d56Sopenharmony_ci ('end', 'element'), 6907db96d56Sopenharmony_ci ('start', 'empty-element'), 6917db96d56Sopenharmony_ci ('end', 'empty-element'), 6927db96d56Sopenharmony_ci ('end', 'root'), 6937db96d56Sopenharmony_ci ]) 6947db96d56Sopenharmony_ci 6957db96d56Sopenharmony_ci with open(SIMPLE_NS_XMLFILE) as f: 6967db96d56Sopenharmony_ci data = f.read() 6977db96d56Sopenharmony_ci class Builder(list): 6987db96d56Sopenharmony_ci def start(self, tag, attrib): 6997db96d56Sopenharmony_ci self.append(("start", tag)) 7007db96d56Sopenharmony_ci def end(self, tag): 7017db96d56Sopenharmony_ci self.append(("end", tag)) 7027db96d56Sopenharmony_ci def data(self, text): 7037db96d56Sopenharmony_ci pass 7047db96d56Sopenharmony_ci def pi(self, target, data): 7057db96d56Sopenharmony_ci self.append(("pi", target, data)) 7067db96d56Sopenharmony_ci def comment(self, data): 7077db96d56Sopenharmony_ci self.append(("comment", data)) 7087db96d56Sopenharmony_ci def start_ns(self, prefix, uri): 7097db96d56Sopenharmony_ci self.append(("start-ns", prefix, uri)) 7107db96d56Sopenharmony_ci def end_ns(self, prefix): 7117db96d56Sopenharmony_ci self.append(("end-ns", prefix)) 7127db96d56Sopenharmony_ci builder = Builder() 7137db96d56Sopenharmony_ci parser = ET.XMLParser(target=builder) 7147db96d56Sopenharmony_ci parser.feed(data) 7157db96d56Sopenharmony_ci self.assertEqual(builder, [ 7167db96d56Sopenharmony_ci ('pi', 'pi', 'data'), 7177db96d56Sopenharmony_ci ('comment', ' comment '), 7187db96d56Sopenharmony_ci ('start-ns', '', 'namespace'), 7197db96d56Sopenharmony_ci ('start', '{namespace}root'), 7207db96d56Sopenharmony_ci ('start', '{namespace}element'), 7217db96d56Sopenharmony_ci ('end', '{namespace}element'), 7227db96d56Sopenharmony_ci ('start', '{namespace}element'), 7237db96d56Sopenharmony_ci ('end', '{namespace}element'), 7247db96d56Sopenharmony_ci ('start', '{namespace}empty-element'), 7257db96d56Sopenharmony_ci ('end', '{namespace}empty-element'), 7267db96d56Sopenharmony_ci ('end', '{namespace}root'), 7277db96d56Sopenharmony_ci ('end-ns', ''), 7287db96d56Sopenharmony_ci ]) 7297db96d56Sopenharmony_ci 7307db96d56Sopenharmony_ci def test_custom_builder_only_end_ns(self): 7317db96d56Sopenharmony_ci class Builder(list): 7327db96d56Sopenharmony_ci def end_ns(self, prefix): 7337db96d56Sopenharmony_ci self.append(("end-ns", prefix)) 7347db96d56Sopenharmony_ci 7357db96d56Sopenharmony_ci builder = Builder() 7367db96d56Sopenharmony_ci parser = ET.XMLParser(target=builder) 7377db96d56Sopenharmony_ci parser.feed(textwrap.dedent("""\ 7387db96d56Sopenharmony_ci <?pi data?> 7397db96d56Sopenharmony_ci <!-- comment --> 7407db96d56Sopenharmony_ci <root xmlns='namespace' xmlns:p='pns' xmlns:a='ans'> 7417db96d56Sopenharmony_ci <a:element key='value'>text</a:element> 7427db96d56Sopenharmony_ci <p:element>text</p:element>tail 7437db96d56Sopenharmony_ci <empty-element/> 7447db96d56Sopenharmony_ci </root> 7457db96d56Sopenharmony_ci """)) 7467db96d56Sopenharmony_ci self.assertEqual(builder, [ 7477db96d56Sopenharmony_ci ('end-ns', 'a'), 7487db96d56Sopenharmony_ci ('end-ns', 'p'), 7497db96d56Sopenharmony_ci ('end-ns', ''), 7507db96d56Sopenharmony_ci ]) 7517db96d56Sopenharmony_ci 7527db96d56Sopenharmony_ci def test_initialize_parser_without_target(self): 7537db96d56Sopenharmony_ci # Explicit None 7547db96d56Sopenharmony_ci parser = ET.XMLParser(target=None) 7557db96d56Sopenharmony_ci self.assertIsInstance(parser.target, ET.TreeBuilder) 7567db96d56Sopenharmony_ci 7577db96d56Sopenharmony_ci # Implicit None 7587db96d56Sopenharmony_ci parser2 = ET.XMLParser() 7597db96d56Sopenharmony_ci self.assertIsInstance(parser2.target, ET.TreeBuilder) 7607db96d56Sopenharmony_ci 7617db96d56Sopenharmony_ci def test_children(self): 7627db96d56Sopenharmony_ci # Test Element children iteration 7637db96d56Sopenharmony_ci 7647db96d56Sopenharmony_ci with open(SIMPLE_XMLFILE, "rb") as f: 7657db96d56Sopenharmony_ci tree = ET.parse(f) 7667db96d56Sopenharmony_ci self.assertEqual([summarize_list(elem) 7677db96d56Sopenharmony_ci for elem in tree.getroot().iter()], [ 7687db96d56Sopenharmony_ci ['element', 'element', 'empty-element'], 7697db96d56Sopenharmony_ci [], 7707db96d56Sopenharmony_ci [], 7717db96d56Sopenharmony_ci [], 7727db96d56Sopenharmony_ci ]) 7737db96d56Sopenharmony_ci self.assertEqual([summarize_list(elem) 7747db96d56Sopenharmony_ci for elem in tree.iter()], [ 7757db96d56Sopenharmony_ci ['element', 'element', 'empty-element'], 7767db96d56Sopenharmony_ci [], 7777db96d56Sopenharmony_ci [], 7787db96d56Sopenharmony_ci [], 7797db96d56Sopenharmony_ci ]) 7807db96d56Sopenharmony_ci 7817db96d56Sopenharmony_ci elem = ET.XML(SAMPLE_XML) 7827db96d56Sopenharmony_ci self.assertEqual(len(list(elem)), 3) 7837db96d56Sopenharmony_ci self.assertEqual(len(list(elem[2])), 1) 7847db96d56Sopenharmony_ci self.assertEqual(elem[:], list(elem)) 7857db96d56Sopenharmony_ci child1 = elem[0] 7867db96d56Sopenharmony_ci child2 = elem[2] 7877db96d56Sopenharmony_ci del elem[1:2] 7887db96d56Sopenharmony_ci self.assertEqual(len(list(elem)), 2) 7897db96d56Sopenharmony_ci self.assertEqual(child1, elem[0]) 7907db96d56Sopenharmony_ci self.assertEqual(child2, elem[1]) 7917db96d56Sopenharmony_ci elem[0:2] = [child2, child1] 7927db96d56Sopenharmony_ci self.assertEqual(child2, elem[0]) 7937db96d56Sopenharmony_ci self.assertEqual(child1, elem[1]) 7947db96d56Sopenharmony_ci self.assertNotEqual(child1, elem[0]) 7957db96d56Sopenharmony_ci elem.clear() 7967db96d56Sopenharmony_ci self.assertEqual(list(elem), []) 7977db96d56Sopenharmony_ci 7987db96d56Sopenharmony_ci def test_writestring(self): 7997db96d56Sopenharmony_ci elem = ET.XML("<html><body>text</body></html>") 8007db96d56Sopenharmony_ci self.assertEqual(ET.tostring(elem), b'<html><body>text</body></html>') 8017db96d56Sopenharmony_ci elem = ET.fromstring("<html><body>text</body></html>") 8027db96d56Sopenharmony_ci self.assertEqual(ET.tostring(elem), b'<html><body>text</body></html>') 8037db96d56Sopenharmony_ci 8047db96d56Sopenharmony_ci def test_indent(self): 8057db96d56Sopenharmony_ci elem = ET.XML("<root></root>") 8067db96d56Sopenharmony_ci ET.indent(elem) 8077db96d56Sopenharmony_ci self.assertEqual(ET.tostring(elem), b'<root />') 8087db96d56Sopenharmony_ci 8097db96d56Sopenharmony_ci elem = ET.XML("<html><body>text</body></html>") 8107db96d56Sopenharmony_ci ET.indent(elem) 8117db96d56Sopenharmony_ci self.assertEqual(ET.tostring(elem), b'<html>\n <body>text</body>\n</html>') 8127db96d56Sopenharmony_ci 8137db96d56Sopenharmony_ci elem = ET.XML("<html> <body>text</body> </html>") 8147db96d56Sopenharmony_ci ET.indent(elem) 8157db96d56Sopenharmony_ci self.assertEqual(ET.tostring(elem), b'<html>\n <body>text</body>\n</html>') 8167db96d56Sopenharmony_ci 8177db96d56Sopenharmony_ci elem = ET.XML("<html><body>text</body>tail</html>") 8187db96d56Sopenharmony_ci ET.indent(elem) 8197db96d56Sopenharmony_ci self.assertEqual(ET.tostring(elem), b'<html>\n <body>text</body>tail</html>') 8207db96d56Sopenharmony_ci 8217db96d56Sopenharmony_ci elem = ET.XML("<html><body><p>par</p>\n<p>text</p>\t<p><br/></p></body></html>") 8227db96d56Sopenharmony_ci ET.indent(elem) 8237db96d56Sopenharmony_ci self.assertEqual( 8247db96d56Sopenharmony_ci ET.tostring(elem), 8257db96d56Sopenharmony_ci b'<html>\n' 8267db96d56Sopenharmony_ci b' <body>\n' 8277db96d56Sopenharmony_ci b' <p>par</p>\n' 8287db96d56Sopenharmony_ci b' <p>text</p>\n' 8297db96d56Sopenharmony_ci b' <p>\n' 8307db96d56Sopenharmony_ci b' <br />\n' 8317db96d56Sopenharmony_ci b' </p>\n' 8327db96d56Sopenharmony_ci b' </body>\n' 8337db96d56Sopenharmony_ci b'</html>' 8347db96d56Sopenharmony_ci ) 8357db96d56Sopenharmony_ci 8367db96d56Sopenharmony_ci elem = ET.XML("<html><body><p>pre<br/>post</p><p>text</p></body></html>") 8377db96d56Sopenharmony_ci ET.indent(elem) 8387db96d56Sopenharmony_ci self.assertEqual( 8397db96d56Sopenharmony_ci ET.tostring(elem), 8407db96d56Sopenharmony_ci b'<html>\n' 8417db96d56Sopenharmony_ci b' <body>\n' 8427db96d56Sopenharmony_ci b' <p>pre<br />post</p>\n' 8437db96d56Sopenharmony_ci b' <p>text</p>\n' 8447db96d56Sopenharmony_ci b' </body>\n' 8457db96d56Sopenharmony_ci b'</html>' 8467db96d56Sopenharmony_ci ) 8477db96d56Sopenharmony_ci 8487db96d56Sopenharmony_ci def test_indent_space(self): 8497db96d56Sopenharmony_ci elem = ET.XML("<html><body><p>pre<br/>post</p><p>text</p></body></html>") 8507db96d56Sopenharmony_ci ET.indent(elem, space='\t') 8517db96d56Sopenharmony_ci self.assertEqual( 8527db96d56Sopenharmony_ci ET.tostring(elem), 8537db96d56Sopenharmony_ci b'<html>\n' 8547db96d56Sopenharmony_ci b'\t<body>\n' 8557db96d56Sopenharmony_ci b'\t\t<p>pre<br />post</p>\n' 8567db96d56Sopenharmony_ci b'\t\t<p>text</p>\n' 8577db96d56Sopenharmony_ci b'\t</body>\n' 8587db96d56Sopenharmony_ci b'</html>' 8597db96d56Sopenharmony_ci ) 8607db96d56Sopenharmony_ci 8617db96d56Sopenharmony_ci elem = ET.XML("<html><body><p>pre<br/>post</p><p>text</p></body></html>") 8627db96d56Sopenharmony_ci ET.indent(elem, space='') 8637db96d56Sopenharmony_ci self.assertEqual( 8647db96d56Sopenharmony_ci ET.tostring(elem), 8657db96d56Sopenharmony_ci b'<html>\n' 8667db96d56Sopenharmony_ci b'<body>\n' 8677db96d56Sopenharmony_ci b'<p>pre<br />post</p>\n' 8687db96d56Sopenharmony_ci b'<p>text</p>\n' 8697db96d56Sopenharmony_ci b'</body>\n' 8707db96d56Sopenharmony_ci b'</html>' 8717db96d56Sopenharmony_ci ) 8727db96d56Sopenharmony_ci 8737db96d56Sopenharmony_ci def test_indent_space_caching(self): 8747db96d56Sopenharmony_ci elem = ET.XML("<html><body><p>par</p><p>text</p><p><br/></p><p /></body></html>") 8757db96d56Sopenharmony_ci ET.indent(elem) 8767db96d56Sopenharmony_ci self.assertEqual( 8777db96d56Sopenharmony_ci {el.tail for el in elem.iter()}, 8787db96d56Sopenharmony_ci {None, "\n", "\n ", "\n "} 8797db96d56Sopenharmony_ci ) 8807db96d56Sopenharmony_ci self.assertEqual( 8817db96d56Sopenharmony_ci {el.text for el in elem.iter()}, 8827db96d56Sopenharmony_ci {None, "\n ", "\n ", "\n ", "par", "text"} 8837db96d56Sopenharmony_ci ) 8847db96d56Sopenharmony_ci self.assertEqual( 8857db96d56Sopenharmony_ci len({el.tail for el in elem.iter()}), 8867db96d56Sopenharmony_ci len({id(el.tail) for el in elem.iter()}), 8877db96d56Sopenharmony_ci ) 8887db96d56Sopenharmony_ci 8897db96d56Sopenharmony_ci def test_indent_level(self): 8907db96d56Sopenharmony_ci elem = ET.XML("<html><body><p>pre<br/>post</p><p>text</p></body></html>") 8917db96d56Sopenharmony_ci with self.assertRaises(ValueError): 8927db96d56Sopenharmony_ci ET.indent(elem, level=-1) 8937db96d56Sopenharmony_ci self.assertEqual( 8947db96d56Sopenharmony_ci ET.tostring(elem), 8957db96d56Sopenharmony_ci b"<html><body><p>pre<br />post</p><p>text</p></body></html>" 8967db96d56Sopenharmony_ci ) 8977db96d56Sopenharmony_ci 8987db96d56Sopenharmony_ci ET.indent(elem, level=2) 8997db96d56Sopenharmony_ci self.assertEqual( 9007db96d56Sopenharmony_ci ET.tostring(elem), 9017db96d56Sopenharmony_ci b'<html>\n' 9027db96d56Sopenharmony_ci b' <body>\n' 9037db96d56Sopenharmony_ci b' <p>pre<br />post</p>\n' 9047db96d56Sopenharmony_ci b' <p>text</p>\n' 9057db96d56Sopenharmony_ci b' </body>\n' 9067db96d56Sopenharmony_ci b' </html>' 9077db96d56Sopenharmony_ci ) 9087db96d56Sopenharmony_ci 9097db96d56Sopenharmony_ci elem = ET.XML("<html><body><p>pre<br/>post</p><p>text</p></body></html>") 9107db96d56Sopenharmony_ci ET.indent(elem, level=1, space=' ') 9117db96d56Sopenharmony_ci self.assertEqual( 9127db96d56Sopenharmony_ci ET.tostring(elem), 9137db96d56Sopenharmony_ci b'<html>\n' 9147db96d56Sopenharmony_ci b' <body>\n' 9157db96d56Sopenharmony_ci b' <p>pre<br />post</p>\n' 9167db96d56Sopenharmony_ci b' <p>text</p>\n' 9177db96d56Sopenharmony_ci b' </body>\n' 9187db96d56Sopenharmony_ci b' </html>' 9197db96d56Sopenharmony_ci ) 9207db96d56Sopenharmony_ci 9217db96d56Sopenharmony_ci def test_tostring_default_namespace(self): 9227db96d56Sopenharmony_ci elem = ET.XML('<body xmlns="http://effbot.org/ns"><tag/></body>') 9237db96d56Sopenharmony_ci self.assertEqual( 9247db96d56Sopenharmony_ci ET.tostring(elem, encoding='unicode'), 9257db96d56Sopenharmony_ci '<ns0:body xmlns:ns0="http://effbot.org/ns"><ns0:tag /></ns0:body>' 9267db96d56Sopenharmony_ci ) 9277db96d56Sopenharmony_ci self.assertEqual( 9287db96d56Sopenharmony_ci ET.tostring(elem, encoding='unicode', default_namespace='http://effbot.org/ns'), 9297db96d56Sopenharmony_ci '<body xmlns="http://effbot.org/ns"><tag /></body>' 9307db96d56Sopenharmony_ci ) 9317db96d56Sopenharmony_ci 9327db96d56Sopenharmony_ci def test_tostring_default_namespace_different_namespace(self): 9337db96d56Sopenharmony_ci elem = ET.XML('<body xmlns="http://effbot.org/ns"><tag/></body>') 9347db96d56Sopenharmony_ci self.assertEqual( 9357db96d56Sopenharmony_ci ET.tostring(elem, encoding='unicode', default_namespace='foobar'), 9367db96d56Sopenharmony_ci '<ns1:body xmlns="foobar" xmlns:ns1="http://effbot.org/ns"><ns1:tag /></ns1:body>' 9377db96d56Sopenharmony_ci ) 9387db96d56Sopenharmony_ci 9397db96d56Sopenharmony_ci def test_tostring_default_namespace_original_no_namespace(self): 9407db96d56Sopenharmony_ci elem = ET.XML('<body><tag/></body>') 9417db96d56Sopenharmony_ci EXPECTED_MSG = '^cannot use non-qualified names with default_namespace option$' 9427db96d56Sopenharmony_ci with self.assertRaisesRegex(ValueError, EXPECTED_MSG): 9437db96d56Sopenharmony_ci ET.tostring(elem, encoding='unicode', default_namespace='foobar') 9447db96d56Sopenharmony_ci 9457db96d56Sopenharmony_ci def test_tostring_no_xml_declaration(self): 9467db96d56Sopenharmony_ci elem = ET.XML('<body><tag/></body>') 9477db96d56Sopenharmony_ci self.assertEqual( 9487db96d56Sopenharmony_ci ET.tostring(elem, encoding='unicode'), 9497db96d56Sopenharmony_ci '<body><tag /></body>' 9507db96d56Sopenharmony_ci ) 9517db96d56Sopenharmony_ci 9527db96d56Sopenharmony_ci def test_tostring_xml_declaration(self): 9537db96d56Sopenharmony_ci elem = ET.XML('<body><tag/></body>') 9547db96d56Sopenharmony_ci self.assertEqual( 9557db96d56Sopenharmony_ci ET.tostring(elem, encoding='utf8', xml_declaration=True), 9567db96d56Sopenharmony_ci b"<?xml version='1.0' encoding='utf8'?>\n<body><tag /></body>" 9577db96d56Sopenharmony_ci ) 9587db96d56Sopenharmony_ci 9597db96d56Sopenharmony_ci def test_tostring_xml_declaration_unicode_encoding(self): 9607db96d56Sopenharmony_ci elem = ET.XML('<body><tag/></body>') 9617db96d56Sopenharmony_ci self.assertEqual( 9627db96d56Sopenharmony_ci ET.tostring(elem, encoding='unicode', xml_declaration=True), 9637db96d56Sopenharmony_ci "<?xml version='1.0' encoding='utf-8'?>\n<body><tag /></body>" 9647db96d56Sopenharmony_ci ) 9657db96d56Sopenharmony_ci 9667db96d56Sopenharmony_ci def test_tostring_xml_declaration_cases(self): 9677db96d56Sopenharmony_ci elem = ET.XML('<body><tag>ø</tag></body>') 9687db96d56Sopenharmony_ci TESTCASES = [ 9697db96d56Sopenharmony_ci # (expected_retval, encoding, xml_declaration) 9707db96d56Sopenharmony_ci # ... xml_declaration = None 9717db96d56Sopenharmony_ci (b'<body><tag>ø</tag></body>', None, None), 9727db96d56Sopenharmony_ci (b'<body><tag>\xc3\xb8</tag></body>', 'UTF-8', None), 9737db96d56Sopenharmony_ci (b'<body><tag>ø</tag></body>', 'US-ASCII', None), 9747db96d56Sopenharmony_ci (b"<?xml version='1.0' encoding='ISO-8859-1'?>\n" 9757db96d56Sopenharmony_ci b"<body><tag>\xf8</tag></body>", 'ISO-8859-1', None), 9767db96d56Sopenharmony_ci ('<body><tag>ø</tag></body>', 'unicode', None), 9777db96d56Sopenharmony_ci 9787db96d56Sopenharmony_ci # ... xml_declaration = False 9797db96d56Sopenharmony_ci (b"<body><tag>ø</tag></body>", None, False), 9807db96d56Sopenharmony_ci (b"<body><tag>\xc3\xb8</tag></body>", 'UTF-8', False), 9817db96d56Sopenharmony_ci (b"<body><tag>ø</tag></body>", 'US-ASCII', False), 9827db96d56Sopenharmony_ci (b"<body><tag>\xf8</tag></body>", 'ISO-8859-1', False), 9837db96d56Sopenharmony_ci ("<body><tag>ø</tag></body>", 'unicode', False), 9847db96d56Sopenharmony_ci 9857db96d56Sopenharmony_ci # ... xml_declaration = True 9867db96d56Sopenharmony_ci (b"<?xml version='1.0' encoding='us-ascii'?>\n" 9877db96d56Sopenharmony_ci b"<body><tag>ø</tag></body>", None, True), 9887db96d56Sopenharmony_ci (b"<?xml version='1.0' encoding='UTF-8'?>\n" 9897db96d56Sopenharmony_ci b"<body><tag>\xc3\xb8</tag></body>", 'UTF-8', True), 9907db96d56Sopenharmony_ci (b"<?xml version='1.0' encoding='US-ASCII'?>\n" 9917db96d56Sopenharmony_ci b"<body><tag>ø</tag></body>", 'US-ASCII', True), 9927db96d56Sopenharmony_ci (b"<?xml version='1.0' encoding='ISO-8859-1'?>\n" 9937db96d56Sopenharmony_ci b"<body><tag>\xf8</tag></body>", 'ISO-8859-1', True), 9947db96d56Sopenharmony_ci ("<?xml version='1.0' encoding='utf-8'?>\n" 9957db96d56Sopenharmony_ci "<body><tag>ø</tag></body>", 'unicode', True), 9967db96d56Sopenharmony_ci 9977db96d56Sopenharmony_ci ] 9987db96d56Sopenharmony_ci for expected_retval, encoding, xml_declaration in TESTCASES: 9997db96d56Sopenharmony_ci with self.subTest(f'encoding={encoding} ' 10007db96d56Sopenharmony_ci f'xml_declaration={xml_declaration}'): 10017db96d56Sopenharmony_ci self.assertEqual( 10027db96d56Sopenharmony_ci ET.tostring( 10037db96d56Sopenharmony_ci elem, 10047db96d56Sopenharmony_ci encoding=encoding, 10057db96d56Sopenharmony_ci xml_declaration=xml_declaration 10067db96d56Sopenharmony_ci ), 10077db96d56Sopenharmony_ci expected_retval 10087db96d56Sopenharmony_ci ) 10097db96d56Sopenharmony_ci 10107db96d56Sopenharmony_ci def test_tostringlist_default_namespace(self): 10117db96d56Sopenharmony_ci elem = ET.XML('<body xmlns="http://effbot.org/ns"><tag/></body>') 10127db96d56Sopenharmony_ci self.assertEqual( 10137db96d56Sopenharmony_ci ''.join(ET.tostringlist(elem, encoding='unicode')), 10147db96d56Sopenharmony_ci '<ns0:body xmlns:ns0="http://effbot.org/ns"><ns0:tag /></ns0:body>' 10157db96d56Sopenharmony_ci ) 10167db96d56Sopenharmony_ci self.assertEqual( 10177db96d56Sopenharmony_ci ''.join(ET.tostringlist(elem, encoding='unicode', default_namespace='http://effbot.org/ns')), 10187db96d56Sopenharmony_ci '<body xmlns="http://effbot.org/ns"><tag /></body>' 10197db96d56Sopenharmony_ci ) 10207db96d56Sopenharmony_ci 10217db96d56Sopenharmony_ci def test_tostringlist_xml_declaration(self): 10227db96d56Sopenharmony_ci elem = ET.XML('<body><tag/></body>') 10237db96d56Sopenharmony_ci self.assertEqual( 10247db96d56Sopenharmony_ci ''.join(ET.tostringlist(elem, encoding='unicode')), 10257db96d56Sopenharmony_ci '<body><tag /></body>' 10267db96d56Sopenharmony_ci ) 10277db96d56Sopenharmony_ci self.assertEqual( 10287db96d56Sopenharmony_ci b''.join(ET.tostringlist(elem, xml_declaration=True)), 10297db96d56Sopenharmony_ci b"<?xml version='1.0' encoding='us-ascii'?>\n<body><tag /></body>" 10307db96d56Sopenharmony_ci ) 10317db96d56Sopenharmony_ci 10327db96d56Sopenharmony_ci stringlist = ET.tostringlist(elem, encoding='unicode', xml_declaration=True) 10337db96d56Sopenharmony_ci self.assertEqual( 10347db96d56Sopenharmony_ci ''.join(stringlist), 10357db96d56Sopenharmony_ci "<?xml version='1.0' encoding='utf-8'?>\n<body><tag /></body>" 10367db96d56Sopenharmony_ci ) 10377db96d56Sopenharmony_ci self.assertRegex(stringlist[0], r"^<\?xml version='1.0' encoding='.+'?>") 10387db96d56Sopenharmony_ci self.assertEqual(['<body', '>', '<tag', ' />', '</body>'], stringlist[1:]) 10397db96d56Sopenharmony_ci 10407db96d56Sopenharmony_ci def test_encoding(self): 10417db96d56Sopenharmony_ci def check(encoding, body=''): 10427db96d56Sopenharmony_ci xml = ("<?xml version='1.0' encoding='%s'?><xml>%s</xml>" % 10437db96d56Sopenharmony_ci (encoding, body)) 10447db96d56Sopenharmony_ci self.assertEqual(ET.XML(xml.encode(encoding)).text, body) 10457db96d56Sopenharmony_ci self.assertEqual(ET.XML(xml).text, body) 10467db96d56Sopenharmony_ci check("ascii", 'a') 10477db96d56Sopenharmony_ci check("us-ascii", 'a') 10487db96d56Sopenharmony_ci check("iso-8859-1", '\xbd') 10497db96d56Sopenharmony_ci check("iso-8859-15", '\u20ac') 10507db96d56Sopenharmony_ci check("cp437", '\u221a') 10517db96d56Sopenharmony_ci check("mac-roman", '\u02da') 10527db96d56Sopenharmony_ci 10537db96d56Sopenharmony_ci def xml(encoding): 10547db96d56Sopenharmony_ci return "<?xml version='1.0' encoding='%s'?><xml />" % encoding 10557db96d56Sopenharmony_ci def bxml(encoding): 10567db96d56Sopenharmony_ci return xml(encoding).encode(encoding) 10577db96d56Sopenharmony_ci supported_encodings = [ 10587db96d56Sopenharmony_ci 'ascii', 'utf-8', 'utf-8-sig', 'utf-16', 'utf-16be', 'utf-16le', 10597db96d56Sopenharmony_ci 'iso8859-1', 'iso8859-2', 'iso8859-3', 'iso8859-4', 'iso8859-5', 10607db96d56Sopenharmony_ci 'iso8859-6', 'iso8859-7', 'iso8859-8', 'iso8859-9', 'iso8859-10', 10617db96d56Sopenharmony_ci 'iso8859-13', 'iso8859-14', 'iso8859-15', 'iso8859-16', 10627db96d56Sopenharmony_ci 'cp437', 'cp720', 'cp737', 'cp775', 'cp850', 'cp852', 10637db96d56Sopenharmony_ci 'cp855', 'cp856', 'cp857', 'cp858', 'cp860', 'cp861', 'cp862', 10647db96d56Sopenharmony_ci 'cp863', 'cp865', 'cp866', 'cp869', 'cp874', 'cp1006', 'cp1125', 10657db96d56Sopenharmony_ci 'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255', 10667db96d56Sopenharmony_ci 'cp1256', 'cp1257', 'cp1258', 10677db96d56Sopenharmony_ci 'mac-cyrillic', 'mac-greek', 'mac-iceland', 'mac-latin2', 10687db96d56Sopenharmony_ci 'mac-roman', 'mac-turkish', 10697db96d56Sopenharmony_ci 'iso2022-jp', 'iso2022-jp-1', 'iso2022-jp-2', 'iso2022-jp-2004', 10707db96d56Sopenharmony_ci 'iso2022-jp-3', 'iso2022-jp-ext', 10717db96d56Sopenharmony_ci 'koi8-r', 'koi8-t', 'koi8-u', 'kz1048', 10727db96d56Sopenharmony_ci 'hz', 'ptcp154', 10737db96d56Sopenharmony_ci ] 10747db96d56Sopenharmony_ci for encoding in supported_encodings: 10757db96d56Sopenharmony_ci self.assertEqual(ET.tostring(ET.XML(bxml(encoding))), b'<xml />') 10767db96d56Sopenharmony_ci 10777db96d56Sopenharmony_ci unsupported_ascii_compatible_encodings = [ 10787db96d56Sopenharmony_ci 'big5', 'big5hkscs', 10797db96d56Sopenharmony_ci 'cp932', 'cp949', 'cp950', 10807db96d56Sopenharmony_ci 'euc-jp', 'euc-jis-2004', 'euc-jisx0213', 'euc-kr', 10817db96d56Sopenharmony_ci 'gb2312', 'gbk', 'gb18030', 10827db96d56Sopenharmony_ci 'iso2022-kr', 'johab', 10837db96d56Sopenharmony_ci 'shift-jis', 'shift-jis-2004', 'shift-jisx0213', 10847db96d56Sopenharmony_ci 'utf-7', 10857db96d56Sopenharmony_ci ] 10867db96d56Sopenharmony_ci for encoding in unsupported_ascii_compatible_encodings: 10877db96d56Sopenharmony_ci self.assertRaises(ValueError, ET.XML, bxml(encoding)) 10887db96d56Sopenharmony_ci 10897db96d56Sopenharmony_ci unsupported_ascii_incompatible_encodings = [ 10907db96d56Sopenharmony_ci 'cp037', 'cp424', 'cp500', 'cp864', 'cp875', 'cp1026', 'cp1140', 10917db96d56Sopenharmony_ci 'utf_32', 'utf_32_be', 'utf_32_le', 10927db96d56Sopenharmony_ci ] 10937db96d56Sopenharmony_ci for encoding in unsupported_ascii_incompatible_encodings: 10947db96d56Sopenharmony_ci self.assertRaises(ET.ParseError, ET.XML, bxml(encoding)) 10957db96d56Sopenharmony_ci 10967db96d56Sopenharmony_ci self.assertRaises(ValueError, ET.XML, xml('undefined').encode('ascii')) 10977db96d56Sopenharmony_ci self.assertRaises(LookupError, ET.XML, xml('xxx').encode('ascii')) 10987db96d56Sopenharmony_ci 10997db96d56Sopenharmony_ci def test_methods(self): 11007db96d56Sopenharmony_ci # Test serialization methods. 11017db96d56Sopenharmony_ci 11027db96d56Sopenharmony_ci e = ET.XML("<html><link/><script>1 < 2</script></html>") 11037db96d56Sopenharmony_ci e.tail = "\n" 11047db96d56Sopenharmony_ci self.assertEqual(serialize(e), 11057db96d56Sopenharmony_ci '<html><link /><script>1 < 2</script></html>\n') 11067db96d56Sopenharmony_ci self.assertEqual(serialize(e, method=None), 11077db96d56Sopenharmony_ci '<html><link /><script>1 < 2</script></html>\n') 11087db96d56Sopenharmony_ci self.assertEqual(serialize(e, method="xml"), 11097db96d56Sopenharmony_ci '<html><link /><script>1 < 2</script></html>\n') 11107db96d56Sopenharmony_ci self.assertEqual(serialize(e, method="html"), 11117db96d56Sopenharmony_ci '<html><link><script>1 < 2</script></html>\n') 11127db96d56Sopenharmony_ci self.assertEqual(serialize(e, method="text"), '1 < 2\n') 11137db96d56Sopenharmony_ci 11147db96d56Sopenharmony_ci def test_issue18347(self): 11157db96d56Sopenharmony_ci e = ET.XML('<html><CamelCase>text</CamelCase></html>') 11167db96d56Sopenharmony_ci self.assertEqual(serialize(e), 11177db96d56Sopenharmony_ci '<html><CamelCase>text</CamelCase></html>') 11187db96d56Sopenharmony_ci self.assertEqual(serialize(e, method="html"), 11197db96d56Sopenharmony_ci '<html><CamelCase>text</CamelCase></html>') 11207db96d56Sopenharmony_ci 11217db96d56Sopenharmony_ci def test_entity(self): 11227db96d56Sopenharmony_ci # Test entity handling. 11237db96d56Sopenharmony_ci 11247db96d56Sopenharmony_ci # 1) good entities 11257db96d56Sopenharmony_ci 11267db96d56Sopenharmony_ci e = ET.XML("<document title='舰'>test</document>") 11277db96d56Sopenharmony_ci self.assertEqual(serialize(e, encoding="us-ascii"), 11287db96d56Sopenharmony_ci b'<document title="舰">test</document>') 11297db96d56Sopenharmony_ci self.serialize_check(e, '<document title="\u8230">test</document>') 11307db96d56Sopenharmony_ci 11317db96d56Sopenharmony_ci # 2) bad entities 11327db96d56Sopenharmony_ci 11337db96d56Sopenharmony_ci with self.assertRaises(ET.ParseError) as cm: 11347db96d56Sopenharmony_ci ET.XML("<document>&entity;</document>") 11357db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 11367db96d56Sopenharmony_ci 'undefined entity: line 1, column 10') 11377db96d56Sopenharmony_ci 11387db96d56Sopenharmony_ci with self.assertRaises(ET.ParseError) as cm: 11397db96d56Sopenharmony_ci ET.XML(ENTITY_XML) 11407db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 11417db96d56Sopenharmony_ci 'undefined entity &entity;: line 5, column 10') 11427db96d56Sopenharmony_ci 11437db96d56Sopenharmony_ci # 3) custom entity 11447db96d56Sopenharmony_ci 11457db96d56Sopenharmony_ci parser = ET.XMLParser() 11467db96d56Sopenharmony_ci parser.entity["entity"] = "text" 11477db96d56Sopenharmony_ci parser.feed(ENTITY_XML) 11487db96d56Sopenharmony_ci root = parser.close() 11497db96d56Sopenharmony_ci self.serialize_check(root, '<document>text</document>') 11507db96d56Sopenharmony_ci 11517db96d56Sopenharmony_ci # 4) external (SYSTEM) entity 11527db96d56Sopenharmony_ci 11537db96d56Sopenharmony_ci with self.assertRaises(ET.ParseError) as cm: 11547db96d56Sopenharmony_ci ET.XML(EXTERNAL_ENTITY_XML) 11557db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 11567db96d56Sopenharmony_ci 'undefined entity &entity;: line 4, column 10') 11577db96d56Sopenharmony_ci 11587db96d56Sopenharmony_ci def test_namespace(self): 11597db96d56Sopenharmony_ci # Test namespace issues. 11607db96d56Sopenharmony_ci 11617db96d56Sopenharmony_ci # 1) xml namespace 11627db96d56Sopenharmony_ci 11637db96d56Sopenharmony_ci elem = ET.XML("<tag xml:lang='en' />") 11647db96d56Sopenharmony_ci self.serialize_check(elem, '<tag xml:lang="en" />') # 1.1 11657db96d56Sopenharmony_ci 11667db96d56Sopenharmony_ci # 2) other "well-known" namespaces 11677db96d56Sopenharmony_ci 11687db96d56Sopenharmony_ci elem = ET.XML("<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' />") 11697db96d56Sopenharmony_ci self.serialize_check(elem, 11707db96d56Sopenharmony_ci '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" />') # 2.1 11717db96d56Sopenharmony_ci 11727db96d56Sopenharmony_ci elem = ET.XML("<html:html xmlns:html='http://www.w3.org/1999/xhtml' />") 11737db96d56Sopenharmony_ci self.serialize_check(elem, 11747db96d56Sopenharmony_ci '<html:html xmlns:html="http://www.w3.org/1999/xhtml" />') # 2.2 11757db96d56Sopenharmony_ci 11767db96d56Sopenharmony_ci elem = ET.XML("<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope' />") 11777db96d56Sopenharmony_ci self.serialize_check(elem, 11787db96d56Sopenharmony_ci '<ns0:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope" />') # 2.3 11797db96d56Sopenharmony_ci 11807db96d56Sopenharmony_ci # 3) unknown namespaces 11817db96d56Sopenharmony_ci elem = ET.XML(SAMPLE_XML_NS) 11827db96d56Sopenharmony_ci self.serialize_check(elem, 11837db96d56Sopenharmony_ci '<ns0:body xmlns:ns0="http://effbot.org/ns">\n' 11847db96d56Sopenharmony_ci ' <ns0:tag>text</ns0:tag>\n' 11857db96d56Sopenharmony_ci ' <ns0:tag />\n' 11867db96d56Sopenharmony_ci ' <ns0:section>\n' 11877db96d56Sopenharmony_ci ' <ns0:tag>subtext</ns0:tag>\n' 11887db96d56Sopenharmony_ci ' </ns0:section>\n' 11897db96d56Sopenharmony_ci '</ns0:body>') 11907db96d56Sopenharmony_ci 11917db96d56Sopenharmony_ci def test_qname(self): 11927db96d56Sopenharmony_ci # Test QName handling. 11937db96d56Sopenharmony_ci 11947db96d56Sopenharmony_ci # 1) decorated tags 11957db96d56Sopenharmony_ci 11967db96d56Sopenharmony_ci elem = ET.Element("{uri}tag") 11977db96d56Sopenharmony_ci self.serialize_check(elem, '<ns0:tag xmlns:ns0="uri" />') # 1.1 11987db96d56Sopenharmony_ci elem = ET.Element(ET.QName("{uri}tag")) 11997db96d56Sopenharmony_ci self.serialize_check(elem, '<ns0:tag xmlns:ns0="uri" />') # 1.2 12007db96d56Sopenharmony_ci elem = ET.Element(ET.QName("uri", "tag")) 12017db96d56Sopenharmony_ci self.serialize_check(elem, '<ns0:tag xmlns:ns0="uri" />') # 1.3 12027db96d56Sopenharmony_ci elem = ET.Element(ET.QName("uri", "tag")) 12037db96d56Sopenharmony_ci subelem = ET.SubElement(elem, ET.QName("uri", "tag1")) 12047db96d56Sopenharmony_ci subelem = ET.SubElement(elem, ET.QName("uri", "tag2")) 12057db96d56Sopenharmony_ci self.serialize_check(elem, 12067db96d56Sopenharmony_ci '<ns0:tag xmlns:ns0="uri"><ns0:tag1 /><ns0:tag2 /></ns0:tag>') # 1.4 12077db96d56Sopenharmony_ci 12087db96d56Sopenharmony_ci # 2) decorated attributes 12097db96d56Sopenharmony_ci 12107db96d56Sopenharmony_ci elem.clear() 12117db96d56Sopenharmony_ci elem.attrib["{uri}key"] = "value" 12127db96d56Sopenharmony_ci self.serialize_check(elem, 12137db96d56Sopenharmony_ci '<ns0:tag xmlns:ns0="uri" ns0:key="value" />') # 2.1 12147db96d56Sopenharmony_ci 12157db96d56Sopenharmony_ci elem.clear() 12167db96d56Sopenharmony_ci elem.attrib[ET.QName("{uri}key")] = "value" 12177db96d56Sopenharmony_ci self.serialize_check(elem, 12187db96d56Sopenharmony_ci '<ns0:tag xmlns:ns0="uri" ns0:key="value" />') # 2.2 12197db96d56Sopenharmony_ci 12207db96d56Sopenharmony_ci # 3) decorated values are not converted by default, but the 12217db96d56Sopenharmony_ci # QName wrapper can be used for values 12227db96d56Sopenharmony_ci 12237db96d56Sopenharmony_ci elem.clear() 12247db96d56Sopenharmony_ci elem.attrib["{uri}key"] = "{uri}value" 12257db96d56Sopenharmony_ci self.serialize_check(elem, 12267db96d56Sopenharmony_ci '<ns0:tag xmlns:ns0="uri" ns0:key="{uri}value" />') # 3.1 12277db96d56Sopenharmony_ci 12287db96d56Sopenharmony_ci elem.clear() 12297db96d56Sopenharmony_ci elem.attrib["{uri}key"] = ET.QName("{uri}value") 12307db96d56Sopenharmony_ci self.serialize_check(elem, 12317db96d56Sopenharmony_ci '<ns0:tag xmlns:ns0="uri" ns0:key="ns0:value" />') # 3.2 12327db96d56Sopenharmony_ci 12337db96d56Sopenharmony_ci elem.clear() 12347db96d56Sopenharmony_ci subelem = ET.Element("tag") 12357db96d56Sopenharmony_ci subelem.attrib["{uri1}key"] = ET.QName("{uri2}value") 12367db96d56Sopenharmony_ci elem.append(subelem) 12377db96d56Sopenharmony_ci elem.append(subelem) 12387db96d56Sopenharmony_ci self.serialize_check(elem, 12397db96d56Sopenharmony_ci '<ns0:tag xmlns:ns0="uri" xmlns:ns1="uri1" xmlns:ns2="uri2">' 12407db96d56Sopenharmony_ci '<tag ns1:key="ns2:value" />' 12417db96d56Sopenharmony_ci '<tag ns1:key="ns2:value" />' 12427db96d56Sopenharmony_ci '</ns0:tag>') # 3.3 12437db96d56Sopenharmony_ci 12447db96d56Sopenharmony_ci # 4) Direct QName tests 12457db96d56Sopenharmony_ci 12467db96d56Sopenharmony_ci self.assertEqual(str(ET.QName('ns', 'tag')), '{ns}tag') 12477db96d56Sopenharmony_ci self.assertEqual(str(ET.QName('{ns}tag')), '{ns}tag') 12487db96d56Sopenharmony_ci q1 = ET.QName('ns', 'tag') 12497db96d56Sopenharmony_ci q2 = ET.QName('ns', 'tag') 12507db96d56Sopenharmony_ci self.assertEqual(q1, q2) 12517db96d56Sopenharmony_ci q2 = ET.QName('ns', 'other-tag') 12527db96d56Sopenharmony_ci self.assertNotEqual(q1, q2) 12537db96d56Sopenharmony_ci self.assertNotEqual(q1, 'ns:tag') 12547db96d56Sopenharmony_ci self.assertEqual(q1, '{ns}tag') 12557db96d56Sopenharmony_ci 12567db96d56Sopenharmony_ci def test_doctype_public(self): 12577db96d56Sopenharmony_ci # Test PUBLIC doctype. 12587db96d56Sopenharmony_ci 12597db96d56Sopenharmony_ci elem = ET.XML('<!DOCTYPE html PUBLIC' 12607db96d56Sopenharmony_ci ' "-//W3C//DTD XHTML 1.0 Transitional//EN"' 12617db96d56Sopenharmony_ci ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' 12627db96d56Sopenharmony_ci '<html>text</html>') 12637db96d56Sopenharmony_ci 12647db96d56Sopenharmony_ci def test_xpath_tokenizer(self): 12657db96d56Sopenharmony_ci # Test the XPath tokenizer. 12667db96d56Sopenharmony_ci from xml.etree import ElementPath 12677db96d56Sopenharmony_ci def check(p, expected, namespaces=None): 12687db96d56Sopenharmony_ci self.assertEqual([op or tag 12697db96d56Sopenharmony_ci for op, tag in ElementPath.xpath_tokenizer(p, namespaces)], 12707db96d56Sopenharmony_ci expected) 12717db96d56Sopenharmony_ci 12727db96d56Sopenharmony_ci # tests from the xml specification 12737db96d56Sopenharmony_ci check("*", ['*']) 12747db96d56Sopenharmony_ci check("text()", ['text', '()']) 12757db96d56Sopenharmony_ci check("@name", ['@', 'name']) 12767db96d56Sopenharmony_ci check("@*", ['@', '*']) 12777db96d56Sopenharmony_ci check("para[1]", ['para', '[', '1', ']']) 12787db96d56Sopenharmony_ci check("para[last()]", ['para', '[', 'last', '()', ']']) 12797db96d56Sopenharmony_ci check("*/para", ['*', '/', 'para']) 12807db96d56Sopenharmony_ci check("/doc/chapter[5]/section[2]", 12817db96d56Sopenharmony_ci ['/', 'doc', '/', 'chapter', '[', '5', ']', 12827db96d56Sopenharmony_ci '/', 'section', '[', '2', ']']) 12837db96d56Sopenharmony_ci check("chapter//para", ['chapter', '//', 'para']) 12847db96d56Sopenharmony_ci check("//para", ['//', 'para']) 12857db96d56Sopenharmony_ci check("//olist/item", ['//', 'olist', '/', 'item']) 12867db96d56Sopenharmony_ci check(".", ['.']) 12877db96d56Sopenharmony_ci check(".//para", ['.', '//', 'para']) 12887db96d56Sopenharmony_ci check("..", ['..']) 12897db96d56Sopenharmony_ci check("../@lang", ['..', '/', '@', 'lang']) 12907db96d56Sopenharmony_ci check("chapter[title]", ['chapter', '[', 'title', ']']) 12917db96d56Sopenharmony_ci check("employee[@secretary and @assistant]", ['employee', 12927db96d56Sopenharmony_ci '[', '@', 'secretary', '', 'and', '', '@', 'assistant', ']']) 12937db96d56Sopenharmony_ci 12947db96d56Sopenharmony_ci # additional tests 12957db96d56Sopenharmony_ci check("@{ns}attr", ['@', '{ns}attr']) 12967db96d56Sopenharmony_ci check("{http://spam}egg", ['{http://spam}egg']) 12977db96d56Sopenharmony_ci check("./spam.egg", ['.', '/', 'spam.egg']) 12987db96d56Sopenharmony_ci check(".//{http://spam}egg", ['.', '//', '{http://spam}egg']) 12997db96d56Sopenharmony_ci 13007db96d56Sopenharmony_ci # wildcard tags 13017db96d56Sopenharmony_ci check("{ns}*", ['{ns}*']) 13027db96d56Sopenharmony_ci check("{}*", ['{}*']) 13037db96d56Sopenharmony_ci check("{*}tag", ['{*}tag']) 13047db96d56Sopenharmony_ci check("{*}*", ['{*}*']) 13057db96d56Sopenharmony_ci check(".//{*}tag", ['.', '//', '{*}tag']) 13067db96d56Sopenharmony_ci 13077db96d56Sopenharmony_ci # namespace prefix resolution 13087db96d56Sopenharmony_ci check("./xsd:type", ['.', '/', '{http://www.w3.org/2001/XMLSchema}type'], 13097db96d56Sopenharmony_ci {'xsd': 'http://www.w3.org/2001/XMLSchema'}) 13107db96d56Sopenharmony_ci check("type", ['{http://www.w3.org/2001/XMLSchema}type'], 13117db96d56Sopenharmony_ci {'': 'http://www.w3.org/2001/XMLSchema'}) 13127db96d56Sopenharmony_ci check("@xsd:type", ['@', '{http://www.w3.org/2001/XMLSchema}type'], 13137db96d56Sopenharmony_ci {'xsd': 'http://www.w3.org/2001/XMLSchema'}) 13147db96d56Sopenharmony_ci check("@type", ['@', 'type'], 13157db96d56Sopenharmony_ci {'': 'http://www.w3.org/2001/XMLSchema'}) 13167db96d56Sopenharmony_ci check("@{*}type", ['@', '{*}type'], 13177db96d56Sopenharmony_ci {'': 'http://www.w3.org/2001/XMLSchema'}) 13187db96d56Sopenharmony_ci check("@{ns}attr", ['@', '{ns}attr'], 13197db96d56Sopenharmony_ci {'': 'http://www.w3.org/2001/XMLSchema', 13207db96d56Sopenharmony_ci 'ns': 'http://www.w3.org/2001/XMLSchema'}) 13217db96d56Sopenharmony_ci 13227db96d56Sopenharmony_ci def test_processinginstruction(self): 13237db96d56Sopenharmony_ci # Test ProcessingInstruction directly 13247db96d56Sopenharmony_ci 13257db96d56Sopenharmony_ci self.assertEqual(ET.tostring(ET.ProcessingInstruction('test', 'instruction')), 13267db96d56Sopenharmony_ci b'<?test instruction?>') 13277db96d56Sopenharmony_ci self.assertEqual(ET.tostring(ET.PI('test', 'instruction')), 13287db96d56Sopenharmony_ci b'<?test instruction?>') 13297db96d56Sopenharmony_ci 13307db96d56Sopenharmony_ci # Issue #2746 13317db96d56Sopenharmony_ci 13327db96d56Sopenharmony_ci self.assertEqual(ET.tostring(ET.PI('test', '<testing&>')), 13337db96d56Sopenharmony_ci b'<?test <testing&>?>') 13347db96d56Sopenharmony_ci self.assertEqual(ET.tostring(ET.PI('test', '<testing&>\xe3'), 'latin-1'), 13357db96d56Sopenharmony_ci b"<?xml version='1.0' encoding='latin-1'?>\n" 13367db96d56Sopenharmony_ci b"<?test <testing&>\xe3?>") 13377db96d56Sopenharmony_ci 13387db96d56Sopenharmony_ci def test_html_empty_elems_serialization(self): 13397db96d56Sopenharmony_ci # issue 15970 13407db96d56Sopenharmony_ci # from http://www.w3.org/TR/html401/index/elements.html 13417db96d56Sopenharmony_ci for element in ['AREA', 'BASE', 'BASEFONT', 'BR', 'COL', 'EMBED', 'FRAME', 13427db96d56Sopenharmony_ci 'HR', 'IMG', 'INPUT', 'ISINDEX', 'LINK', 'META', 'PARAM', 13437db96d56Sopenharmony_ci 'SOURCE', 'TRACK', 'WBR']: 13447db96d56Sopenharmony_ci for elem in [element, element.lower()]: 13457db96d56Sopenharmony_ci expected = '<%s>' % elem 13467db96d56Sopenharmony_ci serialized = serialize(ET.XML('<%s />' % elem), method='html') 13477db96d56Sopenharmony_ci self.assertEqual(serialized, expected) 13487db96d56Sopenharmony_ci serialized = serialize(ET.XML('<%s></%s>' % (elem,elem)), 13497db96d56Sopenharmony_ci method='html') 13507db96d56Sopenharmony_ci self.assertEqual(serialized, expected) 13517db96d56Sopenharmony_ci 13527db96d56Sopenharmony_ci def test_dump_attribute_order(self): 13537db96d56Sopenharmony_ci # See BPO 34160 13547db96d56Sopenharmony_ci e = ET.Element('cirriculum', status='public', company='example') 13557db96d56Sopenharmony_ci with support.captured_stdout() as stdout: 13567db96d56Sopenharmony_ci ET.dump(e) 13577db96d56Sopenharmony_ci self.assertEqual(stdout.getvalue(), 13587db96d56Sopenharmony_ci '<cirriculum status="public" company="example" />\n') 13597db96d56Sopenharmony_ci 13607db96d56Sopenharmony_ci def test_tree_write_attribute_order(self): 13617db96d56Sopenharmony_ci # See BPO 34160 13627db96d56Sopenharmony_ci root = ET.Element('cirriculum', status='public', company='example') 13637db96d56Sopenharmony_ci self.assertEqual(serialize(root), 13647db96d56Sopenharmony_ci '<cirriculum status="public" company="example" />') 13657db96d56Sopenharmony_ci self.assertEqual(serialize(root, method='html'), 13667db96d56Sopenharmony_ci '<cirriculum status="public" company="example"></cirriculum>') 13677db96d56Sopenharmony_ci 13687db96d56Sopenharmony_ci def test_attlist_default(self): 13697db96d56Sopenharmony_ci # Test default attribute values; See BPO 42151. 13707db96d56Sopenharmony_ci root = ET.fromstring(ATTLIST_XML) 13717db96d56Sopenharmony_ci self.assertEqual(root[0].attrib, 13727db96d56Sopenharmony_ci {'{http://www.w3.org/XML/1998/namespace}lang': 'eng'}) 13737db96d56Sopenharmony_ci 13747db96d56Sopenharmony_ci 13757db96d56Sopenharmony_ciclass XMLPullParserTest(unittest.TestCase): 13767db96d56Sopenharmony_ci 13777db96d56Sopenharmony_ci def _feed(self, parser, data, chunk_size=None): 13787db96d56Sopenharmony_ci if chunk_size is None: 13797db96d56Sopenharmony_ci parser.feed(data) 13807db96d56Sopenharmony_ci else: 13817db96d56Sopenharmony_ci for i in range(0, len(data), chunk_size): 13827db96d56Sopenharmony_ci parser.feed(data[i:i+chunk_size]) 13837db96d56Sopenharmony_ci 13847db96d56Sopenharmony_ci def assert_events(self, parser, expected, max_events=None): 13857db96d56Sopenharmony_ci self.assertEqual( 13867db96d56Sopenharmony_ci [(event, (elem.tag, elem.text)) 13877db96d56Sopenharmony_ci for event, elem in islice(parser.read_events(), max_events)], 13887db96d56Sopenharmony_ci expected) 13897db96d56Sopenharmony_ci 13907db96d56Sopenharmony_ci def assert_event_tuples(self, parser, expected, max_events=None): 13917db96d56Sopenharmony_ci self.assertEqual( 13927db96d56Sopenharmony_ci list(islice(parser.read_events(), max_events)), 13937db96d56Sopenharmony_ci expected) 13947db96d56Sopenharmony_ci 13957db96d56Sopenharmony_ci def assert_event_tags(self, parser, expected, max_events=None): 13967db96d56Sopenharmony_ci events = islice(parser.read_events(), max_events) 13977db96d56Sopenharmony_ci self.assertEqual([(action, elem.tag) for action, elem in events], 13987db96d56Sopenharmony_ci expected) 13997db96d56Sopenharmony_ci 14007db96d56Sopenharmony_ci def test_simple_xml(self): 14017db96d56Sopenharmony_ci for chunk_size in (None, 1, 5): 14027db96d56Sopenharmony_ci with self.subTest(chunk_size=chunk_size): 14037db96d56Sopenharmony_ci parser = ET.XMLPullParser() 14047db96d56Sopenharmony_ci self.assert_event_tags(parser, []) 14057db96d56Sopenharmony_ci self._feed(parser, "<!-- comment -->\n", chunk_size) 14067db96d56Sopenharmony_ci self.assert_event_tags(parser, []) 14077db96d56Sopenharmony_ci self._feed(parser, 14087db96d56Sopenharmony_ci "<root>\n <element key='value'>text</element", 14097db96d56Sopenharmony_ci chunk_size) 14107db96d56Sopenharmony_ci self.assert_event_tags(parser, []) 14117db96d56Sopenharmony_ci self._feed(parser, ">\n", chunk_size) 14127db96d56Sopenharmony_ci self.assert_event_tags(parser, [('end', 'element')]) 14137db96d56Sopenharmony_ci self._feed(parser, "<element>text</element>tail\n", chunk_size) 14147db96d56Sopenharmony_ci self._feed(parser, "<empty-element/>\n", chunk_size) 14157db96d56Sopenharmony_ci self.assert_event_tags(parser, [ 14167db96d56Sopenharmony_ci ('end', 'element'), 14177db96d56Sopenharmony_ci ('end', 'empty-element'), 14187db96d56Sopenharmony_ci ]) 14197db96d56Sopenharmony_ci self._feed(parser, "</root>\n", chunk_size) 14207db96d56Sopenharmony_ci self.assert_event_tags(parser, [('end', 'root')]) 14217db96d56Sopenharmony_ci self.assertIsNone(parser.close()) 14227db96d56Sopenharmony_ci 14237db96d56Sopenharmony_ci def test_feed_while_iterating(self): 14247db96d56Sopenharmony_ci parser = ET.XMLPullParser() 14257db96d56Sopenharmony_ci it = parser.read_events() 14267db96d56Sopenharmony_ci self._feed(parser, "<root>\n <element key='value'>text</element>\n") 14277db96d56Sopenharmony_ci action, elem = next(it) 14287db96d56Sopenharmony_ci self.assertEqual((action, elem.tag), ('end', 'element')) 14297db96d56Sopenharmony_ci self._feed(parser, "</root>\n") 14307db96d56Sopenharmony_ci action, elem = next(it) 14317db96d56Sopenharmony_ci self.assertEqual((action, elem.tag), ('end', 'root')) 14327db96d56Sopenharmony_ci with self.assertRaises(StopIteration): 14337db96d56Sopenharmony_ci next(it) 14347db96d56Sopenharmony_ci 14357db96d56Sopenharmony_ci def test_simple_xml_with_ns(self): 14367db96d56Sopenharmony_ci parser = ET.XMLPullParser() 14377db96d56Sopenharmony_ci self.assert_event_tags(parser, []) 14387db96d56Sopenharmony_ci self._feed(parser, "<!-- comment -->\n") 14397db96d56Sopenharmony_ci self.assert_event_tags(parser, []) 14407db96d56Sopenharmony_ci self._feed(parser, "<root xmlns='namespace'>\n") 14417db96d56Sopenharmony_ci self.assert_event_tags(parser, []) 14427db96d56Sopenharmony_ci self._feed(parser, "<element key='value'>text</element") 14437db96d56Sopenharmony_ci self.assert_event_tags(parser, []) 14447db96d56Sopenharmony_ci self._feed(parser, ">\n") 14457db96d56Sopenharmony_ci self.assert_event_tags(parser, [('end', '{namespace}element')]) 14467db96d56Sopenharmony_ci self._feed(parser, "<element>text</element>tail\n") 14477db96d56Sopenharmony_ci self._feed(parser, "<empty-element/>\n") 14487db96d56Sopenharmony_ci self.assert_event_tags(parser, [ 14497db96d56Sopenharmony_ci ('end', '{namespace}element'), 14507db96d56Sopenharmony_ci ('end', '{namespace}empty-element'), 14517db96d56Sopenharmony_ci ]) 14527db96d56Sopenharmony_ci self._feed(parser, "</root>\n") 14537db96d56Sopenharmony_ci self.assert_event_tags(parser, [('end', '{namespace}root')]) 14547db96d56Sopenharmony_ci self.assertIsNone(parser.close()) 14557db96d56Sopenharmony_ci 14567db96d56Sopenharmony_ci def test_ns_events(self): 14577db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=('start-ns', 'end-ns')) 14587db96d56Sopenharmony_ci self._feed(parser, "<!-- comment -->\n") 14597db96d56Sopenharmony_ci self._feed(parser, "<root xmlns='namespace'>\n") 14607db96d56Sopenharmony_ci self.assertEqual( 14617db96d56Sopenharmony_ci list(parser.read_events()), 14627db96d56Sopenharmony_ci [('start-ns', ('', 'namespace'))]) 14637db96d56Sopenharmony_ci self._feed(parser, "<element key='value'>text</element") 14647db96d56Sopenharmony_ci self._feed(parser, ">\n") 14657db96d56Sopenharmony_ci self._feed(parser, "<element>text</element>tail\n") 14667db96d56Sopenharmony_ci self._feed(parser, "<empty-element/>\n") 14677db96d56Sopenharmony_ci self._feed(parser, "</root>\n") 14687db96d56Sopenharmony_ci self.assertEqual(list(parser.read_events()), [('end-ns', None)]) 14697db96d56Sopenharmony_ci self.assertIsNone(parser.close()) 14707db96d56Sopenharmony_ci 14717db96d56Sopenharmony_ci def test_ns_events_start(self): 14727db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=('start-ns', 'start', 'end')) 14737db96d56Sopenharmony_ci self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n") 14747db96d56Sopenharmony_ci self.assert_event_tuples(parser, [ 14757db96d56Sopenharmony_ci ('start-ns', ('', 'abc')), 14767db96d56Sopenharmony_ci ('start-ns', ('p', 'xyz')), 14777db96d56Sopenharmony_ci ], max_events=2) 14787db96d56Sopenharmony_ci self.assert_event_tags(parser, [ 14797db96d56Sopenharmony_ci ('start', '{abc}tag'), 14807db96d56Sopenharmony_ci ], max_events=1) 14817db96d56Sopenharmony_ci 14827db96d56Sopenharmony_ci self._feed(parser, "<child />\n") 14837db96d56Sopenharmony_ci self.assert_event_tags(parser, [ 14847db96d56Sopenharmony_ci ('start', '{abc}child'), 14857db96d56Sopenharmony_ci ('end', '{abc}child'), 14867db96d56Sopenharmony_ci ]) 14877db96d56Sopenharmony_ci 14887db96d56Sopenharmony_ci self._feed(parser, "</tag>\n") 14897db96d56Sopenharmony_ci parser.close() 14907db96d56Sopenharmony_ci self.assert_event_tags(parser, [ 14917db96d56Sopenharmony_ci ('end', '{abc}tag'), 14927db96d56Sopenharmony_ci ]) 14937db96d56Sopenharmony_ci 14947db96d56Sopenharmony_ci def test_ns_events_start_end(self): 14957db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=('start-ns', 'start', 'end', 'end-ns')) 14967db96d56Sopenharmony_ci self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n") 14977db96d56Sopenharmony_ci self.assert_event_tuples(parser, [ 14987db96d56Sopenharmony_ci ('start-ns', ('', 'abc')), 14997db96d56Sopenharmony_ci ('start-ns', ('p', 'xyz')), 15007db96d56Sopenharmony_ci ], max_events=2) 15017db96d56Sopenharmony_ci self.assert_event_tags(parser, [ 15027db96d56Sopenharmony_ci ('start', '{abc}tag'), 15037db96d56Sopenharmony_ci ], max_events=1) 15047db96d56Sopenharmony_ci 15057db96d56Sopenharmony_ci self._feed(parser, "<child />\n") 15067db96d56Sopenharmony_ci self.assert_event_tags(parser, [ 15077db96d56Sopenharmony_ci ('start', '{abc}child'), 15087db96d56Sopenharmony_ci ('end', '{abc}child'), 15097db96d56Sopenharmony_ci ]) 15107db96d56Sopenharmony_ci 15117db96d56Sopenharmony_ci self._feed(parser, "</tag>\n") 15127db96d56Sopenharmony_ci parser.close() 15137db96d56Sopenharmony_ci self.assert_event_tags(parser, [ 15147db96d56Sopenharmony_ci ('end', '{abc}tag'), 15157db96d56Sopenharmony_ci ], max_events=1) 15167db96d56Sopenharmony_ci self.assert_event_tuples(parser, [ 15177db96d56Sopenharmony_ci ('end-ns', None), 15187db96d56Sopenharmony_ci ('end-ns', None), 15197db96d56Sopenharmony_ci ]) 15207db96d56Sopenharmony_ci 15217db96d56Sopenharmony_ci def test_events(self): 15227db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=()) 15237db96d56Sopenharmony_ci self._feed(parser, "<root/>\n") 15247db96d56Sopenharmony_ci self.assert_event_tags(parser, []) 15257db96d56Sopenharmony_ci 15267db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=('start', 'end')) 15277db96d56Sopenharmony_ci self._feed(parser, "<!-- text here -->\n") 15287db96d56Sopenharmony_ci self.assert_events(parser, []) 15297db96d56Sopenharmony_ci 15307db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=('start', 'end')) 15317db96d56Sopenharmony_ci self._feed(parser, "<root>\n") 15327db96d56Sopenharmony_ci self.assert_event_tags(parser, [('start', 'root')]) 15337db96d56Sopenharmony_ci self._feed(parser, "<element key='value'>text</element") 15347db96d56Sopenharmony_ci self.assert_event_tags(parser, [('start', 'element')]) 15357db96d56Sopenharmony_ci self._feed(parser, ">\n") 15367db96d56Sopenharmony_ci self.assert_event_tags(parser, [('end', 'element')]) 15377db96d56Sopenharmony_ci self._feed(parser, 15387db96d56Sopenharmony_ci "<element xmlns='foo'>text<empty-element/></element>tail\n") 15397db96d56Sopenharmony_ci self.assert_event_tags(parser, [ 15407db96d56Sopenharmony_ci ('start', '{foo}element'), 15417db96d56Sopenharmony_ci ('start', '{foo}empty-element'), 15427db96d56Sopenharmony_ci ('end', '{foo}empty-element'), 15437db96d56Sopenharmony_ci ('end', '{foo}element'), 15447db96d56Sopenharmony_ci ]) 15457db96d56Sopenharmony_ci self._feed(parser, "</root>") 15467db96d56Sopenharmony_ci self.assertIsNone(parser.close()) 15477db96d56Sopenharmony_ci self.assert_event_tags(parser, [('end', 'root')]) 15487db96d56Sopenharmony_ci 15497db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=('start',)) 15507db96d56Sopenharmony_ci self._feed(parser, "<!-- comment -->\n") 15517db96d56Sopenharmony_ci self.assert_event_tags(parser, []) 15527db96d56Sopenharmony_ci self._feed(parser, "<root>\n") 15537db96d56Sopenharmony_ci self.assert_event_tags(parser, [('start', 'root')]) 15547db96d56Sopenharmony_ci self._feed(parser, "<element key='value'>text</element") 15557db96d56Sopenharmony_ci self.assert_event_tags(parser, [('start', 'element')]) 15567db96d56Sopenharmony_ci self._feed(parser, ">\n") 15577db96d56Sopenharmony_ci self.assert_event_tags(parser, []) 15587db96d56Sopenharmony_ci self._feed(parser, 15597db96d56Sopenharmony_ci "<element xmlns='foo'>text<empty-element/></element>tail\n") 15607db96d56Sopenharmony_ci self.assert_event_tags(parser, [ 15617db96d56Sopenharmony_ci ('start', '{foo}element'), 15627db96d56Sopenharmony_ci ('start', '{foo}empty-element'), 15637db96d56Sopenharmony_ci ]) 15647db96d56Sopenharmony_ci self._feed(parser, "</root>") 15657db96d56Sopenharmony_ci self.assertIsNone(parser.close()) 15667db96d56Sopenharmony_ci 15677db96d56Sopenharmony_ci def test_events_comment(self): 15687db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=('start', 'comment', 'end')) 15697db96d56Sopenharmony_ci self._feed(parser, "<!-- text here -->\n") 15707db96d56Sopenharmony_ci self.assert_events(parser, [('comment', (ET.Comment, ' text here '))]) 15717db96d56Sopenharmony_ci self._feed(parser, "<!-- more text here -->\n") 15727db96d56Sopenharmony_ci self.assert_events(parser, [('comment', (ET.Comment, ' more text here '))]) 15737db96d56Sopenharmony_ci self._feed(parser, "<root-tag>text") 15747db96d56Sopenharmony_ci self.assert_event_tags(parser, [('start', 'root-tag')]) 15757db96d56Sopenharmony_ci self._feed(parser, "<!-- inner comment-->\n") 15767db96d56Sopenharmony_ci self.assert_events(parser, [('comment', (ET.Comment, ' inner comment'))]) 15777db96d56Sopenharmony_ci self._feed(parser, "</root-tag>\n") 15787db96d56Sopenharmony_ci self.assert_event_tags(parser, [('end', 'root-tag')]) 15797db96d56Sopenharmony_ci self._feed(parser, "<!-- outer comment -->\n") 15807db96d56Sopenharmony_ci self.assert_events(parser, [('comment', (ET.Comment, ' outer comment '))]) 15817db96d56Sopenharmony_ci 15827db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=('comment',)) 15837db96d56Sopenharmony_ci self._feed(parser, "<!-- text here -->\n") 15847db96d56Sopenharmony_ci self.assert_events(parser, [('comment', (ET.Comment, ' text here '))]) 15857db96d56Sopenharmony_ci 15867db96d56Sopenharmony_ci def test_events_pi(self): 15877db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=('start', 'pi', 'end')) 15887db96d56Sopenharmony_ci self._feed(parser, "<?pitarget?>\n") 15897db96d56Sopenharmony_ci self.assert_events(parser, [('pi', (ET.PI, 'pitarget'))]) 15907db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=('pi',)) 15917db96d56Sopenharmony_ci self._feed(parser, "<?pitarget some text ?>\n") 15927db96d56Sopenharmony_ci self.assert_events(parser, [('pi', (ET.PI, 'pitarget some text '))]) 15937db96d56Sopenharmony_ci 15947db96d56Sopenharmony_ci def test_events_sequence(self): 15957db96d56Sopenharmony_ci # Test that events can be some sequence that's not just a tuple or list 15967db96d56Sopenharmony_ci eventset = {'end', 'start'} 15977db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=eventset) 15987db96d56Sopenharmony_ci self._feed(parser, "<foo>bar</foo>") 15997db96d56Sopenharmony_ci self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')]) 16007db96d56Sopenharmony_ci 16017db96d56Sopenharmony_ci class DummyIter: 16027db96d56Sopenharmony_ci def __init__(self): 16037db96d56Sopenharmony_ci self.events = iter(['start', 'end', 'start-ns']) 16047db96d56Sopenharmony_ci def __iter__(self): 16057db96d56Sopenharmony_ci return self 16067db96d56Sopenharmony_ci def __next__(self): 16077db96d56Sopenharmony_ci return next(self.events) 16087db96d56Sopenharmony_ci 16097db96d56Sopenharmony_ci parser = ET.XMLPullParser(events=DummyIter()) 16107db96d56Sopenharmony_ci self._feed(parser, "<foo>bar</foo>") 16117db96d56Sopenharmony_ci self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')]) 16127db96d56Sopenharmony_ci 16137db96d56Sopenharmony_ci def test_unknown_event(self): 16147db96d56Sopenharmony_ci with self.assertRaises(ValueError): 16157db96d56Sopenharmony_ci ET.XMLPullParser(events=('start', 'end', 'bogus')) 16167db96d56Sopenharmony_ci 16177db96d56Sopenharmony_ci 16187db96d56Sopenharmony_ci# 16197db96d56Sopenharmony_ci# xinclude tests (samples from appendix C of the xinclude specification) 16207db96d56Sopenharmony_ci 16217db96d56Sopenharmony_ciXINCLUDE = {} 16227db96d56Sopenharmony_ci 16237db96d56Sopenharmony_ciXINCLUDE["C1.xml"] = """\ 16247db96d56Sopenharmony_ci<?xml version='1.0'?> 16257db96d56Sopenharmony_ci<document xmlns:xi="http://www.w3.org/2001/XInclude"> 16267db96d56Sopenharmony_ci <p>120 Mz is adequate for an average home user.</p> 16277db96d56Sopenharmony_ci <xi:include href="disclaimer.xml"/> 16287db96d56Sopenharmony_ci</document> 16297db96d56Sopenharmony_ci""" 16307db96d56Sopenharmony_ci 16317db96d56Sopenharmony_ciXINCLUDE["disclaimer.xml"] = """\ 16327db96d56Sopenharmony_ci<?xml version='1.0'?> 16337db96d56Sopenharmony_ci<disclaimer> 16347db96d56Sopenharmony_ci <p>The opinions represented herein represent those of the individual 16357db96d56Sopenharmony_ci and should not be interpreted as official policy endorsed by this 16367db96d56Sopenharmony_ci organization.</p> 16377db96d56Sopenharmony_ci</disclaimer> 16387db96d56Sopenharmony_ci""" 16397db96d56Sopenharmony_ci 16407db96d56Sopenharmony_ciXINCLUDE["C2.xml"] = """\ 16417db96d56Sopenharmony_ci<?xml version='1.0'?> 16427db96d56Sopenharmony_ci<document xmlns:xi="http://www.w3.org/2001/XInclude"> 16437db96d56Sopenharmony_ci <p>This document has been accessed 16447db96d56Sopenharmony_ci <xi:include href="count.txt" parse="text"/> times.</p> 16457db96d56Sopenharmony_ci</document> 16467db96d56Sopenharmony_ci""" 16477db96d56Sopenharmony_ci 16487db96d56Sopenharmony_ciXINCLUDE["count.txt"] = "324387" 16497db96d56Sopenharmony_ci 16507db96d56Sopenharmony_ciXINCLUDE["C2b.xml"] = """\ 16517db96d56Sopenharmony_ci<?xml version='1.0'?> 16527db96d56Sopenharmony_ci<document xmlns:xi="http://www.w3.org/2001/XInclude"> 16537db96d56Sopenharmony_ci <p>This document has been <em>accessed</em> 16547db96d56Sopenharmony_ci <xi:include href="count.txt" parse="text"/> times.</p> 16557db96d56Sopenharmony_ci</document> 16567db96d56Sopenharmony_ci""" 16577db96d56Sopenharmony_ci 16587db96d56Sopenharmony_ciXINCLUDE["C3.xml"] = """\ 16597db96d56Sopenharmony_ci<?xml version='1.0'?> 16607db96d56Sopenharmony_ci<document xmlns:xi="http://www.w3.org/2001/XInclude"> 16617db96d56Sopenharmony_ci <p>The following is the source of the "data.xml" resource:</p> 16627db96d56Sopenharmony_ci <example><xi:include href="data.xml" parse="text"/></example> 16637db96d56Sopenharmony_ci</document> 16647db96d56Sopenharmony_ci""" 16657db96d56Sopenharmony_ci 16667db96d56Sopenharmony_ciXINCLUDE["data.xml"] = """\ 16677db96d56Sopenharmony_ci<?xml version='1.0'?> 16687db96d56Sopenharmony_ci<data> 16697db96d56Sopenharmony_ci <item><![CDATA[Brooks & Shields]]></item> 16707db96d56Sopenharmony_ci</data> 16717db96d56Sopenharmony_ci""" 16727db96d56Sopenharmony_ci 16737db96d56Sopenharmony_ciXINCLUDE["C5.xml"] = """\ 16747db96d56Sopenharmony_ci<?xml version='1.0'?> 16757db96d56Sopenharmony_ci<div xmlns:xi="http://www.w3.org/2001/XInclude"> 16767db96d56Sopenharmony_ci <xi:include href="example.txt" parse="text"> 16777db96d56Sopenharmony_ci <xi:fallback> 16787db96d56Sopenharmony_ci <xi:include href="fallback-example.txt" parse="text"> 16797db96d56Sopenharmony_ci <xi:fallback><a href="mailto:bob@example.org">Report error</a></xi:fallback> 16807db96d56Sopenharmony_ci </xi:include> 16817db96d56Sopenharmony_ci </xi:fallback> 16827db96d56Sopenharmony_ci </xi:include> 16837db96d56Sopenharmony_ci</div> 16847db96d56Sopenharmony_ci""" 16857db96d56Sopenharmony_ci 16867db96d56Sopenharmony_ciXINCLUDE["default.xml"] = """\ 16877db96d56Sopenharmony_ci<?xml version='1.0'?> 16887db96d56Sopenharmony_ci<document xmlns:xi="http://www.w3.org/2001/XInclude"> 16897db96d56Sopenharmony_ci <p>Example.</p> 16907db96d56Sopenharmony_ci <xi:include href="{}"/> 16917db96d56Sopenharmony_ci</document> 16927db96d56Sopenharmony_ci""".format(html.escape(SIMPLE_XMLFILE, True)) 16937db96d56Sopenharmony_ci 16947db96d56Sopenharmony_ciXINCLUDE["include_c1_repeated.xml"] = """\ 16957db96d56Sopenharmony_ci<?xml version='1.0'?> 16967db96d56Sopenharmony_ci<document xmlns:xi="http://www.w3.org/2001/XInclude"> 16977db96d56Sopenharmony_ci <p>The following is the source code of Recursive1.xml:</p> 16987db96d56Sopenharmony_ci <xi:include href="C1.xml"/> 16997db96d56Sopenharmony_ci <xi:include href="C1.xml"/> 17007db96d56Sopenharmony_ci <xi:include href="C1.xml"/> 17017db96d56Sopenharmony_ci <xi:include href="C1.xml"/> 17027db96d56Sopenharmony_ci</document> 17037db96d56Sopenharmony_ci""" 17047db96d56Sopenharmony_ci 17057db96d56Sopenharmony_ci# 17067db96d56Sopenharmony_ci# badly formatted xi:include tags 17077db96d56Sopenharmony_ci 17087db96d56Sopenharmony_ciXINCLUDE_BAD = {} 17097db96d56Sopenharmony_ci 17107db96d56Sopenharmony_ciXINCLUDE_BAD["B1.xml"] = """\ 17117db96d56Sopenharmony_ci<?xml version='1.0'?> 17127db96d56Sopenharmony_ci<document xmlns:xi="http://www.w3.org/2001/XInclude"> 17137db96d56Sopenharmony_ci <p>120 Mz is adequate for an average home user.</p> 17147db96d56Sopenharmony_ci <xi:include href="disclaimer.xml" parse="BAD_TYPE"/> 17157db96d56Sopenharmony_ci</document> 17167db96d56Sopenharmony_ci""" 17177db96d56Sopenharmony_ci 17187db96d56Sopenharmony_ciXINCLUDE_BAD["B2.xml"] = """\ 17197db96d56Sopenharmony_ci<?xml version='1.0'?> 17207db96d56Sopenharmony_ci<div xmlns:xi="http://www.w3.org/2001/XInclude"> 17217db96d56Sopenharmony_ci <xi:fallback></xi:fallback> 17227db96d56Sopenharmony_ci</div> 17237db96d56Sopenharmony_ci""" 17247db96d56Sopenharmony_ci 17257db96d56Sopenharmony_ciXINCLUDE["Recursive1.xml"] = """\ 17267db96d56Sopenharmony_ci<?xml version='1.0'?> 17277db96d56Sopenharmony_ci<document xmlns:xi="http://www.w3.org/2001/XInclude"> 17287db96d56Sopenharmony_ci <p>The following is the source code of Recursive2.xml:</p> 17297db96d56Sopenharmony_ci <xi:include href="Recursive2.xml"/> 17307db96d56Sopenharmony_ci</document> 17317db96d56Sopenharmony_ci""" 17327db96d56Sopenharmony_ci 17337db96d56Sopenharmony_ciXINCLUDE["Recursive2.xml"] = """\ 17347db96d56Sopenharmony_ci<?xml version='1.0'?> 17357db96d56Sopenharmony_ci<document xmlns:xi="http://www.w3.org/2001/XInclude"> 17367db96d56Sopenharmony_ci <p>The following is the source code of Recursive3.xml:</p> 17377db96d56Sopenharmony_ci <xi:include href="Recursive3.xml"/> 17387db96d56Sopenharmony_ci</document> 17397db96d56Sopenharmony_ci""" 17407db96d56Sopenharmony_ci 17417db96d56Sopenharmony_ciXINCLUDE["Recursive3.xml"] = """\ 17427db96d56Sopenharmony_ci<?xml version='1.0'?> 17437db96d56Sopenharmony_ci<document xmlns:xi="http://www.w3.org/2001/XInclude"> 17447db96d56Sopenharmony_ci <p>The following is the source code of Recursive1.xml:</p> 17457db96d56Sopenharmony_ci <xi:include href="Recursive1.xml"/> 17467db96d56Sopenharmony_ci</document> 17477db96d56Sopenharmony_ci""" 17487db96d56Sopenharmony_ci 17497db96d56Sopenharmony_ci 17507db96d56Sopenharmony_ciclass XIncludeTest(unittest.TestCase): 17517db96d56Sopenharmony_ci 17527db96d56Sopenharmony_ci def xinclude_loader(self, href, parse="xml", encoding=None): 17537db96d56Sopenharmony_ci try: 17547db96d56Sopenharmony_ci data = XINCLUDE[href] 17557db96d56Sopenharmony_ci except KeyError: 17567db96d56Sopenharmony_ci raise OSError("resource not found") 17577db96d56Sopenharmony_ci if parse == "xml": 17587db96d56Sopenharmony_ci data = ET.XML(data) 17597db96d56Sopenharmony_ci return data 17607db96d56Sopenharmony_ci 17617db96d56Sopenharmony_ci def none_loader(self, href, parser, encoding=None): 17627db96d56Sopenharmony_ci return None 17637db96d56Sopenharmony_ci 17647db96d56Sopenharmony_ci def _my_loader(self, href, parse): 17657db96d56Sopenharmony_ci # Used to avoid a test-dependency problem where the default loader 17667db96d56Sopenharmony_ci # of ElementInclude uses the pyET parser for cET tests. 17677db96d56Sopenharmony_ci if parse == 'xml': 17687db96d56Sopenharmony_ci with open(href, 'rb') as f: 17697db96d56Sopenharmony_ci return ET.parse(f).getroot() 17707db96d56Sopenharmony_ci else: 17717db96d56Sopenharmony_ci return None 17727db96d56Sopenharmony_ci 17737db96d56Sopenharmony_ci def test_xinclude_default(self): 17747db96d56Sopenharmony_ci from xml.etree import ElementInclude 17757db96d56Sopenharmony_ci doc = self.xinclude_loader('default.xml') 17767db96d56Sopenharmony_ci ElementInclude.include(doc, self._my_loader) 17777db96d56Sopenharmony_ci self.assertEqual(serialize(doc), 17787db96d56Sopenharmony_ci '<document>\n' 17797db96d56Sopenharmony_ci ' <p>Example.</p>\n' 17807db96d56Sopenharmony_ci ' <root>\n' 17817db96d56Sopenharmony_ci ' <element key="value">text</element>\n' 17827db96d56Sopenharmony_ci ' <element>text</element>tail\n' 17837db96d56Sopenharmony_ci ' <empty-element />\n' 17847db96d56Sopenharmony_ci '</root>\n' 17857db96d56Sopenharmony_ci '</document>') 17867db96d56Sopenharmony_ci 17877db96d56Sopenharmony_ci def test_xinclude(self): 17887db96d56Sopenharmony_ci from xml.etree import ElementInclude 17897db96d56Sopenharmony_ci 17907db96d56Sopenharmony_ci # Basic inclusion example (XInclude C.1) 17917db96d56Sopenharmony_ci document = self.xinclude_loader("C1.xml") 17927db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader) 17937db96d56Sopenharmony_ci self.assertEqual(serialize(document), 17947db96d56Sopenharmony_ci '<document>\n' 17957db96d56Sopenharmony_ci ' <p>120 Mz is adequate for an average home user.</p>\n' 17967db96d56Sopenharmony_ci ' <disclaimer>\n' 17977db96d56Sopenharmony_ci ' <p>The opinions represented herein represent those of the individual\n' 17987db96d56Sopenharmony_ci ' and should not be interpreted as official policy endorsed by this\n' 17997db96d56Sopenharmony_ci ' organization.</p>\n' 18007db96d56Sopenharmony_ci '</disclaimer>\n' 18017db96d56Sopenharmony_ci '</document>') # C1 18027db96d56Sopenharmony_ci 18037db96d56Sopenharmony_ci # Textual inclusion example (XInclude C.2) 18047db96d56Sopenharmony_ci document = self.xinclude_loader("C2.xml") 18057db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader) 18067db96d56Sopenharmony_ci self.assertEqual(serialize(document), 18077db96d56Sopenharmony_ci '<document>\n' 18087db96d56Sopenharmony_ci ' <p>This document has been accessed\n' 18097db96d56Sopenharmony_ci ' 324387 times.</p>\n' 18107db96d56Sopenharmony_ci '</document>') # C2 18117db96d56Sopenharmony_ci 18127db96d56Sopenharmony_ci # Textual inclusion after sibling element (based on modified XInclude C.2) 18137db96d56Sopenharmony_ci document = self.xinclude_loader("C2b.xml") 18147db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader) 18157db96d56Sopenharmony_ci self.assertEqual(serialize(document), 18167db96d56Sopenharmony_ci '<document>\n' 18177db96d56Sopenharmony_ci ' <p>This document has been <em>accessed</em>\n' 18187db96d56Sopenharmony_ci ' 324387 times.</p>\n' 18197db96d56Sopenharmony_ci '</document>') # C2b 18207db96d56Sopenharmony_ci 18217db96d56Sopenharmony_ci # Textual inclusion of XML example (XInclude C.3) 18227db96d56Sopenharmony_ci document = self.xinclude_loader("C3.xml") 18237db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader) 18247db96d56Sopenharmony_ci self.assertEqual(serialize(document), 18257db96d56Sopenharmony_ci '<document>\n' 18267db96d56Sopenharmony_ci ' <p>The following is the source of the "data.xml" resource:</p>\n' 18277db96d56Sopenharmony_ci " <example><?xml version='1.0'?>\n" 18287db96d56Sopenharmony_ci '<data>\n' 18297db96d56Sopenharmony_ci ' <item><![CDATA[Brooks & Shields]]></item>\n' 18307db96d56Sopenharmony_ci '</data>\n' 18317db96d56Sopenharmony_ci '</example>\n' 18327db96d56Sopenharmony_ci '</document>') # C3 18337db96d56Sopenharmony_ci 18347db96d56Sopenharmony_ci # Fallback example (XInclude C.5) 18357db96d56Sopenharmony_ci # Note! Fallback support is not yet implemented 18367db96d56Sopenharmony_ci document = self.xinclude_loader("C5.xml") 18377db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 18387db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader) 18397db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 'resource not found') 18407db96d56Sopenharmony_ci self.assertEqual(serialize(document), 18417db96d56Sopenharmony_ci '<div xmlns:ns0="http://www.w3.org/2001/XInclude">\n' 18427db96d56Sopenharmony_ci ' <ns0:include href="example.txt" parse="text">\n' 18437db96d56Sopenharmony_ci ' <ns0:fallback>\n' 18447db96d56Sopenharmony_ci ' <ns0:include href="fallback-example.txt" parse="text">\n' 18457db96d56Sopenharmony_ci ' <ns0:fallback><a href="mailto:bob@example.org">Report error</a></ns0:fallback>\n' 18467db96d56Sopenharmony_ci ' </ns0:include>\n' 18477db96d56Sopenharmony_ci ' </ns0:fallback>\n' 18487db96d56Sopenharmony_ci ' </ns0:include>\n' 18497db96d56Sopenharmony_ci '</div>') # C5 18507db96d56Sopenharmony_ci 18517db96d56Sopenharmony_ci def test_xinclude_repeated(self): 18527db96d56Sopenharmony_ci from xml.etree import ElementInclude 18537db96d56Sopenharmony_ci 18547db96d56Sopenharmony_ci document = self.xinclude_loader("include_c1_repeated.xml") 18557db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader) 18567db96d56Sopenharmony_ci self.assertEqual(1+4*2, len(document.findall(".//p"))) 18577db96d56Sopenharmony_ci 18587db96d56Sopenharmony_ci def test_xinclude_failures(self): 18597db96d56Sopenharmony_ci from xml.etree import ElementInclude 18607db96d56Sopenharmony_ci 18617db96d56Sopenharmony_ci # Test failure to locate included XML file. 18627db96d56Sopenharmony_ci document = ET.XML(XINCLUDE["C1.xml"]) 18637db96d56Sopenharmony_ci with self.assertRaises(ElementInclude.FatalIncludeError) as cm: 18647db96d56Sopenharmony_ci ElementInclude.include(document, loader=self.none_loader) 18657db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 18667db96d56Sopenharmony_ci "cannot load 'disclaimer.xml' as 'xml'") 18677db96d56Sopenharmony_ci 18687db96d56Sopenharmony_ci # Test failure to locate included text file. 18697db96d56Sopenharmony_ci document = ET.XML(XINCLUDE["C2.xml"]) 18707db96d56Sopenharmony_ci with self.assertRaises(ElementInclude.FatalIncludeError) as cm: 18717db96d56Sopenharmony_ci ElementInclude.include(document, loader=self.none_loader) 18727db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 18737db96d56Sopenharmony_ci "cannot load 'count.txt' as 'text'") 18747db96d56Sopenharmony_ci 18757db96d56Sopenharmony_ci # Test bad parse type. 18767db96d56Sopenharmony_ci document = ET.XML(XINCLUDE_BAD["B1.xml"]) 18777db96d56Sopenharmony_ci with self.assertRaises(ElementInclude.FatalIncludeError) as cm: 18787db96d56Sopenharmony_ci ElementInclude.include(document, loader=self.none_loader) 18797db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 18807db96d56Sopenharmony_ci "unknown parse type in xi:include tag ('BAD_TYPE')") 18817db96d56Sopenharmony_ci 18827db96d56Sopenharmony_ci # Test xi:fallback outside xi:include. 18837db96d56Sopenharmony_ci document = ET.XML(XINCLUDE_BAD["B2.xml"]) 18847db96d56Sopenharmony_ci with self.assertRaises(ElementInclude.FatalIncludeError) as cm: 18857db96d56Sopenharmony_ci ElementInclude.include(document, loader=self.none_loader) 18867db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 18877db96d56Sopenharmony_ci "xi:fallback tag must be child of xi:include " 18887db96d56Sopenharmony_ci "('{http://www.w3.org/2001/XInclude}fallback')") 18897db96d56Sopenharmony_ci 18907db96d56Sopenharmony_ci # Test infinitely recursive includes. 18917db96d56Sopenharmony_ci document = self.xinclude_loader("Recursive1.xml") 18927db96d56Sopenharmony_ci with self.assertRaises(ElementInclude.FatalIncludeError) as cm: 18937db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader) 18947db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 18957db96d56Sopenharmony_ci "recursive include of Recursive2.xml") 18967db96d56Sopenharmony_ci 18977db96d56Sopenharmony_ci # Test 'max_depth' limitation. 18987db96d56Sopenharmony_ci document = self.xinclude_loader("Recursive1.xml") 18997db96d56Sopenharmony_ci with self.assertRaises(ElementInclude.FatalIncludeError) as cm: 19007db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader, max_depth=None) 19017db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 19027db96d56Sopenharmony_ci "recursive include of Recursive2.xml") 19037db96d56Sopenharmony_ci 19047db96d56Sopenharmony_ci document = self.xinclude_loader("Recursive1.xml") 19057db96d56Sopenharmony_ci with self.assertRaises(ElementInclude.LimitedRecursiveIncludeError) as cm: 19067db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader, max_depth=0) 19077db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 19087db96d56Sopenharmony_ci "maximum xinclude depth reached when including file Recursive2.xml") 19097db96d56Sopenharmony_ci 19107db96d56Sopenharmony_ci document = self.xinclude_loader("Recursive1.xml") 19117db96d56Sopenharmony_ci with self.assertRaises(ElementInclude.LimitedRecursiveIncludeError) as cm: 19127db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader, max_depth=1) 19137db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 19147db96d56Sopenharmony_ci "maximum xinclude depth reached when including file Recursive3.xml") 19157db96d56Sopenharmony_ci 19167db96d56Sopenharmony_ci document = self.xinclude_loader("Recursive1.xml") 19177db96d56Sopenharmony_ci with self.assertRaises(ElementInclude.LimitedRecursiveIncludeError) as cm: 19187db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader, max_depth=2) 19197db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 19207db96d56Sopenharmony_ci "maximum xinclude depth reached when including file Recursive1.xml") 19217db96d56Sopenharmony_ci 19227db96d56Sopenharmony_ci document = self.xinclude_loader("Recursive1.xml") 19237db96d56Sopenharmony_ci with self.assertRaises(ElementInclude.FatalIncludeError) as cm: 19247db96d56Sopenharmony_ci ElementInclude.include(document, self.xinclude_loader, max_depth=3) 19257db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 19267db96d56Sopenharmony_ci "recursive include of Recursive2.xml") 19277db96d56Sopenharmony_ci 19287db96d56Sopenharmony_ci 19297db96d56Sopenharmony_ci# -------------------------------------------------------------------- 19307db96d56Sopenharmony_ci# reported bugs 19317db96d56Sopenharmony_ci 19327db96d56Sopenharmony_ciclass BugsTest(unittest.TestCase): 19337db96d56Sopenharmony_ci 19347db96d56Sopenharmony_ci def test_bug_xmltoolkit21(self): 19357db96d56Sopenharmony_ci # marshaller gives obscure errors for non-string values 19367db96d56Sopenharmony_ci 19377db96d56Sopenharmony_ci def check(elem): 19387db96d56Sopenharmony_ci with self.assertRaises(TypeError) as cm: 19397db96d56Sopenharmony_ci serialize(elem) 19407db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 19417db96d56Sopenharmony_ci 'cannot serialize 123 (type int)') 19427db96d56Sopenharmony_ci 19437db96d56Sopenharmony_ci elem = ET.Element(123) 19447db96d56Sopenharmony_ci check(elem) # tag 19457db96d56Sopenharmony_ci 19467db96d56Sopenharmony_ci elem = ET.Element("elem") 19477db96d56Sopenharmony_ci elem.text = 123 19487db96d56Sopenharmony_ci check(elem) # text 19497db96d56Sopenharmony_ci 19507db96d56Sopenharmony_ci elem = ET.Element("elem") 19517db96d56Sopenharmony_ci elem.tail = 123 19527db96d56Sopenharmony_ci check(elem) # tail 19537db96d56Sopenharmony_ci 19547db96d56Sopenharmony_ci elem = ET.Element("elem") 19557db96d56Sopenharmony_ci elem.set(123, "123") 19567db96d56Sopenharmony_ci check(elem) # attribute key 19577db96d56Sopenharmony_ci 19587db96d56Sopenharmony_ci elem = ET.Element("elem") 19597db96d56Sopenharmony_ci elem.set("123", 123) 19607db96d56Sopenharmony_ci check(elem) # attribute value 19617db96d56Sopenharmony_ci 19627db96d56Sopenharmony_ci def test_bug_xmltoolkit25(self): 19637db96d56Sopenharmony_ci # typo in ElementTree.findtext 19647db96d56Sopenharmony_ci 19657db96d56Sopenharmony_ci elem = ET.XML(SAMPLE_XML) 19667db96d56Sopenharmony_ci tree = ET.ElementTree(elem) 19677db96d56Sopenharmony_ci self.assertEqual(tree.findtext("tag"), 'text') 19687db96d56Sopenharmony_ci self.assertEqual(tree.findtext("section/tag"), 'subtext') 19697db96d56Sopenharmony_ci 19707db96d56Sopenharmony_ci def test_bug_xmltoolkit28(self): 19717db96d56Sopenharmony_ci # .//tag causes exceptions 19727db96d56Sopenharmony_ci 19737db96d56Sopenharmony_ci tree = ET.XML("<doc><table><tbody/></table></doc>") 19747db96d56Sopenharmony_ci self.assertEqual(summarize_list(tree.findall(".//thead")), []) 19757db96d56Sopenharmony_ci self.assertEqual(summarize_list(tree.findall(".//tbody")), ['tbody']) 19767db96d56Sopenharmony_ci 19777db96d56Sopenharmony_ci def test_bug_xmltoolkitX1(self): 19787db96d56Sopenharmony_ci # dump() doesn't flush the output buffer 19797db96d56Sopenharmony_ci 19807db96d56Sopenharmony_ci tree = ET.XML("<doc><table><tbody/></table></doc>") 19817db96d56Sopenharmony_ci with support.captured_stdout() as stdout: 19827db96d56Sopenharmony_ci ET.dump(tree) 19837db96d56Sopenharmony_ci self.assertEqual(stdout.getvalue(), '<doc><table><tbody /></table></doc>\n') 19847db96d56Sopenharmony_ci 19857db96d56Sopenharmony_ci def test_bug_xmltoolkit39(self): 19867db96d56Sopenharmony_ci # non-ascii element and attribute names doesn't work 19877db96d56Sopenharmony_ci 19887db96d56Sopenharmony_ci tree = ET.XML(b"<?xml version='1.0' encoding='iso-8859-1'?><t\xe4g />") 19897db96d56Sopenharmony_ci self.assertEqual(ET.tostring(tree, "utf-8"), b'<t\xc3\xa4g />') 19907db96d56Sopenharmony_ci 19917db96d56Sopenharmony_ci tree = ET.XML(b"<?xml version='1.0' encoding='iso-8859-1'?>" 19927db96d56Sopenharmony_ci b"<tag \xe4ttr='välue' />") 19937db96d56Sopenharmony_ci self.assertEqual(tree.attrib, {'\xe4ttr': 'v\xe4lue'}) 19947db96d56Sopenharmony_ci self.assertEqual(ET.tostring(tree, "utf-8"), 19957db96d56Sopenharmony_ci b'<tag \xc3\xa4ttr="v\xc3\xa4lue" />') 19967db96d56Sopenharmony_ci 19977db96d56Sopenharmony_ci tree = ET.XML(b"<?xml version='1.0' encoding='iso-8859-1'?>" 19987db96d56Sopenharmony_ci b'<t\xe4g>text</t\xe4g>') 19997db96d56Sopenharmony_ci self.assertEqual(ET.tostring(tree, "utf-8"), 20007db96d56Sopenharmony_ci b'<t\xc3\xa4g>text</t\xc3\xa4g>') 20017db96d56Sopenharmony_ci 20027db96d56Sopenharmony_ci tree = ET.Element("t\u00e4g") 20037db96d56Sopenharmony_ci self.assertEqual(ET.tostring(tree, "utf-8"), b'<t\xc3\xa4g />') 20047db96d56Sopenharmony_ci 20057db96d56Sopenharmony_ci tree = ET.Element("tag") 20067db96d56Sopenharmony_ci tree.set("\u00e4ttr", "v\u00e4lue") 20077db96d56Sopenharmony_ci self.assertEqual(ET.tostring(tree, "utf-8"), 20087db96d56Sopenharmony_ci b'<tag \xc3\xa4ttr="v\xc3\xa4lue" />') 20097db96d56Sopenharmony_ci 20107db96d56Sopenharmony_ci def test_bug_xmltoolkit54(self): 20117db96d56Sopenharmony_ci # problems handling internally defined entities 20127db96d56Sopenharmony_ci 20137db96d56Sopenharmony_ci e = ET.XML("<!DOCTYPE doc [<!ENTITY ldots '舰'>]>" 20147db96d56Sopenharmony_ci '<doc>&ldots;</doc>') 20157db96d56Sopenharmony_ci self.assertEqual(serialize(e, encoding="us-ascii"), 20167db96d56Sopenharmony_ci b'<doc>舰</doc>') 20177db96d56Sopenharmony_ci self.assertEqual(serialize(e), '<doc>\u8230</doc>') 20187db96d56Sopenharmony_ci 20197db96d56Sopenharmony_ci def test_bug_xmltoolkit55(self): 20207db96d56Sopenharmony_ci # make sure we're reporting the first error, not the last 20217db96d56Sopenharmony_ci 20227db96d56Sopenharmony_ci with self.assertRaises(ET.ParseError) as cm: 20237db96d56Sopenharmony_ci ET.XML(b"<!DOCTYPE doc SYSTEM 'doc.dtd'>" 20247db96d56Sopenharmony_ci b'<doc>&ldots;&ndots;&rdots;</doc>') 20257db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 20267db96d56Sopenharmony_ci 'undefined entity &ldots;: line 1, column 36') 20277db96d56Sopenharmony_ci 20287db96d56Sopenharmony_ci def test_bug_xmltoolkit60(self): 20297db96d56Sopenharmony_ci # Handle crash in stream source. 20307db96d56Sopenharmony_ci 20317db96d56Sopenharmony_ci class ExceptionFile: 20327db96d56Sopenharmony_ci def read(self, x): 20337db96d56Sopenharmony_ci raise OSError 20347db96d56Sopenharmony_ci 20357db96d56Sopenharmony_ci self.assertRaises(OSError, ET.parse, ExceptionFile()) 20367db96d56Sopenharmony_ci 20377db96d56Sopenharmony_ci def test_bug_xmltoolkit62(self): 20387db96d56Sopenharmony_ci # Don't crash when using custom entities. 20397db96d56Sopenharmony_ci 20407db96d56Sopenharmony_ci ENTITIES = {'rsquo': '\u2019', 'lsquo': '\u2018'} 20417db96d56Sopenharmony_ci parser = ET.XMLParser() 20427db96d56Sopenharmony_ci parser.entity.update(ENTITIES) 20437db96d56Sopenharmony_ci parser.feed("""<?xml version="1.0" encoding="UTF-8"?> 20447db96d56Sopenharmony_ci<!DOCTYPE patent-application-publication SYSTEM "pap-v15-2001-01-31.dtd" []> 20457db96d56Sopenharmony_ci<patent-application-publication> 20467db96d56Sopenharmony_ci<subdoc-abstract> 20477db96d56Sopenharmony_ci<paragraph id="A-0001" lvl="0">A new cultivar of Begonia plant named ‘BCT9801BEG’.</paragraph> 20487db96d56Sopenharmony_ci</subdoc-abstract> 20497db96d56Sopenharmony_ci</patent-application-publication>""") 20507db96d56Sopenharmony_ci t = parser.close() 20517db96d56Sopenharmony_ci self.assertEqual(t.find('.//paragraph').text, 20527db96d56Sopenharmony_ci 'A new cultivar of Begonia plant named \u2018BCT9801BEG\u2019.') 20537db96d56Sopenharmony_ci 20547db96d56Sopenharmony_ci @unittest.skipIf(sys.gettrace(), "Skips under coverage.") 20557db96d56Sopenharmony_ci def test_bug_xmltoolkit63(self): 20567db96d56Sopenharmony_ci # Check reference leak. 20577db96d56Sopenharmony_ci def xmltoolkit63(): 20587db96d56Sopenharmony_ci tree = ET.TreeBuilder() 20597db96d56Sopenharmony_ci tree.start("tag", {}) 20607db96d56Sopenharmony_ci tree.data("text") 20617db96d56Sopenharmony_ci tree.end("tag") 20627db96d56Sopenharmony_ci 20637db96d56Sopenharmony_ci xmltoolkit63() 20647db96d56Sopenharmony_ci count = sys.getrefcount(None) 20657db96d56Sopenharmony_ci for i in range(1000): 20667db96d56Sopenharmony_ci xmltoolkit63() 20677db96d56Sopenharmony_ci self.assertEqual(sys.getrefcount(None), count) 20687db96d56Sopenharmony_ci 20697db96d56Sopenharmony_ci def test_bug_200708_newline(self): 20707db96d56Sopenharmony_ci # Preserve newlines in attributes. 20717db96d56Sopenharmony_ci 20727db96d56Sopenharmony_ci e = ET.Element('SomeTag', text="def _f():\n return 3\n") 20737db96d56Sopenharmony_ci self.assertEqual(ET.tostring(e), 20747db96d56Sopenharmony_ci b'<SomeTag text="def _f(): return 3 " />') 20757db96d56Sopenharmony_ci self.assertEqual(ET.XML(ET.tostring(e)).get("text"), 20767db96d56Sopenharmony_ci 'def _f():\n return 3\n') 20777db96d56Sopenharmony_ci self.assertEqual(ET.tostring(ET.XML(ET.tostring(e))), 20787db96d56Sopenharmony_ci b'<SomeTag text="def _f(): return 3 " />') 20797db96d56Sopenharmony_ci 20807db96d56Sopenharmony_ci def test_bug_200708_close(self): 20817db96d56Sopenharmony_ci # Test default builder. 20827db96d56Sopenharmony_ci parser = ET.XMLParser() # default 20837db96d56Sopenharmony_ci parser.feed("<element>some text</element>") 20847db96d56Sopenharmony_ci self.assertEqual(parser.close().tag, 'element') 20857db96d56Sopenharmony_ci 20867db96d56Sopenharmony_ci # Test custom builder. 20877db96d56Sopenharmony_ci class EchoTarget: 20887db96d56Sopenharmony_ci def close(self): 20897db96d56Sopenharmony_ci return ET.Element("element") # simulate root 20907db96d56Sopenharmony_ci parser = ET.XMLParser(target=EchoTarget()) 20917db96d56Sopenharmony_ci parser.feed("<element>some text</element>") 20927db96d56Sopenharmony_ci self.assertEqual(parser.close().tag, 'element') 20937db96d56Sopenharmony_ci 20947db96d56Sopenharmony_ci def test_bug_200709_default_namespace(self): 20957db96d56Sopenharmony_ci e = ET.Element("{default}elem") 20967db96d56Sopenharmony_ci s = ET.SubElement(e, "{default}elem") 20977db96d56Sopenharmony_ci self.assertEqual(serialize(e, default_namespace="default"), # 1 20987db96d56Sopenharmony_ci '<elem xmlns="default"><elem /></elem>') 20997db96d56Sopenharmony_ci 21007db96d56Sopenharmony_ci e = ET.Element("{default}elem") 21017db96d56Sopenharmony_ci s = ET.SubElement(e, "{default}elem") 21027db96d56Sopenharmony_ci s = ET.SubElement(e, "{not-default}elem") 21037db96d56Sopenharmony_ci self.assertEqual(serialize(e, default_namespace="default"), # 2 21047db96d56Sopenharmony_ci '<elem xmlns="default" xmlns:ns1="not-default">' 21057db96d56Sopenharmony_ci '<elem />' 21067db96d56Sopenharmony_ci '<ns1:elem />' 21077db96d56Sopenharmony_ci '</elem>') 21087db96d56Sopenharmony_ci 21097db96d56Sopenharmony_ci e = ET.Element("{default}elem") 21107db96d56Sopenharmony_ci s = ET.SubElement(e, "{default}elem") 21117db96d56Sopenharmony_ci s = ET.SubElement(e, "elem") # unprefixed name 21127db96d56Sopenharmony_ci with self.assertRaises(ValueError) as cm: 21137db96d56Sopenharmony_ci serialize(e, default_namespace="default") # 3 21147db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 21157db96d56Sopenharmony_ci 'cannot use non-qualified names with default_namespace option') 21167db96d56Sopenharmony_ci 21177db96d56Sopenharmony_ci def test_bug_200709_register_namespace(self): 21187db96d56Sopenharmony_ci e = ET.Element("{http://namespace.invalid/does/not/exist/}title") 21197db96d56Sopenharmony_ci self.assertEqual(ET.tostring(e), 21207db96d56Sopenharmony_ci b'<ns0:title xmlns:ns0="http://namespace.invalid/does/not/exist/" />') 21217db96d56Sopenharmony_ci ET.register_namespace("foo", "http://namespace.invalid/does/not/exist/") 21227db96d56Sopenharmony_ci e = ET.Element("{http://namespace.invalid/does/not/exist/}title") 21237db96d56Sopenharmony_ci self.assertEqual(ET.tostring(e), 21247db96d56Sopenharmony_ci b'<foo:title xmlns:foo="http://namespace.invalid/does/not/exist/" />') 21257db96d56Sopenharmony_ci 21267db96d56Sopenharmony_ci # And the Dublin Core namespace is in the default list: 21277db96d56Sopenharmony_ci 21287db96d56Sopenharmony_ci e = ET.Element("{http://purl.org/dc/elements/1.1/}title") 21297db96d56Sopenharmony_ci self.assertEqual(ET.tostring(e), 21307db96d56Sopenharmony_ci b'<dc:title xmlns:dc="http://purl.org/dc/elements/1.1/" />') 21317db96d56Sopenharmony_ci 21327db96d56Sopenharmony_ci def test_bug_200709_element_comment(self): 21337db96d56Sopenharmony_ci # Not sure if this can be fixed, really (since the serializer needs 21347db96d56Sopenharmony_ci # ET.Comment, not cET.comment). 21357db96d56Sopenharmony_ci 21367db96d56Sopenharmony_ci a = ET.Element('a') 21377db96d56Sopenharmony_ci a.append(ET.Comment('foo')) 21387db96d56Sopenharmony_ci self.assertEqual(a[0].tag, ET.Comment) 21397db96d56Sopenharmony_ci 21407db96d56Sopenharmony_ci a = ET.Element('a') 21417db96d56Sopenharmony_ci a.append(ET.PI('foo')) 21427db96d56Sopenharmony_ci self.assertEqual(a[0].tag, ET.PI) 21437db96d56Sopenharmony_ci 21447db96d56Sopenharmony_ci def test_bug_200709_element_insert(self): 21457db96d56Sopenharmony_ci a = ET.Element('a') 21467db96d56Sopenharmony_ci b = ET.SubElement(a, 'b') 21477db96d56Sopenharmony_ci c = ET.SubElement(a, 'c') 21487db96d56Sopenharmony_ci d = ET.Element('d') 21497db96d56Sopenharmony_ci a.insert(0, d) 21507db96d56Sopenharmony_ci self.assertEqual(summarize_list(a), ['d', 'b', 'c']) 21517db96d56Sopenharmony_ci a.insert(-1, d) 21527db96d56Sopenharmony_ci self.assertEqual(summarize_list(a), ['d', 'b', 'd', 'c']) 21537db96d56Sopenharmony_ci 21547db96d56Sopenharmony_ci def test_bug_200709_iter_comment(self): 21557db96d56Sopenharmony_ci a = ET.Element('a') 21567db96d56Sopenharmony_ci b = ET.SubElement(a, 'b') 21577db96d56Sopenharmony_ci comment_b = ET.Comment("TEST-b") 21587db96d56Sopenharmony_ci b.append(comment_b) 21597db96d56Sopenharmony_ci self.assertEqual(summarize_list(a.iter(ET.Comment)), [ET.Comment]) 21607db96d56Sopenharmony_ci 21617db96d56Sopenharmony_ci # -------------------------------------------------------------------- 21627db96d56Sopenharmony_ci # reported on bugs.python.org 21637db96d56Sopenharmony_ci 21647db96d56Sopenharmony_ci def test_bug_1534630(self): 21657db96d56Sopenharmony_ci bob = ET.TreeBuilder() 21667db96d56Sopenharmony_ci e = bob.data("data") 21677db96d56Sopenharmony_ci e = bob.start("tag", {}) 21687db96d56Sopenharmony_ci e = bob.end("tag") 21697db96d56Sopenharmony_ci e = bob.close() 21707db96d56Sopenharmony_ci self.assertEqual(serialize(e), '<tag />') 21717db96d56Sopenharmony_ci 21727db96d56Sopenharmony_ci def test_issue6233(self): 21737db96d56Sopenharmony_ci e = ET.XML(b"<?xml version='1.0' encoding='utf-8'?>" 21747db96d56Sopenharmony_ci b'<body>t\xc3\xa3g</body>') 21757db96d56Sopenharmony_ci self.assertEqual(ET.tostring(e, 'ascii'), 21767db96d56Sopenharmony_ci b"<?xml version='1.0' encoding='ascii'?>\n" 21777db96d56Sopenharmony_ci b'<body>tãg</body>') 21787db96d56Sopenharmony_ci e = ET.XML(b"<?xml version='1.0' encoding='iso-8859-1'?>" 21797db96d56Sopenharmony_ci b'<body>t\xe3g</body>') 21807db96d56Sopenharmony_ci self.assertEqual(ET.tostring(e, 'ascii'), 21817db96d56Sopenharmony_ci b"<?xml version='1.0' encoding='ascii'?>\n" 21827db96d56Sopenharmony_ci b'<body>tãg</body>') 21837db96d56Sopenharmony_ci 21847db96d56Sopenharmony_ci def test_issue6565(self): 21857db96d56Sopenharmony_ci elem = ET.XML("<body><tag/></body>") 21867db96d56Sopenharmony_ci self.assertEqual(summarize_list(elem), ['tag']) 21877db96d56Sopenharmony_ci newelem = ET.XML(SAMPLE_XML) 21887db96d56Sopenharmony_ci elem[:] = newelem[:] 21897db96d56Sopenharmony_ci self.assertEqual(summarize_list(elem), ['tag', 'tag', 'section']) 21907db96d56Sopenharmony_ci 21917db96d56Sopenharmony_ci def test_issue10777(self): 21927db96d56Sopenharmony_ci # Registering a namespace twice caused a "dictionary changed size during 21937db96d56Sopenharmony_ci # iteration" bug. 21947db96d56Sopenharmony_ci 21957db96d56Sopenharmony_ci ET.register_namespace('test10777', 'http://myuri/') 21967db96d56Sopenharmony_ci ET.register_namespace('test10777', 'http://myuri/') 21977db96d56Sopenharmony_ci 21987db96d56Sopenharmony_ci def test_lost_text(self): 21997db96d56Sopenharmony_ci # Issue #25902: Borrowed text can disappear 22007db96d56Sopenharmony_ci class Text: 22017db96d56Sopenharmony_ci def __bool__(self): 22027db96d56Sopenharmony_ci e.text = 'changed' 22037db96d56Sopenharmony_ci return True 22047db96d56Sopenharmony_ci 22057db96d56Sopenharmony_ci e = ET.Element('tag') 22067db96d56Sopenharmony_ci e.text = Text() 22077db96d56Sopenharmony_ci i = e.itertext() 22087db96d56Sopenharmony_ci t = next(i) 22097db96d56Sopenharmony_ci self.assertIsInstance(t, Text) 22107db96d56Sopenharmony_ci self.assertIsInstance(e.text, str) 22117db96d56Sopenharmony_ci self.assertEqual(e.text, 'changed') 22127db96d56Sopenharmony_ci 22137db96d56Sopenharmony_ci def test_lost_tail(self): 22147db96d56Sopenharmony_ci # Issue #25902: Borrowed tail can disappear 22157db96d56Sopenharmony_ci class Text: 22167db96d56Sopenharmony_ci def __bool__(self): 22177db96d56Sopenharmony_ci e[0].tail = 'changed' 22187db96d56Sopenharmony_ci return True 22197db96d56Sopenharmony_ci 22207db96d56Sopenharmony_ci e = ET.Element('root') 22217db96d56Sopenharmony_ci e.append(ET.Element('tag')) 22227db96d56Sopenharmony_ci e[0].tail = Text() 22237db96d56Sopenharmony_ci i = e.itertext() 22247db96d56Sopenharmony_ci t = next(i) 22257db96d56Sopenharmony_ci self.assertIsInstance(t, Text) 22267db96d56Sopenharmony_ci self.assertIsInstance(e[0].tail, str) 22277db96d56Sopenharmony_ci self.assertEqual(e[0].tail, 'changed') 22287db96d56Sopenharmony_ci 22297db96d56Sopenharmony_ci def test_lost_elem(self): 22307db96d56Sopenharmony_ci # Issue #25902: Borrowed element can disappear 22317db96d56Sopenharmony_ci class Tag: 22327db96d56Sopenharmony_ci def __eq__(self, other): 22337db96d56Sopenharmony_ci e[0] = ET.Element('changed') 22347db96d56Sopenharmony_ci next(i) 22357db96d56Sopenharmony_ci return True 22367db96d56Sopenharmony_ci 22377db96d56Sopenharmony_ci e = ET.Element('root') 22387db96d56Sopenharmony_ci e.append(ET.Element(Tag())) 22397db96d56Sopenharmony_ci e.append(ET.Element('tag')) 22407db96d56Sopenharmony_ci i = e.iter('tag') 22417db96d56Sopenharmony_ci try: 22427db96d56Sopenharmony_ci t = next(i) 22437db96d56Sopenharmony_ci except ValueError: 22447db96d56Sopenharmony_ci self.skipTest('generators are not reentrant') 22457db96d56Sopenharmony_ci self.assertIsInstance(t.tag, Tag) 22467db96d56Sopenharmony_ci self.assertIsInstance(e[0].tag, str) 22477db96d56Sopenharmony_ci self.assertEqual(e[0].tag, 'changed') 22487db96d56Sopenharmony_ci 22497db96d56Sopenharmony_ci def check_expat224_utf8_bug(self, text): 22507db96d56Sopenharmony_ci xml = b'<a b="%s"/>' % text 22517db96d56Sopenharmony_ci root = ET.XML(xml) 22527db96d56Sopenharmony_ci self.assertEqual(root.get('b'), text.decode('utf-8')) 22537db96d56Sopenharmony_ci 22547db96d56Sopenharmony_ci def test_expat224_utf8_bug(self): 22557db96d56Sopenharmony_ci # bpo-31170: Expat 2.2.3 had a bug in its UTF-8 decoder. 22567db96d56Sopenharmony_ci # Check that Expat 2.2.4 fixed the bug. 22577db96d56Sopenharmony_ci # 22587db96d56Sopenharmony_ci # Test buffer bounds at odd and even positions. 22597db96d56Sopenharmony_ci 22607db96d56Sopenharmony_ci text = b'\xc3\xa0' * 1024 22617db96d56Sopenharmony_ci self.check_expat224_utf8_bug(text) 22627db96d56Sopenharmony_ci 22637db96d56Sopenharmony_ci text = b'x' + b'\xc3\xa0' * 1024 22647db96d56Sopenharmony_ci self.check_expat224_utf8_bug(text) 22657db96d56Sopenharmony_ci 22667db96d56Sopenharmony_ci def test_expat224_utf8_bug_file(self): 22677db96d56Sopenharmony_ci with open(UTF8_BUG_XMLFILE, 'rb') as fp: 22687db96d56Sopenharmony_ci raw = fp.read() 22697db96d56Sopenharmony_ci root = ET.fromstring(raw) 22707db96d56Sopenharmony_ci xmlattr = root.get('b') 22717db96d56Sopenharmony_ci 22727db96d56Sopenharmony_ci # "Parse" manually the XML file to extract the value of the 'b' 22737db96d56Sopenharmony_ci # attribute of the <a b='xxx' /> XML element 22747db96d56Sopenharmony_ci text = raw.decode('utf-8').strip() 22757db96d56Sopenharmony_ci text = text.replace('\r\n', ' ') 22767db96d56Sopenharmony_ci text = text[6:-4] 22777db96d56Sopenharmony_ci self.assertEqual(root.get('b'), text) 22787db96d56Sopenharmony_ci 22797db96d56Sopenharmony_ci def test_39495_treebuilder_start(self): 22807db96d56Sopenharmony_ci self.assertRaises(TypeError, ET.TreeBuilder().start, "tag") 22817db96d56Sopenharmony_ci self.assertRaises(TypeError, ET.TreeBuilder().start, "tag", None) 22827db96d56Sopenharmony_ci 22837db96d56Sopenharmony_ci 22847db96d56Sopenharmony_ci 22857db96d56Sopenharmony_ci# -------------------------------------------------------------------- 22867db96d56Sopenharmony_ci 22877db96d56Sopenharmony_ci 22887db96d56Sopenharmony_ciclass BasicElementTest(ElementTestCase, unittest.TestCase): 22897db96d56Sopenharmony_ci 22907db96d56Sopenharmony_ci def test___init__(self): 22917db96d56Sopenharmony_ci tag = "foo" 22927db96d56Sopenharmony_ci attrib = { "zix": "wyp" } 22937db96d56Sopenharmony_ci 22947db96d56Sopenharmony_ci element_foo = ET.Element(tag, attrib) 22957db96d56Sopenharmony_ci 22967db96d56Sopenharmony_ci # traits of an element 22977db96d56Sopenharmony_ci self.assertIsInstance(element_foo, ET.Element) 22987db96d56Sopenharmony_ci self.assertIn("tag", dir(element_foo)) 22997db96d56Sopenharmony_ci self.assertIn("attrib", dir(element_foo)) 23007db96d56Sopenharmony_ci self.assertIn("text", dir(element_foo)) 23017db96d56Sopenharmony_ci self.assertIn("tail", dir(element_foo)) 23027db96d56Sopenharmony_ci 23037db96d56Sopenharmony_ci # string attributes have expected values 23047db96d56Sopenharmony_ci self.assertEqual(element_foo.tag, tag) 23057db96d56Sopenharmony_ci self.assertIsNone(element_foo.text) 23067db96d56Sopenharmony_ci self.assertIsNone(element_foo.tail) 23077db96d56Sopenharmony_ci 23087db96d56Sopenharmony_ci # attrib is a copy 23097db96d56Sopenharmony_ci self.assertIsNot(element_foo.attrib, attrib) 23107db96d56Sopenharmony_ci self.assertEqual(element_foo.attrib, attrib) 23117db96d56Sopenharmony_ci 23127db96d56Sopenharmony_ci # attrib isn't linked 23137db96d56Sopenharmony_ci attrib["bar"] = "baz" 23147db96d56Sopenharmony_ci self.assertIsNot(element_foo.attrib, attrib) 23157db96d56Sopenharmony_ci self.assertNotEqual(element_foo.attrib, attrib) 23167db96d56Sopenharmony_ci 23177db96d56Sopenharmony_ci def test_copy(self): 23187db96d56Sopenharmony_ci # Only run this test if Element.copy() is defined. 23197db96d56Sopenharmony_ci if "copy" not in dir(ET.Element): 23207db96d56Sopenharmony_ci raise unittest.SkipTest("Element.copy() not present") 23217db96d56Sopenharmony_ci 23227db96d56Sopenharmony_ci element_foo = ET.Element("foo", { "zix": "wyp" }) 23237db96d56Sopenharmony_ci element_foo.append(ET.Element("bar", { "baz": "qix" })) 23247db96d56Sopenharmony_ci 23257db96d56Sopenharmony_ci with self.assertWarns(DeprecationWarning): 23267db96d56Sopenharmony_ci element_foo2 = element_foo.copy() 23277db96d56Sopenharmony_ci 23287db96d56Sopenharmony_ci # elements are not the same 23297db96d56Sopenharmony_ci self.assertIsNot(element_foo2, element_foo) 23307db96d56Sopenharmony_ci 23317db96d56Sopenharmony_ci # string attributes are equal 23327db96d56Sopenharmony_ci self.assertEqual(element_foo2.tag, element_foo.tag) 23337db96d56Sopenharmony_ci self.assertEqual(element_foo2.text, element_foo.text) 23347db96d56Sopenharmony_ci self.assertEqual(element_foo2.tail, element_foo.tail) 23357db96d56Sopenharmony_ci 23367db96d56Sopenharmony_ci # number of children is the same 23377db96d56Sopenharmony_ci self.assertEqual(len(element_foo2), len(element_foo)) 23387db96d56Sopenharmony_ci 23397db96d56Sopenharmony_ci # children are the same 23407db96d56Sopenharmony_ci for (child1, child2) in itertools.zip_longest(element_foo, element_foo2): 23417db96d56Sopenharmony_ci self.assertIs(child1, child2) 23427db96d56Sopenharmony_ci 23437db96d56Sopenharmony_ci # attrib is a copy 23447db96d56Sopenharmony_ci self.assertEqual(element_foo2.attrib, element_foo.attrib) 23457db96d56Sopenharmony_ci 23467db96d56Sopenharmony_ci def test___copy__(self): 23477db96d56Sopenharmony_ci element_foo = ET.Element("foo", { "zix": "wyp" }) 23487db96d56Sopenharmony_ci element_foo.append(ET.Element("bar", { "baz": "qix" })) 23497db96d56Sopenharmony_ci 23507db96d56Sopenharmony_ci element_foo2 = copy.copy(element_foo) 23517db96d56Sopenharmony_ci 23527db96d56Sopenharmony_ci # elements are not the same 23537db96d56Sopenharmony_ci self.assertIsNot(element_foo2, element_foo) 23547db96d56Sopenharmony_ci 23557db96d56Sopenharmony_ci # string attributes are equal 23567db96d56Sopenharmony_ci self.assertEqual(element_foo2.tag, element_foo.tag) 23577db96d56Sopenharmony_ci self.assertEqual(element_foo2.text, element_foo.text) 23587db96d56Sopenharmony_ci self.assertEqual(element_foo2.tail, element_foo.tail) 23597db96d56Sopenharmony_ci 23607db96d56Sopenharmony_ci # number of children is the same 23617db96d56Sopenharmony_ci self.assertEqual(len(element_foo2), len(element_foo)) 23627db96d56Sopenharmony_ci 23637db96d56Sopenharmony_ci # children are the same 23647db96d56Sopenharmony_ci for (child1, child2) in itertools.zip_longest(element_foo, element_foo2): 23657db96d56Sopenharmony_ci self.assertIs(child1, child2) 23667db96d56Sopenharmony_ci 23677db96d56Sopenharmony_ci # attrib is a copy 23687db96d56Sopenharmony_ci self.assertEqual(element_foo2.attrib, element_foo.attrib) 23697db96d56Sopenharmony_ci 23707db96d56Sopenharmony_ci def test___deepcopy__(self): 23717db96d56Sopenharmony_ci element_foo = ET.Element("foo", { "zix": "wyp" }) 23727db96d56Sopenharmony_ci element_foo.append(ET.Element("bar", { "baz": "qix" })) 23737db96d56Sopenharmony_ci 23747db96d56Sopenharmony_ci element_foo2 = copy.deepcopy(element_foo) 23757db96d56Sopenharmony_ci 23767db96d56Sopenharmony_ci # elements are not the same 23777db96d56Sopenharmony_ci self.assertIsNot(element_foo2, element_foo) 23787db96d56Sopenharmony_ci 23797db96d56Sopenharmony_ci # string attributes are equal 23807db96d56Sopenharmony_ci self.assertEqual(element_foo2.tag, element_foo.tag) 23817db96d56Sopenharmony_ci self.assertEqual(element_foo2.text, element_foo.text) 23827db96d56Sopenharmony_ci self.assertEqual(element_foo2.tail, element_foo.tail) 23837db96d56Sopenharmony_ci 23847db96d56Sopenharmony_ci # number of children is the same 23857db96d56Sopenharmony_ci self.assertEqual(len(element_foo2), len(element_foo)) 23867db96d56Sopenharmony_ci 23877db96d56Sopenharmony_ci # children are not the same 23887db96d56Sopenharmony_ci for (child1, child2) in itertools.zip_longest(element_foo, element_foo2): 23897db96d56Sopenharmony_ci self.assertIsNot(child1, child2) 23907db96d56Sopenharmony_ci 23917db96d56Sopenharmony_ci # attrib is a copy 23927db96d56Sopenharmony_ci self.assertIsNot(element_foo2.attrib, element_foo.attrib) 23937db96d56Sopenharmony_ci self.assertEqual(element_foo2.attrib, element_foo.attrib) 23947db96d56Sopenharmony_ci 23957db96d56Sopenharmony_ci # attrib isn't linked 23967db96d56Sopenharmony_ci element_foo.attrib["bar"] = "baz" 23977db96d56Sopenharmony_ci self.assertIsNot(element_foo2.attrib, element_foo.attrib) 23987db96d56Sopenharmony_ci self.assertNotEqual(element_foo2.attrib, element_foo.attrib) 23997db96d56Sopenharmony_ci 24007db96d56Sopenharmony_ci def test_augmentation_type_errors(self): 24017db96d56Sopenharmony_ci e = ET.Element('joe') 24027db96d56Sopenharmony_ci self.assertRaises(TypeError, e.append, 'b') 24037db96d56Sopenharmony_ci self.assertRaises(TypeError, e.extend, [ET.Element('bar'), 'foo']) 24047db96d56Sopenharmony_ci self.assertRaises(TypeError, e.insert, 0, 'foo') 24057db96d56Sopenharmony_ci e[:] = [ET.Element('bar')] 24067db96d56Sopenharmony_ci with self.assertRaises(TypeError): 24077db96d56Sopenharmony_ci e[0] = 'foo' 24087db96d56Sopenharmony_ci with self.assertRaises(TypeError): 24097db96d56Sopenharmony_ci e[:] = [ET.Element('bar'), 'foo'] 24107db96d56Sopenharmony_ci 24117db96d56Sopenharmony_ci if hasattr(e, '__setstate__'): 24127db96d56Sopenharmony_ci state = { 24137db96d56Sopenharmony_ci 'tag': 'tag', 24147db96d56Sopenharmony_ci '_children': [None], # non-Element 24157db96d56Sopenharmony_ci 'attrib': 'attr', 24167db96d56Sopenharmony_ci 'tail': 'tail', 24177db96d56Sopenharmony_ci 'text': 'text', 24187db96d56Sopenharmony_ci } 24197db96d56Sopenharmony_ci self.assertRaises(TypeError, e.__setstate__, state) 24207db96d56Sopenharmony_ci 24217db96d56Sopenharmony_ci if hasattr(e, '__deepcopy__'): 24227db96d56Sopenharmony_ci class E(ET.Element): 24237db96d56Sopenharmony_ci def __deepcopy__(self, memo): 24247db96d56Sopenharmony_ci return None # non-Element 24257db96d56Sopenharmony_ci e[:] = [E('bar')] 24267db96d56Sopenharmony_ci self.assertRaises(TypeError, copy.deepcopy, e) 24277db96d56Sopenharmony_ci 24287db96d56Sopenharmony_ci def test_cyclic_gc(self): 24297db96d56Sopenharmony_ci class Dummy: 24307db96d56Sopenharmony_ci pass 24317db96d56Sopenharmony_ci 24327db96d56Sopenharmony_ci # Test the shortest cycle: d->element->d 24337db96d56Sopenharmony_ci d = Dummy() 24347db96d56Sopenharmony_ci d.dummyref = ET.Element('joe', attr=d) 24357db96d56Sopenharmony_ci wref = weakref.ref(d) 24367db96d56Sopenharmony_ci del d 24377db96d56Sopenharmony_ci gc_collect() 24387db96d56Sopenharmony_ci self.assertIsNone(wref()) 24397db96d56Sopenharmony_ci 24407db96d56Sopenharmony_ci # A longer cycle: d->e->e2->d 24417db96d56Sopenharmony_ci e = ET.Element('joe') 24427db96d56Sopenharmony_ci d = Dummy() 24437db96d56Sopenharmony_ci d.dummyref = e 24447db96d56Sopenharmony_ci wref = weakref.ref(d) 24457db96d56Sopenharmony_ci e2 = ET.SubElement(e, 'foo', attr=d) 24467db96d56Sopenharmony_ci del d, e, e2 24477db96d56Sopenharmony_ci gc_collect() 24487db96d56Sopenharmony_ci self.assertIsNone(wref()) 24497db96d56Sopenharmony_ci 24507db96d56Sopenharmony_ci # A cycle between Element objects as children of one another 24517db96d56Sopenharmony_ci # e1->e2->e3->e1 24527db96d56Sopenharmony_ci e1 = ET.Element('e1') 24537db96d56Sopenharmony_ci e2 = ET.Element('e2') 24547db96d56Sopenharmony_ci e3 = ET.Element('e3') 24557db96d56Sopenharmony_ci e3.append(e1) 24567db96d56Sopenharmony_ci e2.append(e3) 24577db96d56Sopenharmony_ci e1.append(e2) 24587db96d56Sopenharmony_ci wref = weakref.ref(e1) 24597db96d56Sopenharmony_ci del e1, e2, e3 24607db96d56Sopenharmony_ci gc_collect() 24617db96d56Sopenharmony_ci self.assertIsNone(wref()) 24627db96d56Sopenharmony_ci 24637db96d56Sopenharmony_ci def test_weakref(self): 24647db96d56Sopenharmony_ci flag = False 24657db96d56Sopenharmony_ci def wref_cb(w): 24667db96d56Sopenharmony_ci nonlocal flag 24677db96d56Sopenharmony_ci flag = True 24687db96d56Sopenharmony_ci e = ET.Element('e') 24697db96d56Sopenharmony_ci wref = weakref.ref(e, wref_cb) 24707db96d56Sopenharmony_ci self.assertEqual(wref().tag, 'e') 24717db96d56Sopenharmony_ci del e 24727db96d56Sopenharmony_ci gc_collect() # For PyPy or other GCs. 24737db96d56Sopenharmony_ci self.assertEqual(flag, True) 24747db96d56Sopenharmony_ci self.assertEqual(wref(), None) 24757db96d56Sopenharmony_ci 24767db96d56Sopenharmony_ci def test_get_keyword_args(self): 24777db96d56Sopenharmony_ci e1 = ET.Element('foo' , x=1, y=2, z=3) 24787db96d56Sopenharmony_ci self.assertEqual(e1.get('x', default=7), 1) 24797db96d56Sopenharmony_ci self.assertEqual(e1.get('w', default=7), 7) 24807db96d56Sopenharmony_ci 24817db96d56Sopenharmony_ci def test_pickle(self): 24827db96d56Sopenharmony_ci # issue #16076: the C implementation wasn't pickleable. 24837db96d56Sopenharmony_ci for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): 24847db96d56Sopenharmony_ci for dumper, loader in product(self.modules, repeat=2): 24857db96d56Sopenharmony_ci e = dumper.Element('foo', bar=42) 24867db96d56Sopenharmony_ci e.text = "text goes here" 24877db96d56Sopenharmony_ci e.tail = "opposite of head" 24887db96d56Sopenharmony_ci dumper.SubElement(e, 'child').append(dumper.Element('grandchild')) 24897db96d56Sopenharmony_ci e.append(dumper.Element('child')) 24907db96d56Sopenharmony_ci e.findall('.//grandchild')[0].set('attr', 'other value') 24917db96d56Sopenharmony_ci 24927db96d56Sopenharmony_ci e2 = self.pickleRoundTrip(e, 'xml.etree.ElementTree', 24937db96d56Sopenharmony_ci dumper, loader, proto) 24947db96d56Sopenharmony_ci 24957db96d56Sopenharmony_ci self.assertEqual(e2.tag, 'foo') 24967db96d56Sopenharmony_ci self.assertEqual(e2.attrib['bar'], 42) 24977db96d56Sopenharmony_ci self.assertEqual(len(e2), 2) 24987db96d56Sopenharmony_ci self.assertEqualElements(e, e2) 24997db96d56Sopenharmony_ci 25007db96d56Sopenharmony_ci def test_pickle_issue18997(self): 25017db96d56Sopenharmony_ci for proto in range(2, pickle.HIGHEST_PROTOCOL + 1): 25027db96d56Sopenharmony_ci for dumper, loader in product(self.modules, repeat=2): 25037db96d56Sopenharmony_ci XMLTEXT = """<?xml version="1.0"?> 25047db96d56Sopenharmony_ci <group><dogs>4</dogs> 25057db96d56Sopenharmony_ci </group>""" 25067db96d56Sopenharmony_ci e1 = dumper.fromstring(XMLTEXT) 25077db96d56Sopenharmony_ci self.assertEqual(e1.__getstate__()['tag'], 'group') 25087db96d56Sopenharmony_ci e2 = self.pickleRoundTrip(e1, 'xml.etree.ElementTree', 25097db96d56Sopenharmony_ci dumper, loader, proto) 25107db96d56Sopenharmony_ci self.assertEqual(e2.tag, 'group') 25117db96d56Sopenharmony_ci self.assertEqual(e2[0].tag, 'dogs') 25127db96d56Sopenharmony_ci 25137db96d56Sopenharmony_ci 25147db96d56Sopenharmony_ciclass BadElementTest(ElementTestCase, unittest.TestCase): 25157db96d56Sopenharmony_ci def test_extend_mutable_list(self): 25167db96d56Sopenharmony_ci class X: 25177db96d56Sopenharmony_ci @property 25187db96d56Sopenharmony_ci def __class__(self): 25197db96d56Sopenharmony_ci L[:] = [ET.Element('baz')] 25207db96d56Sopenharmony_ci return ET.Element 25217db96d56Sopenharmony_ci L = [X()] 25227db96d56Sopenharmony_ci e = ET.Element('foo') 25237db96d56Sopenharmony_ci try: 25247db96d56Sopenharmony_ci e.extend(L) 25257db96d56Sopenharmony_ci except TypeError: 25267db96d56Sopenharmony_ci pass 25277db96d56Sopenharmony_ci 25287db96d56Sopenharmony_ci class Y(X, ET.Element): 25297db96d56Sopenharmony_ci pass 25307db96d56Sopenharmony_ci L = [Y('x')] 25317db96d56Sopenharmony_ci e = ET.Element('foo') 25327db96d56Sopenharmony_ci e.extend(L) 25337db96d56Sopenharmony_ci 25347db96d56Sopenharmony_ci def test_extend_mutable_list2(self): 25357db96d56Sopenharmony_ci class X: 25367db96d56Sopenharmony_ci @property 25377db96d56Sopenharmony_ci def __class__(self): 25387db96d56Sopenharmony_ci del L[:] 25397db96d56Sopenharmony_ci return ET.Element 25407db96d56Sopenharmony_ci L = [X(), ET.Element('baz')] 25417db96d56Sopenharmony_ci e = ET.Element('foo') 25427db96d56Sopenharmony_ci try: 25437db96d56Sopenharmony_ci e.extend(L) 25447db96d56Sopenharmony_ci except TypeError: 25457db96d56Sopenharmony_ci pass 25467db96d56Sopenharmony_ci 25477db96d56Sopenharmony_ci class Y(X, ET.Element): 25487db96d56Sopenharmony_ci pass 25497db96d56Sopenharmony_ci L = [Y('bar'), ET.Element('baz')] 25507db96d56Sopenharmony_ci e = ET.Element('foo') 25517db96d56Sopenharmony_ci e.extend(L) 25527db96d56Sopenharmony_ci 25537db96d56Sopenharmony_ci def test_remove_with_mutating(self): 25547db96d56Sopenharmony_ci class X(ET.Element): 25557db96d56Sopenharmony_ci def __eq__(self, o): 25567db96d56Sopenharmony_ci del e[:] 25577db96d56Sopenharmony_ci return False 25587db96d56Sopenharmony_ci e = ET.Element('foo') 25597db96d56Sopenharmony_ci e.extend([X('bar')]) 25607db96d56Sopenharmony_ci self.assertRaises(ValueError, e.remove, ET.Element('baz')) 25617db96d56Sopenharmony_ci 25627db96d56Sopenharmony_ci e = ET.Element('foo') 25637db96d56Sopenharmony_ci e.extend([ET.Element('bar')]) 25647db96d56Sopenharmony_ci self.assertRaises(ValueError, e.remove, X('baz')) 25657db96d56Sopenharmony_ci 25667db96d56Sopenharmony_ci def test_recursive_repr(self): 25677db96d56Sopenharmony_ci # Issue #25455 25687db96d56Sopenharmony_ci e = ET.Element('foo') 25697db96d56Sopenharmony_ci with swap_attr(e, 'tag', e): 25707db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 25717db96d56Sopenharmony_ci repr(e) # Should not crash 25727db96d56Sopenharmony_ci 25737db96d56Sopenharmony_ci def test_element_get_text(self): 25747db96d56Sopenharmony_ci # Issue #27863 25757db96d56Sopenharmony_ci class X(str): 25767db96d56Sopenharmony_ci def __del__(self): 25777db96d56Sopenharmony_ci try: 25787db96d56Sopenharmony_ci elem.text 25797db96d56Sopenharmony_ci except NameError: 25807db96d56Sopenharmony_ci pass 25817db96d56Sopenharmony_ci 25827db96d56Sopenharmony_ci b = ET.TreeBuilder() 25837db96d56Sopenharmony_ci b.start('tag', {}) 25847db96d56Sopenharmony_ci b.data('ABCD') 25857db96d56Sopenharmony_ci b.data(X('EFGH')) 25867db96d56Sopenharmony_ci b.data('IJKL') 25877db96d56Sopenharmony_ci b.end('tag') 25887db96d56Sopenharmony_ci 25897db96d56Sopenharmony_ci elem = b.close() 25907db96d56Sopenharmony_ci self.assertEqual(elem.text, 'ABCDEFGHIJKL') 25917db96d56Sopenharmony_ci 25927db96d56Sopenharmony_ci def test_element_get_tail(self): 25937db96d56Sopenharmony_ci # Issue #27863 25947db96d56Sopenharmony_ci class X(str): 25957db96d56Sopenharmony_ci def __del__(self): 25967db96d56Sopenharmony_ci try: 25977db96d56Sopenharmony_ci elem[0].tail 25987db96d56Sopenharmony_ci except NameError: 25997db96d56Sopenharmony_ci pass 26007db96d56Sopenharmony_ci 26017db96d56Sopenharmony_ci b = ET.TreeBuilder() 26027db96d56Sopenharmony_ci b.start('root', {}) 26037db96d56Sopenharmony_ci b.start('tag', {}) 26047db96d56Sopenharmony_ci b.end('tag') 26057db96d56Sopenharmony_ci b.data('ABCD') 26067db96d56Sopenharmony_ci b.data(X('EFGH')) 26077db96d56Sopenharmony_ci b.data('IJKL') 26087db96d56Sopenharmony_ci b.end('root') 26097db96d56Sopenharmony_ci 26107db96d56Sopenharmony_ci elem = b.close() 26117db96d56Sopenharmony_ci self.assertEqual(elem[0].tail, 'ABCDEFGHIJKL') 26127db96d56Sopenharmony_ci 26137db96d56Sopenharmony_ci def test_subscr(self): 26147db96d56Sopenharmony_ci # Issue #27863 26157db96d56Sopenharmony_ci class X: 26167db96d56Sopenharmony_ci def __index__(self): 26177db96d56Sopenharmony_ci del e[:] 26187db96d56Sopenharmony_ci return 1 26197db96d56Sopenharmony_ci 26207db96d56Sopenharmony_ci e = ET.Element('elem') 26217db96d56Sopenharmony_ci e.append(ET.Element('child')) 26227db96d56Sopenharmony_ci e[:X()] # shouldn't crash 26237db96d56Sopenharmony_ci 26247db96d56Sopenharmony_ci e.append(ET.Element('child')) 26257db96d56Sopenharmony_ci e[0:10:X()] # shouldn't crash 26267db96d56Sopenharmony_ci 26277db96d56Sopenharmony_ci def test_ass_subscr(self): 26287db96d56Sopenharmony_ci # Issue #27863 26297db96d56Sopenharmony_ci class X: 26307db96d56Sopenharmony_ci def __index__(self): 26317db96d56Sopenharmony_ci e[:] = [] 26327db96d56Sopenharmony_ci return 1 26337db96d56Sopenharmony_ci 26347db96d56Sopenharmony_ci e = ET.Element('elem') 26357db96d56Sopenharmony_ci for _ in range(10): 26367db96d56Sopenharmony_ci e.insert(0, ET.Element('child')) 26377db96d56Sopenharmony_ci 26387db96d56Sopenharmony_ci e[0:10:X()] = [] # shouldn't crash 26397db96d56Sopenharmony_ci 26407db96d56Sopenharmony_ci def test_treebuilder_start(self): 26417db96d56Sopenharmony_ci # Issue #27863 26427db96d56Sopenharmony_ci def element_factory(x, y): 26437db96d56Sopenharmony_ci return [] 26447db96d56Sopenharmony_ci b = ET.TreeBuilder(element_factory=element_factory) 26457db96d56Sopenharmony_ci 26467db96d56Sopenharmony_ci b.start('tag', {}) 26477db96d56Sopenharmony_ci b.data('ABCD') 26487db96d56Sopenharmony_ci self.assertRaises(AttributeError, b.start, 'tag2', {}) 26497db96d56Sopenharmony_ci del b 26507db96d56Sopenharmony_ci gc_collect() 26517db96d56Sopenharmony_ci 26527db96d56Sopenharmony_ci def test_treebuilder_end(self): 26537db96d56Sopenharmony_ci # Issue #27863 26547db96d56Sopenharmony_ci def element_factory(x, y): 26557db96d56Sopenharmony_ci return [] 26567db96d56Sopenharmony_ci b = ET.TreeBuilder(element_factory=element_factory) 26577db96d56Sopenharmony_ci 26587db96d56Sopenharmony_ci b.start('tag', {}) 26597db96d56Sopenharmony_ci b.data('ABCD') 26607db96d56Sopenharmony_ci self.assertRaises(AttributeError, b.end, 'tag') 26617db96d56Sopenharmony_ci del b 26627db96d56Sopenharmony_ci gc_collect() 26637db96d56Sopenharmony_ci 26647db96d56Sopenharmony_ci 26657db96d56Sopenharmony_ciclass MutatingElementPath(str): 26667db96d56Sopenharmony_ci def __new__(cls, elem, *args): 26677db96d56Sopenharmony_ci self = str.__new__(cls, *args) 26687db96d56Sopenharmony_ci self.elem = elem 26697db96d56Sopenharmony_ci return self 26707db96d56Sopenharmony_ci def __eq__(self, o): 26717db96d56Sopenharmony_ci del self.elem[:] 26727db96d56Sopenharmony_ci return True 26737db96d56Sopenharmony_ciMutatingElementPath.__hash__ = str.__hash__ 26747db96d56Sopenharmony_ci 26757db96d56Sopenharmony_ciclass BadElementPath(str): 26767db96d56Sopenharmony_ci def __eq__(self, o): 26777db96d56Sopenharmony_ci raise 1/0 26787db96d56Sopenharmony_ciBadElementPath.__hash__ = str.__hash__ 26797db96d56Sopenharmony_ci 26807db96d56Sopenharmony_ciclass BadElementPathTest(ElementTestCase, unittest.TestCase): 26817db96d56Sopenharmony_ci def setUp(self): 26827db96d56Sopenharmony_ci super().setUp() 26837db96d56Sopenharmony_ci from xml.etree import ElementPath 26847db96d56Sopenharmony_ci self.path_cache = ElementPath._cache 26857db96d56Sopenharmony_ci ElementPath._cache = {} 26867db96d56Sopenharmony_ci 26877db96d56Sopenharmony_ci def tearDown(self): 26887db96d56Sopenharmony_ci from xml.etree import ElementPath 26897db96d56Sopenharmony_ci ElementPath._cache = self.path_cache 26907db96d56Sopenharmony_ci super().tearDown() 26917db96d56Sopenharmony_ci 26927db96d56Sopenharmony_ci def test_find_with_mutating(self): 26937db96d56Sopenharmony_ci e = ET.Element('foo') 26947db96d56Sopenharmony_ci e.extend([ET.Element('bar')]) 26957db96d56Sopenharmony_ci e.find(MutatingElementPath(e, 'x')) 26967db96d56Sopenharmony_ci 26977db96d56Sopenharmony_ci def test_find_with_error(self): 26987db96d56Sopenharmony_ci e = ET.Element('foo') 26997db96d56Sopenharmony_ci e.extend([ET.Element('bar')]) 27007db96d56Sopenharmony_ci try: 27017db96d56Sopenharmony_ci e.find(BadElementPath('x')) 27027db96d56Sopenharmony_ci except ZeroDivisionError: 27037db96d56Sopenharmony_ci pass 27047db96d56Sopenharmony_ci 27057db96d56Sopenharmony_ci def test_findtext_with_mutating(self): 27067db96d56Sopenharmony_ci e = ET.Element('foo') 27077db96d56Sopenharmony_ci e.extend([ET.Element('bar')]) 27087db96d56Sopenharmony_ci e.findtext(MutatingElementPath(e, 'x')) 27097db96d56Sopenharmony_ci 27107db96d56Sopenharmony_ci def test_findtext_with_error(self): 27117db96d56Sopenharmony_ci e = ET.Element('foo') 27127db96d56Sopenharmony_ci e.extend([ET.Element('bar')]) 27137db96d56Sopenharmony_ci try: 27147db96d56Sopenharmony_ci e.findtext(BadElementPath('x')) 27157db96d56Sopenharmony_ci except ZeroDivisionError: 27167db96d56Sopenharmony_ci pass 27177db96d56Sopenharmony_ci 27187db96d56Sopenharmony_ci def test_findtext_with_falsey_text_attribute(self): 27197db96d56Sopenharmony_ci root_elem = ET.Element('foo') 27207db96d56Sopenharmony_ci sub_elem = ET.SubElement(root_elem, 'bar') 27217db96d56Sopenharmony_ci falsey = ["", 0, False, [], (), {}] 27227db96d56Sopenharmony_ci for val in falsey: 27237db96d56Sopenharmony_ci sub_elem.text = val 27247db96d56Sopenharmony_ci self.assertEqual(root_elem.findtext('./bar'), val) 27257db96d56Sopenharmony_ci 27267db96d56Sopenharmony_ci def test_findtext_with_none_text_attribute(self): 27277db96d56Sopenharmony_ci root_elem = ET.Element('foo') 27287db96d56Sopenharmony_ci sub_elem = ET.SubElement(root_elem, 'bar') 27297db96d56Sopenharmony_ci sub_elem.text = None 27307db96d56Sopenharmony_ci self.assertEqual(root_elem.findtext('./bar'), '') 27317db96d56Sopenharmony_ci 27327db96d56Sopenharmony_ci def test_findall_with_mutating(self): 27337db96d56Sopenharmony_ci e = ET.Element('foo') 27347db96d56Sopenharmony_ci e.extend([ET.Element('bar')]) 27357db96d56Sopenharmony_ci e.findall(MutatingElementPath(e, 'x')) 27367db96d56Sopenharmony_ci 27377db96d56Sopenharmony_ci def test_findall_with_error(self): 27387db96d56Sopenharmony_ci e = ET.Element('foo') 27397db96d56Sopenharmony_ci e.extend([ET.Element('bar')]) 27407db96d56Sopenharmony_ci try: 27417db96d56Sopenharmony_ci e.findall(BadElementPath('x')) 27427db96d56Sopenharmony_ci except ZeroDivisionError: 27437db96d56Sopenharmony_ci pass 27447db96d56Sopenharmony_ci 27457db96d56Sopenharmony_ci 27467db96d56Sopenharmony_ciclass ElementTreeTypeTest(unittest.TestCase): 27477db96d56Sopenharmony_ci def test_istype(self): 27487db96d56Sopenharmony_ci self.assertIsInstance(ET.ParseError, type) 27497db96d56Sopenharmony_ci self.assertIsInstance(ET.QName, type) 27507db96d56Sopenharmony_ci self.assertIsInstance(ET.ElementTree, type) 27517db96d56Sopenharmony_ci self.assertIsInstance(ET.Element, type) 27527db96d56Sopenharmony_ci self.assertIsInstance(ET.TreeBuilder, type) 27537db96d56Sopenharmony_ci self.assertIsInstance(ET.XMLParser, type) 27547db96d56Sopenharmony_ci 27557db96d56Sopenharmony_ci def test_Element_subclass_trivial(self): 27567db96d56Sopenharmony_ci class MyElement(ET.Element): 27577db96d56Sopenharmony_ci pass 27587db96d56Sopenharmony_ci 27597db96d56Sopenharmony_ci mye = MyElement('foo') 27607db96d56Sopenharmony_ci self.assertIsInstance(mye, ET.Element) 27617db96d56Sopenharmony_ci self.assertIsInstance(mye, MyElement) 27627db96d56Sopenharmony_ci self.assertEqual(mye.tag, 'foo') 27637db96d56Sopenharmony_ci 27647db96d56Sopenharmony_ci # test that attribute assignment works (issue 14849) 27657db96d56Sopenharmony_ci mye.text = "joe" 27667db96d56Sopenharmony_ci self.assertEqual(mye.text, "joe") 27677db96d56Sopenharmony_ci 27687db96d56Sopenharmony_ci def test_Element_subclass_constructor(self): 27697db96d56Sopenharmony_ci class MyElement(ET.Element): 27707db96d56Sopenharmony_ci def __init__(self, tag, attrib={}, **extra): 27717db96d56Sopenharmony_ci super(MyElement, self).__init__(tag + '__', attrib, **extra) 27727db96d56Sopenharmony_ci 27737db96d56Sopenharmony_ci mye = MyElement('foo', {'a': 1, 'b': 2}, c=3, d=4) 27747db96d56Sopenharmony_ci self.assertEqual(mye.tag, 'foo__') 27757db96d56Sopenharmony_ci self.assertEqual(sorted(mye.items()), 27767db96d56Sopenharmony_ci [('a', 1), ('b', 2), ('c', 3), ('d', 4)]) 27777db96d56Sopenharmony_ci 27787db96d56Sopenharmony_ci def test_Element_subclass_new_method(self): 27797db96d56Sopenharmony_ci class MyElement(ET.Element): 27807db96d56Sopenharmony_ci def newmethod(self): 27817db96d56Sopenharmony_ci return self.tag 27827db96d56Sopenharmony_ci 27837db96d56Sopenharmony_ci mye = MyElement('joe') 27847db96d56Sopenharmony_ci self.assertEqual(mye.newmethod(), 'joe') 27857db96d56Sopenharmony_ci 27867db96d56Sopenharmony_ci def test_Element_subclass_find(self): 27877db96d56Sopenharmony_ci class MyElement(ET.Element): 27887db96d56Sopenharmony_ci pass 27897db96d56Sopenharmony_ci 27907db96d56Sopenharmony_ci e = ET.Element('foo') 27917db96d56Sopenharmony_ci e.text = 'text' 27927db96d56Sopenharmony_ci sub = MyElement('bar') 27937db96d56Sopenharmony_ci sub.text = 'subtext' 27947db96d56Sopenharmony_ci e.append(sub) 27957db96d56Sopenharmony_ci self.assertEqual(e.findtext('bar'), 'subtext') 27967db96d56Sopenharmony_ci self.assertEqual(e.find('bar').tag, 'bar') 27977db96d56Sopenharmony_ci found = list(e.findall('bar')) 27987db96d56Sopenharmony_ci self.assertEqual(len(found), 1, found) 27997db96d56Sopenharmony_ci self.assertEqual(found[0].tag, 'bar') 28007db96d56Sopenharmony_ci 28017db96d56Sopenharmony_ci 28027db96d56Sopenharmony_ciclass ElementFindTest(unittest.TestCase): 28037db96d56Sopenharmony_ci def test_find_simple(self): 28047db96d56Sopenharmony_ci e = ET.XML(SAMPLE_XML) 28057db96d56Sopenharmony_ci self.assertEqual(e.find('tag').tag, 'tag') 28067db96d56Sopenharmony_ci self.assertEqual(e.find('section/tag').tag, 'tag') 28077db96d56Sopenharmony_ci self.assertEqual(e.find('./tag').tag, 'tag') 28087db96d56Sopenharmony_ci 28097db96d56Sopenharmony_ci e[2] = ET.XML(SAMPLE_SECTION) 28107db96d56Sopenharmony_ci self.assertEqual(e.find('section/nexttag').tag, 'nexttag') 28117db96d56Sopenharmony_ci 28127db96d56Sopenharmony_ci self.assertEqual(e.findtext('./tag'), 'text') 28137db96d56Sopenharmony_ci self.assertEqual(e.findtext('section/tag'), 'subtext') 28147db96d56Sopenharmony_ci 28157db96d56Sopenharmony_ci # section/nexttag is found but has no text 28167db96d56Sopenharmony_ci self.assertEqual(e.findtext('section/nexttag'), '') 28177db96d56Sopenharmony_ci self.assertEqual(e.findtext('section/nexttag', 'default'), '') 28187db96d56Sopenharmony_ci 28197db96d56Sopenharmony_ci # tog doesn't exist and 'default' kicks in 28207db96d56Sopenharmony_ci self.assertIsNone(e.findtext('tog')) 28217db96d56Sopenharmony_ci self.assertEqual(e.findtext('tog', 'default'), 'default') 28227db96d56Sopenharmony_ci 28237db96d56Sopenharmony_ci # Issue #16922 28247db96d56Sopenharmony_ci self.assertEqual(ET.XML('<tag><empty /></tag>').findtext('empty'), '') 28257db96d56Sopenharmony_ci 28267db96d56Sopenharmony_ci def test_find_xpath(self): 28277db96d56Sopenharmony_ci LINEAR_XML = ''' 28287db96d56Sopenharmony_ci <body> 28297db96d56Sopenharmony_ci <tag class='a'/> 28307db96d56Sopenharmony_ci <tag class='b'/> 28317db96d56Sopenharmony_ci <tag class='c'/> 28327db96d56Sopenharmony_ci <tag class='d'/> 28337db96d56Sopenharmony_ci </body>''' 28347db96d56Sopenharmony_ci e = ET.XML(LINEAR_XML) 28357db96d56Sopenharmony_ci 28367db96d56Sopenharmony_ci # Test for numeric indexing and last() 28377db96d56Sopenharmony_ci self.assertEqual(e.find('./tag[1]').attrib['class'], 'a') 28387db96d56Sopenharmony_ci self.assertEqual(e.find('./tag[2]').attrib['class'], 'b') 28397db96d56Sopenharmony_ci self.assertEqual(e.find('./tag[last()]').attrib['class'], 'd') 28407db96d56Sopenharmony_ci self.assertEqual(e.find('./tag[last()-1]').attrib['class'], 'c') 28417db96d56Sopenharmony_ci self.assertEqual(e.find('./tag[last()-2]').attrib['class'], 'b') 28427db96d56Sopenharmony_ci 28437db96d56Sopenharmony_ci self.assertRaisesRegex(SyntaxError, 'XPath', e.find, './tag[0]') 28447db96d56Sopenharmony_ci self.assertRaisesRegex(SyntaxError, 'XPath', e.find, './tag[-1]') 28457db96d56Sopenharmony_ci self.assertRaisesRegex(SyntaxError, 'XPath', e.find, './tag[last()-0]') 28467db96d56Sopenharmony_ci self.assertRaisesRegex(SyntaxError, 'XPath', e.find, './tag[last()+1]') 28477db96d56Sopenharmony_ci 28487db96d56Sopenharmony_ci def test_findall(self): 28497db96d56Sopenharmony_ci e = ET.XML(SAMPLE_XML) 28507db96d56Sopenharmony_ci e[2] = ET.XML(SAMPLE_SECTION) 28517db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.')), ['body']) 28527db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('tag')), ['tag', 'tag']) 28537db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('tog')), []) 28547db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('tog/foo')), []) 28557db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('*')), 28567db96d56Sopenharmony_ci ['tag', 'tag', 'section']) 28577db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//tag')), 28587db96d56Sopenharmony_ci ['tag'] * 4) 28597db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('section/tag')), ['tag']) 28607db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('section//tag')), ['tag'] * 2) 28617db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('section/*')), 28627db96d56Sopenharmony_ci ['tag', 'nexttag', 'nextsection']) 28637db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('section//*')), 28647db96d56Sopenharmony_ci ['tag', 'nexttag', 'nextsection', 'tag']) 28657db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('section/.//*')), 28667db96d56Sopenharmony_ci ['tag', 'nexttag', 'nextsection', 'tag']) 28677db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('*/*')), 28687db96d56Sopenharmony_ci ['tag', 'nexttag', 'nextsection']) 28697db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('*//*')), 28707db96d56Sopenharmony_ci ['tag', 'nexttag', 'nextsection', 'tag']) 28717db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('*/tag')), ['tag']) 28727db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('*/./tag')), ['tag']) 28737db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('./tag')), ['tag'] * 2) 28747db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('././tag')), ['tag'] * 2) 28757db96d56Sopenharmony_ci 28767db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//tag[@class]')), 28777db96d56Sopenharmony_ci ['tag'] * 3) 28787db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//tag[@class="a"]')), 28797db96d56Sopenharmony_ci ['tag']) 28807db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//tag[@class!="a"]')), 28817db96d56Sopenharmony_ci ['tag'] * 2) 28827db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//tag[@class="b"]')), 28837db96d56Sopenharmony_ci ['tag'] * 2) 28847db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//tag[@class!="b"]')), 28857db96d56Sopenharmony_ci ['tag']) 28867db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//tag[@id]')), 28877db96d56Sopenharmony_ci ['tag']) 28887db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//section[tag]')), 28897db96d56Sopenharmony_ci ['section']) 28907db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//section[element]')), []) 28917db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('../tag')), []) 28927db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('section/../tag')), 28937db96d56Sopenharmony_ci ['tag'] * 2) 28947db96d56Sopenharmony_ci self.assertEqual(e.findall('section//'), e.findall('section//*')) 28957db96d56Sopenharmony_ci 28967db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//section[tag='subtext']")), 28977db96d56Sopenharmony_ci ['section']) 28987db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//section[tag ='subtext']")), 28997db96d56Sopenharmony_ci ['section']) 29007db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//section[tag= 'subtext']")), 29017db96d56Sopenharmony_ci ['section']) 29027db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//section[tag = 'subtext']")), 29037db96d56Sopenharmony_ci ['section']) 29047db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//section[ tag = 'subtext' ]")), 29057db96d56Sopenharmony_ci ['section']) 29067db96d56Sopenharmony_ci 29077db96d56Sopenharmony_ci # Negations of above tests. They match nothing because the sole section 29087db96d56Sopenharmony_ci # tag has subtext. 29097db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//section[tag!='subtext']")), 29107db96d56Sopenharmony_ci []) 29117db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//section[tag !='subtext']")), 29127db96d56Sopenharmony_ci []) 29137db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//section[tag!= 'subtext']")), 29147db96d56Sopenharmony_ci []) 29157db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//section[tag != 'subtext']")), 29167db96d56Sopenharmony_ci []) 29177db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//section[ tag != 'subtext' ]")), 29187db96d56Sopenharmony_ci []) 29197db96d56Sopenharmony_ci 29207db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//tag[.='subtext']")), 29217db96d56Sopenharmony_ci ['tag']) 29227db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//tag[. ='subtext']")), 29237db96d56Sopenharmony_ci ['tag']) 29247db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//tag[.= "subtext"]')), 29257db96d56Sopenharmony_ci ['tag']) 29267db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//tag[ . = "subtext" ]')), 29277db96d56Sopenharmony_ci ['tag']) 29287db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//tag[. = 'subtext']")), 29297db96d56Sopenharmony_ci ['tag']) 29307db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//tag[. = 'subtext ']")), 29317db96d56Sopenharmony_ci []) 29327db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//tag[.= ' subtext']")), 29337db96d56Sopenharmony_ci []) 29347db96d56Sopenharmony_ci 29357db96d56Sopenharmony_ci # Negations of above tests. 29367db96d56Sopenharmony_ci # Matches everything but the tag containing subtext 29377db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//tag[.!='subtext']")), 29387db96d56Sopenharmony_ci ['tag'] * 3) 29397db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//tag[. !='subtext']")), 29407db96d56Sopenharmony_ci ['tag'] * 3) 29417db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//tag[.!= "subtext"]')), 29427db96d56Sopenharmony_ci ['tag'] * 3) 29437db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('.//tag[ . != "subtext" ]')), 29447db96d56Sopenharmony_ci ['tag'] * 3) 29457db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//tag[. != 'subtext']")), 29467db96d56Sopenharmony_ci ['tag'] * 3) 29477db96d56Sopenharmony_ci # Matches all tags. 29487db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//tag[. != 'subtext ']")), 29497db96d56Sopenharmony_ci ['tag'] * 4) 29507db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//tag[.!= ' subtext']")), 29517db96d56Sopenharmony_ci ['tag'] * 4) 29527db96d56Sopenharmony_ci 29537db96d56Sopenharmony_ci # duplicate section => 2x tag matches 29547db96d56Sopenharmony_ci e[1] = e[2] 29557db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//section[tag = 'subtext']")), 29567db96d56Sopenharmony_ci ['section', 'section']) 29577db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall(".//tag[. = 'subtext']")), 29587db96d56Sopenharmony_ci ['tag', 'tag']) 29597db96d56Sopenharmony_ci 29607db96d56Sopenharmony_ci def test_test_find_with_ns(self): 29617db96d56Sopenharmony_ci e = ET.XML(SAMPLE_XML_NS) 29627db96d56Sopenharmony_ci self.assertEqual(summarize_list(e.findall('tag')), []) 29637db96d56Sopenharmony_ci self.assertEqual( 29647db96d56Sopenharmony_ci summarize_list(e.findall("{http://effbot.org/ns}tag")), 29657db96d56Sopenharmony_ci ['{http://effbot.org/ns}tag'] * 2) 29667db96d56Sopenharmony_ci self.assertEqual( 29677db96d56Sopenharmony_ci summarize_list(e.findall(".//{http://effbot.org/ns}tag")), 29687db96d56Sopenharmony_ci ['{http://effbot.org/ns}tag'] * 3) 29697db96d56Sopenharmony_ci 29707db96d56Sopenharmony_ci def test_findall_different_nsmaps(self): 29717db96d56Sopenharmony_ci root = ET.XML(''' 29727db96d56Sopenharmony_ci <a xmlns:x="X" xmlns:y="Y"> 29737db96d56Sopenharmony_ci <x:b><c/></x:b> 29747db96d56Sopenharmony_ci <b/> 29757db96d56Sopenharmony_ci <c><x:b/><b/></c><y:b/> 29767db96d56Sopenharmony_ci </a>''') 29777db96d56Sopenharmony_ci nsmap = {'xx': 'X'} 29787db96d56Sopenharmony_ci self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2) 29797db96d56Sopenharmony_ci self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2) 29807db96d56Sopenharmony_ci nsmap = {'xx': 'Y'} 29817db96d56Sopenharmony_ci self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1) 29827db96d56Sopenharmony_ci self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2) 29837db96d56Sopenharmony_ci nsmap = {'xx': 'X', '': 'Y'} 29847db96d56Sopenharmony_ci self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2) 29857db96d56Sopenharmony_ci self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 1) 29867db96d56Sopenharmony_ci 29877db96d56Sopenharmony_ci def test_findall_wildcard(self): 29887db96d56Sopenharmony_ci root = ET.XML(''' 29897db96d56Sopenharmony_ci <a xmlns:x="X" xmlns:y="Y"> 29907db96d56Sopenharmony_ci <x:b><c/></x:b> 29917db96d56Sopenharmony_ci <b/> 29927db96d56Sopenharmony_ci <c><x:b/><b/></c><y:b/> 29937db96d56Sopenharmony_ci </a>''') 29947db96d56Sopenharmony_ci root.append(ET.Comment('test')) 29957db96d56Sopenharmony_ci 29967db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall("{*}b")), 29977db96d56Sopenharmony_ci ['{X}b', 'b', '{Y}b']) 29987db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall("{*}c")), 29997db96d56Sopenharmony_ci ['c']) 30007db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall("{X}*")), 30017db96d56Sopenharmony_ci ['{X}b']) 30027db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall("{Y}*")), 30037db96d56Sopenharmony_ci ['{Y}b']) 30047db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall("{}*")), 30057db96d56Sopenharmony_ci ['b', 'c']) 30067db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall("{}b")), # only for consistency 30077db96d56Sopenharmony_ci ['b']) 30087db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall("{}b")), 30097db96d56Sopenharmony_ci summarize_list(root.findall("b"))) 30107db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall("{*}*")), 30117db96d56Sopenharmony_ci ['{X}b', 'b', 'c', '{Y}b']) 30127db96d56Sopenharmony_ci # This is an unfortunate difference, but that's how find('*') works. 30137db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall("{*}*") + [root[-1]]), 30147db96d56Sopenharmony_ci summarize_list(root.findall("*"))) 30157db96d56Sopenharmony_ci 30167db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall(".//{*}b")), 30177db96d56Sopenharmony_ci ['{X}b', 'b', '{X}b', 'b', '{Y}b']) 30187db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall(".//{*}c")), 30197db96d56Sopenharmony_ci ['c', 'c']) 30207db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall(".//{X}*")), 30217db96d56Sopenharmony_ci ['{X}b', '{X}b']) 30227db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall(".//{Y}*")), 30237db96d56Sopenharmony_ci ['{Y}b']) 30247db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall(".//{}*")), 30257db96d56Sopenharmony_ci ['c', 'b', 'c', 'b']) 30267db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall(".//{}b")), # only for consistency 30277db96d56Sopenharmony_ci ['b', 'b']) 30287db96d56Sopenharmony_ci self.assertEqual(summarize_list(root.findall(".//{}b")), 30297db96d56Sopenharmony_ci summarize_list(root.findall(".//b"))) 30307db96d56Sopenharmony_ci 30317db96d56Sopenharmony_ci def test_bad_find(self): 30327db96d56Sopenharmony_ci e = ET.XML(SAMPLE_XML) 30337db96d56Sopenharmony_ci with self.assertRaisesRegex(SyntaxError, 'cannot use absolute path'): 30347db96d56Sopenharmony_ci e.findall('/tag') 30357db96d56Sopenharmony_ci 30367db96d56Sopenharmony_ci def test_find_through_ElementTree(self): 30377db96d56Sopenharmony_ci e = ET.XML(SAMPLE_XML) 30387db96d56Sopenharmony_ci self.assertEqual(ET.ElementTree(e).find('tag').tag, 'tag') 30397db96d56Sopenharmony_ci self.assertEqual(ET.ElementTree(e).findtext('tag'), 'text') 30407db96d56Sopenharmony_ci self.assertEqual(summarize_list(ET.ElementTree(e).findall('tag')), 30417db96d56Sopenharmony_ci ['tag'] * 2) 30427db96d56Sopenharmony_ci # this produces a warning 30437db96d56Sopenharmony_ci msg = ("This search is broken in 1.3 and earlier, and will be fixed " 30447db96d56Sopenharmony_ci "in a future version. If you rely on the current behaviour, " 30457db96d56Sopenharmony_ci "change it to '.+'") 30467db96d56Sopenharmony_ci with self.assertWarnsRegex(FutureWarning, msg): 30477db96d56Sopenharmony_ci it = ET.ElementTree(e).findall('//tag') 30487db96d56Sopenharmony_ci self.assertEqual(summarize_list(it), ['tag'] * 3) 30497db96d56Sopenharmony_ci 30507db96d56Sopenharmony_ci 30517db96d56Sopenharmony_ciclass ElementIterTest(unittest.TestCase): 30527db96d56Sopenharmony_ci def _ilist(self, elem, tag=None): 30537db96d56Sopenharmony_ci return summarize_list(elem.iter(tag)) 30547db96d56Sopenharmony_ci 30557db96d56Sopenharmony_ci def test_basic(self): 30567db96d56Sopenharmony_ci doc = ET.XML("<html><body>this is a <i>paragraph</i>.</body>..</html>") 30577db96d56Sopenharmony_ci self.assertEqual(self._ilist(doc), ['html', 'body', 'i']) 30587db96d56Sopenharmony_ci self.assertEqual(self._ilist(doc.find('body')), ['body', 'i']) 30597db96d56Sopenharmony_ci self.assertEqual(next(doc.iter()).tag, 'html') 30607db96d56Sopenharmony_ci self.assertEqual(''.join(doc.itertext()), 'this is a paragraph...') 30617db96d56Sopenharmony_ci self.assertEqual(''.join(doc.find('body').itertext()), 30627db96d56Sopenharmony_ci 'this is a paragraph.') 30637db96d56Sopenharmony_ci self.assertEqual(next(doc.itertext()), 'this is a ') 30647db96d56Sopenharmony_ci 30657db96d56Sopenharmony_ci # iterparse should return an iterator 30667db96d56Sopenharmony_ci sourcefile = serialize(doc, to_string=False) 30677db96d56Sopenharmony_ci self.assertEqual(next(ET.iterparse(sourcefile))[0], 'end') 30687db96d56Sopenharmony_ci 30697db96d56Sopenharmony_ci # With an explicit parser too (issue #9708) 30707db96d56Sopenharmony_ci sourcefile = serialize(doc, to_string=False) 30717db96d56Sopenharmony_ci parser = ET.XMLParser(target=ET.TreeBuilder()) 30727db96d56Sopenharmony_ci self.assertEqual(next(ET.iterparse(sourcefile, parser=parser))[0], 30737db96d56Sopenharmony_ci 'end') 30747db96d56Sopenharmony_ci 30757db96d56Sopenharmony_ci tree = ET.ElementTree(None) 30767db96d56Sopenharmony_ci self.assertRaises(AttributeError, tree.iter) 30777db96d56Sopenharmony_ci 30787db96d56Sopenharmony_ci # Issue #16913 30797db96d56Sopenharmony_ci doc = ET.XML("<root>a&<sub>b&</sub>c&</root>") 30807db96d56Sopenharmony_ci self.assertEqual(''.join(doc.itertext()), 'a&b&c&') 30817db96d56Sopenharmony_ci 30827db96d56Sopenharmony_ci def test_corners(self): 30837db96d56Sopenharmony_ci # single root, no subelements 30847db96d56Sopenharmony_ci a = ET.Element('a') 30857db96d56Sopenharmony_ci self.assertEqual(self._ilist(a), ['a']) 30867db96d56Sopenharmony_ci 30877db96d56Sopenharmony_ci # one child 30887db96d56Sopenharmony_ci b = ET.SubElement(a, 'b') 30897db96d56Sopenharmony_ci self.assertEqual(self._ilist(a), ['a', 'b']) 30907db96d56Sopenharmony_ci 30917db96d56Sopenharmony_ci # one child and one grandchild 30927db96d56Sopenharmony_ci c = ET.SubElement(b, 'c') 30937db96d56Sopenharmony_ci self.assertEqual(self._ilist(a), ['a', 'b', 'c']) 30947db96d56Sopenharmony_ci 30957db96d56Sopenharmony_ci # two children, only first with grandchild 30967db96d56Sopenharmony_ci d = ET.SubElement(a, 'd') 30977db96d56Sopenharmony_ci self.assertEqual(self._ilist(a), ['a', 'b', 'c', 'd']) 30987db96d56Sopenharmony_ci 30997db96d56Sopenharmony_ci # replace first child by second 31007db96d56Sopenharmony_ci a[0] = a[1] 31017db96d56Sopenharmony_ci del a[1] 31027db96d56Sopenharmony_ci self.assertEqual(self._ilist(a), ['a', 'd']) 31037db96d56Sopenharmony_ci 31047db96d56Sopenharmony_ci def test_iter_by_tag(self): 31057db96d56Sopenharmony_ci doc = ET.XML(''' 31067db96d56Sopenharmony_ci <document> 31077db96d56Sopenharmony_ci <house> 31087db96d56Sopenharmony_ci <room>bedroom1</room> 31097db96d56Sopenharmony_ci <room>bedroom2</room> 31107db96d56Sopenharmony_ci </house> 31117db96d56Sopenharmony_ci <shed>nothing here 31127db96d56Sopenharmony_ci </shed> 31137db96d56Sopenharmony_ci <house> 31147db96d56Sopenharmony_ci <room>bedroom8</room> 31157db96d56Sopenharmony_ci </house> 31167db96d56Sopenharmony_ci </document>''') 31177db96d56Sopenharmony_ci 31187db96d56Sopenharmony_ci self.assertEqual(self._ilist(doc, 'room'), ['room'] * 3) 31197db96d56Sopenharmony_ci self.assertEqual(self._ilist(doc, 'house'), ['house'] * 2) 31207db96d56Sopenharmony_ci 31217db96d56Sopenharmony_ci # test that iter also accepts 'tag' as a keyword arg 31227db96d56Sopenharmony_ci self.assertEqual( 31237db96d56Sopenharmony_ci summarize_list(doc.iter(tag='room')), 31247db96d56Sopenharmony_ci ['room'] * 3) 31257db96d56Sopenharmony_ci 31267db96d56Sopenharmony_ci # make sure both tag=None and tag='*' return all tags 31277db96d56Sopenharmony_ci all_tags = ['document', 'house', 'room', 'room', 31287db96d56Sopenharmony_ci 'shed', 'house', 'room'] 31297db96d56Sopenharmony_ci self.assertEqual(summarize_list(doc.iter()), all_tags) 31307db96d56Sopenharmony_ci self.assertEqual(self._ilist(doc), all_tags) 31317db96d56Sopenharmony_ci self.assertEqual(self._ilist(doc, '*'), all_tags) 31327db96d56Sopenharmony_ci 31337db96d56Sopenharmony_ci def test_copy(self): 31347db96d56Sopenharmony_ci a = ET.Element('a') 31357db96d56Sopenharmony_ci it = a.iter() 31367db96d56Sopenharmony_ci with self.assertRaises(TypeError): 31377db96d56Sopenharmony_ci copy.copy(it) 31387db96d56Sopenharmony_ci 31397db96d56Sopenharmony_ci def test_pickle(self): 31407db96d56Sopenharmony_ci a = ET.Element('a') 31417db96d56Sopenharmony_ci it = a.iter() 31427db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 31437db96d56Sopenharmony_ci with self.assertRaises((TypeError, pickle.PicklingError)): 31447db96d56Sopenharmony_ci pickle.dumps(it, proto) 31457db96d56Sopenharmony_ci 31467db96d56Sopenharmony_ci 31477db96d56Sopenharmony_ciclass TreeBuilderTest(unittest.TestCase): 31487db96d56Sopenharmony_ci sample1 = ('<!DOCTYPE html PUBLIC' 31497db96d56Sopenharmony_ci ' "-//W3C//DTD XHTML 1.0 Transitional//EN"' 31507db96d56Sopenharmony_ci ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' 31517db96d56Sopenharmony_ci '<html>text<div>subtext</div>tail</html>') 31527db96d56Sopenharmony_ci 31537db96d56Sopenharmony_ci sample2 = '''<toplevel>sometext</toplevel>''' 31547db96d56Sopenharmony_ci 31557db96d56Sopenharmony_ci def _check_sample1_element(self, e): 31567db96d56Sopenharmony_ci self.assertEqual(e.tag, 'html') 31577db96d56Sopenharmony_ci self.assertEqual(e.text, 'text') 31587db96d56Sopenharmony_ci self.assertEqual(e.tail, None) 31597db96d56Sopenharmony_ci self.assertEqual(e.attrib, {}) 31607db96d56Sopenharmony_ci children = list(e) 31617db96d56Sopenharmony_ci self.assertEqual(len(children), 1) 31627db96d56Sopenharmony_ci child = children[0] 31637db96d56Sopenharmony_ci self.assertEqual(child.tag, 'div') 31647db96d56Sopenharmony_ci self.assertEqual(child.text, 'subtext') 31657db96d56Sopenharmony_ci self.assertEqual(child.tail, 'tail') 31667db96d56Sopenharmony_ci self.assertEqual(child.attrib, {}) 31677db96d56Sopenharmony_ci 31687db96d56Sopenharmony_ci def test_dummy_builder(self): 31697db96d56Sopenharmony_ci class BaseDummyBuilder: 31707db96d56Sopenharmony_ci def close(self): 31717db96d56Sopenharmony_ci return 42 31727db96d56Sopenharmony_ci 31737db96d56Sopenharmony_ci class DummyBuilder(BaseDummyBuilder): 31747db96d56Sopenharmony_ci data = start = end = lambda *a: None 31757db96d56Sopenharmony_ci 31767db96d56Sopenharmony_ci parser = ET.XMLParser(target=DummyBuilder()) 31777db96d56Sopenharmony_ci parser.feed(self.sample1) 31787db96d56Sopenharmony_ci self.assertEqual(parser.close(), 42) 31797db96d56Sopenharmony_ci 31807db96d56Sopenharmony_ci parser = ET.XMLParser(target=BaseDummyBuilder()) 31817db96d56Sopenharmony_ci parser.feed(self.sample1) 31827db96d56Sopenharmony_ci self.assertEqual(parser.close(), 42) 31837db96d56Sopenharmony_ci 31847db96d56Sopenharmony_ci parser = ET.XMLParser(target=object()) 31857db96d56Sopenharmony_ci parser.feed(self.sample1) 31867db96d56Sopenharmony_ci self.assertIsNone(parser.close()) 31877db96d56Sopenharmony_ci 31887db96d56Sopenharmony_ci def test_treebuilder_comment(self): 31897db96d56Sopenharmony_ci b = ET.TreeBuilder() 31907db96d56Sopenharmony_ci self.assertEqual(b.comment('ctext').tag, ET.Comment) 31917db96d56Sopenharmony_ci self.assertEqual(b.comment('ctext').text, 'ctext') 31927db96d56Sopenharmony_ci 31937db96d56Sopenharmony_ci b = ET.TreeBuilder(comment_factory=ET.Comment) 31947db96d56Sopenharmony_ci self.assertEqual(b.comment('ctext').tag, ET.Comment) 31957db96d56Sopenharmony_ci self.assertEqual(b.comment('ctext').text, 'ctext') 31967db96d56Sopenharmony_ci 31977db96d56Sopenharmony_ci b = ET.TreeBuilder(comment_factory=len) 31987db96d56Sopenharmony_ci self.assertEqual(b.comment('ctext'), len('ctext')) 31997db96d56Sopenharmony_ci 32007db96d56Sopenharmony_ci def test_treebuilder_pi(self): 32017db96d56Sopenharmony_ci b = ET.TreeBuilder() 32027db96d56Sopenharmony_ci self.assertEqual(b.pi('target', None).tag, ET.PI) 32037db96d56Sopenharmony_ci self.assertEqual(b.pi('target', None).text, 'target') 32047db96d56Sopenharmony_ci 32057db96d56Sopenharmony_ci b = ET.TreeBuilder(pi_factory=ET.PI) 32067db96d56Sopenharmony_ci self.assertEqual(b.pi('target').tag, ET.PI) 32077db96d56Sopenharmony_ci self.assertEqual(b.pi('target').text, "target") 32087db96d56Sopenharmony_ci self.assertEqual(b.pi('pitarget', ' text ').tag, ET.PI) 32097db96d56Sopenharmony_ci self.assertEqual(b.pi('pitarget', ' text ').text, "pitarget text ") 32107db96d56Sopenharmony_ci 32117db96d56Sopenharmony_ci b = ET.TreeBuilder(pi_factory=lambda target, text: (len(target), text)) 32127db96d56Sopenharmony_ci self.assertEqual(b.pi('target'), (len('target'), None)) 32137db96d56Sopenharmony_ci self.assertEqual(b.pi('pitarget', ' text '), (len('pitarget'), ' text ')) 32147db96d56Sopenharmony_ci 32157db96d56Sopenharmony_ci def test_late_tail(self): 32167db96d56Sopenharmony_ci # Issue #37399: The tail of an ignored comment could overwrite the text before it. 32177db96d56Sopenharmony_ci class TreeBuilderSubclass(ET.TreeBuilder): 32187db96d56Sopenharmony_ci pass 32197db96d56Sopenharmony_ci 32207db96d56Sopenharmony_ci xml = "<a>text<!-- comment -->tail</a>" 32217db96d56Sopenharmony_ci a = ET.fromstring(xml) 32227db96d56Sopenharmony_ci self.assertEqual(a.text, "texttail") 32237db96d56Sopenharmony_ci 32247db96d56Sopenharmony_ci parser = ET.XMLParser(target=TreeBuilderSubclass()) 32257db96d56Sopenharmony_ci parser.feed(xml) 32267db96d56Sopenharmony_ci a = parser.close() 32277db96d56Sopenharmony_ci self.assertEqual(a.text, "texttail") 32287db96d56Sopenharmony_ci 32297db96d56Sopenharmony_ci xml = "<a>text<?pi data?>tail</a>" 32307db96d56Sopenharmony_ci a = ET.fromstring(xml) 32317db96d56Sopenharmony_ci self.assertEqual(a.text, "texttail") 32327db96d56Sopenharmony_ci 32337db96d56Sopenharmony_ci xml = "<a>text<?pi data?>tail</a>" 32347db96d56Sopenharmony_ci parser = ET.XMLParser(target=TreeBuilderSubclass()) 32357db96d56Sopenharmony_ci parser.feed(xml) 32367db96d56Sopenharmony_ci a = parser.close() 32377db96d56Sopenharmony_ci self.assertEqual(a.text, "texttail") 32387db96d56Sopenharmony_ci 32397db96d56Sopenharmony_ci def test_late_tail_mix_pi_comments(self): 32407db96d56Sopenharmony_ci # Issue #37399: The tail of an ignored comment could overwrite the text before it. 32417db96d56Sopenharmony_ci # Test appending tails to comments/pis. 32427db96d56Sopenharmony_ci class TreeBuilderSubclass(ET.TreeBuilder): 32437db96d56Sopenharmony_ci pass 32447db96d56Sopenharmony_ci 32457db96d56Sopenharmony_ci xml = "<a>text<?pi1?> <!-- comment -->\n<?pi2?>tail</a>" 32467db96d56Sopenharmony_ci parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True)) 32477db96d56Sopenharmony_ci parser.feed(xml) 32487db96d56Sopenharmony_ci a = parser.close() 32497db96d56Sopenharmony_ci self.assertEqual(a[0].text, ' comment ') 32507db96d56Sopenharmony_ci self.assertEqual(a[0].tail, '\ntail') 32517db96d56Sopenharmony_ci self.assertEqual(a.text, "text ") 32527db96d56Sopenharmony_ci 32537db96d56Sopenharmony_ci parser = ET.XMLParser(target=TreeBuilderSubclass(insert_comments=True)) 32547db96d56Sopenharmony_ci parser.feed(xml) 32557db96d56Sopenharmony_ci a = parser.close() 32567db96d56Sopenharmony_ci self.assertEqual(a[0].text, ' comment ') 32577db96d56Sopenharmony_ci self.assertEqual(a[0].tail, '\ntail') 32587db96d56Sopenharmony_ci self.assertEqual(a.text, "text ") 32597db96d56Sopenharmony_ci 32607db96d56Sopenharmony_ci xml = "<a>text<!-- comment -->\n<?pi data?>tail</a>" 32617db96d56Sopenharmony_ci parser = ET.XMLParser(target=ET.TreeBuilder(insert_pis=True)) 32627db96d56Sopenharmony_ci parser.feed(xml) 32637db96d56Sopenharmony_ci a = parser.close() 32647db96d56Sopenharmony_ci self.assertEqual(a[0].text, 'pi data') 32657db96d56Sopenharmony_ci self.assertEqual(a[0].tail, 'tail') 32667db96d56Sopenharmony_ci self.assertEqual(a.text, "text\n") 32677db96d56Sopenharmony_ci 32687db96d56Sopenharmony_ci parser = ET.XMLParser(target=TreeBuilderSubclass(insert_pis=True)) 32697db96d56Sopenharmony_ci parser.feed(xml) 32707db96d56Sopenharmony_ci a = parser.close() 32717db96d56Sopenharmony_ci self.assertEqual(a[0].text, 'pi data') 32727db96d56Sopenharmony_ci self.assertEqual(a[0].tail, 'tail') 32737db96d56Sopenharmony_ci self.assertEqual(a.text, "text\n") 32747db96d56Sopenharmony_ci 32757db96d56Sopenharmony_ci def test_treebuilder_elementfactory_none(self): 32767db96d56Sopenharmony_ci parser = ET.XMLParser(target=ET.TreeBuilder(element_factory=None)) 32777db96d56Sopenharmony_ci parser.feed(self.sample1) 32787db96d56Sopenharmony_ci e = parser.close() 32797db96d56Sopenharmony_ci self._check_sample1_element(e) 32807db96d56Sopenharmony_ci 32817db96d56Sopenharmony_ci def test_subclass(self): 32827db96d56Sopenharmony_ci class MyTreeBuilder(ET.TreeBuilder): 32837db96d56Sopenharmony_ci def foobar(self, x): 32847db96d56Sopenharmony_ci return x * 2 32857db96d56Sopenharmony_ci 32867db96d56Sopenharmony_ci tb = MyTreeBuilder() 32877db96d56Sopenharmony_ci self.assertEqual(tb.foobar(10), 20) 32887db96d56Sopenharmony_ci 32897db96d56Sopenharmony_ci parser = ET.XMLParser(target=tb) 32907db96d56Sopenharmony_ci parser.feed(self.sample1) 32917db96d56Sopenharmony_ci 32927db96d56Sopenharmony_ci e = parser.close() 32937db96d56Sopenharmony_ci self._check_sample1_element(e) 32947db96d56Sopenharmony_ci 32957db96d56Sopenharmony_ci def test_subclass_comment_pi(self): 32967db96d56Sopenharmony_ci class MyTreeBuilder(ET.TreeBuilder): 32977db96d56Sopenharmony_ci def foobar(self, x): 32987db96d56Sopenharmony_ci return x * 2 32997db96d56Sopenharmony_ci 33007db96d56Sopenharmony_ci tb = MyTreeBuilder(comment_factory=ET.Comment, pi_factory=ET.PI) 33017db96d56Sopenharmony_ci self.assertEqual(tb.foobar(10), 20) 33027db96d56Sopenharmony_ci 33037db96d56Sopenharmony_ci parser = ET.XMLParser(target=tb) 33047db96d56Sopenharmony_ci parser.feed(self.sample1) 33057db96d56Sopenharmony_ci parser.feed('<!-- a comment--><?and a pi?>') 33067db96d56Sopenharmony_ci 33077db96d56Sopenharmony_ci e = parser.close() 33087db96d56Sopenharmony_ci self._check_sample1_element(e) 33097db96d56Sopenharmony_ci 33107db96d56Sopenharmony_ci def test_element_factory(self): 33117db96d56Sopenharmony_ci lst = [] 33127db96d56Sopenharmony_ci def myfactory(tag, attrib): 33137db96d56Sopenharmony_ci nonlocal lst 33147db96d56Sopenharmony_ci lst.append(tag) 33157db96d56Sopenharmony_ci return ET.Element(tag, attrib) 33167db96d56Sopenharmony_ci 33177db96d56Sopenharmony_ci tb = ET.TreeBuilder(element_factory=myfactory) 33187db96d56Sopenharmony_ci parser = ET.XMLParser(target=tb) 33197db96d56Sopenharmony_ci parser.feed(self.sample2) 33207db96d56Sopenharmony_ci parser.close() 33217db96d56Sopenharmony_ci 33227db96d56Sopenharmony_ci self.assertEqual(lst, ['toplevel']) 33237db96d56Sopenharmony_ci 33247db96d56Sopenharmony_ci def _check_element_factory_class(self, cls): 33257db96d56Sopenharmony_ci tb = ET.TreeBuilder(element_factory=cls) 33267db96d56Sopenharmony_ci 33277db96d56Sopenharmony_ci parser = ET.XMLParser(target=tb) 33287db96d56Sopenharmony_ci parser.feed(self.sample1) 33297db96d56Sopenharmony_ci e = parser.close() 33307db96d56Sopenharmony_ci self.assertIsInstance(e, cls) 33317db96d56Sopenharmony_ci self._check_sample1_element(e) 33327db96d56Sopenharmony_ci 33337db96d56Sopenharmony_ci def test_element_factory_subclass(self): 33347db96d56Sopenharmony_ci class MyElement(ET.Element): 33357db96d56Sopenharmony_ci pass 33367db96d56Sopenharmony_ci self._check_element_factory_class(MyElement) 33377db96d56Sopenharmony_ci 33387db96d56Sopenharmony_ci def test_element_factory_pure_python_subclass(self): 33397db96d56Sopenharmony_ci # Mimic SimpleTAL's behaviour (issue #16089): both versions of 33407db96d56Sopenharmony_ci # TreeBuilder should be able to cope with a subclass of the 33417db96d56Sopenharmony_ci # pure Python Element class. 33427db96d56Sopenharmony_ci base = ET._Element_Py 33437db96d56Sopenharmony_ci # Not from a C extension 33447db96d56Sopenharmony_ci self.assertEqual(base.__module__, 'xml.etree.ElementTree') 33457db96d56Sopenharmony_ci # Force some multiple inheritance with a C class to make things 33467db96d56Sopenharmony_ci # more interesting. 33477db96d56Sopenharmony_ci class MyElement(base, ValueError): 33487db96d56Sopenharmony_ci pass 33497db96d56Sopenharmony_ci self._check_element_factory_class(MyElement) 33507db96d56Sopenharmony_ci 33517db96d56Sopenharmony_ci def test_doctype(self): 33527db96d56Sopenharmony_ci class DoctypeParser: 33537db96d56Sopenharmony_ci _doctype = None 33547db96d56Sopenharmony_ci 33557db96d56Sopenharmony_ci def doctype(self, name, pubid, system): 33567db96d56Sopenharmony_ci self._doctype = (name, pubid, system) 33577db96d56Sopenharmony_ci 33587db96d56Sopenharmony_ci def close(self): 33597db96d56Sopenharmony_ci return self._doctype 33607db96d56Sopenharmony_ci 33617db96d56Sopenharmony_ci parser = ET.XMLParser(target=DoctypeParser()) 33627db96d56Sopenharmony_ci parser.feed(self.sample1) 33637db96d56Sopenharmony_ci 33647db96d56Sopenharmony_ci self.assertEqual(parser.close(), 33657db96d56Sopenharmony_ci ('html', '-//W3C//DTD XHTML 1.0 Transitional//EN', 33667db96d56Sopenharmony_ci 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd')) 33677db96d56Sopenharmony_ci 33687db96d56Sopenharmony_ci def test_builder_lookup_errors(self): 33697db96d56Sopenharmony_ci class RaisingBuilder: 33707db96d56Sopenharmony_ci def __init__(self, raise_in=None, what=ValueError): 33717db96d56Sopenharmony_ci self.raise_in = raise_in 33727db96d56Sopenharmony_ci self.what = what 33737db96d56Sopenharmony_ci 33747db96d56Sopenharmony_ci def __getattr__(self, name): 33757db96d56Sopenharmony_ci if name == self.raise_in: 33767db96d56Sopenharmony_ci raise self.what(self.raise_in) 33777db96d56Sopenharmony_ci def handle(*args): 33787db96d56Sopenharmony_ci pass 33797db96d56Sopenharmony_ci return handle 33807db96d56Sopenharmony_ci 33817db96d56Sopenharmony_ci ET.XMLParser(target=RaisingBuilder()) 33827db96d56Sopenharmony_ci # cET also checks for 'close' and 'doctype', PyET does it only at need 33837db96d56Sopenharmony_ci for event in ('start', 'data', 'end', 'comment', 'pi'): 33847db96d56Sopenharmony_ci with self.assertRaisesRegex(ValueError, event): 33857db96d56Sopenharmony_ci ET.XMLParser(target=RaisingBuilder(event)) 33867db96d56Sopenharmony_ci 33877db96d56Sopenharmony_ci ET.XMLParser(target=RaisingBuilder(what=AttributeError)) 33887db96d56Sopenharmony_ci for event in ('start', 'data', 'end', 'comment', 'pi'): 33897db96d56Sopenharmony_ci parser = ET.XMLParser(target=RaisingBuilder(event, what=AttributeError)) 33907db96d56Sopenharmony_ci parser.feed(self.sample1) 33917db96d56Sopenharmony_ci self.assertIsNone(parser.close()) 33927db96d56Sopenharmony_ci 33937db96d56Sopenharmony_ci 33947db96d56Sopenharmony_ciclass XMLParserTest(unittest.TestCase): 33957db96d56Sopenharmony_ci sample1 = b'<file><line>22</line></file>' 33967db96d56Sopenharmony_ci sample2 = (b'<!DOCTYPE html PUBLIC' 33977db96d56Sopenharmony_ci b' "-//W3C//DTD XHTML 1.0 Transitional//EN"' 33987db96d56Sopenharmony_ci b' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' 33997db96d56Sopenharmony_ci b'<html>text</html>') 34007db96d56Sopenharmony_ci sample3 = ('<?xml version="1.0" encoding="iso-8859-1"?>\n' 34017db96d56Sopenharmony_ci '<money value="$\xa3\u20ac\U0001017b">$\xa3\u20ac\U0001017b</money>') 34027db96d56Sopenharmony_ci 34037db96d56Sopenharmony_ci def _check_sample_element(self, e): 34047db96d56Sopenharmony_ci self.assertEqual(e.tag, 'file') 34057db96d56Sopenharmony_ci self.assertEqual(e[0].tag, 'line') 34067db96d56Sopenharmony_ci self.assertEqual(e[0].text, '22') 34077db96d56Sopenharmony_ci 34087db96d56Sopenharmony_ci def test_constructor_args(self): 34097db96d56Sopenharmony_ci parser2 = ET.XMLParser(encoding='utf-8', 34107db96d56Sopenharmony_ci target=ET.TreeBuilder()) 34117db96d56Sopenharmony_ci parser2.feed(self.sample1) 34127db96d56Sopenharmony_ci self._check_sample_element(parser2.close()) 34137db96d56Sopenharmony_ci 34147db96d56Sopenharmony_ci def test_subclass(self): 34157db96d56Sopenharmony_ci class MyParser(ET.XMLParser): 34167db96d56Sopenharmony_ci pass 34177db96d56Sopenharmony_ci parser = MyParser() 34187db96d56Sopenharmony_ci parser.feed(self.sample1) 34197db96d56Sopenharmony_ci self._check_sample_element(parser.close()) 34207db96d56Sopenharmony_ci 34217db96d56Sopenharmony_ci def test_doctype_warning(self): 34227db96d56Sopenharmony_ci with warnings.catch_warnings(): 34237db96d56Sopenharmony_ci warnings.simplefilter('error', DeprecationWarning) 34247db96d56Sopenharmony_ci parser = ET.XMLParser() 34257db96d56Sopenharmony_ci parser.feed(self.sample2) 34267db96d56Sopenharmony_ci parser.close() 34277db96d56Sopenharmony_ci 34287db96d56Sopenharmony_ci def test_subclass_doctype(self): 34297db96d56Sopenharmony_ci _doctype = None 34307db96d56Sopenharmony_ci class MyParserWithDoctype(ET.XMLParser): 34317db96d56Sopenharmony_ci def doctype(self, *args, **kwargs): 34327db96d56Sopenharmony_ci nonlocal _doctype 34337db96d56Sopenharmony_ci _doctype = (args, kwargs) 34347db96d56Sopenharmony_ci 34357db96d56Sopenharmony_ci parser = MyParserWithDoctype() 34367db96d56Sopenharmony_ci with self.assertWarnsRegex(RuntimeWarning, 'doctype'): 34377db96d56Sopenharmony_ci parser.feed(self.sample2) 34387db96d56Sopenharmony_ci parser.close() 34397db96d56Sopenharmony_ci self.assertIsNone(_doctype) 34407db96d56Sopenharmony_ci 34417db96d56Sopenharmony_ci _doctype = _doctype2 = None 34427db96d56Sopenharmony_ci with warnings.catch_warnings(): 34437db96d56Sopenharmony_ci warnings.simplefilter('error', DeprecationWarning) 34447db96d56Sopenharmony_ci warnings.simplefilter('error', RuntimeWarning) 34457db96d56Sopenharmony_ci class DoctypeParser: 34467db96d56Sopenharmony_ci def doctype(self, name, pubid, system): 34477db96d56Sopenharmony_ci nonlocal _doctype2 34487db96d56Sopenharmony_ci _doctype2 = (name, pubid, system) 34497db96d56Sopenharmony_ci 34507db96d56Sopenharmony_ci parser = MyParserWithDoctype(target=DoctypeParser()) 34517db96d56Sopenharmony_ci parser.feed(self.sample2) 34527db96d56Sopenharmony_ci parser.close() 34537db96d56Sopenharmony_ci self.assertIsNone(_doctype) 34547db96d56Sopenharmony_ci self.assertEqual(_doctype2, 34557db96d56Sopenharmony_ci ('html', '-//W3C//DTD XHTML 1.0 Transitional//EN', 34567db96d56Sopenharmony_ci 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd')) 34577db96d56Sopenharmony_ci 34587db96d56Sopenharmony_ci def test_inherited_doctype(self): 34597db96d56Sopenharmony_ci '''Ensure that ordinary usage is not deprecated (Issue 19176)''' 34607db96d56Sopenharmony_ci with warnings.catch_warnings(): 34617db96d56Sopenharmony_ci warnings.simplefilter('error', DeprecationWarning) 34627db96d56Sopenharmony_ci warnings.simplefilter('error', RuntimeWarning) 34637db96d56Sopenharmony_ci class MyParserWithoutDoctype(ET.XMLParser): 34647db96d56Sopenharmony_ci pass 34657db96d56Sopenharmony_ci parser = MyParserWithoutDoctype() 34667db96d56Sopenharmony_ci parser.feed(self.sample2) 34677db96d56Sopenharmony_ci parser.close() 34687db96d56Sopenharmony_ci 34697db96d56Sopenharmony_ci def test_parse_string(self): 34707db96d56Sopenharmony_ci parser = ET.XMLParser(target=ET.TreeBuilder()) 34717db96d56Sopenharmony_ci parser.feed(self.sample3) 34727db96d56Sopenharmony_ci e = parser.close() 34737db96d56Sopenharmony_ci self.assertEqual(e.tag, 'money') 34747db96d56Sopenharmony_ci self.assertEqual(e.attrib['value'], '$\xa3\u20ac\U0001017b') 34757db96d56Sopenharmony_ci self.assertEqual(e.text, '$\xa3\u20ac\U0001017b') 34767db96d56Sopenharmony_ci 34777db96d56Sopenharmony_ci 34787db96d56Sopenharmony_ciclass NamespaceParseTest(unittest.TestCase): 34797db96d56Sopenharmony_ci def test_find_with_namespace(self): 34807db96d56Sopenharmony_ci nsmap = {'h': 'hello', 'f': 'foo'} 34817db96d56Sopenharmony_ci doc = ET.fromstring(SAMPLE_XML_NS_ELEMS) 34827db96d56Sopenharmony_ci 34837db96d56Sopenharmony_ci self.assertEqual(len(doc.findall('{hello}table', nsmap)), 1) 34847db96d56Sopenharmony_ci self.assertEqual(len(doc.findall('.//{hello}td', nsmap)), 2) 34857db96d56Sopenharmony_ci self.assertEqual(len(doc.findall('.//{foo}name', nsmap)), 1) 34867db96d56Sopenharmony_ci 34877db96d56Sopenharmony_ci 34887db96d56Sopenharmony_ciclass ElementSlicingTest(unittest.TestCase): 34897db96d56Sopenharmony_ci def _elem_tags(self, elemlist): 34907db96d56Sopenharmony_ci return [e.tag for e in elemlist] 34917db96d56Sopenharmony_ci 34927db96d56Sopenharmony_ci def _subelem_tags(self, elem): 34937db96d56Sopenharmony_ci return self._elem_tags(list(elem)) 34947db96d56Sopenharmony_ci 34957db96d56Sopenharmony_ci def _make_elem_with_children(self, numchildren): 34967db96d56Sopenharmony_ci """Create an Element with a tag 'a', with the given amount of children 34977db96d56Sopenharmony_ci named 'a0', 'a1' ... and so on. 34987db96d56Sopenharmony_ci 34997db96d56Sopenharmony_ci """ 35007db96d56Sopenharmony_ci e = ET.Element('a') 35017db96d56Sopenharmony_ci for i in range(numchildren): 35027db96d56Sopenharmony_ci ET.SubElement(e, 'a%s' % i) 35037db96d56Sopenharmony_ci return e 35047db96d56Sopenharmony_ci 35057db96d56Sopenharmony_ci def test_getslice_single_index(self): 35067db96d56Sopenharmony_ci e = self._make_elem_with_children(10) 35077db96d56Sopenharmony_ci 35087db96d56Sopenharmony_ci self.assertEqual(e[1].tag, 'a1') 35097db96d56Sopenharmony_ci self.assertEqual(e[-2].tag, 'a8') 35107db96d56Sopenharmony_ci 35117db96d56Sopenharmony_ci self.assertRaises(IndexError, lambda: e[12]) 35127db96d56Sopenharmony_ci self.assertRaises(IndexError, lambda: e[-12]) 35137db96d56Sopenharmony_ci 35147db96d56Sopenharmony_ci def test_getslice_range(self): 35157db96d56Sopenharmony_ci e = self._make_elem_with_children(6) 35167db96d56Sopenharmony_ci 35177db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[3:]), ['a3', 'a4', 'a5']) 35187db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[3:6]), ['a3', 'a4', 'a5']) 35197db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[3:16]), ['a3', 'a4', 'a5']) 35207db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[3:5]), ['a3', 'a4']) 35217db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[3:-1]), ['a3', 'a4']) 35227db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[:2]), ['a0', 'a1']) 35237db96d56Sopenharmony_ci 35247db96d56Sopenharmony_ci def test_getslice_steps(self): 35257db96d56Sopenharmony_ci e = self._make_elem_with_children(10) 35267db96d56Sopenharmony_ci 35277db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[8:10:1]), ['a8', 'a9']) 35287db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[::3]), ['a0', 'a3', 'a6', 'a9']) 35297db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[::8]), ['a0', 'a8']) 35307db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[1::8]), ['a1', 'a9']) 35317db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[3::sys.maxsize]), ['a3']) 35327db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[3::sys.maxsize<<64]), ['a3']) 35337db96d56Sopenharmony_ci 35347db96d56Sopenharmony_ci def test_getslice_negative_steps(self): 35357db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 35367db96d56Sopenharmony_ci 35377db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[::-1]), ['a3', 'a2', 'a1', 'a0']) 35387db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[::-2]), ['a3', 'a1']) 35397db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[3::-sys.maxsize]), ['a3']) 35407db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[3::-sys.maxsize-1]), ['a3']) 35417db96d56Sopenharmony_ci self.assertEqual(self._elem_tags(e[3::-sys.maxsize<<64]), ['a3']) 35427db96d56Sopenharmony_ci 35437db96d56Sopenharmony_ci def test_delslice(self): 35447db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 35457db96d56Sopenharmony_ci del e[0:2] 35467db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a2', 'a3']) 35477db96d56Sopenharmony_ci 35487db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 35497db96d56Sopenharmony_ci del e[0:] 35507db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), []) 35517db96d56Sopenharmony_ci 35527db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 35537db96d56Sopenharmony_ci del e[::-1] 35547db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), []) 35557db96d56Sopenharmony_ci 35567db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 35577db96d56Sopenharmony_ci del e[::-2] 35587db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'a2']) 35597db96d56Sopenharmony_ci 35607db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 35617db96d56Sopenharmony_ci del e[1::2] 35627db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'a2']) 35637db96d56Sopenharmony_ci 35647db96d56Sopenharmony_ci e = self._make_elem_with_children(2) 35657db96d56Sopenharmony_ci del e[::2] 35667db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a1']) 35677db96d56Sopenharmony_ci 35687db96d56Sopenharmony_ci def test_setslice_single_index(self): 35697db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 35707db96d56Sopenharmony_ci e[1] = ET.Element('b') 35717db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3']) 35727db96d56Sopenharmony_ci 35737db96d56Sopenharmony_ci e[-2] = ET.Element('c') 35747db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3']) 35757db96d56Sopenharmony_ci 35767db96d56Sopenharmony_ci with self.assertRaises(IndexError): 35777db96d56Sopenharmony_ci e[5] = ET.Element('d') 35787db96d56Sopenharmony_ci with self.assertRaises(IndexError): 35797db96d56Sopenharmony_ci e[-5] = ET.Element('d') 35807db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3']) 35817db96d56Sopenharmony_ci 35827db96d56Sopenharmony_ci def test_setslice_range(self): 35837db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 35847db96d56Sopenharmony_ci e[1:3] = [ET.Element('b%s' % i) for i in range(2)] 35857db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'a3']) 35867db96d56Sopenharmony_ci 35877db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 35887db96d56Sopenharmony_ci e[1:3] = [ET.Element('b')] 35897db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a3']) 35907db96d56Sopenharmony_ci 35917db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 35927db96d56Sopenharmony_ci e[1:3] = [ET.Element('b%s' % i) for i in range(3)] 35937db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'b2', 'a3']) 35947db96d56Sopenharmony_ci 35957db96d56Sopenharmony_ci def test_setslice_steps(self): 35967db96d56Sopenharmony_ci e = self._make_elem_with_children(6) 35977db96d56Sopenharmony_ci e[1:5:2] = [ET.Element('b%s' % i) for i in range(2)] 35987db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'a2', 'b1', 'a4', 'a5']) 35997db96d56Sopenharmony_ci 36007db96d56Sopenharmony_ci e = self._make_elem_with_children(6) 36017db96d56Sopenharmony_ci with self.assertRaises(ValueError): 36027db96d56Sopenharmony_ci e[1:5:2] = [ET.Element('b')] 36037db96d56Sopenharmony_ci with self.assertRaises(ValueError): 36047db96d56Sopenharmony_ci e[1:5:2] = [ET.Element('b%s' % i) for i in range(3)] 36057db96d56Sopenharmony_ci with self.assertRaises(ValueError): 36067db96d56Sopenharmony_ci e[1:5:2] = [] 36077db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3', 'a4', 'a5']) 36087db96d56Sopenharmony_ci 36097db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 36107db96d56Sopenharmony_ci e[1::sys.maxsize] = [ET.Element('b')] 36117db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3']) 36127db96d56Sopenharmony_ci e[1::sys.maxsize<<64] = [ET.Element('c')] 36137db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3']) 36147db96d56Sopenharmony_ci 36157db96d56Sopenharmony_ci def test_setslice_negative_steps(self): 36167db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 36177db96d56Sopenharmony_ci e[2:0:-1] = [ET.Element('b%s' % i) for i in range(2)] 36187db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'b1', 'b0', 'a3']) 36197db96d56Sopenharmony_ci 36207db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 36217db96d56Sopenharmony_ci with self.assertRaises(ValueError): 36227db96d56Sopenharmony_ci e[2:0:-1] = [ET.Element('b')] 36237db96d56Sopenharmony_ci with self.assertRaises(ValueError): 36247db96d56Sopenharmony_ci e[2:0:-1] = [ET.Element('b%s' % i) for i in range(3)] 36257db96d56Sopenharmony_ci with self.assertRaises(ValueError): 36267db96d56Sopenharmony_ci e[2:0:-1] = [] 36277db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3']) 36287db96d56Sopenharmony_ci 36297db96d56Sopenharmony_ci e = self._make_elem_with_children(4) 36307db96d56Sopenharmony_ci e[1::-sys.maxsize] = [ET.Element('b')] 36317db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3']) 36327db96d56Sopenharmony_ci e[1::-sys.maxsize-1] = [ET.Element('c')] 36337db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3']) 36347db96d56Sopenharmony_ci e[1::-sys.maxsize<<64] = [ET.Element('d')] 36357db96d56Sopenharmony_ci self.assertEqual(self._subelem_tags(e), ['a0', 'd', 'a2', 'a3']) 36367db96d56Sopenharmony_ci 36377db96d56Sopenharmony_ci 36387db96d56Sopenharmony_ciclass IOTest(unittest.TestCase): 36397db96d56Sopenharmony_ci def test_encoding(self): 36407db96d56Sopenharmony_ci # Test encoding issues. 36417db96d56Sopenharmony_ci elem = ET.Element("tag") 36427db96d56Sopenharmony_ci elem.text = "abc" 36437db96d56Sopenharmony_ci self.assertEqual(serialize(elem), '<tag>abc</tag>') 36447db96d56Sopenharmony_ci for enc in ("utf-8", "us-ascii"): 36457db96d56Sopenharmony_ci with self.subTest(enc): 36467db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding=enc), 36477db96d56Sopenharmony_ci b'<tag>abc</tag>') 36487db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding=enc.upper()), 36497db96d56Sopenharmony_ci b'<tag>abc</tag>') 36507db96d56Sopenharmony_ci for enc in ("iso-8859-1", "utf-16", "utf-32"): 36517db96d56Sopenharmony_ci with self.subTest(enc): 36527db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding=enc), 36537db96d56Sopenharmony_ci ("<?xml version='1.0' encoding='%s'?>\n" 36547db96d56Sopenharmony_ci "<tag>abc</tag>" % enc).encode(enc)) 36557db96d56Sopenharmony_ci upper = enc.upper() 36567db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding=upper), 36577db96d56Sopenharmony_ci ("<?xml version='1.0' encoding='%s'?>\n" 36587db96d56Sopenharmony_ci "<tag>abc</tag>" % upper).encode(enc)) 36597db96d56Sopenharmony_ci 36607db96d56Sopenharmony_ci elem = ET.Element("tag") 36617db96d56Sopenharmony_ci elem.text = "<&\"\'>" 36627db96d56Sopenharmony_ci self.assertEqual(serialize(elem), '<tag><&"\'></tag>') 36637db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding="utf-8"), 36647db96d56Sopenharmony_ci b'<tag><&"\'></tag>') 36657db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding="us-ascii"), 36667db96d56Sopenharmony_ci b'<tag><&"\'></tag>') 36677db96d56Sopenharmony_ci for enc in ("iso-8859-1", "utf-16", "utf-32"): 36687db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding=enc), 36697db96d56Sopenharmony_ci ("<?xml version='1.0' encoding='%s'?>\n" 36707db96d56Sopenharmony_ci "<tag><&\"'></tag>" % enc).encode(enc)) 36717db96d56Sopenharmony_ci 36727db96d56Sopenharmony_ci elem = ET.Element("tag") 36737db96d56Sopenharmony_ci elem.attrib["key"] = "<&\"\'>" 36747db96d56Sopenharmony_ci self.assertEqual(serialize(elem), '<tag key="<&"\'>" />') 36757db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding="utf-8"), 36767db96d56Sopenharmony_ci b'<tag key="<&"\'>" />') 36777db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding="us-ascii"), 36787db96d56Sopenharmony_ci b'<tag key="<&"\'>" />') 36797db96d56Sopenharmony_ci for enc in ("iso-8859-1", "utf-16", "utf-32"): 36807db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding=enc), 36817db96d56Sopenharmony_ci ("<?xml version='1.0' encoding='%s'?>\n" 36827db96d56Sopenharmony_ci "<tag key=\"<&"'>\" />" % enc).encode(enc)) 36837db96d56Sopenharmony_ci 36847db96d56Sopenharmony_ci elem = ET.Element("tag") 36857db96d56Sopenharmony_ci elem.text = '\xe5\xf6\xf6<>' 36867db96d56Sopenharmony_ci self.assertEqual(serialize(elem), '<tag>\xe5\xf6\xf6<></tag>') 36877db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding="utf-8"), 36887db96d56Sopenharmony_ci b'<tag>\xc3\xa5\xc3\xb6\xc3\xb6<></tag>') 36897db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding="us-ascii"), 36907db96d56Sopenharmony_ci b'<tag>åöö<></tag>') 36917db96d56Sopenharmony_ci for enc in ("iso-8859-1", "utf-16", "utf-32"): 36927db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding=enc), 36937db96d56Sopenharmony_ci ("<?xml version='1.0' encoding='%s'?>\n" 36947db96d56Sopenharmony_ci "<tag>åöö<></tag>" % enc).encode(enc)) 36957db96d56Sopenharmony_ci 36967db96d56Sopenharmony_ci elem = ET.Element("tag") 36977db96d56Sopenharmony_ci elem.attrib["key"] = '\xe5\xf6\xf6<>' 36987db96d56Sopenharmony_ci self.assertEqual(serialize(elem), '<tag key="\xe5\xf6\xf6<>" />') 36997db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding="utf-8"), 37007db96d56Sopenharmony_ci b'<tag key="\xc3\xa5\xc3\xb6\xc3\xb6<>" />') 37017db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding="us-ascii"), 37027db96d56Sopenharmony_ci b'<tag key="åöö<>" />') 37037db96d56Sopenharmony_ci for enc in ("iso-8859-1", "utf-16", "utf-16le", "utf-16be", "utf-32"): 37047db96d56Sopenharmony_ci self.assertEqual(serialize(elem, encoding=enc), 37057db96d56Sopenharmony_ci ("<?xml version='1.0' encoding='%s'?>\n" 37067db96d56Sopenharmony_ci "<tag key=\"åöö<>\" />" % enc).encode(enc)) 37077db96d56Sopenharmony_ci 37087db96d56Sopenharmony_ci def test_write_to_filename(self): 37097db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN) 37107db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site>\xf8</site>''')) 37117db96d56Sopenharmony_ci tree.write(TESTFN) 37127db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 37137db96d56Sopenharmony_ci self.assertEqual(f.read(), b'''<site>ø</site>''') 37147db96d56Sopenharmony_ci 37157db96d56Sopenharmony_ci def test_write_to_filename_with_encoding(self): 37167db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN) 37177db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site>\xf8</site>''')) 37187db96d56Sopenharmony_ci tree.write(TESTFN, encoding='utf-8') 37197db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 37207db96d56Sopenharmony_ci self.assertEqual(f.read(), b'''<site>\xc3\xb8</site>''') 37217db96d56Sopenharmony_ci 37227db96d56Sopenharmony_ci tree.write(TESTFN, encoding='ISO-8859-1') 37237db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 37247db96d56Sopenharmony_ci self.assertEqual(f.read(), convlinesep( 37257db96d56Sopenharmony_ci b'''<?xml version='1.0' encoding='ISO-8859-1'?>\n''' 37267db96d56Sopenharmony_ci b'''<site>\xf8</site>''')) 37277db96d56Sopenharmony_ci 37287db96d56Sopenharmony_ci def test_write_to_filename_as_unicode(self): 37297db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN) 37307db96d56Sopenharmony_ci with open(TESTFN, 'w') as f: 37317db96d56Sopenharmony_ci encoding = f.encoding 37327db96d56Sopenharmony_ci os_helper.unlink(TESTFN) 37337db96d56Sopenharmony_ci 37347db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site>\xf8</site>''')) 37357db96d56Sopenharmony_ci tree.write(TESTFN, encoding='unicode') 37367db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 37377db96d56Sopenharmony_ci self.assertEqual(f.read(), b"<site>\xc3\xb8</site>") 37387db96d56Sopenharmony_ci 37397db96d56Sopenharmony_ci def test_write_to_text_file(self): 37407db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN) 37417db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site>\xf8</site>''')) 37427db96d56Sopenharmony_ci with open(TESTFN, 'w', encoding='utf-8') as f: 37437db96d56Sopenharmony_ci tree.write(f, encoding='unicode') 37447db96d56Sopenharmony_ci self.assertFalse(f.closed) 37457db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 37467db96d56Sopenharmony_ci self.assertEqual(f.read(), b'''<site>\xc3\xb8</site>''') 37477db96d56Sopenharmony_ci 37487db96d56Sopenharmony_ci with open(TESTFN, 'w', encoding='ascii', errors='xmlcharrefreplace') as f: 37497db96d56Sopenharmony_ci tree.write(f, encoding='unicode') 37507db96d56Sopenharmony_ci self.assertFalse(f.closed) 37517db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 37527db96d56Sopenharmony_ci self.assertEqual(f.read(), b'''<site>ø</site>''') 37537db96d56Sopenharmony_ci 37547db96d56Sopenharmony_ci with open(TESTFN, 'w', encoding='ISO-8859-1') as f: 37557db96d56Sopenharmony_ci tree.write(f, encoding='unicode') 37567db96d56Sopenharmony_ci self.assertFalse(f.closed) 37577db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 37587db96d56Sopenharmony_ci self.assertEqual(f.read(), b'''<site>\xf8</site>''') 37597db96d56Sopenharmony_ci 37607db96d56Sopenharmony_ci def test_write_to_binary_file(self): 37617db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN) 37627db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site>\xf8</site>''')) 37637db96d56Sopenharmony_ci with open(TESTFN, 'wb') as f: 37647db96d56Sopenharmony_ci tree.write(f) 37657db96d56Sopenharmony_ci self.assertFalse(f.closed) 37667db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 37677db96d56Sopenharmony_ci self.assertEqual(f.read(), b'''<site>ø</site>''') 37687db96d56Sopenharmony_ci 37697db96d56Sopenharmony_ci def test_write_to_binary_file_with_encoding(self): 37707db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN) 37717db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site>\xf8</site>''')) 37727db96d56Sopenharmony_ci with open(TESTFN, 'wb') as f: 37737db96d56Sopenharmony_ci tree.write(f, encoding='utf-8') 37747db96d56Sopenharmony_ci self.assertFalse(f.closed) 37757db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 37767db96d56Sopenharmony_ci self.assertEqual(f.read(), b'''<site>\xc3\xb8</site>''') 37777db96d56Sopenharmony_ci 37787db96d56Sopenharmony_ci with open(TESTFN, 'wb') as f: 37797db96d56Sopenharmony_ci tree.write(f, encoding='ISO-8859-1') 37807db96d56Sopenharmony_ci self.assertFalse(f.closed) 37817db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 37827db96d56Sopenharmony_ci self.assertEqual(f.read(), 37837db96d56Sopenharmony_ci b'''<?xml version='1.0' encoding='ISO-8859-1'?>\n''' 37847db96d56Sopenharmony_ci b'''<site>\xf8</site>''') 37857db96d56Sopenharmony_ci 37867db96d56Sopenharmony_ci def test_write_to_binary_file_with_bom(self): 37877db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN) 37887db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site>\xf8</site>''')) 37897db96d56Sopenharmony_ci # test BOM writing to buffered file 37907db96d56Sopenharmony_ci with open(TESTFN, 'wb') as f: 37917db96d56Sopenharmony_ci tree.write(f, encoding='utf-16') 37927db96d56Sopenharmony_ci self.assertFalse(f.closed) 37937db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 37947db96d56Sopenharmony_ci self.assertEqual(f.read(), 37957db96d56Sopenharmony_ci '''<?xml version='1.0' encoding='utf-16'?>\n''' 37967db96d56Sopenharmony_ci '''<site>\xf8</site>'''.encode("utf-16")) 37977db96d56Sopenharmony_ci # test BOM writing to non-buffered file 37987db96d56Sopenharmony_ci with open(TESTFN, 'wb', buffering=0) as f: 37997db96d56Sopenharmony_ci tree.write(f, encoding='utf-16') 38007db96d56Sopenharmony_ci self.assertFalse(f.closed) 38017db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 38027db96d56Sopenharmony_ci self.assertEqual(f.read(), 38037db96d56Sopenharmony_ci '''<?xml version='1.0' encoding='utf-16'?>\n''' 38047db96d56Sopenharmony_ci '''<site>\xf8</site>'''.encode("utf-16")) 38057db96d56Sopenharmony_ci 38067db96d56Sopenharmony_ci def test_read_from_stringio(self): 38077db96d56Sopenharmony_ci tree = ET.ElementTree() 38087db96d56Sopenharmony_ci stream = io.StringIO('''<?xml version="1.0"?><site></site>''') 38097db96d56Sopenharmony_ci tree.parse(stream) 38107db96d56Sopenharmony_ci self.assertEqual(tree.getroot().tag, 'site') 38117db96d56Sopenharmony_ci 38127db96d56Sopenharmony_ci def test_write_to_stringio(self): 38137db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site>\xf8</site>''')) 38147db96d56Sopenharmony_ci stream = io.StringIO() 38157db96d56Sopenharmony_ci tree.write(stream, encoding='unicode') 38167db96d56Sopenharmony_ci self.assertEqual(stream.getvalue(), '''<site>\xf8</site>''') 38177db96d56Sopenharmony_ci 38187db96d56Sopenharmony_ci def test_read_from_bytesio(self): 38197db96d56Sopenharmony_ci tree = ET.ElementTree() 38207db96d56Sopenharmony_ci raw = io.BytesIO(b'''<?xml version="1.0"?><site></site>''') 38217db96d56Sopenharmony_ci tree.parse(raw) 38227db96d56Sopenharmony_ci self.assertEqual(tree.getroot().tag, 'site') 38237db96d56Sopenharmony_ci 38247db96d56Sopenharmony_ci def test_write_to_bytesio(self): 38257db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site>\xf8</site>''')) 38267db96d56Sopenharmony_ci raw = io.BytesIO() 38277db96d56Sopenharmony_ci tree.write(raw) 38287db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b'''<site>ø</site>''') 38297db96d56Sopenharmony_ci 38307db96d56Sopenharmony_ci class dummy: 38317db96d56Sopenharmony_ci pass 38327db96d56Sopenharmony_ci 38337db96d56Sopenharmony_ci def test_read_from_user_text_reader(self): 38347db96d56Sopenharmony_ci stream = io.StringIO('''<?xml version="1.0"?><site></site>''') 38357db96d56Sopenharmony_ci reader = self.dummy() 38367db96d56Sopenharmony_ci reader.read = stream.read 38377db96d56Sopenharmony_ci tree = ET.ElementTree() 38387db96d56Sopenharmony_ci tree.parse(reader) 38397db96d56Sopenharmony_ci self.assertEqual(tree.getroot().tag, 'site') 38407db96d56Sopenharmony_ci 38417db96d56Sopenharmony_ci def test_write_to_user_text_writer(self): 38427db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site>\xf8</site>''')) 38437db96d56Sopenharmony_ci stream = io.StringIO() 38447db96d56Sopenharmony_ci writer = self.dummy() 38457db96d56Sopenharmony_ci writer.write = stream.write 38467db96d56Sopenharmony_ci tree.write(writer, encoding='unicode') 38477db96d56Sopenharmony_ci self.assertEqual(stream.getvalue(), '''<site>\xf8</site>''') 38487db96d56Sopenharmony_ci 38497db96d56Sopenharmony_ci def test_read_from_user_binary_reader(self): 38507db96d56Sopenharmony_ci raw = io.BytesIO(b'''<?xml version="1.0"?><site></site>''') 38517db96d56Sopenharmony_ci reader = self.dummy() 38527db96d56Sopenharmony_ci reader.read = raw.read 38537db96d56Sopenharmony_ci tree = ET.ElementTree() 38547db96d56Sopenharmony_ci tree.parse(reader) 38557db96d56Sopenharmony_ci self.assertEqual(tree.getroot().tag, 'site') 38567db96d56Sopenharmony_ci tree = ET.ElementTree() 38577db96d56Sopenharmony_ci 38587db96d56Sopenharmony_ci def test_write_to_user_binary_writer(self): 38597db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site>\xf8</site>''')) 38607db96d56Sopenharmony_ci raw = io.BytesIO() 38617db96d56Sopenharmony_ci writer = self.dummy() 38627db96d56Sopenharmony_ci writer.write = raw.write 38637db96d56Sopenharmony_ci tree.write(writer) 38647db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b'''<site>ø</site>''') 38657db96d56Sopenharmony_ci 38667db96d56Sopenharmony_ci def test_write_to_user_binary_writer_with_bom(self): 38677db96d56Sopenharmony_ci tree = ET.ElementTree(ET.XML('''<site />''')) 38687db96d56Sopenharmony_ci raw = io.BytesIO() 38697db96d56Sopenharmony_ci writer = self.dummy() 38707db96d56Sopenharmony_ci writer.write = raw.write 38717db96d56Sopenharmony_ci writer.seekable = lambda: True 38727db96d56Sopenharmony_ci writer.tell = raw.tell 38737db96d56Sopenharmony_ci tree.write(writer, encoding="utf-16") 38747db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), 38757db96d56Sopenharmony_ci '''<?xml version='1.0' encoding='utf-16'?>\n''' 38767db96d56Sopenharmony_ci '''<site />'''.encode("utf-16")) 38777db96d56Sopenharmony_ci 38787db96d56Sopenharmony_ci def test_tostringlist_invariant(self): 38797db96d56Sopenharmony_ci root = ET.fromstring('<tag>foo</tag>') 38807db96d56Sopenharmony_ci self.assertEqual( 38817db96d56Sopenharmony_ci ET.tostring(root, 'unicode'), 38827db96d56Sopenharmony_ci ''.join(ET.tostringlist(root, 'unicode'))) 38837db96d56Sopenharmony_ci self.assertEqual( 38847db96d56Sopenharmony_ci ET.tostring(root, 'utf-16'), 38857db96d56Sopenharmony_ci b''.join(ET.tostringlist(root, 'utf-16'))) 38867db96d56Sopenharmony_ci 38877db96d56Sopenharmony_ci def test_short_empty_elements(self): 38887db96d56Sopenharmony_ci root = ET.fromstring('<tag>a<x />b<y></y>c</tag>') 38897db96d56Sopenharmony_ci self.assertEqual( 38907db96d56Sopenharmony_ci ET.tostring(root, 'unicode'), 38917db96d56Sopenharmony_ci '<tag>a<x />b<y />c</tag>') 38927db96d56Sopenharmony_ci self.assertEqual( 38937db96d56Sopenharmony_ci ET.tostring(root, 'unicode', short_empty_elements=True), 38947db96d56Sopenharmony_ci '<tag>a<x />b<y />c</tag>') 38957db96d56Sopenharmony_ci self.assertEqual( 38967db96d56Sopenharmony_ci ET.tostring(root, 'unicode', short_empty_elements=False), 38977db96d56Sopenharmony_ci '<tag>a<x></x>b<y></y>c</tag>') 38987db96d56Sopenharmony_ci 38997db96d56Sopenharmony_ci 39007db96d56Sopenharmony_ciclass ParseErrorTest(unittest.TestCase): 39017db96d56Sopenharmony_ci def test_subclass(self): 39027db96d56Sopenharmony_ci self.assertIsInstance(ET.ParseError(), SyntaxError) 39037db96d56Sopenharmony_ci 39047db96d56Sopenharmony_ci def _get_error(self, s): 39057db96d56Sopenharmony_ci try: 39067db96d56Sopenharmony_ci ET.fromstring(s) 39077db96d56Sopenharmony_ci except ET.ParseError as e: 39087db96d56Sopenharmony_ci return e 39097db96d56Sopenharmony_ci 39107db96d56Sopenharmony_ci def test_error_position(self): 39117db96d56Sopenharmony_ci self.assertEqual(self._get_error('foo').position, (1, 0)) 39127db96d56Sopenharmony_ci self.assertEqual(self._get_error('<tag>&foo;</tag>').position, (1, 5)) 39137db96d56Sopenharmony_ci self.assertEqual(self._get_error('foobar<').position, (1, 6)) 39147db96d56Sopenharmony_ci 39157db96d56Sopenharmony_ci def test_error_code(self): 39167db96d56Sopenharmony_ci import xml.parsers.expat.errors as ERRORS 39177db96d56Sopenharmony_ci self.assertEqual(self._get_error('foo').code, 39187db96d56Sopenharmony_ci ERRORS.codes[ERRORS.XML_ERROR_SYNTAX]) 39197db96d56Sopenharmony_ci 39207db96d56Sopenharmony_ci 39217db96d56Sopenharmony_ciclass KeywordArgsTest(unittest.TestCase): 39227db96d56Sopenharmony_ci # Test various issues with keyword arguments passed to ET.Element 39237db96d56Sopenharmony_ci # constructor and methods 39247db96d56Sopenharmony_ci def test_issue14818(self): 39257db96d56Sopenharmony_ci x = ET.XML("<a>foo</a>") 39267db96d56Sopenharmony_ci self.assertEqual(x.find('a', None), 39277db96d56Sopenharmony_ci x.find(path='a', namespaces=None)) 39287db96d56Sopenharmony_ci self.assertEqual(x.findtext('a', None, None), 39297db96d56Sopenharmony_ci x.findtext(path='a', default=None, namespaces=None)) 39307db96d56Sopenharmony_ci self.assertEqual(x.findall('a', None), 39317db96d56Sopenharmony_ci x.findall(path='a', namespaces=None)) 39327db96d56Sopenharmony_ci self.assertEqual(list(x.iterfind('a', None)), 39337db96d56Sopenharmony_ci list(x.iterfind(path='a', namespaces=None))) 39347db96d56Sopenharmony_ci 39357db96d56Sopenharmony_ci self.assertEqual(ET.Element('a').attrib, {}) 39367db96d56Sopenharmony_ci elements = [ 39377db96d56Sopenharmony_ci ET.Element('a', dict(href="#", id="foo")), 39387db96d56Sopenharmony_ci ET.Element('a', attrib=dict(href="#", id="foo")), 39397db96d56Sopenharmony_ci ET.Element('a', dict(href="#"), id="foo"), 39407db96d56Sopenharmony_ci ET.Element('a', href="#", id="foo"), 39417db96d56Sopenharmony_ci ET.Element('a', dict(href="#", id="foo"), href="#", id="foo"), 39427db96d56Sopenharmony_ci ] 39437db96d56Sopenharmony_ci for e in elements: 39447db96d56Sopenharmony_ci self.assertEqual(e.tag, 'a') 39457db96d56Sopenharmony_ci self.assertEqual(e.attrib, dict(href="#", id="foo")) 39467db96d56Sopenharmony_ci 39477db96d56Sopenharmony_ci e2 = ET.SubElement(elements[0], 'foobar', attrib={'key1': 'value1'}) 39487db96d56Sopenharmony_ci self.assertEqual(e2.attrib['key1'], 'value1') 39497db96d56Sopenharmony_ci 39507db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, 'must be dict, not str'): 39517db96d56Sopenharmony_ci ET.Element('a', "I'm not a dict") 39527db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, 'must be dict, not str'): 39537db96d56Sopenharmony_ci ET.Element('a', attrib="I'm not a dict") 39547db96d56Sopenharmony_ci 39557db96d56Sopenharmony_ci# -------------------------------------------------------------------- 39567db96d56Sopenharmony_ci 39577db96d56Sopenharmony_ciclass NoAcceleratorTest(unittest.TestCase): 39587db96d56Sopenharmony_ci def setUp(self): 39597db96d56Sopenharmony_ci if not pyET: 39607db96d56Sopenharmony_ci raise unittest.SkipTest('only for the Python version') 39617db96d56Sopenharmony_ci 39627db96d56Sopenharmony_ci # Test that the C accelerator was not imported for pyET 39637db96d56Sopenharmony_ci def test_correct_import_pyET(self): 39647db96d56Sopenharmony_ci # The type of methods defined in Python code is types.FunctionType, 39657db96d56Sopenharmony_ci # while the type of methods defined inside _elementtree is 39667db96d56Sopenharmony_ci # <class 'wrapper_descriptor'> 39677db96d56Sopenharmony_ci self.assertIsInstance(pyET.Element.__init__, types.FunctionType) 39687db96d56Sopenharmony_ci self.assertIsInstance(pyET.XMLParser.__init__, types.FunctionType) 39697db96d56Sopenharmony_ci 39707db96d56Sopenharmony_ci 39717db96d56Sopenharmony_ci# -------------------------------------------------------------------- 39727db96d56Sopenharmony_ci 39737db96d56Sopenharmony_cidef c14n_roundtrip(xml, **options): 39747db96d56Sopenharmony_ci return pyET.canonicalize(xml, **options) 39757db96d56Sopenharmony_ci 39767db96d56Sopenharmony_ci 39777db96d56Sopenharmony_ciclass C14NTest(unittest.TestCase): 39787db96d56Sopenharmony_ci maxDiff = None 39797db96d56Sopenharmony_ci 39807db96d56Sopenharmony_ci # 39817db96d56Sopenharmony_ci # simple roundtrip tests (from c14n.py) 39827db96d56Sopenharmony_ci 39837db96d56Sopenharmony_ci def test_simple_roundtrip(self): 39847db96d56Sopenharmony_ci # Basics 39857db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip("<doc/>"), '<doc></doc>') 39867db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip("<doc xmlns='uri'/>"), # FIXME 39877db96d56Sopenharmony_ci '<doc xmlns="uri"></doc>') 39887db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip("<prefix:doc xmlns:prefix='uri'/>"), 39897db96d56Sopenharmony_ci '<prefix:doc xmlns:prefix="uri"></prefix:doc>') 39907db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip("<doc xmlns:prefix='uri'><prefix:bar/></doc>"), 39917db96d56Sopenharmony_ci '<doc><prefix:bar xmlns:prefix="uri"></prefix:bar></doc>') 39927db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip("<elem xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' />"), 39937db96d56Sopenharmony_ci '<elem></elem>') 39947db96d56Sopenharmony_ci 39957db96d56Sopenharmony_ci # C14N spec 39967db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip("<doc>Hello, world!<!-- Comment 1 --></doc>"), 39977db96d56Sopenharmony_ci '<doc>Hello, world!</doc>') 39987db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip("<value>2</value>"), 39997db96d56Sopenharmony_ci '<value>2</value>') 40007db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip('<compute><![CDATA[value>"0" && value<"10" ?"valid":"error"]]></compute>'), 40017db96d56Sopenharmony_ci '<compute>value>"0" && value<"10" ?"valid":"error"</compute>') 40027db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip('''<compute expr='value>"0" && value<"10" ?"valid":"error"'>valid</compute>'''), 40037db96d56Sopenharmony_ci '<compute expr="value>"0" && value<"10" ?"valid":"error"">valid</compute>') 40047db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip("<norm attr=' '   
	 ' '/>"), 40057db96d56Sopenharmony_ci '<norm attr=" \' 
	 \' "></norm>') 40067db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip("<normNames attr=' A   
	 B '/>"), 40077db96d56Sopenharmony_ci '<normNames attr=" A 
	 B "></normNames>') 40087db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip("<normId id=' '   
	 ' '/>"), 40097db96d56Sopenharmony_ci '<normId id=" \' 
	 \' "></normId>') 40107db96d56Sopenharmony_ci 40117db96d56Sopenharmony_ci # fragments from PJ's tests 40127db96d56Sopenharmony_ci #self.assertEqual(c14n_roundtrip("<doc xmlns:x='http://example.com/x' xmlns='http://example.com/default'><b y:a1='1' xmlns='http://example.com/default' a3='3' xmlns:y='http://example.com/y' y:a2='2'/></doc>"), 40137db96d56Sopenharmony_ci #'<doc xmlns:x="http://example.com/x"><b xmlns:y="http://example.com/y" a3="3" y:a1="1" y:a2="2"></b></doc>') 40147db96d56Sopenharmony_ci 40157db96d56Sopenharmony_ci # Namespace issues 40167db96d56Sopenharmony_ci xml = '<X xmlns="http://nps/a"><Y targets="abc,xyz"></Y></X>' 40177db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip(xml), xml) 40187db96d56Sopenharmony_ci xml = '<X xmlns="http://nps/a"><Y xmlns="http://nsp/b" targets="abc,xyz"></Y></X>' 40197db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip(xml), xml) 40207db96d56Sopenharmony_ci xml = '<X xmlns="http://nps/a"><Y xmlns:b="http://nsp/b" b:targets="abc,xyz"></Y></X>' 40217db96d56Sopenharmony_ci self.assertEqual(c14n_roundtrip(xml), xml) 40227db96d56Sopenharmony_ci 40237db96d56Sopenharmony_ci def test_c14n_exclusion(self): 40247db96d56Sopenharmony_ci xml = textwrap.dedent("""\ 40257db96d56Sopenharmony_ci <root xmlns:x="http://example.com/x"> 40267db96d56Sopenharmony_ci <a x:attr="attrx"> 40277db96d56Sopenharmony_ci <b>abtext</b> 40287db96d56Sopenharmony_ci </a> 40297db96d56Sopenharmony_ci <b>btext</b> 40307db96d56Sopenharmony_ci <c> 40317db96d56Sopenharmony_ci <x:d>dtext</x:d> 40327db96d56Sopenharmony_ci </c> 40337db96d56Sopenharmony_ci </root> 40347db96d56Sopenharmony_ci """) 40357db96d56Sopenharmony_ci self.assertEqual( 40367db96d56Sopenharmony_ci c14n_roundtrip(xml, strip_text=True), 40377db96d56Sopenharmony_ci '<root>' 40387db96d56Sopenharmony_ci '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>' 40397db96d56Sopenharmony_ci '<b>btext</b>' 40407db96d56Sopenharmony_ci '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>' 40417db96d56Sopenharmony_ci '</root>') 40427db96d56Sopenharmony_ci self.assertEqual( 40437db96d56Sopenharmony_ci c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr']), 40447db96d56Sopenharmony_ci '<root>' 40457db96d56Sopenharmony_ci '<a><b>abtext</b></a>' 40467db96d56Sopenharmony_ci '<b>btext</b>' 40477db96d56Sopenharmony_ci '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>' 40487db96d56Sopenharmony_ci '</root>') 40497db96d56Sopenharmony_ci self.assertEqual( 40507db96d56Sopenharmony_ci c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d']), 40517db96d56Sopenharmony_ci '<root>' 40527db96d56Sopenharmony_ci '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>' 40537db96d56Sopenharmony_ci '<b>btext</b>' 40547db96d56Sopenharmony_ci '<c></c>' 40557db96d56Sopenharmony_ci '</root>') 40567db96d56Sopenharmony_ci self.assertEqual( 40577db96d56Sopenharmony_ci c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr'], 40587db96d56Sopenharmony_ci exclude_tags=['{http://example.com/x}d']), 40597db96d56Sopenharmony_ci '<root>' 40607db96d56Sopenharmony_ci '<a><b>abtext</b></a>' 40617db96d56Sopenharmony_ci '<b>btext</b>' 40627db96d56Sopenharmony_ci '<c></c>' 40637db96d56Sopenharmony_ci '</root>') 40647db96d56Sopenharmony_ci self.assertEqual( 40657db96d56Sopenharmony_ci c14n_roundtrip(xml, strip_text=True, exclude_tags=['a', 'b']), 40667db96d56Sopenharmony_ci '<root>' 40677db96d56Sopenharmony_ci '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>' 40687db96d56Sopenharmony_ci '</root>') 40697db96d56Sopenharmony_ci self.assertEqual( 40707db96d56Sopenharmony_ci c14n_roundtrip(xml, exclude_tags=['a', 'b']), 40717db96d56Sopenharmony_ci '<root>\n' 40727db96d56Sopenharmony_ci ' \n' 40737db96d56Sopenharmony_ci ' \n' 40747db96d56Sopenharmony_ci ' <c>\n' 40757db96d56Sopenharmony_ci ' <x:d xmlns:x="http://example.com/x">dtext</x:d>\n' 40767db96d56Sopenharmony_ci ' </c>\n' 40777db96d56Sopenharmony_ci '</root>') 40787db96d56Sopenharmony_ci self.assertEqual( 40797db96d56Sopenharmony_ci c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d', 'b']), 40807db96d56Sopenharmony_ci '<root>' 40817db96d56Sopenharmony_ci '<a xmlns:x="http://example.com/x" x:attr="attrx"></a>' 40827db96d56Sopenharmony_ci '<c></c>' 40837db96d56Sopenharmony_ci '</root>') 40847db96d56Sopenharmony_ci self.assertEqual( 40857db96d56Sopenharmony_ci c14n_roundtrip(xml, exclude_tags=['{http://example.com/x}d', 'b']), 40867db96d56Sopenharmony_ci '<root>\n' 40877db96d56Sopenharmony_ci ' <a xmlns:x="http://example.com/x" x:attr="attrx">\n' 40887db96d56Sopenharmony_ci ' \n' 40897db96d56Sopenharmony_ci ' </a>\n' 40907db96d56Sopenharmony_ci ' \n' 40917db96d56Sopenharmony_ci ' <c>\n' 40927db96d56Sopenharmony_ci ' \n' 40937db96d56Sopenharmony_ci ' </c>\n' 40947db96d56Sopenharmony_ci '</root>') 40957db96d56Sopenharmony_ci 40967db96d56Sopenharmony_ci # 40977db96d56Sopenharmony_ci # basic method=c14n tests from the c14n 2.0 specification. uses 40987db96d56Sopenharmony_ci # test files under xmltestdata/c14n-20. 40997db96d56Sopenharmony_ci 41007db96d56Sopenharmony_ci # note that this uses generated C14N versions of the standard ET.write 41017db96d56Sopenharmony_ci # output, not roundtripped C14N (see above). 41027db96d56Sopenharmony_ci 41037db96d56Sopenharmony_ci def test_xml_c14n2(self): 41047db96d56Sopenharmony_ci datadir = findfile("c14n-20", subdir="xmltestdata") 41057db96d56Sopenharmony_ci full_path = partial(os.path.join, datadir) 41067db96d56Sopenharmony_ci 41077db96d56Sopenharmony_ci files = [filename[:-4] for filename in sorted(os.listdir(datadir)) 41087db96d56Sopenharmony_ci if filename.endswith('.xml')] 41097db96d56Sopenharmony_ci input_files = [ 41107db96d56Sopenharmony_ci filename for filename in files 41117db96d56Sopenharmony_ci if filename.startswith('in') 41127db96d56Sopenharmony_ci ] 41137db96d56Sopenharmony_ci configs = { 41147db96d56Sopenharmony_ci filename: { 41157db96d56Sopenharmony_ci # <c14n2:PrefixRewrite>sequential</c14n2:PrefixRewrite> 41167db96d56Sopenharmony_ci option.tag.split('}')[-1]: ((option.text or '').strip(), option) 41177db96d56Sopenharmony_ci for option in ET.parse(full_path(filename) + ".xml").getroot() 41187db96d56Sopenharmony_ci } 41197db96d56Sopenharmony_ci for filename in files 41207db96d56Sopenharmony_ci if filename.startswith('c14n') 41217db96d56Sopenharmony_ci } 41227db96d56Sopenharmony_ci 41237db96d56Sopenharmony_ci tests = { 41247db96d56Sopenharmony_ci input_file: [ 41257db96d56Sopenharmony_ci (filename, configs[filename.rsplit('_', 1)[-1]]) 41267db96d56Sopenharmony_ci for filename in files 41277db96d56Sopenharmony_ci if filename.startswith(f'out_{input_file}_') 41287db96d56Sopenharmony_ci and filename.rsplit('_', 1)[-1] in configs 41297db96d56Sopenharmony_ci ] 41307db96d56Sopenharmony_ci for input_file in input_files 41317db96d56Sopenharmony_ci } 41327db96d56Sopenharmony_ci 41337db96d56Sopenharmony_ci # Make sure we found all test cases. 41347db96d56Sopenharmony_ci self.assertEqual(30, len([ 41357db96d56Sopenharmony_ci output_file for output_files in tests.values() 41367db96d56Sopenharmony_ci for output_file in output_files])) 41377db96d56Sopenharmony_ci 41387db96d56Sopenharmony_ci def get_option(config, option_name, default=None): 41397db96d56Sopenharmony_ci return config.get(option_name, (default, ()))[0] 41407db96d56Sopenharmony_ci 41417db96d56Sopenharmony_ci for input_file, output_files in tests.items(): 41427db96d56Sopenharmony_ci for output_file, config in output_files: 41437db96d56Sopenharmony_ci keep_comments = get_option( 41447db96d56Sopenharmony_ci config, 'IgnoreComments') == 'true' # no, it's right :) 41457db96d56Sopenharmony_ci strip_text = get_option( 41467db96d56Sopenharmony_ci config, 'TrimTextNodes') == 'true' 41477db96d56Sopenharmony_ci rewrite_prefixes = get_option( 41487db96d56Sopenharmony_ci config, 'PrefixRewrite') == 'sequential' 41497db96d56Sopenharmony_ci if 'QNameAware' in config: 41507db96d56Sopenharmony_ci qattrs = [ 41517db96d56Sopenharmony_ci f"{{{el.get('NS')}}}{el.get('Name')}" 41527db96d56Sopenharmony_ci for el in config['QNameAware'][1].findall( 41537db96d56Sopenharmony_ci '{http://www.w3.org/2010/xml-c14n2}QualifiedAttr') 41547db96d56Sopenharmony_ci ] 41557db96d56Sopenharmony_ci qtags = [ 41567db96d56Sopenharmony_ci f"{{{el.get('NS')}}}{el.get('Name')}" 41577db96d56Sopenharmony_ci for el in config['QNameAware'][1].findall( 41587db96d56Sopenharmony_ci '{http://www.w3.org/2010/xml-c14n2}Element') 41597db96d56Sopenharmony_ci ] 41607db96d56Sopenharmony_ci else: 41617db96d56Sopenharmony_ci qtags = qattrs = None 41627db96d56Sopenharmony_ci 41637db96d56Sopenharmony_ci # Build subtest description from config. 41647db96d56Sopenharmony_ci config_descr = ','.join( 41657db96d56Sopenharmony_ci f"{name}={value or ','.join(c.tag.split('}')[-1] for c in children)}" 41667db96d56Sopenharmony_ci for name, (value, children) in sorted(config.items()) 41677db96d56Sopenharmony_ci ) 41687db96d56Sopenharmony_ci 41697db96d56Sopenharmony_ci with self.subTest(f"{output_file}({config_descr})"): 41707db96d56Sopenharmony_ci if input_file == 'inNsRedecl' and not rewrite_prefixes: 41717db96d56Sopenharmony_ci self.skipTest( 41727db96d56Sopenharmony_ci f"Redeclared namespace handling is not supported in {output_file}") 41737db96d56Sopenharmony_ci if input_file == 'inNsSuperfluous' and not rewrite_prefixes: 41747db96d56Sopenharmony_ci self.skipTest( 41757db96d56Sopenharmony_ci f"Redeclared namespace handling is not supported in {output_file}") 41767db96d56Sopenharmony_ci if 'QNameAware' in config and config['QNameAware'][1].find( 41777db96d56Sopenharmony_ci '{http://www.w3.org/2010/xml-c14n2}XPathElement') is not None: 41787db96d56Sopenharmony_ci self.skipTest( 41797db96d56Sopenharmony_ci f"QName rewriting in XPath text is not supported in {output_file}") 41807db96d56Sopenharmony_ci 41817db96d56Sopenharmony_ci f = full_path(input_file + ".xml") 41827db96d56Sopenharmony_ci if input_file == 'inC14N5': 41837db96d56Sopenharmony_ci # Hack: avoid setting up external entity resolution in the parser. 41847db96d56Sopenharmony_ci with open(full_path('world.txt'), 'rb') as entity_file: 41857db96d56Sopenharmony_ci with open(f, 'rb') as f: 41867db96d56Sopenharmony_ci f = io.BytesIO(f.read().replace(b'&ent2;', entity_file.read())) 41877db96d56Sopenharmony_ci 41887db96d56Sopenharmony_ci text = ET.canonicalize( 41897db96d56Sopenharmony_ci from_file=f, 41907db96d56Sopenharmony_ci with_comments=keep_comments, 41917db96d56Sopenharmony_ci strip_text=strip_text, 41927db96d56Sopenharmony_ci rewrite_prefixes=rewrite_prefixes, 41937db96d56Sopenharmony_ci qname_aware_tags=qtags, qname_aware_attrs=qattrs) 41947db96d56Sopenharmony_ci 41957db96d56Sopenharmony_ci with open(full_path(output_file + ".xml"), 'r', encoding='utf8') as f: 41967db96d56Sopenharmony_ci expected = f.read() 41977db96d56Sopenharmony_ci if input_file == 'inC14N3': 41987db96d56Sopenharmony_ci # FIXME: cET resolves default attributes but ET does not! 41997db96d56Sopenharmony_ci expected = expected.replace(' attr="default"', '') 42007db96d56Sopenharmony_ci text = text.replace(' attr="default"', '') 42017db96d56Sopenharmony_ci self.assertEqual(expected, text) 42027db96d56Sopenharmony_ci 42037db96d56Sopenharmony_ci# -------------------------------------------------------------------- 42047db96d56Sopenharmony_ci 42057db96d56Sopenharmony_ci 42067db96d56Sopenharmony_cidef test_main(module=None): 42077db96d56Sopenharmony_ci # When invoked without a module, runs the Python ET tests by loading pyET. 42087db96d56Sopenharmony_ci # Otherwise, uses the given module as the ET. 42097db96d56Sopenharmony_ci global pyET 42107db96d56Sopenharmony_ci pyET = import_fresh_module('xml.etree.ElementTree', 42117db96d56Sopenharmony_ci blocked=['_elementtree']) 42127db96d56Sopenharmony_ci if module is None: 42137db96d56Sopenharmony_ci module = pyET 42147db96d56Sopenharmony_ci 42157db96d56Sopenharmony_ci global ET 42167db96d56Sopenharmony_ci ET = module 42177db96d56Sopenharmony_ci 42187db96d56Sopenharmony_ci test_classes = [ 42197db96d56Sopenharmony_ci ModuleTest, 42207db96d56Sopenharmony_ci ElementSlicingTest, 42217db96d56Sopenharmony_ci BasicElementTest, 42227db96d56Sopenharmony_ci BadElementTest, 42237db96d56Sopenharmony_ci BadElementPathTest, 42247db96d56Sopenharmony_ci ElementTreeTest, 42257db96d56Sopenharmony_ci IOTest, 42267db96d56Sopenharmony_ci ParseErrorTest, 42277db96d56Sopenharmony_ci XIncludeTest, 42287db96d56Sopenharmony_ci ElementTreeTypeTest, 42297db96d56Sopenharmony_ci ElementFindTest, 42307db96d56Sopenharmony_ci ElementIterTest, 42317db96d56Sopenharmony_ci TreeBuilderTest, 42327db96d56Sopenharmony_ci XMLParserTest, 42337db96d56Sopenharmony_ci XMLPullParserTest, 42347db96d56Sopenharmony_ci BugsTest, 42357db96d56Sopenharmony_ci KeywordArgsTest, 42367db96d56Sopenharmony_ci C14NTest, 42377db96d56Sopenharmony_ci ] 42387db96d56Sopenharmony_ci 42397db96d56Sopenharmony_ci # These tests will only run for the pure-Python version that doesn't import 42407db96d56Sopenharmony_ci # _elementtree. We can't use skipUnless here, because pyET is filled in only 42417db96d56Sopenharmony_ci # after the module is loaded. 42427db96d56Sopenharmony_ci if pyET is not ET: 42437db96d56Sopenharmony_ci test_classes.extend([ 42447db96d56Sopenharmony_ci NoAcceleratorTest, 42457db96d56Sopenharmony_ci ]) 42467db96d56Sopenharmony_ci 42477db96d56Sopenharmony_ci # Provide default namespace mapping and path cache. 42487db96d56Sopenharmony_ci from xml.etree import ElementPath 42497db96d56Sopenharmony_ci nsmap = ET.register_namespace._namespace_map 42507db96d56Sopenharmony_ci # Copy the default namespace mapping 42517db96d56Sopenharmony_ci nsmap_copy = nsmap.copy() 42527db96d56Sopenharmony_ci # Copy the path cache (should be empty) 42537db96d56Sopenharmony_ci path_cache = ElementPath._cache 42547db96d56Sopenharmony_ci ElementPath._cache = path_cache.copy() 42557db96d56Sopenharmony_ci # Align the Comment/PI factories. 42567db96d56Sopenharmony_ci if hasattr(ET, '_set_factories'): 42577db96d56Sopenharmony_ci old_factories = ET._set_factories(ET.Comment, ET.PI) 42587db96d56Sopenharmony_ci else: 42597db96d56Sopenharmony_ci old_factories = None 42607db96d56Sopenharmony_ci 42617db96d56Sopenharmony_ci try: 42627db96d56Sopenharmony_ci support.run_unittest(*test_classes) 42637db96d56Sopenharmony_ci finally: 42647db96d56Sopenharmony_ci from xml.etree import ElementPath 42657db96d56Sopenharmony_ci # Restore mapping and path cache 42667db96d56Sopenharmony_ci nsmap.clear() 42677db96d56Sopenharmony_ci nsmap.update(nsmap_copy) 42687db96d56Sopenharmony_ci ElementPath._cache = path_cache 42697db96d56Sopenharmony_ci if old_factories is not None: 42707db96d56Sopenharmony_ci ET._set_factories(*old_factories) 42717db96d56Sopenharmony_ci # don't interfere with subsequent tests 42727db96d56Sopenharmony_ci ET = pyET = None 42737db96d56Sopenharmony_ci 42747db96d56Sopenharmony_ci 42757db96d56Sopenharmony_ciif __name__ == '__main__': 42767db96d56Sopenharmony_ci test_main() 4277