]> granicus.if.org Git - python/commitdiff
SF patch# 1769016 by James Brotchie.
authorGuido van Rossum <guido@python.org>
Tue, 7 Aug 2007 14:26:40 +0000 (14:26 +0000)
committerGuido van Rossum <guido@python.org>
Tue, 7 Aug 2007 14:26:40 +0000 (14:26 +0000)
Change plistlib to use bytes instead of strings.
Fix test_plistlib accordingly.

Lib/plat-mac/plistlib.py
Lib/test/test_plistlib.py

index 709e8e15fa1978380b911560ac930b9d980d30aa..f035729b76b0e5c7cb430e89f63dd4955bd664d6 100644 (file)
@@ -12,8 +12,8 @@ To parse a plist from a file, use the readPlist(pathOrFile) function,
 with a file name or a (readable) file object as the only argument. It
 returns the top level object (again, usually a dictionary).
 
-To work with plist data in strings, you can use readPlistFromString()
-and writePlistToString().
+To work with plist data in bytes objects, you can use readPlistFromBytes()
+and writePlistToBytes().
 
 Values can be strings, integers, floats, booleans, tuples, lists,
 dictionaries, Data or datetime.datetime objects. String values (including
@@ -21,7 +21,7 @@ dictionary keys) may be unicode strings -- they will be written out as
 UTF-8.
 
 The <data> plist type is supported through the Data class. This is a
-thin wrapper around a Python string.
+thin wrapper around a Python bytes object.
 
 Generate Plist example:
 
@@ -36,8 +36,8 @@ Generate Plist example:
             aTrueValue=True,
             aFalseValue=False,
         ),
-        someData = Data("<binary gunk>"),
-        someMoreData = Data("<lots of binary gunk>" * 10),
+        someData = Data(b"<binary gunk>"),
+        someMoreData = Data(b"<lots of binary gunk>" * 10),
         aDate = datetime.datetime.fromtimestamp(time.mktime(time.gmtime())),
     )
     # unicode keys are possible, but a little awkward to use:
@@ -52,7 +52,7 @@ Parse Plist example:
 
 
 __all__ = [
-    "readPlist", "writePlist", "readPlistFromString", "writePlistToString",
+    "readPlist", "writePlist", "readPlistFromBytes", "writePlistToBytes",
     "readPlistFromResource", "writePlistToResource",
     "Plist", "Data", "Dict"
 ]
@@ -60,7 +60,7 @@ __all__ = [
 
 import binascii
 import datetime
-from cStringIO import StringIO
+from io import BytesIO
 import re
 
 
@@ -71,7 +71,7 @@ def readPlist(pathOrFile):
     """
     didOpen = 0
     if isinstance(pathOrFile, str):
-        pathOrFile = open(pathOrFile)
+        pathOrFile = open(pathOrFile, 'rb')
         didOpen = 1
     p = PlistParser()
     rootObject = p.parse(pathOrFile)
@@ -86,7 +86,7 @@ def writePlist(rootObject, pathOrFile):
     """
     didOpen = 0
     if isinstance(pathOrFile, str):
-        pathOrFile = open(pathOrFile, "w")
+        pathOrFile = open(pathOrFile, 'wb')
         didOpen = 1
     writer = PlistWriter(pathOrFile)
     writer.writeln("<plist version=\"1.0\">")
@@ -96,16 +96,16 @@ def writePlist(rootObject, pathOrFile):
         pathOrFile.close()
 
 
-def readPlistFromString(data):
-    """Read a plist data from a string. Return the root object.
+def readPlistFromBytes(data):
+    """Read a plist data from a bytes object. Return the root object.
     """
-    return readPlist(StringIO(data))
+    return readPlist(BytesIO(data))
 
 
-def writePlistToString(rootObject):
-    """Return 'rootObject' as a plist-formatted string.
+def writePlistToBytes(rootObject):
+    """Return 'rootObject' as a plist-formatted bytes object.
     """
-    f = StringIO()
+    f = BytesIO()
     writePlist(rootObject, f)
     return f.getvalue()
 
@@ -145,7 +145,6 @@ def writePlistToResource(rootObject, path, restype='plst', resid=0):
 
 
 class DumbXMLWriter:
-
     def __init__(self, file, indentLevel=0, indent="\t"):
         self.file = file
         self.stack = []
@@ -172,9 +171,12 @@ class DumbXMLWriter:
 
     def writeln(self, line):
         if line:
-            self.file.write(self.indentLevel * self.indent + line + "\n")
-        else:
-            self.file.write("\n")
+            # plist has fixed encoding of utf-8
+            if isinstance(line, str):
+                line = line.encode('utf-8')
+            self.file.write(self.indentLevel * self.indent)
+            self.file.write(line)
+        self.file.write('\n')
 
 
 # Contents should conform to a subset of ISO 8601
@@ -355,13 +357,15 @@ def _encodeBase64(s, maxlinelength=76):
     for i in range(0, len(s), maxbinsize):
         chunk = s[i : i + maxbinsize]
         pieces.append(binascii.b2a_base64(chunk))
-    return "".join(pieces)
+    return b''.join(pieces)
 
 class Data:
 
     """Wrapper for binary data."""
 
     def __init__(self, data):
+        if not isinstance(data, bytes):
+            raise TypeError("data must be as bytes")
         self.data = data
 
     def fromBase64(cls, data):
@@ -426,11 +430,7 @@ class PlistParser:
             self.stack[-1].append(value)
 
     def getData(self):
-        data = "".join(self.data)
-        try:
-            data = data.encode("ascii")
-        except UnicodeError:
-            pass
+        data = ''.join(self.data)
         self.data = []
         return data
 
index 1b8012e56dee77c8722226a0a4c03b45e522b352..4ef3ea692803ec454ede1514b088754b05cd5715 100644 (file)
@@ -9,7 +9,7 @@ from test import test_support
 
 
 # This test data was generated through Cocoa's NSDictionary class
-TESTDATA = """<?xml version="1.0" encoding="UTF-8"?>
+TESTDATA = b"""<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \
 "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
@@ -109,9 +109,9 @@ class TestPlistlib(unittest.TestCase):
                 aFalseValue=False,
                 deeperDict=dict(a=17, b=32.5, c=[1, 2, "text"]),
             ),
