summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/plat-mac/plistlib.py50
-rw-r--r--Lib/test/test_plistlib.py48
2 files changed, 45 insertions, 53 deletions
diff --git a/Lib/plat-mac/plistlib.py b/Lib/plat-mac/plistlib.py
index 709e8e15fa..f035729b76 100644
--- a/Lib/plat-mac/plistlib.py
+++ b/Lib/plat-mac/plistlib.py
@@ -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
diff --git a/Lib/test/test_plistlib.py b/Lib/test/test_plistlib.py
index 1b8012e56d..4ef3ea6928 100644
--- a/Lib/test/test_plistlib.py
+++ b/Lib/test/test_plistlib.py
@@ -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)