diff -r b3e1be1493a5 Lib/test/test_sax.py --- a/Lib/test/test_sax.py Tue May 07 11:21:21 2013 +0300 +++ b/Lib/test/test_sax.py Tue May 07 16:31:10 2013 +0300 @@ -15,6 +15,7 @@ from xml.sax.handler import feature_namespaces from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl from io import BytesIO, StringIO +import codecs import os.path import shutil from test import support @@ -538,6 +539,34 @@ def getvalue(self): return b''.join(self) +class StreamWriterXmlgenTest(XmlgenTest, unittest.TestCase): + def ioclass(self): + raw = BytesIO() + writer = codecs.getwriter('ascii')(raw, 'xmlcharrefreplace') + writer.getvalue = raw.getvalue + return writer + + def xml(self, doc, encoding='iso-8859-1'): + return ('\n%s' % + (encoding, doc)).encode('ascii', 'xmlcharrefreplace') + +class StreamReaderWriterXmlgenTest(XmlgenTest, unittest.TestCase): + fname = support.TESTFN + '-codecs' + + def ioclass(self): + writer = codecs.open(self.fname, 'w', encoding='ascii', + errors='xmlcharrefreplace', buffering=0) + self.addCleanup(support.unlink, self.fname) + writer.getvalue = self.getvalue + return writer + + def getvalue(self): + with open(self.fname, 'rb') as f: + return f.read() + + def xml(self, doc, encoding='iso-8859-1'): + return ('\n%s' % + (encoding, doc)).encode('ascii', 'xmlcharrefreplace') start = b'\n' @@ -946,6 +975,8 @@ StringXmlgenTest, BytesXmlgenTest, WriterXmlgenTest, + StreamWriterXmlgenTest, + StreamReaderWriterXmlgenTest, ExpatReaderTest, ErrorReportingTest, XmlReaderTest) diff -r b3e1be1493a5 Lib/xml/sax/saxutils.py --- a/Lib/xml/sax/saxutils.py Tue May 07 11:21:21 2013 +0300 +++ b/Lib/xml/sax/saxutils.py Tue May 07 16:31:10 2013 +0300 @@ -5,6 +5,7 @@ import os, urllib.parse, urllib.request import io +import codecs from . import handler from . import xmlreader @@ -77,6 +78,10 @@ # use a text writer as is return out + if isinstance(out, (codecs.StreamWriter, codecs.StreamReaderWriter)): + # use a codecs stream writer as is + return out + # wrap a binary writer with TextIOWrapper if isinstance(out, io.RawIOBase): # Keep the original file open when the TextIOWrapper is