-            someData = plistlib.Data("<binary gunk>"),
-            someMoreData = plistlib.Data("<lots of binary gunk>\0\1\2\3" * 10),
-            nestedData = [plistlib.Data("<lots of binary gunk>\0\1\2\3" * 10)],
+            someData = plistlib.Data(b"<binary gunk>"),
+            someMoreData = plistlib.Data(b"<lots of binary gunk>\0\1\2\3" * 10),
+            nestedData = [plistlib.Data(b"<lots of binary gunk>\0\1\2\3" * 10)],
             aDate = datetime.datetime(2004, 10, 26, 10, 33, 33),
         )
         pl['\xc5benraa'] = "That was a unicode key."
@@ -128,40 +128,32 @@ class TestPlistlib(unittest.TestCase):
         pl2 = plistlib.readPlist(test_support.TESTFN)
         self.assertEqual(dict(pl), dict(pl2))
 
-    def test_string(self):
+    def test_bytes(self):
         pl = self._create()
-        data = plistlib.writePlistToString(pl)
-        pl2 = plistlib.readPlistFromString(data)
+        data = plistlib.writePlistToBytes(pl)
+        pl2 = plistlib.readPlistFromBytes(data)
         self.assertEqual(dict(pl), dict(pl2))
-        data2 = plistlib.writePlistToString(pl2)
+        data2 = plistlib.writePlistToBytes(pl2)
         self.assertEqual(data, data2)
 
     def test_appleformatting(self):
-        pl = plistlib.readPlistFromString(TESTDATA)
-        data = plistlib.writePlistToString(pl)
+        pl = plistlib.readPlistFromBytes(TESTDATA)
+        data = plistlib.writePlistToBytes(pl)
         self.assertEqual(data, TESTDATA,
                          "generated data was not identical to Apple's output")
 
     def test_appleformattingfromliteral(self):
         pl = self._create()
-        pl2 = plistlib.readPlistFromString(TESTDATA)
+        pl2 = plistlib.readPlistFromBytes(TESTDATA)
         self.assertEqual(dict(pl), dict(pl2),
                          "generated data was not identical to Apple's output")
 
-    def test_stringio(self):
-        from StringIO import StringIO
-        f = StringIO()
+    def test_bytesio(self):
+        from io import BytesIO
+        b = BytesIO()
         pl = self._create()
-        plistlib.writePlist(pl, f)
-        pl2 = plistlib.readPlist(StringIO(f.getvalue()))
-        self.assertEqual(dict(pl), dict(pl2))
-
-    def test_cstringio(self):
-        from cStringIO import StringIO
-        f = StringIO()
-        pl = self._create()
-        plistlib.writePlist(pl, f)
-        pl2 = plistlib.readPlist(StringIO(f.getvalue()))
+        plistlib.writePlist(pl, b)
+        pl2 = plistlib.readPlist(BytesIO(b.getvalue()))
         self.assertEqual(dict(pl), dict(pl2))
 
     def test_controlcharacters(self):
@@ -170,17 +162,17 @@ class TestPlistlib(unittest.TestCase):
             testString = "string containing %s" % c
             if i >= 32 or c in "\r\n\t":
                 # \r, \n and \t are the only legal control chars in XML
-                plistlib.writePlistToString(testString)
+                plistlib.writePlistToBytes(testString)
             else:
                 self.assertRaises(ValueError,
-                                  plistlib.writePlistToString,
+                                  plistlib.writePlistToBytes,
                                   testString)
 
     def test_nondictroot(self):
         test1 = "abc"
         test2 = [1, 2, 3, "abc"]
-        result1 = plistlib.readPlistFromString(plistlib.writePlistToString(test1))
-        result2 = plistlib.readPlistFromString(plistlib.writePlistToString(test2))
+        result1 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test1))
+        result2 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test2))
         self.assertEqual(test1, result1)
         self.assertEqual(test2, result2)