17db96d56Sopenharmony_ci# regression test for SAX 2.0 27db96d56Sopenharmony_ci# $Id$ 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_cifrom xml.sax import make_parser, ContentHandler, \ 57db96d56Sopenharmony_ci SAXException, SAXReaderNotAvailable, SAXParseException 67db96d56Sopenharmony_ciimport unittest 77db96d56Sopenharmony_cifrom unittest import mock 87db96d56Sopenharmony_citry: 97db96d56Sopenharmony_ci make_parser() 107db96d56Sopenharmony_ciexcept SAXReaderNotAvailable: 117db96d56Sopenharmony_ci # don't try to test this module if we cannot create a parser 127db96d56Sopenharmony_ci raise unittest.SkipTest("no XML parsers available") 137db96d56Sopenharmony_cifrom xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \ 147db96d56Sopenharmony_ci XMLFilterBase, prepare_input_source 157db96d56Sopenharmony_cifrom xml.sax.expatreader import create_parser 167db96d56Sopenharmony_cifrom xml.sax.handler import (feature_namespaces, feature_external_ges, 177db96d56Sopenharmony_ci LexicalHandler) 187db96d56Sopenharmony_cifrom xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl 197db96d56Sopenharmony_cifrom io import BytesIO, StringIO 207db96d56Sopenharmony_ciimport codecs 217db96d56Sopenharmony_ciimport os.path 227db96d56Sopenharmony_ciimport shutil 237db96d56Sopenharmony_ciimport sys 247db96d56Sopenharmony_cifrom urllib.error import URLError 257db96d56Sopenharmony_ciimport urllib.request 267db96d56Sopenharmony_cifrom test.support import os_helper 277db96d56Sopenharmony_cifrom test.support import findfile 287db96d56Sopenharmony_cifrom test.support.os_helper import FakePath, TESTFN 297db96d56Sopenharmony_ci 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ciTEST_XMLFILE = findfile("test.xml", subdir="xmltestdata") 327db96d56Sopenharmony_ciTEST_XMLFILE_OUT = findfile("test.xml.out", subdir="xmltestdata") 337db96d56Sopenharmony_citry: 347db96d56Sopenharmony_ci TEST_XMLFILE.encode("utf-8") 357db96d56Sopenharmony_ci TEST_XMLFILE_OUT.encode("utf-8") 367db96d56Sopenharmony_ciexcept UnicodeEncodeError: 377db96d56Sopenharmony_ci raise unittest.SkipTest("filename is not encodable to utf8") 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_cisupports_nonascii_filenames = True 407db96d56Sopenharmony_ciif not os.path.supports_unicode_filenames: 417db96d56Sopenharmony_ci try: 427db96d56Sopenharmony_ci os_helper.TESTFN_UNICODE.encode(sys.getfilesystemencoding()) 437db96d56Sopenharmony_ci except (UnicodeError, TypeError): 447db96d56Sopenharmony_ci # Either the file system encoding is None, or the file name 457db96d56Sopenharmony_ci # cannot be encoded in the file system encoding. 467db96d56Sopenharmony_ci supports_nonascii_filenames = False 477db96d56Sopenharmony_cirequires_nonascii_filenames = unittest.skipUnless( 487db96d56Sopenharmony_ci supports_nonascii_filenames, 497db96d56Sopenharmony_ci 'Requires non-ascii filenames support') 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_cins_uri = "http://www.python.org/xml-ns/saxtest/" 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ciclass XmlTestBase(unittest.TestCase): 547db96d56Sopenharmony_ci def verify_empty_attrs(self, attrs): 557db96d56Sopenharmony_ci self.assertRaises(KeyError, attrs.getValue, "attr") 567db96d56Sopenharmony_ci self.assertRaises(KeyError, attrs.getValueByQName, "attr") 577db96d56Sopenharmony_ci self.assertRaises(KeyError, attrs.getNameByQName, "attr") 587db96d56Sopenharmony_ci self.assertRaises(KeyError, attrs.getQNameByName, "attr") 597db96d56Sopenharmony_ci self.assertRaises(KeyError, attrs.__getitem__, "attr") 607db96d56Sopenharmony_ci self.assertEqual(attrs.getLength(), 0) 617db96d56Sopenharmony_ci self.assertEqual(attrs.getNames(), []) 627db96d56Sopenharmony_ci self.assertEqual(attrs.getQNames(), []) 637db96d56Sopenharmony_ci self.assertEqual(len(attrs), 0) 647db96d56Sopenharmony_ci self.assertNotIn("attr", attrs) 657db96d56Sopenharmony_ci self.assertEqual(list(attrs.keys()), []) 667db96d56Sopenharmony_ci self.assertEqual(attrs.get("attrs"), None) 677db96d56Sopenharmony_ci self.assertEqual(attrs.get("attrs", 25), 25) 687db96d56Sopenharmony_ci self.assertEqual(list(attrs.items()), []) 697db96d56Sopenharmony_ci self.assertEqual(list(attrs.values()), []) 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci def verify_empty_nsattrs(self, attrs): 727db96d56Sopenharmony_ci self.assertRaises(KeyError, attrs.getValue, (ns_uri, "attr")) 737db96d56Sopenharmony_ci self.assertRaises(KeyError, attrs.getValueByQName, "ns:attr") 747db96d56Sopenharmony_ci self.assertRaises(KeyError, attrs.getNameByQName, "ns:attr") 757db96d56Sopenharmony_ci self.assertRaises(KeyError, attrs.getQNameByName, (ns_uri, "attr")) 767db96d56Sopenharmony_ci self.assertRaises(KeyError, attrs.__getitem__, (ns_uri, "attr")) 777db96d56Sopenharmony_ci self.assertEqual(attrs.getLength(), 0) 787db96d56Sopenharmony_ci self.assertEqual(attrs.getNames(), []) 797db96d56Sopenharmony_ci self.assertEqual(attrs.getQNames(), []) 807db96d56Sopenharmony_ci self.assertEqual(len(attrs), 0) 817db96d56Sopenharmony_ci self.assertNotIn((ns_uri, "attr"), attrs) 827db96d56Sopenharmony_ci self.assertEqual(list(attrs.keys()), []) 837db96d56Sopenharmony_ci self.assertEqual(attrs.get((ns_uri, "attr")), None) 847db96d56Sopenharmony_ci self.assertEqual(attrs.get((ns_uri, "attr"), 25), 25) 857db96d56Sopenharmony_ci self.assertEqual(list(attrs.items()), []) 867db96d56Sopenharmony_ci self.assertEqual(list(attrs.values()), []) 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_ci def verify_attrs_wattr(self, attrs): 897db96d56Sopenharmony_ci self.assertEqual(attrs.getLength(), 1) 907db96d56Sopenharmony_ci self.assertEqual(attrs.getNames(), ["attr"]) 917db96d56Sopenharmony_ci self.assertEqual(attrs.getQNames(), ["attr"]) 927db96d56Sopenharmony_ci self.assertEqual(len(attrs), 1) 937db96d56Sopenharmony_ci self.assertIn("attr", attrs) 947db96d56Sopenharmony_ci self.assertEqual(list(attrs.keys()), ["attr"]) 957db96d56Sopenharmony_ci self.assertEqual(attrs.get("attr"), "val") 967db96d56Sopenharmony_ci self.assertEqual(attrs.get("attr", 25), "val") 977db96d56Sopenharmony_ci self.assertEqual(list(attrs.items()), [("attr", "val")]) 987db96d56Sopenharmony_ci self.assertEqual(list(attrs.values()), ["val"]) 997db96d56Sopenharmony_ci self.assertEqual(attrs.getValue("attr"), "val") 1007db96d56Sopenharmony_ci self.assertEqual(attrs.getValueByQName("attr"), "val") 1017db96d56Sopenharmony_ci self.assertEqual(attrs.getNameByQName("attr"), "attr") 1027db96d56Sopenharmony_ci self.assertEqual(attrs["attr"], "val") 1037db96d56Sopenharmony_ci self.assertEqual(attrs.getQNameByName("attr"), "attr") 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_cidef xml_str(doc, encoding=None): 1077db96d56Sopenharmony_ci if encoding is None: 1087db96d56Sopenharmony_ci return doc 1097db96d56Sopenharmony_ci return '<?xml version="1.0" encoding="%s"?>\n%s' % (encoding, doc) 1107db96d56Sopenharmony_ci 1117db96d56Sopenharmony_cidef xml_bytes(doc, encoding, decl_encoding=...): 1127db96d56Sopenharmony_ci if decl_encoding is ...: 1137db96d56Sopenharmony_ci decl_encoding = encoding 1147db96d56Sopenharmony_ci return xml_str(doc, decl_encoding).encode(encoding, 'xmlcharrefreplace') 1157db96d56Sopenharmony_ci 1167db96d56Sopenharmony_cidef make_xml_file(doc, encoding, decl_encoding=...): 1177db96d56Sopenharmony_ci if decl_encoding is ...: 1187db96d56Sopenharmony_ci decl_encoding = encoding 1197db96d56Sopenharmony_ci with open(TESTFN, 'w', encoding=encoding, errors='xmlcharrefreplace') as f: 1207db96d56Sopenharmony_ci f.write(xml_str(doc, decl_encoding)) 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ciclass ParseTest(unittest.TestCase): 1247db96d56Sopenharmony_ci data = '<money value="$\xa3\u20ac\U0001017b">$\xa3\u20ac\U0001017b</money>' 1257db96d56Sopenharmony_ci 1267db96d56Sopenharmony_ci def tearDown(self): 1277db96d56Sopenharmony_ci os_helper.unlink(TESTFN) 1287db96d56Sopenharmony_ci 1297db96d56Sopenharmony_ci def check_parse(self, f): 1307db96d56Sopenharmony_ci from xml.sax import parse 1317db96d56Sopenharmony_ci result = StringIO() 1327db96d56Sopenharmony_ci parse(f, XMLGenerator(result, 'utf-8')) 1337db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_str(self.data, 'utf-8')) 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci def test_parse_text(self): 1367db96d56Sopenharmony_ci encodings = ('us-ascii', 'iso-8859-1', 'utf-8', 1377db96d56Sopenharmony_ci 'utf-16', 'utf-16le', 'utf-16be') 1387db96d56Sopenharmony_ci for encoding in encodings: 1397db96d56Sopenharmony_ci self.check_parse(StringIO(xml_str(self.data, encoding))) 1407db96d56Sopenharmony_ci make_xml_file(self.data, encoding) 1417db96d56Sopenharmony_ci with open(TESTFN, 'r', encoding=encoding) as f: 1427db96d56Sopenharmony_ci self.check_parse(f) 1437db96d56Sopenharmony_ci self.check_parse(StringIO(self.data)) 1447db96d56Sopenharmony_ci make_xml_file(self.data, encoding, None) 1457db96d56Sopenharmony_ci with open(TESTFN, 'r', encoding=encoding) as f: 1467db96d56Sopenharmony_ci self.check_parse(f) 1477db96d56Sopenharmony_ci 1487db96d56Sopenharmony_ci def test_parse_bytes(self): 1497db96d56Sopenharmony_ci # UTF-8 is default encoding, US-ASCII is compatible with UTF-8, 1507db96d56Sopenharmony_ci # UTF-16 is autodetected 1517db96d56Sopenharmony_ci encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be') 1527db96d56Sopenharmony_ci for encoding in encodings: 1537db96d56Sopenharmony_ci self.check_parse(BytesIO(xml_bytes(self.data, encoding))) 1547db96d56Sopenharmony_ci make_xml_file(self.data, encoding) 1557db96d56Sopenharmony_ci self.check_parse(TESTFN) 1567db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 1577db96d56Sopenharmony_ci self.check_parse(f) 1587db96d56Sopenharmony_ci self.check_parse(BytesIO(xml_bytes(self.data, encoding, None))) 1597db96d56Sopenharmony_ci make_xml_file(self.data, encoding, None) 1607db96d56Sopenharmony_ci self.check_parse(TESTFN) 1617db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 1627db96d56Sopenharmony_ci self.check_parse(f) 1637db96d56Sopenharmony_ci # accept UTF-8 with BOM 1647db96d56Sopenharmony_ci self.check_parse(BytesIO(xml_bytes(self.data, 'utf-8-sig', 'utf-8'))) 1657db96d56Sopenharmony_ci make_xml_file(self.data, 'utf-8-sig', 'utf-8') 1667db96d56Sopenharmony_ci self.check_parse(TESTFN) 1677db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 1687db96d56Sopenharmony_ci self.check_parse(f) 1697db96d56Sopenharmony_ci self.check_parse(BytesIO(xml_bytes(self.data, 'utf-8-sig', None))) 1707db96d56Sopenharmony_ci make_xml_file(self.data, 'utf-8-sig', None) 1717db96d56Sopenharmony_ci self.check_parse(TESTFN) 1727db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 1737db96d56Sopenharmony_ci self.check_parse(f) 1747db96d56Sopenharmony_ci # accept data with declared encoding 1757db96d56Sopenharmony_ci self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1'))) 1767db96d56Sopenharmony_ci make_xml_file(self.data, 'iso-8859-1') 1777db96d56Sopenharmony_ci self.check_parse(TESTFN) 1787db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 1797db96d56Sopenharmony_ci self.check_parse(f) 1807db96d56Sopenharmony_ci # fail on non-UTF-8 incompatible data without declared encoding 1817db96d56Sopenharmony_ci with self.assertRaises(SAXException): 1827db96d56Sopenharmony_ci self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1', None))) 1837db96d56Sopenharmony_ci make_xml_file(self.data, 'iso-8859-1', None) 1847db96d56Sopenharmony_ci with self.assertRaises(SAXException): 1857db96d56Sopenharmony_ci self.check_parse(TESTFN) 1867db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 1877db96d56Sopenharmony_ci with self.assertRaises(SAXException): 1887db96d56Sopenharmony_ci self.check_parse(f) 1897db96d56Sopenharmony_ci 1907db96d56Sopenharmony_ci def test_parse_path_object(self): 1917db96d56Sopenharmony_ci make_xml_file(self.data, 'utf-8', None) 1927db96d56Sopenharmony_ci self.check_parse(FakePath(TESTFN)) 1937db96d56Sopenharmony_ci 1947db96d56Sopenharmony_ci def test_parse_InputSource(self): 1957db96d56Sopenharmony_ci # accept data without declared but with explicitly specified encoding 1967db96d56Sopenharmony_ci make_xml_file(self.data, 'iso-8859-1', None) 1977db96d56Sopenharmony_ci with open(TESTFN, 'rb') as f: 1987db96d56Sopenharmony_ci input = InputSource() 1997db96d56Sopenharmony_ci input.setByteStream(f) 2007db96d56Sopenharmony_ci input.setEncoding('iso-8859-1') 2017db96d56Sopenharmony_ci self.check_parse(input) 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci def test_parse_close_source(self): 2047db96d56Sopenharmony_ci builtin_open = open 2057db96d56Sopenharmony_ci fileobj = None 2067db96d56Sopenharmony_ci 2077db96d56Sopenharmony_ci def mock_open(*args): 2087db96d56Sopenharmony_ci nonlocal fileobj 2097db96d56Sopenharmony_ci fileobj = builtin_open(*args) 2107db96d56Sopenharmony_ci return fileobj 2117db96d56Sopenharmony_ci 2127db96d56Sopenharmony_ci with mock.patch('xml.sax.saxutils.open', side_effect=mock_open): 2137db96d56Sopenharmony_ci make_xml_file(self.data, 'iso-8859-1', None) 2147db96d56Sopenharmony_ci with self.assertRaises(SAXException): 2157db96d56Sopenharmony_ci self.check_parse(TESTFN) 2167db96d56Sopenharmony_ci self.assertTrue(fileobj.closed) 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci def check_parseString(self, s): 2197db96d56Sopenharmony_ci from xml.sax import parseString 2207db96d56Sopenharmony_ci result = StringIO() 2217db96d56Sopenharmony_ci parseString(s, XMLGenerator(result, 'utf-8')) 2227db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_str(self.data, 'utf-8')) 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_ci def test_parseString_text(self): 2257db96d56Sopenharmony_ci encodings = ('us-ascii', 'iso-8859-1', 'utf-8', 2267db96d56Sopenharmony_ci 'utf-16', 'utf-16le', 'utf-16be') 2277db96d56Sopenharmony_ci for encoding in encodings: 2287db96d56Sopenharmony_ci self.check_parseString(xml_str(self.data, encoding)) 2297db96d56Sopenharmony_ci self.check_parseString(self.data) 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_ci def test_parseString_bytes(self): 2327db96d56Sopenharmony_ci # UTF-8 is default encoding, US-ASCII is compatible with UTF-8, 2337db96d56Sopenharmony_ci # UTF-16 is autodetected 2347db96d56Sopenharmony_ci encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be') 2357db96d56Sopenharmony_ci for encoding in encodings: 2367db96d56Sopenharmony_ci self.check_parseString(xml_bytes(self.data, encoding)) 2377db96d56Sopenharmony_ci self.check_parseString(xml_bytes(self.data, encoding, None)) 2387db96d56Sopenharmony_ci # accept UTF-8 with BOM 2397db96d56Sopenharmony_ci self.check_parseString(xml_bytes(self.data, 'utf-8-sig', 'utf-8')) 2407db96d56Sopenharmony_ci self.check_parseString(xml_bytes(self.data, 'utf-8-sig', None)) 2417db96d56Sopenharmony_ci # accept data with declared encoding 2427db96d56Sopenharmony_ci self.check_parseString(xml_bytes(self.data, 'iso-8859-1')) 2437db96d56Sopenharmony_ci # fail on non-UTF-8 incompatible data without declared encoding 2447db96d56Sopenharmony_ci with self.assertRaises(SAXException): 2457db96d56Sopenharmony_ci self.check_parseString(xml_bytes(self.data, 'iso-8859-1', None)) 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ciclass MakeParserTest(unittest.TestCase): 2487db96d56Sopenharmony_ci def test_make_parser2(self): 2497db96d56Sopenharmony_ci # Creating parsers several times in a row should succeed. 2507db96d56Sopenharmony_ci # Testing this because there have been failures of this kind 2517db96d56Sopenharmony_ci # before. 2527db96d56Sopenharmony_ci from xml.sax import make_parser 2537db96d56Sopenharmony_ci p = make_parser() 2547db96d56Sopenharmony_ci from xml.sax import make_parser 2557db96d56Sopenharmony_ci p = make_parser() 2567db96d56Sopenharmony_ci from xml.sax import make_parser 2577db96d56Sopenharmony_ci p = make_parser() 2587db96d56Sopenharmony_ci from xml.sax import make_parser 2597db96d56Sopenharmony_ci p = make_parser() 2607db96d56Sopenharmony_ci from xml.sax import make_parser 2617db96d56Sopenharmony_ci p = make_parser() 2627db96d56Sopenharmony_ci from xml.sax import make_parser 2637db96d56Sopenharmony_ci p = make_parser() 2647db96d56Sopenharmony_ci 2657db96d56Sopenharmony_ci def test_make_parser3(self): 2667db96d56Sopenharmony_ci # Testing that make_parser can handle different types of 2677db96d56Sopenharmony_ci # iterables. 2687db96d56Sopenharmony_ci make_parser(['module']) 2697db96d56Sopenharmony_ci make_parser(('module', )) 2707db96d56Sopenharmony_ci make_parser({'module'}) 2717db96d56Sopenharmony_ci make_parser(frozenset({'module'})) 2727db96d56Sopenharmony_ci make_parser({'module': None}) 2737db96d56Sopenharmony_ci make_parser(iter(['module'])) 2747db96d56Sopenharmony_ci 2757db96d56Sopenharmony_ci def test_make_parser4(self): 2767db96d56Sopenharmony_ci # Testing that make_parser can handle empty iterables. 2777db96d56Sopenharmony_ci make_parser([]) 2787db96d56Sopenharmony_ci make_parser(tuple()) 2797db96d56Sopenharmony_ci make_parser(set()) 2807db96d56Sopenharmony_ci make_parser(frozenset()) 2817db96d56Sopenharmony_ci make_parser({}) 2827db96d56Sopenharmony_ci make_parser(iter([])) 2837db96d56Sopenharmony_ci 2847db96d56Sopenharmony_ci def test_make_parser5(self): 2857db96d56Sopenharmony_ci # Testing that make_parser can handle iterables with more than 2867db96d56Sopenharmony_ci # one item. 2877db96d56Sopenharmony_ci make_parser(['module1', 'module2']) 2887db96d56Sopenharmony_ci make_parser(('module1', 'module2')) 2897db96d56Sopenharmony_ci make_parser({'module1', 'module2'}) 2907db96d56Sopenharmony_ci make_parser(frozenset({'module1', 'module2'})) 2917db96d56Sopenharmony_ci make_parser({'module1': None, 'module2': None}) 2927db96d56Sopenharmony_ci make_parser(iter(['module1', 'module2'])) 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ci# =========================================================================== 2957db96d56Sopenharmony_ci# 2967db96d56Sopenharmony_ci# saxutils tests 2977db96d56Sopenharmony_ci# 2987db96d56Sopenharmony_ci# =========================================================================== 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ciclass SaxutilsTest(unittest.TestCase): 3017db96d56Sopenharmony_ci # ===== escape 3027db96d56Sopenharmony_ci def test_escape_basic(self): 3037db96d56Sopenharmony_ci self.assertEqual(escape("Donald Duck & Co"), "Donald Duck & Co") 3047db96d56Sopenharmony_ci 3057db96d56Sopenharmony_ci def test_escape_all(self): 3067db96d56Sopenharmony_ci self.assertEqual(escape("<Donald Duck & Co>"), 3077db96d56Sopenharmony_ci "<Donald Duck & Co>") 3087db96d56Sopenharmony_ci 3097db96d56Sopenharmony_ci def test_escape_extra(self): 3107db96d56Sopenharmony_ci self.assertEqual(escape("Hei på deg", {"å" : "å"}), 3117db96d56Sopenharmony_ci "Hei på deg") 3127db96d56Sopenharmony_ci 3137db96d56Sopenharmony_ci # ===== unescape 3147db96d56Sopenharmony_ci def test_unescape_basic(self): 3157db96d56Sopenharmony_ci self.assertEqual(unescape("Donald Duck & Co"), "Donald Duck & Co") 3167db96d56Sopenharmony_ci 3177db96d56Sopenharmony_ci def test_unescape_all(self): 3187db96d56Sopenharmony_ci self.assertEqual(unescape("<Donald Duck & Co>"), 3197db96d56Sopenharmony_ci "<Donald Duck & Co>") 3207db96d56Sopenharmony_ci 3217db96d56Sopenharmony_ci def test_unescape_extra(self): 3227db96d56Sopenharmony_ci self.assertEqual(unescape("Hei på deg", {"å" : "å"}), 3237db96d56Sopenharmony_ci "Hei på deg") 3247db96d56Sopenharmony_ci 3257db96d56Sopenharmony_ci def test_unescape_amp_extra(self): 3267db96d56Sopenharmony_ci self.assertEqual(unescape("&foo;", {"&foo;": "splat"}), "&foo;") 3277db96d56Sopenharmony_ci 3287db96d56Sopenharmony_ci # ===== quoteattr 3297db96d56Sopenharmony_ci def test_quoteattr_basic(self): 3307db96d56Sopenharmony_ci self.assertEqual(quoteattr("Donald Duck & Co"), 3317db96d56Sopenharmony_ci '"Donald Duck & Co"') 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_ci def test_single_quoteattr(self): 3347db96d56Sopenharmony_ci self.assertEqual(quoteattr('Includes "double" quotes'), 3357db96d56Sopenharmony_ci '\'Includes "double" quotes\'') 3367db96d56Sopenharmony_ci 3377db96d56Sopenharmony_ci def test_double_quoteattr(self): 3387db96d56Sopenharmony_ci self.assertEqual(quoteattr("Includes 'single' quotes"), 3397db96d56Sopenharmony_ci "\"Includes 'single' quotes\"") 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci def test_single_double_quoteattr(self): 3427db96d56Sopenharmony_ci self.assertEqual(quoteattr("Includes 'single' and \"double\" quotes"), 3437db96d56Sopenharmony_ci "\"Includes 'single' and "double" quotes\"") 3447db96d56Sopenharmony_ci 3457db96d56Sopenharmony_ci # ===== make_parser 3467db96d56Sopenharmony_ci def test_make_parser(self): 3477db96d56Sopenharmony_ci # Creating a parser should succeed - it should fall back 3487db96d56Sopenharmony_ci # to the expatreader 3497db96d56Sopenharmony_ci p = make_parser(['xml.parsers.no_such_parser']) 3507db96d56Sopenharmony_ci 3517db96d56Sopenharmony_ci 3527db96d56Sopenharmony_ciclass PrepareInputSourceTest(unittest.TestCase): 3537db96d56Sopenharmony_ci 3547db96d56Sopenharmony_ci def setUp(self): 3557db96d56Sopenharmony_ci self.file = os_helper.TESTFN 3567db96d56Sopenharmony_ci with open(self.file, "w") as tmp: 3577db96d56Sopenharmony_ci tmp.write("This was read from a file.") 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci def tearDown(self): 3607db96d56Sopenharmony_ci os_helper.unlink(self.file) 3617db96d56Sopenharmony_ci 3627db96d56Sopenharmony_ci def make_byte_stream(self): 3637db96d56Sopenharmony_ci return BytesIO(b"This is a byte stream.") 3647db96d56Sopenharmony_ci 3657db96d56Sopenharmony_ci def make_character_stream(self): 3667db96d56Sopenharmony_ci return StringIO("This is a character stream.") 3677db96d56Sopenharmony_ci 3687db96d56Sopenharmony_ci def checkContent(self, stream, content): 3697db96d56Sopenharmony_ci self.assertIsNotNone(stream) 3707db96d56Sopenharmony_ci self.assertEqual(stream.read(), content) 3717db96d56Sopenharmony_ci stream.close() 3727db96d56Sopenharmony_ci 3737db96d56Sopenharmony_ci 3747db96d56Sopenharmony_ci def test_character_stream(self): 3757db96d56Sopenharmony_ci # If the source is an InputSource with a character stream, use it. 3767db96d56Sopenharmony_ci src = InputSource(self.file) 3777db96d56Sopenharmony_ci src.setCharacterStream(self.make_character_stream()) 3787db96d56Sopenharmony_ci prep = prepare_input_source(src) 3797db96d56Sopenharmony_ci self.assertIsNone(prep.getByteStream()) 3807db96d56Sopenharmony_ci self.checkContent(prep.getCharacterStream(), 3817db96d56Sopenharmony_ci "This is a character stream.") 3827db96d56Sopenharmony_ci 3837db96d56Sopenharmony_ci def test_byte_stream(self): 3847db96d56Sopenharmony_ci # If the source is an InputSource that does not have a character 3857db96d56Sopenharmony_ci # stream but does have a byte stream, use the byte stream. 3867db96d56Sopenharmony_ci src = InputSource(self.file) 3877db96d56Sopenharmony_ci src.setByteStream(self.make_byte_stream()) 3887db96d56Sopenharmony_ci prep = prepare_input_source(src) 3897db96d56Sopenharmony_ci self.assertIsNone(prep.getCharacterStream()) 3907db96d56Sopenharmony_ci self.checkContent(prep.getByteStream(), 3917db96d56Sopenharmony_ci b"This is a byte stream.") 3927db96d56Sopenharmony_ci 3937db96d56Sopenharmony_ci def test_system_id(self): 3947db96d56Sopenharmony_ci # If the source is an InputSource that has neither a character 3957db96d56Sopenharmony_ci # stream nor a byte stream, open the system ID. 3967db96d56Sopenharmony_ci src = InputSource(self.file) 3977db96d56Sopenharmony_ci prep = prepare_input_source(src) 3987db96d56Sopenharmony_ci self.assertIsNone(prep.getCharacterStream()) 3997db96d56Sopenharmony_ci self.checkContent(prep.getByteStream(), 4007db96d56Sopenharmony_ci b"This was read from a file.") 4017db96d56Sopenharmony_ci 4027db96d56Sopenharmony_ci def test_string(self): 4037db96d56Sopenharmony_ci # If the source is a string, use it as a system ID and open it. 4047db96d56Sopenharmony_ci prep = prepare_input_source(self.file) 4057db96d56Sopenharmony_ci self.assertIsNone(prep.getCharacterStream()) 4067db96d56Sopenharmony_ci self.checkContent(prep.getByteStream(), 4077db96d56Sopenharmony_ci b"This was read from a file.") 4087db96d56Sopenharmony_ci 4097db96d56Sopenharmony_ci def test_path_objects(self): 4107db96d56Sopenharmony_ci # If the source is a Path object, use it as a system ID and open it. 4117db96d56Sopenharmony_ci prep = prepare_input_source(FakePath(self.file)) 4127db96d56Sopenharmony_ci self.assertIsNone(prep.getCharacterStream()) 4137db96d56Sopenharmony_ci self.checkContent(prep.getByteStream(), 4147db96d56Sopenharmony_ci b"This was read from a file.") 4157db96d56Sopenharmony_ci 4167db96d56Sopenharmony_ci def test_binary_file(self): 4177db96d56Sopenharmony_ci # If the source is a binary file-like object, use it as a byte 4187db96d56Sopenharmony_ci # stream. 4197db96d56Sopenharmony_ci prep = prepare_input_source(self.make_byte_stream()) 4207db96d56Sopenharmony_ci self.assertIsNone(prep.getCharacterStream()) 4217db96d56Sopenharmony_ci self.checkContent(prep.getByteStream(), 4227db96d56Sopenharmony_ci b"This is a byte stream.") 4237db96d56Sopenharmony_ci 4247db96d56Sopenharmony_ci def test_text_file(self): 4257db96d56Sopenharmony_ci # If the source is a text file-like object, use it as a character 4267db96d56Sopenharmony_ci # stream. 4277db96d56Sopenharmony_ci prep = prepare_input_source(self.make_character_stream()) 4287db96d56Sopenharmony_ci self.assertIsNone(prep.getByteStream()) 4297db96d56Sopenharmony_ci self.checkContent(prep.getCharacterStream(), 4307db96d56Sopenharmony_ci "This is a character stream.") 4317db96d56Sopenharmony_ci 4327db96d56Sopenharmony_ci 4337db96d56Sopenharmony_ci# ===== XMLGenerator 4347db96d56Sopenharmony_ci 4357db96d56Sopenharmony_ciclass XmlgenTest: 4367db96d56Sopenharmony_ci def test_xmlgen_basic(self): 4377db96d56Sopenharmony_ci result = self.ioclass() 4387db96d56Sopenharmony_ci gen = XMLGenerator(result) 4397db96d56Sopenharmony_ci gen.startDocument() 4407db96d56Sopenharmony_ci gen.startElement("doc", {}) 4417db96d56Sopenharmony_ci gen.endElement("doc") 4427db96d56Sopenharmony_ci gen.endDocument() 4437db96d56Sopenharmony_ci 4447db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml("<doc></doc>")) 4457db96d56Sopenharmony_ci 4467db96d56Sopenharmony_ci def test_xmlgen_basic_empty(self): 4477db96d56Sopenharmony_ci result = self.ioclass() 4487db96d56Sopenharmony_ci gen = XMLGenerator(result, short_empty_elements=True) 4497db96d56Sopenharmony_ci gen.startDocument() 4507db96d56Sopenharmony_ci gen.startElement("doc", {}) 4517db96d56Sopenharmony_ci gen.endElement("doc") 4527db96d56Sopenharmony_ci gen.endDocument() 4537db96d56Sopenharmony_ci 4547db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml("<doc/>")) 4557db96d56Sopenharmony_ci 4567db96d56Sopenharmony_ci def test_xmlgen_content(self): 4577db96d56Sopenharmony_ci result = self.ioclass() 4587db96d56Sopenharmony_ci gen = XMLGenerator(result) 4597db96d56Sopenharmony_ci 4607db96d56Sopenharmony_ci gen.startDocument() 4617db96d56Sopenharmony_ci gen.startElement("doc", {}) 4627db96d56Sopenharmony_ci gen.characters("huhei") 4637db96d56Sopenharmony_ci gen.endElement("doc") 4647db96d56Sopenharmony_ci gen.endDocument() 4657db96d56Sopenharmony_ci 4667db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml("<doc>huhei</doc>")) 4677db96d56Sopenharmony_ci 4687db96d56Sopenharmony_ci def test_xmlgen_content_empty(self): 4697db96d56Sopenharmony_ci result = self.ioclass() 4707db96d56Sopenharmony_ci gen = XMLGenerator(result, short_empty_elements=True) 4717db96d56Sopenharmony_ci 4727db96d56Sopenharmony_ci gen.startDocument() 4737db96d56Sopenharmony_ci gen.startElement("doc", {}) 4747db96d56Sopenharmony_ci gen.characters("huhei") 4757db96d56Sopenharmony_ci gen.endElement("doc") 4767db96d56Sopenharmony_ci gen.endDocument() 4777db96d56Sopenharmony_ci 4787db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml("<doc>huhei</doc>")) 4797db96d56Sopenharmony_ci 4807db96d56Sopenharmony_ci def test_xmlgen_pi(self): 4817db96d56Sopenharmony_ci result = self.ioclass() 4827db96d56Sopenharmony_ci gen = XMLGenerator(result) 4837db96d56Sopenharmony_ci 4847db96d56Sopenharmony_ci gen.startDocument() 4857db96d56Sopenharmony_ci gen.processingInstruction("test", "data") 4867db96d56Sopenharmony_ci gen.startElement("doc", {}) 4877db96d56Sopenharmony_ci gen.endElement("doc") 4887db96d56Sopenharmony_ci gen.endDocument() 4897db96d56Sopenharmony_ci 4907db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), 4917db96d56Sopenharmony_ci self.xml("<?test data?><doc></doc>")) 4927db96d56Sopenharmony_ci 4937db96d56Sopenharmony_ci def test_xmlgen_content_escape(self): 4947db96d56Sopenharmony_ci result = self.ioclass() 4957db96d56Sopenharmony_ci gen = XMLGenerator(result) 4967db96d56Sopenharmony_ci 4977db96d56Sopenharmony_ci gen.startDocument() 4987db96d56Sopenharmony_ci gen.startElement("doc", {}) 4997db96d56Sopenharmony_ci gen.characters("<huhei&") 5007db96d56Sopenharmony_ci gen.endElement("doc") 5017db96d56Sopenharmony_ci gen.endDocument() 5027db96d56Sopenharmony_ci 5037db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), 5047db96d56Sopenharmony_ci self.xml("<doc><huhei&</doc>")) 5057db96d56Sopenharmony_ci 5067db96d56Sopenharmony_ci def test_xmlgen_attr_escape(self): 5077db96d56Sopenharmony_ci result = self.ioclass() 5087db96d56Sopenharmony_ci gen = XMLGenerator(result) 5097db96d56Sopenharmony_ci 5107db96d56Sopenharmony_ci gen.startDocument() 5117db96d56Sopenharmony_ci gen.startElement("doc", {"a": '"'}) 5127db96d56Sopenharmony_ci gen.startElement("e", {"a": "'"}) 5137db96d56Sopenharmony_ci gen.endElement("e") 5147db96d56Sopenharmony_ci gen.startElement("e", {"a": "'\""}) 5157db96d56Sopenharmony_ci gen.endElement("e") 5167db96d56Sopenharmony_ci gen.startElement("e", {"a": "\n\r\t"}) 5177db96d56Sopenharmony_ci gen.endElement("e") 5187db96d56Sopenharmony_ci gen.endElement("doc") 5197db96d56Sopenharmony_ci gen.endDocument() 5207db96d56Sopenharmony_ci 5217db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml( 5227db96d56Sopenharmony_ci "<doc a='\"'><e a=\"'\"></e>" 5237db96d56Sopenharmony_ci "<e a=\"'"\"></e>" 5247db96d56Sopenharmony_ci "<e a=\" 	\"></e></doc>")) 5257db96d56Sopenharmony_ci 5267db96d56Sopenharmony_ci def test_xmlgen_encoding(self): 5277db96d56Sopenharmony_ci encodings = ('iso-8859-15', 'utf-8', 'utf-8-sig', 5287db96d56Sopenharmony_ci 'utf-16', 'utf-16be', 'utf-16le', 5297db96d56Sopenharmony_ci 'utf-32', 'utf-32be', 'utf-32le') 5307db96d56Sopenharmony_ci for encoding in encodings: 5317db96d56Sopenharmony_ci result = self.ioclass() 5327db96d56Sopenharmony_ci gen = XMLGenerator(result, encoding=encoding) 5337db96d56Sopenharmony_ci 5347db96d56Sopenharmony_ci gen.startDocument() 5357db96d56Sopenharmony_ci gen.startElement("doc", {"a": '\u20ac'}) 5367db96d56Sopenharmony_ci gen.characters("\u20ac") 5377db96d56Sopenharmony_ci gen.endElement("doc") 5387db96d56Sopenharmony_ci gen.endDocument() 5397db96d56Sopenharmony_ci 5407db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), 5417db96d56Sopenharmony_ci self.xml('<doc a="\u20ac">\u20ac</doc>', encoding=encoding)) 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_ci def test_xmlgen_unencodable(self): 5447db96d56Sopenharmony_ci result = self.ioclass() 5457db96d56Sopenharmony_ci gen = XMLGenerator(result, encoding='ascii') 5467db96d56Sopenharmony_ci 5477db96d56Sopenharmony_ci gen.startDocument() 5487db96d56Sopenharmony_ci gen.startElement("doc", {"a": '\u20ac'}) 5497db96d56Sopenharmony_ci gen.characters("\u20ac") 5507db96d56Sopenharmony_ci gen.endElement("doc") 5517db96d56Sopenharmony_ci gen.endDocument() 5527db96d56Sopenharmony_ci 5537db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), 5547db96d56Sopenharmony_ci self.xml('<doc a="€">€</doc>', encoding='ascii')) 5557db96d56Sopenharmony_ci 5567db96d56Sopenharmony_ci def test_xmlgen_ignorable(self): 5577db96d56Sopenharmony_ci result = self.ioclass() 5587db96d56Sopenharmony_ci gen = XMLGenerator(result) 5597db96d56Sopenharmony_ci 5607db96d56Sopenharmony_ci gen.startDocument() 5617db96d56Sopenharmony_ci gen.startElement("doc", {}) 5627db96d56Sopenharmony_ci gen.ignorableWhitespace(" ") 5637db96d56Sopenharmony_ci gen.endElement("doc") 5647db96d56Sopenharmony_ci gen.endDocument() 5657db96d56Sopenharmony_ci 5667db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml("<doc> </doc>")) 5677db96d56Sopenharmony_ci 5687db96d56Sopenharmony_ci def test_xmlgen_ignorable_empty(self): 5697db96d56Sopenharmony_ci result = self.ioclass() 5707db96d56Sopenharmony_ci gen = XMLGenerator(result, short_empty_elements=True) 5717db96d56Sopenharmony_ci 5727db96d56Sopenharmony_ci gen.startDocument() 5737db96d56Sopenharmony_ci gen.startElement("doc", {}) 5747db96d56Sopenharmony_ci gen.ignorableWhitespace(" ") 5757db96d56Sopenharmony_ci gen.endElement("doc") 5767db96d56Sopenharmony_ci gen.endDocument() 5777db96d56Sopenharmony_ci 5787db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml("<doc> </doc>")) 5797db96d56Sopenharmony_ci 5807db96d56Sopenharmony_ci def test_xmlgen_encoding_bytes(self): 5817db96d56Sopenharmony_ci encodings = ('iso-8859-15', 'utf-8', 'utf-8-sig', 5827db96d56Sopenharmony_ci 'utf-16', 'utf-16be', 'utf-16le', 5837db96d56Sopenharmony_ci 'utf-32', 'utf-32be', 'utf-32le') 5847db96d56Sopenharmony_ci for encoding in encodings: 5857db96d56Sopenharmony_ci result = self.ioclass() 5867db96d56Sopenharmony_ci gen = XMLGenerator(result, encoding=encoding) 5877db96d56Sopenharmony_ci 5887db96d56Sopenharmony_ci gen.startDocument() 5897db96d56Sopenharmony_ci gen.startElement("doc", {"a": '\u20ac'}) 5907db96d56Sopenharmony_ci gen.characters("\u20ac".encode(encoding)) 5917db96d56Sopenharmony_ci gen.ignorableWhitespace(" ".encode(encoding)) 5927db96d56Sopenharmony_ci gen.endElement("doc") 5937db96d56Sopenharmony_ci gen.endDocument() 5947db96d56Sopenharmony_ci 5957db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), 5967db96d56Sopenharmony_ci self.xml('<doc a="\u20ac">\u20ac </doc>', encoding=encoding)) 5977db96d56Sopenharmony_ci 5987db96d56Sopenharmony_ci def test_xmlgen_ns(self): 5997db96d56Sopenharmony_ci result = self.ioclass() 6007db96d56Sopenharmony_ci gen = XMLGenerator(result) 6017db96d56Sopenharmony_ci 6027db96d56Sopenharmony_ci gen.startDocument() 6037db96d56Sopenharmony_ci gen.startPrefixMapping("ns1", ns_uri) 6047db96d56Sopenharmony_ci gen.startElementNS((ns_uri, "doc"), "ns1:doc", {}) 6057db96d56Sopenharmony_ci # add an unqualified name 6067db96d56Sopenharmony_ci gen.startElementNS((None, "udoc"), None, {}) 6077db96d56Sopenharmony_ci gen.endElementNS((None, "udoc"), None) 6087db96d56Sopenharmony_ci gen.endElementNS((ns_uri, "doc"), "ns1:doc") 6097db96d56Sopenharmony_ci gen.endPrefixMapping("ns1") 6107db96d56Sopenharmony_ci gen.endDocument() 6117db96d56Sopenharmony_ci 6127db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml( 6137db96d56Sopenharmony_ci '<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' % 6147db96d56Sopenharmony_ci ns_uri)) 6157db96d56Sopenharmony_ci 6167db96d56Sopenharmony_ci def test_xmlgen_ns_empty(self): 6177db96d56Sopenharmony_ci result = self.ioclass() 6187db96d56Sopenharmony_ci gen = XMLGenerator(result, short_empty_elements=True) 6197db96d56Sopenharmony_ci 6207db96d56Sopenharmony_ci gen.startDocument() 6217db96d56Sopenharmony_ci gen.startPrefixMapping("ns1", ns_uri) 6227db96d56Sopenharmony_ci gen.startElementNS((ns_uri, "doc"), "ns1:doc", {}) 6237db96d56Sopenharmony_ci # add an unqualified name 6247db96d56Sopenharmony_ci gen.startElementNS((None, "udoc"), None, {}) 6257db96d56Sopenharmony_ci gen.endElementNS((None, "udoc"), None) 6267db96d56Sopenharmony_ci gen.endElementNS((ns_uri, "doc"), "ns1:doc") 6277db96d56Sopenharmony_ci gen.endPrefixMapping("ns1") 6287db96d56Sopenharmony_ci gen.endDocument() 6297db96d56Sopenharmony_ci 6307db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml( 6317db96d56Sopenharmony_ci '<ns1:doc xmlns:ns1="%s"><udoc/></ns1:doc>' % 6327db96d56Sopenharmony_ci ns_uri)) 6337db96d56Sopenharmony_ci 6347db96d56Sopenharmony_ci def test_1463026_1(self): 6357db96d56Sopenharmony_ci result = self.ioclass() 6367db96d56Sopenharmony_ci gen = XMLGenerator(result) 6377db96d56Sopenharmony_ci 6387db96d56Sopenharmony_ci gen.startDocument() 6397db96d56Sopenharmony_ci gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'}) 6407db96d56Sopenharmony_ci gen.endElementNS((None, 'a'), 'a') 6417db96d56Sopenharmony_ci gen.endDocument() 6427db96d56Sopenharmony_ci 6437db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml('<a b="c"></a>')) 6447db96d56Sopenharmony_ci 6457db96d56Sopenharmony_ci def test_1463026_1_empty(self): 6467db96d56Sopenharmony_ci result = self.ioclass() 6477db96d56Sopenharmony_ci gen = XMLGenerator(result, short_empty_elements=True) 6487db96d56Sopenharmony_ci 6497db96d56Sopenharmony_ci gen.startDocument() 6507db96d56Sopenharmony_ci gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'}) 6517db96d56Sopenharmony_ci gen.endElementNS((None, 'a'), 'a') 6527db96d56Sopenharmony_ci gen.endDocument() 6537db96d56Sopenharmony_ci 6547db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml('<a b="c"/>')) 6557db96d56Sopenharmony_ci 6567db96d56Sopenharmony_ci def test_1463026_2(self): 6577db96d56Sopenharmony_ci result = self.ioclass() 6587db96d56Sopenharmony_ci gen = XMLGenerator(result) 6597db96d56Sopenharmony_ci 6607db96d56Sopenharmony_ci gen.startDocument() 6617db96d56Sopenharmony_ci gen.startPrefixMapping(None, 'qux') 6627db96d56Sopenharmony_ci gen.startElementNS(('qux', 'a'), 'a', {}) 6637db96d56Sopenharmony_ci gen.endElementNS(('qux', 'a'), 'a') 6647db96d56Sopenharmony_ci gen.endPrefixMapping(None) 6657db96d56Sopenharmony_ci gen.endDocument() 6667db96d56Sopenharmony_ci 6677db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml('<a xmlns="qux"></a>')) 6687db96d56Sopenharmony_ci 6697db96d56Sopenharmony_ci def test_1463026_2_empty(self): 6707db96d56Sopenharmony_ci result = self.ioclass() 6717db96d56Sopenharmony_ci gen = XMLGenerator(result, short_empty_elements=True) 6727db96d56Sopenharmony_ci 6737db96d56Sopenharmony_ci gen.startDocument() 6747db96d56Sopenharmony_ci gen.startPrefixMapping(None, 'qux') 6757db96d56Sopenharmony_ci gen.startElementNS(('qux', 'a'), 'a', {}) 6767db96d56Sopenharmony_ci gen.endElementNS(('qux', 'a'), 'a') 6777db96d56Sopenharmony_ci gen.endPrefixMapping(None) 6787db96d56Sopenharmony_ci gen.endDocument() 6797db96d56Sopenharmony_ci 6807db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), self.xml('<a xmlns="qux"/>')) 6817db96d56Sopenharmony_ci 6827db96d56Sopenharmony_ci def test_1463026_3(self): 6837db96d56Sopenharmony_ci result = self.ioclass() 6847db96d56Sopenharmony_ci gen = XMLGenerator(result) 6857db96d56Sopenharmony_ci 6867db96d56Sopenharmony_ci gen.startDocument() 6877db96d56Sopenharmony_ci gen.startPrefixMapping('my', 'qux') 6887db96d56Sopenharmony_ci gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'}) 6897db96d56Sopenharmony_ci gen.endElementNS(('qux', 'a'), 'a') 6907db96d56Sopenharmony_ci gen.endPrefixMapping('my') 6917db96d56Sopenharmony_ci gen.endDocument() 6927db96d56Sopenharmony_ci 6937db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), 6947db96d56Sopenharmony_ci self.xml('<my:a xmlns:my="qux" b="c"></my:a>')) 6957db96d56Sopenharmony_ci 6967db96d56Sopenharmony_ci def test_1463026_3_empty(self): 6977db96d56Sopenharmony_ci result = self.ioclass() 6987db96d56Sopenharmony_ci gen = XMLGenerator(result, short_empty_elements=True) 6997db96d56Sopenharmony_ci 7007db96d56Sopenharmony_ci gen.startDocument() 7017db96d56Sopenharmony_ci gen.startPrefixMapping('my', 'qux') 7027db96d56Sopenharmony_ci gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'}) 7037db96d56Sopenharmony_ci gen.endElementNS(('qux', 'a'), 'a') 7047db96d56Sopenharmony_ci gen.endPrefixMapping('my') 7057db96d56Sopenharmony_ci gen.endDocument() 7067db96d56Sopenharmony_ci 7077db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), 7087db96d56Sopenharmony_ci self.xml('<my:a xmlns:my="qux" b="c"/>')) 7097db96d56Sopenharmony_ci 7107db96d56Sopenharmony_ci def test_5027_1(self): 7117db96d56Sopenharmony_ci # The xml prefix (as in xml:lang below) is reserved and bound by 7127db96d56Sopenharmony_ci # definition to http://www.w3.org/XML/1998/namespace. XMLGenerator had 7137db96d56Sopenharmony_ci # a bug whereby a KeyError is raised because this namespace is missing 7147db96d56Sopenharmony_ci # from a dictionary. 7157db96d56Sopenharmony_ci # 7167db96d56Sopenharmony_ci # This test demonstrates the bug by parsing a document. 7177db96d56Sopenharmony_ci test_xml = StringIO( 7187db96d56Sopenharmony_ci '<?xml version="1.0"?>' 7197db96d56Sopenharmony_ci '<a:g1 xmlns:a="http://example.com/ns">' 7207db96d56Sopenharmony_ci '<a:g2 xml:lang="en">Hello</a:g2>' 7217db96d56Sopenharmony_ci '</a:g1>') 7227db96d56Sopenharmony_ci 7237db96d56Sopenharmony_ci parser = make_parser() 7247db96d56Sopenharmony_ci parser.setFeature(feature_namespaces, True) 7257db96d56Sopenharmony_ci result = self.ioclass() 7267db96d56Sopenharmony_ci gen = XMLGenerator(result) 7277db96d56Sopenharmony_ci parser.setContentHandler(gen) 7287db96d56Sopenharmony_ci parser.parse(test_xml) 7297db96d56Sopenharmony_ci 7307db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), 7317db96d56Sopenharmony_ci self.xml( 7327db96d56Sopenharmony_ci '<a:g1 xmlns:a="http://example.com/ns">' 7337db96d56Sopenharmony_ci '<a:g2 xml:lang="en">Hello</a:g2>' 7347db96d56Sopenharmony_ci '</a:g1>')) 7357db96d56Sopenharmony_ci 7367db96d56Sopenharmony_ci def test_5027_2(self): 7377db96d56Sopenharmony_ci # The xml prefix (as in xml:lang below) is reserved and bound by 7387db96d56Sopenharmony_ci # definition to http://www.w3.org/XML/1998/namespace. XMLGenerator had 7397db96d56Sopenharmony_ci # a bug whereby a KeyError is raised because this namespace is missing 7407db96d56Sopenharmony_ci # from a dictionary. 7417db96d56Sopenharmony_ci # 7427db96d56Sopenharmony_ci # This test demonstrates the bug by direct manipulation of the 7437db96d56Sopenharmony_ci # XMLGenerator. 7447db96d56Sopenharmony_ci result = self.ioclass() 7457db96d56Sopenharmony_ci gen = XMLGenerator(result) 7467db96d56Sopenharmony_ci 7477db96d56Sopenharmony_ci gen.startDocument() 7487db96d56Sopenharmony_ci gen.startPrefixMapping('a', 'http://example.com/ns') 7497db96d56Sopenharmony_ci gen.startElementNS(('http://example.com/ns', 'g1'), 'g1', {}) 7507db96d56Sopenharmony_ci lang_attr = {('http://www.w3.org/XML/1998/namespace', 'lang'): 'en'} 7517db96d56Sopenharmony_ci gen.startElementNS(('http://example.com/ns', 'g2'), 'g2', lang_attr) 7527db96d56Sopenharmony_ci gen.characters('Hello') 7537db96d56Sopenharmony_ci gen.endElementNS(('http://example.com/ns', 'g2'), 'g2') 7547db96d56Sopenharmony_ci gen.endElementNS(('http://example.com/ns', 'g1'), 'g1') 7557db96d56Sopenharmony_ci gen.endPrefixMapping('a') 7567db96d56Sopenharmony_ci gen.endDocument() 7577db96d56Sopenharmony_ci 7587db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), 7597db96d56Sopenharmony_ci self.xml( 7607db96d56Sopenharmony_ci '<a:g1 xmlns:a="http://example.com/ns">' 7617db96d56Sopenharmony_ci '<a:g2 xml:lang="en">Hello</a:g2>' 7627db96d56Sopenharmony_ci '</a:g1>')) 7637db96d56Sopenharmony_ci 7647db96d56Sopenharmony_ci def test_no_close_file(self): 7657db96d56Sopenharmony_ci result = self.ioclass() 7667db96d56Sopenharmony_ci def func(out): 7677db96d56Sopenharmony_ci gen = XMLGenerator(out) 7687db96d56Sopenharmony_ci gen.startDocument() 7697db96d56Sopenharmony_ci gen.startElement("doc", {}) 7707db96d56Sopenharmony_ci func(result) 7717db96d56Sopenharmony_ci self.assertFalse(result.closed) 7727db96d56Sopenharmony_ci 7737db96d56Sopenharmony_ci def test_xmlgen_fragment(self): 7747db96d56Sopenharmony_ci result = self.ioclass() 7757db96d56Sopenharmony_ci gen = XMLGenerator(result) 7767db96d56Sopenharmony_ci 7777db96d56Sopenharmony_ci # Don't call gen.startDocument() 7787db96d56Sopenharmony_ci gen.startElement("foo", {"a": "1.0"}) 7797db96d56Sopenharmony_ci gen.characters("Hello") 7807db96d56Sopenharmony_ci gen.endElement("foo") 7817db96d56Sopenharmony_ci gen.startElement("bar", {"b": "2.0"}) 7827db96d56Sopenharmony_ci gen.endElement("bar") 7837db96d56Sopenharmony_ci # Don't call gen.endDocument() 7847db96d56Sopenharmony_ci 7857db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), 7867db96d56Sopenharmony_ci self.xml('<foo a="1.0">Hello</foo><bar b="2.0"></bar>')[len(self.xml('')):]) 7877db96d56Sopenharmony_ci 7887db96d56Sopenharmony_ciclass StringXmlgenTest(XmlgenTest, unittest.TestCase): 7897db96d56Sopenharmony_ci ioclass = StringIO 7907db96d56Sopenharmony_ci 7917db96d56Sopenharmony_ci def xml(self, doc, encoding='iso-8859-1'): 7927db96d56Sopenharmony_ci return '<?xml version="1.0" encoding="%s"?>\n%s' % (encoding, doc) 7937db96d56Sopenharmony_ci 7947db96d56Sopenharmony_ci test_xmlgen_unencodable = None 7957db96d56Sopenharmony_ci 7967db96d56Sopenharmony_ciclass BytesXmlgenTest(XmlgenTest, unittest.TestCase): 7977db96d56Sopenharmony_ci ioclass = BytesIO 7987db96d56Sopenharmony_ci 7997db96d56Sopenharmony_ci def xml(self, doc, encoding='iso-8859-1'): 8007db96d56Sopenharmony_ci return ('<?xml version="1.0" encoding="%s"?>\n%s' % 8017db96d56Sopenharmony_ci (encoding, doc)).encode(encoding, 'xmlcharrefreplace') 8027db96d56Sopenharmony_ci 8037db96d56Sopenharmony_ciclass WriterXmlgenTest(BytesXmlgenTest): 8047db96d56Sopenharmony_ci class ioclass(list): 8057db96d56Sopenharmony_ci write = list.append 8067db96d56Sopenharmony_ci closed = False 8077db96d56Sopenharmony_ci 8087db96d56Sopenharmony_ci def seekable(self): 8097db96d56Sopenharmony_ci return True 8107db96d56Sopenharmony_ci 8117db96d56Sopenharmony_ci def tell(self): 8127db96d56Sopenharmony_ci # return 0 at start and not 0 after start 8137db96d56Sopenharmony_ci return len(self) 8147db96d56Sopenharmony_ci 8157db96d56Sopenharmony_ci def getvalue(self): 8167db96d56Sopenharmony_ci return b''.join(self) 8177db96d56Sopenharmony_ci 8187db96d56Sopenharmony_ciclass StreamWriterXmlgenTest(XmlgenTest, unittest.TestCase): 8197db96d56Sopenharmony_ci def ioclass(self): 8207db96d56Sopenharmony_ci raw = BytesIO() 8217db96d56Sopenharmony_ci writer = codecs.getwriter('ascii')(raw, 'xmlcharrefreplace') 8227db96d56Sopenharmony_ci writer.getvalue = raw.getvalue 8237db96d56Sopenharmony_ci return writer 8247db96d56Sopenharmony_ci 8257db96d56Sopenharmony_ci def xml(self, doc, encoding='iso-8859-1'): 8267db96d56Sopenharmony_ci return ('<?xml version="1.0" encoding="%s"?>\n%s' % 8277db96d56Sopenharmony_ci (encoding, doc)).encode('ascii', 'xmlcharrefreplace') 8287db96d56Sopenharmony_ci 8297db96d56Sopenharmony_ciclass StreamReaderWriterXmlgenTest(XmlgenTest, unittest.TestCase): 8307db96d56Sopenharmony_ci fname = os_helper.TESTFN + '-codecs' 8317db96d56Sopenharmony_ci 8327db96d56Sopenharmony_ci def ioclass(self): 8337db96d56Sopenharmony_ci writer = codecs.open(self.fname, 'w', encoding='ascii', 8347db96d56Sopenharmony_ci errors='xmlcharrefreplace', buffering=0) 8357db96d56Sopenharmony_ci def cleanup(): 8367db96d56Sopenharmony_ci writer.close() 8377db96d56Sopenharmony_ci os_helper.unlink(self.fname) 8387db96d56Sopenharmony_ci self.addCleanup(cleanup) 8397db96d56Sopenharmony_ci def getvalue(): 8407db96d56Sopenharmony_ci # Windows will not let use reopen without first closing 8417db96d56Sopenharmony_ci writer.close() 8427db96d56Sopenharmony_ci with open(writer.name, 'rb') as f: 8437db96d56Sopenharmony_ci return f.read() 8447db96d56Sopenharmony_ci writer.getvalue = getvalue 8457db96d56Sopenharmony_ci return writer 8467db96d56Sopenharmony_ci 8477db96d56Sopenharmony_ci def xml(self, doc, encoding='iso-8859-1'): 8487db96d56Sopenharmony_ci return ('<?xml version="1.0" encoding="%s"?>\n%s' % 8497db96d56Sopenharmony_ci (encoding, doc)).encode('ascii', 'xmlcharrefreplace') 8507db96d56Sopenharmony_ci 8517db96d56Sopenharmony_cistart = b'<?xml version="1.0" encoding="iso-8859-1"?>\n' 8527db96d56Sopenharmony_ci 8537db96d56Sopenharmony_ci 8547db96d56Sopenharmony_ciclass XMLFilterBaseTest(unittest.TestCase): 8557db96d56Sopenharmony_ci def test_filter_basic(self): 8567db96d56Sopenharmony_ci result = BytesIO() 8577db96d56Sopenharmony_ci gen = XMLGenerator(result) 8587db96d56Sopenharmony_ci filter = XMLFilterBase() 8597db96d56Sopenharmony_ci filter.setContentHandler(gen) 8607db96d56Sopenharmony_ci 8617db96d56Sopenharmony_ci filter.startDocument() 8627db96d56Sopenharmony_ci filter.startElement("doc", {}) 8637db96d56Sopenharmony_ci filter.characters("content") 8647db96d56Sopenharmony_ci filter.ignorableWhitespace(" ") 8657db96d56Sopenharmony_ci filter.endElement("doc") 8667db96d56Sopenharmony_ci filter.endDocument() 8677db96d56Sopenharmony_ci 8687db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), start + b"<doc>content </doc>") 8697db96d56Sopenharmony_ci 8707db96d56Sopenharmony_ci# =========================================================================== 8717db96d56Sopenharmony_ci# 8727db96d56Sopenharmony_ci# expatreader tests 8737db96d56Sopenharmony_ci# 8747db96d56Sopenharmony_ci# =========================================================================== 8757db96d56Sopenharmony_ci 8767db96d56Sopenharmony_ciwith open(TEST_XMLFILE_OUT, 'rb') as f: 8777db96d56Sopenharmony_ci xml_test_out = f.read() 8787db96d56Sopenharmony_ci 8797db96d56Sopenharmony_ciclass ExpatReaderTest(XmlTestBase): 8807db96d56Sopenharmony_ci 8817db96d56Sopenharmony_ci # ===== XMLReader support 8827db96d56Sopenharmony_ci 8837db96d56Sopenharmony_ci def test_expat_binary_file(self): 8847db96d56Sopenharmony_ci parser = create_parser() 8857db96d56Sopenharmony_ci result = BytesIO() 8867db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 8877db96d56Sopenharmony_ci 8887db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 8897db96d56Sopenharmony_ci with open(TEST_XMLFILE, 'rb') as f: 8907db96d56Sopenharmony_ci parser.parse(f) 8917db96d56Sopenharmony_ci 8927db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_test_out) 8937db96d56Sopenharmony_ci 8947db96d56Sopenharmony_ci def test_expat_text_file(self): 8957db96d56Sopenharmony_ci parser = create_parser() 8967db96d56Sopenharmony_ci result = BytesIO() 8977db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 8987db96d56Sopenharmony_ci 8997db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 9007db96d56Sopenharmony_ci with open(TEST_XMLFILE, 'rt', encoding='iso-8859-1') as f: 9017db96d56Sopenharmony_ci parser.parse(f) 9027db96d56Sopenharmony_ci 9037db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_test_out) 9047db96d56Sopenharmony_ci 9057db96d56Sopenharmony_ci @requires_nonascii_filenames 9067db96d56Sopenharmony_ci def test_expat_binary_file_nonascii(self): 9077db96d56Sopenharmony_ci fname = os_helper.TESTFN_UNICODE 9087db96d56Sopenharmony_ci shutil.copyfile(TEST_XMLFILE, fname) 9097db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, fname) 9107db96d56Sopenharmony_ci 9117db96d56Sopenharmony_ci parser = create_parser() 9127db96d56Sopenharmony_ci result = BytesIO() 9137db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 9147db96d56Sopenharmony_ci 9157db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 9167db96d56Sopenharmony_ci parser.parse(open(fname, 'rb')) 9177db96d56Sopenharmony_ci 9187db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_test_out) 9197db96d56Sopenharmony_ci 9207db96d56Sopenharmony_ci def test_expat_binary_file_bytes_name(self): 9217db96d56Sopenharmony_ci fname = os.fsencode(TEST_XMLFILE) 9227db96d56Sopenharmony_ci parser = create_parser() 9237db96d56Sopenharmony_ci result = BytesIO() 9247db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 9257db96d56Sopenharmony_ci 9267db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 9277db96d56Sopenharmony_ci with open(fname, 'rb') as f: 9287db96d56Sopenharmony_ci parser.parse(f) 9297db96d56Sopenharmony_ci 9307db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_test_out) 9317db96d56Sopenharmony_ci 9327db96d56Sopenharmony_ci def test_expat_binary_file_int_name(self): 9337db96d56Sopenharmony_ci parser = create_parser() 9347db96d56Sopenharmony_ci result = BytesIO() 9357db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 9367db96d56Sopenharmony_ci 9377db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 9387db96d56Sopenharmony_ci with open(TEST_XMLFILE, 'rb') as f: 9397db96d56Sopenharmony_ci with open(f.fileno(), 'rb', closefd=False) as f2: 9407db96d56Sopenharmony_ci parser.parse(f2) 9417db96d56Sopenharmony_ci 9427db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_test_out) 9437db96d56Sopenharmony_ci 9447db96d56Sopenharmony_ci # ===== DTDHandler support 9457db96d56Sopenharmony_ci 9467db96d56Sopenharmony_ci class TestDTDHandler: 9477db96d56Sopenharmony_ci 9487db96d56Sopenharmony_ci def __init__(self): 9497db96d56Sopenharmony_ci self._notations = [] 9507db96d56Sopenharmony_ci self._entities = [] 9517db96d56Sopenharmony_ci 9527db96d56Sopenharmony_ci def notationDecl(self, name, publicId, systemId): 9537db96d56Sopenharmony_ci self._notations.append((name, publicId, systemId)) 9547db96d56Sopenharmony_ci 9557db96d56Sopenharmony_ci def unparsedEntityDecl(self, name, publicId, systemId, ndata): 9567db96d56Sopenharmony_ci self._entities.append((name, publicId, systemId, ndata)) 9577db96d56Sopenharmony_ci 9587db96d56Sopenharmony_ci 9597db96d56Sopenharmony_ci class TestEntityRecorder: 9607db96d56Sopenharmony_ci def __init__(self): 9617db96d56Sopenharmony_ci self.entities = [] 9627db96d56Sopenharmony_ci 9637db96d56Sopenharmony_ci def resolveEntity(self, publicId, systemId): 9647db96d56Sopenharmony_ci self.entities.append((publicId, systemId)) 9657db96d56Sopenharmony_ci source = InputSource() 9667db96d56Sopenharmony_ci source.setPublicId(publicId) 9677db96d56Sopenharmony_ci source.setSystemId(systemId) 9687db96d56Sopenharmony_ci return source 9697db96d56Sopenharmony_ci 9707db96d56Sopenharmony_ci def test_expat_dtdhandler(self): 9717db96d56Sopenharmony_ci parser = create_parser() 9727db96d56Sopenharmony_ci handler = self.TestDTDHandler() 9737db96d56Sopenharmony_ci parser.setDTDHandler(handler) 9747db96d56Sopenharmony_ci 9757db96d56Sopenharmony_ci parser.feed('<!DOCTYPE doc [\n') 9767db96d56Sopenharmony_ci parser.feed(' <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n') 9777db96d56Sopenharmony_ci parser.feed(' <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n') 9787db96d56Sopenharmony_ci parser.feed(']>\n') 9797db96d56Sopenharmony_ci parser.feed('<doc></doc>') 9807db96d56Sopenharmony_ci parser.close() 9817db96d56Sopenharmony_ci 9827db96d56Sopenharmony_ci self.assertEqual(handler._notations, 9837db96d56Sopenharmony_ci [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)]) 9847db96d56Sopenharmony_ci self.assertEqual(handler._entities, [("img", None, "expat.gif", "GIF")]) 9857db96d56Sopenharmony_ci 9867db96d56Sopenharmony_ci def test_expat_external_dtd_enabled(self): 9877db96d56Sopenharmony_ci # clear _opener global variable 9887db96d56Sopenharmony_ci self.addCleanup(urllib.request.urlcleanup) 9897db96d56Sopenharmony_ci 9907db96d56Sopenharmony_ci parser = create_parser() 9917db96d56Sopenharmony_ci parser.setFeature(feature_external_ges, True) 9927db96d56Sopenharmony_ci resolver = self.TestEntityRecorder() 9937db96d56Sopenharmony_ci parser.setEntityResolver(resolver) 9947db96d56Sopenharmony_ci 9957db96d56Sopenharmony_ci with self.assertRaises(URLError): 9967db96d56Sopenharmony_ci parser.feed( 9977db96d56Sopenharmony_ci '<!DOCTYPE external SYSTEM "unsupported://non-existing">\n' 9987db96d56Sopenharmony_ci ) 9997db96d56Sopenharmony_ci self.assertEqual( 10007db96d56Sopenharmony_ci resolver.entities, [(None, 'unsupported://non-existing')] 10017db96d56Sopenharmony_ci ) 10027db96d56Sopenharmony_ci 10037db96d56Sopenharmony_ci def test_expat_external_dtd_default(self): 10047db96d56Sopenharmony_ci parser = create_parser() 10057db96d56Sopenharmony_ci resolver = self.TestEntityRecorder() 10067db96d56Sopenharmony_ci parser.setEntityResolver(resolver) 10077db96d56Sopenharmony_ci 10087db96d56Sopenharmony_ci parser.feed( 10097db96d56Sopenharmony_ci '<!DOCTYPE external SYSTEM "unsupported://non-existing">\n' 10107db96d56Sopenharmony_ci ) 10117db96d56Sopenharmony_ci parser.feed('<doc />') 10127db96d56Sopenharmony_ci parser.close() 10137db96d56Sopenharmony_ci self.assertEqual(resolver.entities, []) 10147db96d56Sopenharmony_ci 10157db96d56Sopenharmony_ci # ===== EntityResolver support 10167db96d56Sopenharmony_ci 10177db96d56Sopenharmony_ci class TestEntityResolver: 10187db96d56Sopenharmony_ci 10197db96d56Sopenharmony_ci def resolveEntity(self, publicId, systemId): 10207db96d56Sopenharmony_ci inpsrc = InputSource() 10217db96d56Sopenharmony_ci inpsrc.setByteStream(BytesIO(b"<entity/>")) 10227db96d56Sopenharmony_ci return inpsrc 10237db96d56Sopenharmony_ci 10247db96d56Sopenharmony_ci def test_expat_entityresolver_enabled(self): 10257db96d56Sopenharmony_ci parser = create_parser() 10267db96d56Sopenharmony_ci parser.setFeature(feature_external_ges, True) 10277db96d56Sopenharmony_ci parser.setEntityResolver(self.TestEntityResolver()) 10287db96d56Sopenharmony_ci result = BytesIO() 10297db96d56Sopenharmony_ci parser.setContentHandler(XMLGenerator(result)) 10307db96d56Sopenharmony_ci 10317db96d56Sopenharmony_ci parser.feed('<!DOCTYPE doc [\n') 10327db96d56Sopenharmony_ci parser.feed(' <!ENTITY test SYSTEM "whatever">\n') 10337db96d56Sopenharmony_ci parser.feed(']>\n') 10347db96d56Sopenharmony_ci parser.feed('<doc>&test;</doc>') 10357db96d56Sopenharmony_ci parser.close() 10367db96d56Sopenharmony_ci 10377db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), start + 10387db96d56Sopenharmony_ci b"<doc><entity></entity></doc>") 10397db96d56Sopenharmony_ci 10407db96d56Sopenharmony_ci def test_expat_entityresolver_default(self): 10417db96d56Sopenharmony_ci parser = create_parser() 10427db96d56Sopenharmony_ci self.assertEqual(parser.getFeature(feature_external_ges), False) 10437db96d56Sopenharmony_ci parser.setEntityResolver(self.TestEntityResolver()) 10447db96d56Sopenharmony_ci result = BytesIO() 10457db96d56Sopenharmony_ci parser.setContentHandler(XMLGenerator(result)) 10467db96d56Sopenharmony_ci 10477db96d56Sopenharmony_ci parser.feed('<!DOCTYPE doc [\n') 10487db96d56Sopenharmony_ci parser.feed(' <!ENTITY test SYSTEM "whatever">\n') 10497db96d56Sopenharmony_ci parser.feed(']>\n') 10507db96d56Sopenharmony_ci parser.feed('<doc>&test;</doc>') 10517db96d56Sopenharmony_ci parser.close() 10527db96d56Sopenharmony_ci 10537db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), start + 10547db96d56Sopenharmony_ci b"<doc></doc>") 10557db96d56Sopenharmony_ci 10567db96d56Sopenharmony_ci # ===== Attributes support 10577db96d56Sopenharmony_ci 10587db96d56Sopenharmony_ci class AttrGatherer(ContentHandler): 10597db96d56Sopenharmony_ci 10607db96d56Sopenharmony_ci def startElement(self, name, attrs): 10617db96d56Sopenharmony_ci self._attrs = attrs 10627db96d56Sopenharmony_ci 10637db96d56Sopenharmony_ci def startElementNS(self, name, qname, attrs): 10647db96d56Sopenharmony_ci self._attrs = attrs 10657db96d56Sopenharmony_ci 10667db96d56Sopenharmony_ci def test_expat_attrs_empty(self): 10677db96d56Sopenharmony_ci parser = create_parser() 10687db96d56Sopenharmony_ci gather = self.AttrGatherer() 10697db96d56Sopenharmony_ci parser.setContentHandler(gather) 10707db96d56Sopenharmony_ci 10717db96d56Sopenharmony_ci parser.feed("<doc/>") 10727db96d56Sopenharmony_ci parser.close() 10737db96d56Sopenharmony_ci 10747db96d56Sopenharmony_ci self.verify_empty_attrs(gather._attrs) 10757db96d56Sopenharmony_ci 10767db96d56Sopenharmony_ci def test_expat_attrs_wattr(self): 10777db96d56Sopenharmony_ci parser = create_parser() 10787db96d56Sopenharmony_ci gather = self.AttrGatherer() 10797db96d56Sopenharmony_ci parser.setContentHandler(gather) 10807db96d56Sopenharmony_ci 10817db96d56Sopenharmony_ci parser.feed("<doc attr='val'/>") 10827db96d56Sopenharmony_ci parser.close() 10837db96d56Sopenharmony_ci 10847db96d56Sopenharmony_ci self.verify_attrs_wattr(gather._attrs) 10857db96d56Sopenharmony_ci 10867db96d56Sopenharmony_ci def test_expat_nsattrs_empty(self): 10877db96d56Sopenharmony_ci parser = create_parser(1) 10887db96d56Sopenharmony_ci gather = self.AttrGatherer() 10897db96d56Sopenharmony_ci parser.setContentHandler(gather) 10907db96d56Sopenharmony_ci 10917db96d56Sopenharmony_ci parser.feed("<doc/>") 10927db96d56Sopenharmony_ci parser.close() 10937db96d56Sopenharmony_ci 10947db96d56Sopenharmony_ci self.verify_empty_nsattrs(gather._attrs) 10957db96d56Sopenharmony_ci 10967db96d56Sopenharmony_ci def test_expat_nsattrs_wattr(self): 10977db96d56Sopenharmony_ci parser = create_parser(1) 10987db96d56Sopenharmony_ci gather = self.AttrGatherer() 10997db96d56Sopenharmony_ci parser.setContentHandler(gather) 11007db96d56Sopenharmony_ci 11017db96d56Sopenharmony_ci parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri) 11027db96d56Sopenharmony_ci parser.close() 11037db96d56Sopenharmony_ci 11047db96d56Sopenharmony_ci attrs = gather._attrs 11057db96d56Sopenharmony_ci 11067db96d56Sopenharmony_ci self.assertEqual(attrs.getLength(), 1) 11077db96d56Sopenharmony_ci self.assertEqual(attrs.getNames(), [(ns_uri, "attr")]) 11087db96d56Sopenharmony_ci self.assertTrue((attrs.getQNames() == [] or 11097db96d56Sopenharmony_ci attrs.getQNames() == ["ns:attr"])) 11107db96d56Sopenharmony_ci self.assertEqual(len(attrs), 1) 11117db96d56Sopenharmony_ci self.assertIn((ns_uri, "attr"), attrs) 11127db96d56Sopenharmony_ci self.assertEqual(attrs.get((ns_uri, "attr")), "val") 11137db96d56Sopenharmony_ci self.assertEqual(attrs.get((ns_uri, "attr"), 25), "val") 11147db96d56Sopenharmony_ci self.assertEqual(list(attrs.items()), [((ns_uri, "attr"), "val")]) 11157db96d56Sopenharmony_ci self.assertEqual(list(attrs.values()), ["val"]) 11167db96d56Sopenharmony_ci self.assertEqual(attrs.getValue((ns_uri, "attr")), "val") 11177db96d56Sopenharmony_ci self.assertEqual(attrs[(ns_uri, "attr")], "val") 11187db96d56Sopenharmony_ci 11197db96d56Sopenharmony_ci # ===== InputSource support 11207db96d56Sopenharmony_ci 11217db96d56Sopenharmony_ci def test_expat_inpsource_filename(self): 11227db96d56Sopenharmony_ci parser = create_parser() 11237db96d56Sopenharmony_ci result = BytesIO() 11247db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 11257db96d56Sopenharmony_ci 11267db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 11277db96d56Sopenharmony_ci parser.parse(TEST_XMLFILE) 11287db96d56Sopenharmony_ci 11297db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_test_out) 11307db96d56Sopenharmony_ci 11317db96d56Sopenharmony_ci def test_expat_inpsource_sysid(self): 11327db96d56Sopenharmony_ci parser = create_parser() 11337db96d56Sopenharmony_ci result = BytesIO() 11347db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 11357db96d56Sopenharmony_ci 11367db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 11377db96d56Sopenharmony_ci parser.parse(InputSource(TEST_XMLFILE)) 11387db96d56Sopenharmony_ci 11397db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_test_out) 11407db96d56Sopenharmony_ci 11417db96d56Sopenharmony_ci @requires_nonascii_filenames 11427db96d56Sopenharmony_ci def test_expat_inpsource_sysid_nonascii(self): 11437db96d56Sopenharmony_ci fname = os_helper.TESTFN_UNICODE 11447db96d56Sopenharmony_ci shutil.copyfile(TEST_XMLFILE, fname) 11457db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, fname) 11467db96d56Sopenharmony_ci 11477db96d56Sopenharmony_ci parser = create_parser() 11487db96d56Sopenharmony_ci result = BytesIO() 11497db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 11507db96d56Sopenharmony_ci 11517db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 11527db96d56Sopenharmony_ci parser.parse(InputSource(fname)) 11537db96d56Sopenharmony_ci 11547db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_test_out) 11557db96d56Sopenharmony_ci 11567db96d56Sopenharmony_ci def test_expat_inpsource_byte_stream(self): 11577db96d56Sopenharmony_ci parser = create_parser() 11587db96d56Sopenharmony_ci result = BytesIO() 11597db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 11607db96d56Sopenharmony_ci 11617db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 11627db96d56Sopenharmony_ci inpsrc = InputSource() 11637db96d56Sopenharmony_ci with open(TEST_XMLFILE, 'rb') as f: 11647db96d56Sopenharmony_ci inpsrc.setByteStream(f) 11657db96d56Sopenharmony_ci parser.parse(inpsrc) 11667db96d56Sopenharmony_ci 11677db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_test_out) 11687db96d56Sopenharmony_ci 11697db96d56Sopenharmony_ci def test_expat_inpsource_character_stream(self): 11707db96d56Sopenharmony_ci parser = create_parser() 11717db96d56Sopenharmony_ci result = BytesIO() 11727db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 11737db96d56Sopenharmony_ci 11747db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 11757db96d56Sopenharmony_ci inpsrc = InputSource() 11767db96d56Sopenharmony_ci with open(TEST_XMLFILE, 'rt', encoding='iso-8859-1') as f: 11777db96d56Sopenharmony_ci inpsrc.setCharacterStream(f) 11787db96d56Sopenharmony_ci parser.parse(inpsrc) 11797db96d56Sopenharmony_ci 11807db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), xml_test_out) 11817db96d56Sopenharmony_ci 11827db96d56Sopenharmony_ci # ===== IncrementalParser support 11837db96d56Sopenharmony_ci 11847db96d56Sopenharmony_ci def test_expat_incremental(self): 11857db96d56Sopenharmony_ci result = BytesIO() 11867db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 11877db96d56Sopenharmony_ci parser = create_parser() 11887db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 11897db96d56Sopenharmony_ci 11907db96d56Sopenharmony_ci parser.feed("<doc>") 11917db96d56Sopenharmony_ci parser.feed("</doc>") 11927db96d56Sopenharmony_ci parser.close() 11937db96d56Sopenharmony_ci 11947db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), start + b"<doc></doc>") 11957db96d56Sopenharmony_ci 11967db96d56Sopenharmony_ci def test_expat_incremental_reset(self): 11977db96d56Sopenharmony_ci result = BytesIO() 11987db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 11997db96d56Sopenharmony_ci parser = create_parser() 12007db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 12017db96d56Sopenharmony_ci 12027db96d56Sopenharmony_ci parser.feed("<doc>") 12037db96d56Sopenharmony_ci parser.feed("text") 12047db96d56Sopenharmony_ci 12057db96d56Sopenharmony_ci result = BytesIO() 12067db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 12077db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 12087db96d56Sopenharmony_ci parser.reset() 12097db96d56Sopenharmony_ci 12107db96d56Sopenharmony_ci parser.feed("<doc>") 12117db96d56Sopenharmony_ci parser.feed("text") 12127db96d56Sopenharmony_ci parser.feed("</doc>") 12137db96d56Sopenharmony_ci parser.close() 12147db96d56Sopenharmony_ci 12157db96d56Sopenharmony_ci self.assertEqual(result.getvalue(), start + b"<doc>text</doc>") 12167db96d56Sopenharmony_ci 12177db96d56Sopenharmony_ci # ===== Locator support 12187db96d56Sopenharmony_ci 12197db96d56Sopenharmony_ci def test_expat_locator_noinfo(self): 12207db96d56Sopenharmony_ci result = BytesIO() 12217db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 12227db96d56Sopenharmony_ci parser = create_parser() 12237db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 12247db96d56Sopenharmony_ci 12257db96d56Sopenharmony_ci parser.feed("<doc>") 12267db96d56Sopenharmony_ci parser.feed("</doc>") 12277db96d56Sopenharmony_ci parser.close() 12287db96d56Sopenharmony_ci 12297db96d56Sopenharmony_ci self.assertEqual(parser.getSystemId(), None) 12307db96d56Sopenharmony_ci self.assertEqual(parser.getPublicId(), None) 12317db96d56Sopenharmony_ci self.assertEqual(parser.getLineNumber(), 1) 12327db96d56Sopenharmony_ci 12337db96d56Sopenharmony_ci def test_expat_locator_withinfo(self): 12347db96d56Sopenharmony_ci result = BytesIO() 12357db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 12367db96d56Sopenharmony_ci parser = create_parser() 12377db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 12387db96d56Sopenharmony_ci parser.parse(TEST_XMLFILE) 12397db96d56Sopenharmony_ci 12407db96d56Sopenharmony_ci self.assertEqual(parser.getSystemId(), TEST_XMLFILE) 12417db96d56Sopenharmony_ci self.assertEqual(parser.getPublicId(), None) 12427db96d56Sopenharmony_ci 12437db96d56Sopenharmony_ci @requires_nonascii_filenames 12447db96d56Sopenharmony_ci def test_expat_locator_withinfo_nonascii(self): 12457db96d56Sopenharmony_ci fname = os_helper.TESTFN_UNICODE 12467db96d56Sopenharmony_ci shutil.copyfile(TEST_XMLFILE, fname) 12477db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, fname) 12487db96d56Sopenharmony_ci 12497db96d56Sopenharmony_ci result = BytesIO() 12507db96d56Sopenharmony_ci xmlgen = XMLGenerator(result) 12517db96d56Sopenharmony_ci parser = create_parser() 12527db96d56Sopenharmony_ci parser.setContentHandler(xmlgen) 12537db96d56Sopenharmony_ci parser.parse(fname) 12547db96d56Sopenharmony_ci 12557db96d56Sopenharmony_ci self.assertEqual(parser.getSystemId(), fname) 12567db96d56Sopenharmony_ci self.assertEqual(parser.getPublicId(), None) 12577db96d56Sopenharmony_ci 12587db96d56Sopenharmony_ci 12597db96d56Sopenharmony_ci# =========================================================================== 12607db96d56Sopenharmony_ci# 12617db96d56Sopenharmony_ci# error reporting 12627db96d56Sopenharmony_ci# 12637db96d56Sopenharmony_ci# =========================================================================== 12647db96d56Sopenharmony_ci 12657db96d56Sopenharmony_ciclass ErrorReportingTest(unittest.TestCase): 12667db96d56Sopenharmony_ci def test_expat_inpsource_location(self): 12677db96d56Sopenharmony_ci parser = create_parser() 12687db96d56Sopenharmony_ci parser.setContentHandler(ContentHandler()) # do nothing 12697db96d56Sopenharmony_ci source = InputSource() 12707db96d56Sopenharmony_ci source.setByteStream(BytesIO(b"<foo bar foobar>")) #ill-formed 12717db96d56Sopenharmony_ci name = "a file name" 12727db96d56Sopenharmony_ci source.setSystemId(name) 12737db96d56Sopenharmony_ci try: 12747db96d56Sopenharmony_ci parser.parse(source) 12757db96d56Sopenharmony_ci self.fail() 12767db96d56Sopenharmony_ci except SAXException as e: 12777db96d56Sopenharmony_ci self.assertEqual(e.getSystemId(), name) 12787db96d56Sopenharmony_ci 12797db96d56Sopenharmony_ci def test_expat_incomplete(self): 12807db96d56Sopenharmony_ci parser = create_parser() 12817db96d56Sopenharmony_ci parser.setContentHandler(ContentHandler()) # do nothing 12827db96d56Sopenharmony_ci self.assertRaises(SAXParseException, parser.parse, StringIO("<foo>")) 12837db96d56Sopenharmony_ci self.assertEqual(parser.getColumnNumber(), 5) 12847db96d56Sopenharmony_ci self.assertEqual(parser.getLineNumber(), 1) 12857db96d56Sopenharmony_ci 12867db96d56Sopenharmony_ci def test_sax_parse_exception_str(self): 12877db96d56Sopenharmony_ci # pass various values from a locator to the SAXParseException to 12887db96d56Sopenharmony_ci # make sure that the __str__() doesn't fall apart when None is 12897db96d56Sopenharmony_ci # passed instead of an integer line and column number 12907db96d56Sopenharmony_ci # 12917db96d56Sopenharmony_ci # use "normal" values for the locator: 12927db96d56Sopenharmony_ci str(SAXParseException("message", None, 12937db96d56Sopenharmony_ci self.DummyLocator(1, 1))) 12947db96d56Sopenharmony_ci # use None for the line number: 12957db96d56Sopenharmony_ci str(SAXParseException("message", None, 12967db96d56Sopenharmony_ci self.DummyLocator(None, 1))) 12977db96d56Sopenharmony_ci # use None for the column number: 12987db96d56Sopenharmony_ci str(SAXParseException("message", None, 12997db96d56Sopenharmony_ci self.DummyLocator(1, None))) 13007db96d56Sopenharmony_ci # use None for both: 13017db96d56Sopenharmony_ci str(SAXParseException("message", None, 13027db96d56Sopenharmony_ci self.DummyLocator(None, None))) 13037db96d56Sopenharmony_ci 13047db96d56Sopenharmony_ci class DummyLocator: 13057db96d56Sopenharmony_ci def __init__(self, lineno, colno): 13067db96d56Sopenharmony_ci self._lineno = lineno 13077db96d56Sopenharmony_ci self._colno = colno 13087db96d56Sopenharmony_ci 13097db96d56Sopenharmony_ci def getPublicId(self): 13107db96d56Sopenharmony_ci return "pubid" 13117db96d56Sopenharmony_ci 13127db96d56Sopenharmony_ci def getSystemId(self): 13137db96d56Sopenharmony_ci return "sysid" 13147db96d56Sopenharmony_ci 13157db96d56Sopenharmony_ci def getLineNumber(self): 13167db96d56Sopenharmony_ci return self._lineno 13177db96d56Sopenharmony_ci 13187db96d56Sopenharmony_ci def getColumnNumber(self): 13197db96d56Sopenharmony_ci return self._colno 13207db96d56Sopenharmony_ci 13217db96d56Sopenharmony_ci# =========================================================================== 13227db96d56Sopenharmony_ci# 13237db96d56Sopenharmony_ci# xmlreader tests 13247db96d56Sopenharmony_ci# 13257db96d56Sopenharmony_ci# =========================================================================== 13267db96d56Sopenharmony_ci 13277db96d56Sopenharmony_ciclass XmlReaderTest(XmlTestBase): 13287db96d56Sopenharmony_ci 13297db96d56Sopenharmony_ci # ===== AttributesImpl 13307db96d56Sopenharmony_ci def test_attrs_empty(self): 13317db96d56Sopenharmony_ci self.verify_empty_attrs(AttributesImpl({})) 13327db96d56Sopenharmony_ci 13337db96d56Sopenharmony_ci def test_attrs_wattr(self): 13347db96d56Sopenharmony_ci self.verify_attrs_wattr(AttributesImpl({"attr" : "val"})) 13357db96d56Sopenharmony_ci 13367db96d56Sopenharmony_ci def test_nsattrs_empty(self): 13377db96d56Sopenharmony_ci self.verify_empty_nsattrs(AttributesNSImpl({}, {})) 13387db96d56Sopenharmony_ci 13397db96d56Sopenharmony_ci def test_nsattrs_wattr(self): 13407db96d56Sopenharmony_ci attrs = AttributesNSImpl({(ns_uri, "attr") : "val"}, 13417db96d56Sopenharmony_ci {(ns_uri, "attr") : "ns:attr"}) 13427db96d56Sopenharmony_ci 13437db96d56Sopenharmony_ci self.assertEqual(attrs.getLength(), 1) 13447db96d56Sopenharmony_ci self.assertEqual(attrs.getNames(), [(ns_uri, "attr")]) 13457db96d56Sopenharmony_ci self.assertEqual(attrs.getQNames(), ["ns:attr"]) 13467db96d56Sopenharmony_ci self.assertEqual(len(attrs), 1) 13477db96d56Sopenharmony_ci self.assertIn((ns_uri, "attr"), attrs) 13487db96d56Sopenharmony_ci self.assertEqual(list(attrs.keys()), [(ns_uri, "attr")]) 13497db96d56Sopenharmony_ci self.assertEqual(attrs.get((ns_uri, "attr")), "val") 13507db96d56Sopenharmony_ci self.assertEqual(attrs.get((ns_uri, "attr"), 25), "val") 13517db96d56Sopenharmony_ci self.assertEqual(list(attrs.items()), [((ns_uri, "attr"), "val")]) 13527db96d56Sopenharmony_ci self.assertEqual(list(attrs.values()), ["val"]) 13537db96d56Sopenharmony_ci self.assertEqual(attrs.getValue((ns_uri, "attr")), "val") 13547db96d56Sopenharmony_ci self.assertEqual(attrs.getValueByQName("ns:attr"), "val") 13557db96d56Sopenharmony_ci self.assertEqual(attrs.getNameByQName("ns:attr"), (ns_uri, "attr")) 13567db96d56Sopenharmony_ci self.assertEqual(attrs[(ns_uri, "attr")], "val") 13577db96d56Sopenharmony_ci self.assertEqual(attrs.getQNameByName((ns_uri, "attr")), "ns:attr") 13587db96d56Sopenharmony_ci 13597db96d56Sopenharmony_ci 13607db96d56Sopenharmony_ciclass LexicalHandlerTest(unittest.TestCase): 13617db96d56Sopenharmony_ci def setUp(self): 13627db96d56Sopenharmony_ci self.parser = None 13637db96d56Sopenharmony_ci 13647db96d56Sopenharmony_ci self.specified_version = '1.0' 13657db96d56Sopenharmony_ci self.specified_encoding = 'UTF-8' 13667db96d56Sopenharmony_ci self.specified_doctype = 'wish' 13677db96d56Sopenharmony_ci self.specified_entity_names = ('nbsp', 'source', 'target') 13687db96d56Sopenharmony_ci self.specified_comment = ('Comment in a DTD', 13697db96d56Sopenharmony_ci 'Really! You think so?') 13707db96d56Sopenharmony_ci self.test_data = StringIO() 13717db96d56Sopenharmony_ci self.test_data.write('<?xml version="{}" encoding="{}"?>\n'. 13727db96d56Sopenharmony_ci format(self.specified_version, 13737db96d56Sopenharmony_ci self.specified_encoding)) 13747db96d56Sopenharmony_ci self.test_data.write('<!DOCTYPE {} [\n'. 13757db96d56Sopenharmony_ci format(self.specified_doctype)) 13767db96d56Sopenharmony_ci self.test_data.write('<!-- {} -->\n'. 13777db96d56Sopenharmony_ci format(self.specified_comment[0])) 13787db96d56Sopenharmony_ci self.test_data.write('<!ELEMENT {} (to,from,heading,body,footer)>\n'. 13797db96d56Sopenharmony_ci format(self.specified_doctype)) 13807db96d56Sopenharmony_ci self.test_data.write('<!ELEMENT to (#PCDATA)>\n') 13817db96d56Sopenharmony_ci self.test_data.write('<!ELEMENT from (#PCDATA)>\n') 13827db96d56Sopenharmony_ci self.test_data.write('<!ELEMENT heading (#PCDATA)>\n') 13837db96d56Sopenharmony_ci self.test_data.write('<!ELEMENT body (#PCDATA)>\n') 13847db96d56Sopenharmony_ci self.test_data.write('<!ELEMENT footer (#PCDATA)>\n') 13857db96d56Sopenharmony_ci self.test_data.write('<!ENTITY {} " ">\n'. 13867db96d56Sopenharmony_ci format(self.specified_entity_names[0])) 13877db96d56Sopenharmony_ci self.test_data.write('<!ENTITY {} "Written by: Alexander.">\n'. 13887db96d56Sopenharmony_ci format(self.specified_entity_names[1])) 13897db96d56Sopenharmony_ci self.test_data.write('<!ENTITY {} "Hope it gets to: Aristotle.">\n'. 13907db96d56Sopenharmony_ci format(self.specified_entity_names[2])) 13917db96d56Sopenharmony_ci self.test_data.write(']>\n') 13927db96d56Sopenharmony_ci self.test_data.write('<{}>'.format(self.specified_doctype)) 13937db96d56Sopenharmony_ci self.test_data.write('<to>Aristotle</to>\n') 13947db96d56Sopenharmony_ci self.test_data.write('<from>Alexander</from>\n') 13957db96d56Sopenharmony_ci self.test_data.write('<heading>Supplication</heading>\n') 13967db96d56Sopenharmony_ci self.test_data.write('<body>Teach me patience!</body>\n') 13977db96d56Sopenharmony_ci self.test_data.write('<footer>&{};&{};&{};</footer>\n'. 13987db96d56Sopenharmony_ci format(self.specified_entity_names[1], 13997db96d56Sopenharmony_ci self.specified_entity_names[0], 14007db96d56Sopenharmony_ci self.specified_entity_names[2])) 14017db96d56Sopenharmony_ci self.test_data.write('<!-- {} -->\n'.format(self.specified_comment[1])) 14027db96d56Sopenharmony_ci self.test_data.write('</{}>\n'.format(self.specified_doctype)) 14037db96d56Sopenharmony_ci self.test_data.seek(0) 14047db96d56Sopenharmony_ci 14057db96d56Sopenharmony_ci # Data received from handlers - to be validated 14067db96d56Sopenharmony_ci self.version = None 14077db96d56Sopenharmony_ci self.encoding = None 14087db96d56Sopenharmony_ci self.standalone = None 14097db96d56Sopenharmony_ci self.doctype = None 14107db96d56Sopenharmony_ci self.publicID = None 14117db96d56Sopenharmony_ci self.systemID = None 14127db96d56Sopenharmony_ci self.end_of_dtd = False 14137db96d56Sopenharmony_ci self.comments = [] 14147db96d56Sopenharmony_ci 14157db96d56Sopenharmony_ci def test_handlers(self): 14167db96d56Sopenharmony_ci class TestLexicalHandler(LexicalHandler): 14177db96d56Sopenharmony_ci def __init__(self, test_harness, *args, **kwargs): 14187db96d56Sopenharmony_ci super().__init__(*args, **kwargs) 14197db96d56Sopenharmony_ci self.test_harness = test_harness 14207db96d56Sopenharmony_ci 14217db96d56Sopenharmony_ci def startDTD(self, doctype, publicID, systemID): 14227db96d56Sopenharmony_ci self.test_harness.doctype = doctype 14237db96d56Sopenharmony_ci self.test_harness.publicID = publicID 14247db96d56Sopenharmony_ci self.test_harness.systemID = systemID 14257db96d56Sopenharmony_ci 14267db96d56Sopenharmony_ci def endDTD(self): 14277db96d56Sopenharmony_ci self.test_harness.end_of_dtd = True 14287db96d56Sopenharmony_ci 14297db96d56Sopenharmony_ci def comment(self, text): 14307db96d56Sopenharmony_ci self.test_harness.comments.append(text) 14317db96d56Sopenharmony_ci 14327db96d56Sopenharmony_ci self.parser = create_parser() 14337db96d56Sopenharmony_ci self.parser.setContentHandler(ContentHandler()) 14347db96d56Sopenharmony_ci self.parser.setProperty( 14357db96d56Sopenharmony_ci 'http://xml.org/sax/properties/lexical-handler', 14367db96d56Sopenharmony_ci TestLexicalHandler(self)) 14377db96d56Sopenharmony_ci source = InputSource() 14387db96d56Sopenharmony_ci source.setCharacterStream(self.test_data) 14397db96d56Sopenharmony_ci self.parser.parse(source) 14407db96d56Sopenharmony_ci self.assertEqual(self.doctype, self.specified_doctype) 14417db96d56Sopenharmony_ci self.assertIsNone(self.publicID) 14427db96d56Sopenharmony_ci self.assertIsNone(self.systemID) 14437db96d56Sopenharmony_ci self.assertTrue(self.end_of_dtd) 14447db96d56Sopenharmony_ci self.assertEqual(len(self.comments), 14457db96d56Sopenharmony_ci len(self.specified_comment)) 14467db96d56Sopenharmony_ci self.assertEqual(f' {self.specified_comment[0]} ', self.comments[0]) 14477db96d56Sopenharmony_ci 14487db96d56Sopenharmony_ci 14497db96d56Sopenharmony_ciclass CDATAHandlerTest(unittest.TestCase): 14507db96d56Sopenharmony_ci def setUp(self): 14517db96d56Sopenharmony_ci self.parser = None 14527db96d56Sopenharmony_ci self.specified_chars = [] 14537db96d56Sopenharmony_ci self.specified_chars.append(('Parseable character data', False)) 14547db96d56Sopenharmony_ci self.specified_chars.append(('<> &% - assorted other XML junk.', True)) 14557db96d56Sopenharmony_ci self.char_index = 0 # Used to index specified results within handlers 14567db96d56Sopenharmony_ci self.test_data = StringIO() 14577db96d56Sopenharmony_ci self.test_data.write('<root_doc>\n') 14587db96d56Sopenharmony_ci self.test_data.write('<some_pcdata>\n') 14597db96d56Sopenharmony_ci self.test_data.write(f'{self.specified_chars[0][0]}\n') 14607db96d56Sopenharmony_ci self.test_data.write('</some_pcdata>\n') 14617db96d56Sopenharmony_ci self.test_data.write('<some_cdata>\n') 14627db96d56Sopenharmony_ci self.test_data.write(f'<![CDATA[{self.specified_chars[1][0]}]]>\n') 14637db96d56Sopenharmony_ci self.test_data.write('</some_cdata>\n') 14647db96d56Sopenharmony_ci self.test_data.write('</root_doc>\n') 14657db96d56Sopenharmony_ci self.test_data.seek(0) 14667db96d56Sopenharmony_ci 14677db96d56Sopenharmony_ci # Data received from handlers - to be validated 14687db96d56Sopenharmony_ci self.chardata = [] 14697db96d56Sopenharmony_ci self.in_cdata = False 14707db96d56Sopenharmony_ci 14717db96d56Sopenharmony_ci def test_handlers(self): 14727db96d56Sopenharmony_ci class TestLexicalHandler(LexicalHandler): 14737db96d56Sopenharmony_ci def __init__(self, test_harness, *args, **kwargs): 14747db96d56Sopenharmony_ci super().__init__(*args, **kwargs) 14757db96d56Sopenharmony_ci self.test_harness = test_harness 14767db96d56Sopenharmony_ci 14777db96d56Sopenharmony_ci def startCDATA(self): 14787db96d56Sopenharmony_ci self.test_harness.in_cdata = True 14797db96d56Sopenharmony_ci 14807db96d56Sopenharmony_ci def endCDATA(self): 14817db96d56Sopenharmony_ci self.test_harness.in_cdata = False 14827db96d56Sopenharmony_ci 14837db96d56Sopenharmony_ci class TestCharHandler(ContentHandler): 14847db96d56Sopenharmony_ci def __init__(self, test_harness, *args, **kwargs): 14857db96d56Sopenharmony_ci super().__init__(*args, **kwargs) 14867db96d56Sopenharmony_ci self.test_harness = test_harness 14877db96d56Sopenharmony_ci 14887db96d56Sopenharmony_ci def characters(self, content): 14897db96d56Sopenharmony_ci if content != '\n': 14907db96d56Sopenharmony_ci h = self.test_harness 14917db96d56Sopenharmony_ci t = h.specified_chars[h.char_index] 14927db96d56Sopenharmony_ci h.assertEqual(t[0], content) 14937db96d56Sopenharmony_ci h.assertEqual(t[1], h.in_cdata) 14947db96d56Sopenharmony_ci h.char_index += 1 14957db96d56Sopenharmony_ci 14967db96d56Sopenharmony_ci self.parser = create_parser() 14977db96d56Sopenharmony_ci self.parser.setContentHandler(TestCharHandler(self)) 14987db96d56Sopenharmony_ci self.parser.setProperty( 14997db96d56Sopenharmony_ci 'http://xml.org/sax/properties/lexical-handler', 15007db96d56Sopenharmony_ci TestLexicalHandler(self)) 15017db96d56Sopenharmony_ci source = InputSource() 15027db96d56Sopenharmony_ci source.setCharacterStream(self.test_data) 15037db96d56Sopenharmony_ci self.parser.parse(source) 15047db96d56Sopenharmony_ci 15057db96d56Sopenharmony_ci self.assertFalse(self.in_cdata) 15067db96d56Sopenharmony_ci self.assertEqual(self.char_index, 2) 15077db96d56Sopenharmony_ci 15087db96d56Sopenharmony_ci 15097db96d56Sopenharmony_ciif __name__ == "__main__": 15107db96d56Sopenharmony_ci unittest.main() 1511