[Python-checkins] r59050 - in python/branches/release25-maint/Lib: encodings/utf_8_sig.py test/test_codecs.py

walter.doerwald python-checkins at python.org
Mon Nov 19 13:43:40 CET 2007


Author: walter.doerwald
Date: Mon Nov 19 13:43:39 2007
New Revision: 59050

Modified:
   python/branches/release25-maint/Lib/encodings/utf_8_sig.py
   python/branches/release25-maint/Lib/test/test_codecs.py
Log:
Backport r59049:
Fix for #1444: utf_8_sig.StreamReader was (indirectly through decode())
calling codecs.utf_8_decode() with final==True, which falled with incomplete
byte sequences. Fix and test by James G. Sack.


Modified: python/branches/release25-maint/Lib/encodings/utf_8_sig.py
==============================================================================
--- python/branches/release25-maint/Lib/encodings/utf_8_sig.py	(original)
+++ python/branches/release25-maint/Lib/encodings/utf_8_sig.py	Mon Nov 19 13:43:39 2007
@@ -84,12 +84,18 @@
             pass
 
     def decode(self, input, errors='strict'):
-        if len(input) < 3 and codecs.BOM_UTF8.startswith(input):
-            # not enough data to decide if this is a BOM
-            # => try again on the next call
-            return (u"", 0)
+        if len(input) < 3:
+            if codecs.BOM_UTF8.startswith(input):
+                # not enough data to decide if this is a BOM
+                # => try again on the next call
+                return (u"", 0)
+        elif input[:3] == codecs.BOM_UTF8:
+            self.decode = codecs.utf_8_decode
+            (output, consumed) = codecs.utf_8_decode(input[3:],errors)
+            return (output, consumed+3)
+        # (else) no BOM present
         self.decode = codecs.utf_8_decode
-        return decode(input, errors)
+        return codecs.utf_8_decode(input, errors)
 
 ### encodings module API
 

Modified: python/branches/release25-maint/Lib/test/test_codecs.py
==============================================================================
--- python/branches/release25-maint/Lib/test/test_codecs.py	(original)
+++ python/branches/release25-maint/Lib/test/test_codecs.py	Mon Nov 19 13:43:39 2007
@@ -435,6 +435,50 @@
         s = u"spam"
         self.assertEqual(d.decode(s.encode("utf-8-sig")), s)
 
+    def test_stream_bom(self):
+        unistring = u"ABC\u00A1\u2200XYZ"
+        bytestring = codecs.BOM_UTF8 + "ABC\xC2\xA1\xE2\x88\x80XYZ"
+
+        reader = codecs.getreader("utf-8-sig")
+        for sizehint in [None] + range(1, 11) + \
+                        [64, 128, 256, 512, 1024]:
+            istream = reader(StringIO.StringIO(bytestring))
+            ostream = StringIO.StringIO()
+            while 1:
+                if sizehint is not None:
+                    data = istream.read(sizehint)
+                else:
+                    data = istream.read()
+
+                if not data:
+                    break
+                ostream.write(data)
+
+            got = ostream.getvalue()
+            self.assertEqual(got, unistring)
+
+    def test_stream_bare(self):
+        unistring = u"ABC\u00A1\u2200XYZ"
+        bytestring = "ABC\xC2\xA1\xE2\x88\x80XYZ"
+
+        reader = codecs.getreader("utf-8-sig")
+        for sizehint in [None] + range(1, 11) + \
+                        [64, 128, 256, 512, 1024]:
+            istream = reader(StringIO.StringIO(bytestring))
+            ostream = StringIO.StringIO()
+            while 1:
+                if sizehint is not None:
+                    data = istream.read(sizehint)
+                else:
+                    data = istream.read()
+
+                if not data:
+                    break
+                ostream.write(data)
+
+            got = ostream.getvalue()
+            self.assertEqual(got, unistring)
+
 class EscapeDecodeTest(unittest.TestCase):
     def test_empty(self):
         self.assertEquals(codecs.escape_decode(""), ("", 0))


More information about the Python-checkins mailing list