cpython: 03b878d636cf (original) (raw)

--- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -13,7 +13,7 @@ from xml.sax.saxutils import XMLGenerato from xml.sax.expatreader import create_parser from xml.sax.handler import feature_namespaces from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl -from io import StringIO +from io import BytesIO, StringIO import os.path import shutil from test import support @@ -173,31 +173,29 @@ class SaxutilsTest(unittest.TestCase):

===== XMLGenerator

-start = '\n' - -class XmlgenTest(unittest.TestCase): +class XmlgenTest: def test_xmlgen_basic(self):

def test_xmlgen_basic_empty(self):

def test_xmlgen_content(self):

gen.startDocument() @@ -206,10 +204,10 @@ class XmlgenTest(unittest.TestCase): gen.endElement("doc") gen.endDocument()

def test_xmlgen_content_empty(self):

gen.startDocument() @@ -218,10 +216,10 @@ class XmlgenTest(unittest.TestCase): gen.endElement("doc") gen.endDocument()

def test_xmlgen_pi(self):

gen.startDocument() @@ -230,10 +228,11 @@ class XmlgenTest(unittest.TestCase): gen.endElement("doc") gen.endDocument()

def test_xmlgen_content_escape(self):

gen.startDocument() @@ -243,10 +242,10 @@ class XmlgenTest(unittest.TestCase): gen.endDocument() self.assertEqual(result.getvalue(),

def test_xmlgen_attr_escape(self):

gen.startDocument() @@ -260,13 +259,43 @@ class XmlgenTest(unittest.TestCase): gen.endElement("doc") gen.endDocument()

+

+

+

+

+

+

def test_xmlgen_ignorable(self):

gen.startDocument() @@ -275,10 +304,10 @@ class XmlgenTest(unittest.TestCase): gen.endElement("doc") gen.endDocument()

def test_xmlgen_ignorable_empty(self):

gen.startDocument() @@ -287,10 +316,10 @@ class XmlgenTest(unittest.TestCase): gen.endElement("doc") gen.endDocument()

def test_xmlgen_ns(self):

gen.startDocument() @@ -303,12 +332,12 @@ class XmlgenTest(unittest.TestCase): gen.endPrefixMapping("ns1") gen.endDocument()

def test_xmlgen_ns_empty(self):

gen.startDocument() @@ -321,12 +350,12 @@ class XmlgenTest(unittest.TestCase): gen.endPrefixMapping("ns1") gen.endDocument()

def test_1463026_1(self):

gen.startDocument() @@ -334,10 +363,10 @@ class XmlgenTest(unittest.TestCase): gen.endElementNS((None, 'a'), 'a') gen.endDocument()

def test_1463026_1_empty(self):

gen.startDocument() @@ -345,10 +374,10 @@ class XmlgenTest(unittest.TestCase): gen.endElementNS((None, 'a'), 'a') gen.endDocument()

def test_1463026_2(self):

gen.startDocument() @@ -358,10 +387,10 @@ class XmlgenTest(unittest.TestCase): gen.endPrefixMapping(None) gen.endDocument()

def test_1463026_2_empty(self):

gen.startDocument() @@ -371,10 +400,10 @@ class XmlgenTest(unittest.TestCase): gen.endPrefixMapping(None) gen.endDocument()

def test_1463026_3(self):

gen.startDocument() @@ -385,10 +414,10 @@ class XmlgenTest(unittest.TestCase): gen.endDocument() self.assertEqual(result.getvalue(),

def test_1463026_3_empty(self):

gen.startDocument() @@ -399,7 +428,7 @@ class XmlgenTest(unittest.TestCase): gen.endDocument() self.assertEqual(result.getvalue(),

def test_5027_1(self): # The xml prefix (as in xml:lang below) is reserved and bound by @@ -416,13 +445,13 @@ class XmlgenTest(unittest.TestCase): parser = make_parser() parser.setFeature(feature_namespaces, True)

self.assertEqual(result.getvalue(),

@@ -435,7 +464,7 @@ class XmlgenTest(unittest.TestCase): # # This test demonstrates the bug by direct manipulation of the # XMLGenerator.

gen.startDocument() @@ -450,15 +479,57 @@ class XmlgenTest(unittest.TestCase): gen.endDocument() self.assertEqual(result.getvalue(),

+ +class StringXmlgenTest(XmlgenTest, unittest.TestCase):

+

+

+ +class BytesXmlgenTest(XmlgenTest, unittest.TestCase):

+

+ +class WriterXmlgenTest(BytesXmlgenTest):

+

+

+

+ + +start = b'\n' + class XMLFilterBaseTest(unittest.TestCase): def test_filter_basic(self):

@@ -470,7 +541,7 @@ class XMLFilterBaseTest(unittest.TestCas filter.endElement("doc") filter.endDocument()

===========================================================================

# @@ -478,7 +549,7 @@ class XMLFilterBaseTest(unittest.TestCas #

===========================================================================

-with open(TEST_XMLFILE_OUT) as f: +with open(TEST_XMLFILE_OUT, 'rb') as f: xml_test_out = f.read() class ExpatReaderTest(XmlTestBase): @@ -487,11 +558,11 @@ class ExpatReaderTest(XmlTestBase): def test_expat_file(self): parser = create_parser()

parser.setContentHandler(xmlgen)

self.assertEqual(result.getvalue(), xml_test_out) @@ -503,7 +574,7 @@ class ExpatReaderTest(XmlTestBase): self.addCleanup(support.unlink, fname) parser = create_parser()

parser.setContentHandler(xmlgen) @@ -547,13 +618,13 @@ class ExpatReaderTest(XmlTestBase): def resolveEntity(self, publicId, systemId): inpsrc = InputSource()

def test_expat_entityresolver(self): parser = create_parser() parser.setEntityResolver(self.TestEntityResolver())

parser.feed('<!DOCTYPE doc [\n') @@ -563,7 +634,7 @@ class ExpatReaderTest(XmlTestBase): parser.close() self.assertEqual(result.getvalue(), start +

# ===== Attributes support @@ -632,7 +703,7 @@ class ExpatReaderTest(XmlTestBase): def test_expat_inpsource_filename(self): parser = create_parser()

parser.setContentHandler(xmlgen) @@ -642,7 +713,7 @@ class ExpatReaderTest(XmlTestBase): def test_expat_inpsource_sysid(self): parser = create_parser()

parser.setContentHandler(xmlgen) @@ -657,7 +728,7 @@ class ExpatReaderTest(XmlTestBase): self.addCleanup(support.unlink, fname) parser = create_parser()

parser.setContentHandler(xmlgen) @@ -667,12 +738,12 @@ class ExpatReaderTest(XmlTestBase): def test_expat_inpsource_stream(self): parser = create_parser()

parser.setContentHandler(xmlgen) inpsrc = InputSource()

@@ -681,7 +752,7 @@ class ExpatReaderTest(XmlTestBase): # ===== IncrementalParser support def test_expat_incremental(self):

@@ -690,10 +761,10 @@ class ExpatReaderTest(XmlTestBase): parser.feed("") parser.close()

def test_expat_incremental_reset(self):

@@ -701,7 +772,7 @@ class ExpatReaderTest(XmlTestBase): parser.feed("") parser.feed("text")

@@ -711,12 +782,12 @@ class ExpatReaderTest(XmlTestBase): parser.feed("") parser.close()

# ===== Locator support def test_expat_locator_noinfo(self):

@@ -730,7 +801,7 @@ class ExpatReaderTest(XmlTestBase): self.assertEqual(parser.getLineNumber(), 1) def test_expat_locator_withinfo(self):

@@ -745,7 +816,7 @@ class ExpatReaderTest(XmlTestBase): shutil.copyfile(TEST_XMLFILE, fname) self.addCleanup(support.unlink, fname)

@@ -766,7 +837,7 @@ class ErrorReportingTest(unittest.TestCa parser = create_parser() parser.setContentHandler(ContentHandler()) # do nothing source = InputSource()

@@ -857,7 +928,9 @@ class XmlReaderTest(XmlTestBase): def test_main(): run_unittest(MakeParserTest, SaxutilsTest,

--- a/Lib/xml/sax/saxutils.py +++ b/Lib/xml/sax/saxutils.py @@ -4,18 +4,10 @@ convenience of application and driver wr """ import os, urllib.parse, urllib.request +import io from . import handler from . import xmlreader -# See whether the xmlcharrefreplace error handler is -# supported -try:

-except ImportError:

- def __dict_replace(s, d): """Replace substrings of a string using a dictionary.""" for key, value in d.items(): @@ -76,14 +68,50 @@ def quoteattr(data, entities={}): return data +def _gettextwriter(out, encoding):

+

+

+ class XMLGenerator(handler.ContentHandler): def init(self, out=None, encoding="iso-8859-1", short_empty_elements=False):

@@ -91,12 +119,6 @@ class XMLGenerator(handler.ContentHandle self._short_empty_elements = short_empty_elements self._pending_start_element = False

- def _qname(self, name): """Builds a qualified name from a (ns_url, localname) pair""" if name[0]: @@ -125,6 +147,9 @@ class XMLGenerator(handler.ContentHandle self._write('\n' % self._encoding)

+ def startPrefixMapping(self, prefix, uri): self._ns_contexts.append(self._current_context.copy()) self._current_context[uri] = prefix @@ -157,9 +182,9 @@ class XMLGenerator(handler.ContentHandle for prefix, uri in self._undeclared_ns_maps: if prefix:

for (name, value) in attrs.items():

--- a/Misc/NEWS +++ b/Misc/NEWS @@ -172,6 +172,8 @@ Core and Builtins Library ------- +- Issue #1470548: XMLGenerator now works with binary output streams. +