Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cd869d8

Browse files
committed
SF patch# 1769016 by James Brotchie.
Change plistlib to use bytes instead of strings. Fix test_plistlib accordingly.
1 parent ca8dd91 commit cd869d8

2 files changed

Lines changed: 45 additions & 53 deletions

File tree

Lib/plat-mac/plistlib.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@
1212
with a file name or a (readable) file object as the only argument. It
1313
returns the top level object (again, usually a dictionary).
1414
15-
To work with plist data in strings, you can use readPlistFromString()
16-
and writePlistToString().
15+
To work with plist data in bytes objects, you can use readPlistFromBytes()
16+
and writePlistToBytes().
1717
1818
Values can be strings, integers, floats, booleans, tuples, lists,
1919
dictionaries, Data or datetime.datetime objects. String values (including
2020
dictionary keys) may be unicode strings -- they will be written out as
2121
UTF-8.
2222
2323
The <data> plist type is supported through the Data class. This is a
24-
thin wrapper around a Python string.
24+
thin wrapper around a Python bytes object.
2525
2626
Generate Plist example:
2727
@@ -36,8 +36,8 @@
3636
aTrueValue=True,
3737
aFalseValue=False,
3838
),
39-
someData = Data("<binary gunk>"),
40-
someMoreData = Data("<lots of binary gunk>" * 10),
39+
someData = Data(b"<binary gunk>"),
40+
someMoreData = Data(b"<lots of binary gunk>" * 10),
4141
aDate = datetime.datetime.fromtimestamp(time.mktime(time.gmtime())),
4242
)
4343
# unicode keys are possible, but a little awkward to use:
@@ -52,15 +52,15 @@
5252

5353

5454
__all__ = [
55-
"readPlist", "writePlist", "readPlistFromString", "writePlistToString",
55+
"readPlist", "writePlist", "readPlistFromBytes", "writePlistToBytes",
5656
"readPlistFromResource", "writePlistToResource",
5757
"Plist", "Data", "Dict"
5858
]
5959
# Note: the Plist and Dict classes have been deprecated.
6060

6161
import binascii
6262
import datetime
63-
from cStringIO import StringIO
63+
from io import BytesIO
6464
import re
6565

6666

@@ -71,7 +71,7 @@ def readPlist(pathOrFile):
7171
"""
7272
didOpen = 0
7373
if isinstance(pathOrFile, str):
74-
pathOrFile = open(pathOrFile)
74+
pathOrFile = open(pathOrFile, 'rb')
7575
didOpen = 1
7676
p = PlistParser()
7777
rootObject = p.parse(pathOrFile)
@@ -86,7 +86,7 @@ def writePlist(rootObject, pathOrFile):
8686
"""
8787
didOpen = 0
8888
if isinstance(pathOrFile, str):
89-
pathOrFile = open(pathOrFile, "w")
89+
pathOrFile = open(pathOrFile, 'wb')
9090
didOpen = 1
9191
writer = PlistWriter(pathOrFile)
9292
writer.writeln("<plist version=\"1.0\">")
@@ -96,16 +96,16 @@ def writePlist(rootObject, pathOrFile):
9696
pathOrFile.close()
9797

9898

99-
def readPlistFromString(data):
100-
"""Read a plist data from a string. Return the root object.
99+
def readPlistFromBytes(data):
100+
"""Read a plist data from a bytes object. Return the root object.
101101
"""
102-
return readPlist(StringIO(data))
102+
return readPlist(BytesIO(data))
103103

104104

105-
def writePlistToString(rootObject):
106-
"""Return 'rootObject' as a plist-formatted string.
105+
def writePlistToBytes(rootObject):
106+
"""Return 'rootObject' as a plist-formatted bytes object.
107107
"""
108-
f = StringIO()
108+
f = BytesIO()
109109
writePlist(rootObject, f)
110110
return f.getvalue()
111111

@@ -145,7 +145,6 @@ def writePlistToResource(rootObject, path, restype='plst', resid=0):
145145

146146

147147
class DumbXMLWriter:
148-
149148
def __init__(self, file, indentLevel=0, indent="\t"):
150149
self.file = file
151150
self.stack = []
@@ -172,9 +171,12 @@ def simpleElement(self, element, value=None):
172171

173172
def writeln(self, line):
174173
if line:
175-
self.file.write(self.indentLevel * self.indent + line + "\n")
176-
else:
177-
self.file.write("\n")
174+
# plist has fixed encoding of utf-8
175+
if isinstance(line, str):
176+
line = line.encode('utf-8')
177+
self.file.write(self.indentLevel * self.indent)
178+
self.file.write(line)
179+
self.file.write('\n')
178180

179181

180182
# Contents should conform to a subset of ISO 8601
@@ -355,13 +357,15 @@ def _encodeBase64(s, maxlinelength=76):
355357
for i in range(0, len(s), maxbinsize):
356358
chunk = s[i : i + maxbinsize]
357359
pieces.append(binascii.b2a_base64(chunk))
358-
return "".join(pieces)
360+
return b''.join(pieces)
359361

360362
class Data:
361363

362364
"""Wrapper for binary data."""
363365

364366
def __init__(self, data):
367+
if not isinstance(data, bytes):
368+
raise TypeError("data must be as bytes")
365369
self.data = data
366370

367371
def fromBase64(cls, data):
@@ -426,11 +430,7 @@ def addObject(self, value):
426430
self.stack[-1].append(value)
427431

428432
def getData(self):
429-
data = "".join(self.data)
430-
try:
431-
data = data.encode("ascii")
432-
except UnicodeError:
433-
pass
433+
data = ''.join(self.data)
434434
self.data = []
435435
return data
436436

Lib/test/test_plistlib.py

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
# This test data was generated through Cocoa's NSDictionary class
12-
TESTDATA = """<?xml version="1.0" encoding="UTF-8"?>
12+
TESTDATA = b"""<?xml version="1.0" encoding="UTF-8"?>
1313
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \
1414
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
1515
<plist version="1.0">
@@ -109,9 +109,9 @@ def _create(self):
109109
aFalseValue=False,
110110
deeperDict=dict(a=17, b=32.5, c=[1, 2, "text"]),
111111
),
112-
someData = plistlib.Data("<binary gunk>"),
113-
someMoreData = plistlib.Data("<lots of binary gunk>\0\1\2\3" * 10),
114-
nestedData = [plistlib.Data("<lots of binary gunk>\0\1\2\3" * 10)],
112+
someData = plistlib.Data(b"<binary gunk>"),
113+
someMoreData = plistlib.Data(b"<lots of binary gunk>\0\1\2\3" * 10),
114+
nestedData = [plistlib.Data(b"<lots of binary gunk>\0\1\2\3" * 10)],
115115
aDate = datetime.datetime(2004, 10, 26, 10, 33, 33),
116116
)
117117
pl['\xc5benraa'] = "That was a unicode key."
@@ -128,40 +128,32 @@ def test_io(self):
128128
pl2 = plistlib.readPlist(test_support.TESTFN)
129129
self.assertEqual(dict(pl), dict(pl2))
130130

131-
def test_string(self):
131+
def test_bytes(self):
132132
pl = self._create()
133-
data = plistlib.writePlistToString(pl)
134-
pl2 = plistlib.readPlistFromString(data)
133+
data = plistlib.writePlistToBytes(pl)
134+
pl2 = plistlib.readPlistFromBytes(data)
135135
self.assertEqual(dict(pl), dict(pl2))
136-
data2 = plistlib.writePlistToString(pl2)
136+
data2 = plistlib.writePlistToBytes(pl2)
137137
self.assertEqual(data, data2)
138138

139139
def test_appleformatting(self):
140-
pl = plistlib.readPlistFromString(TESTDATA)
141-
data = plistlib.writePlistToString(pl)
140+
pl = plistlib.readPlistFromBytes(TESTDATA)
141+
data = plistlib.writePlistToBytes(pl)
142142
self.assertEqual(data, TESTDATA,
143143
"generated data was not identical to Apple's output")
144144

145145
def test_appleformattingfromliteral(self):
146146
pl = self._create()
147-
pl2 = plistlib.readPlistFromString(TESTDATA)
147+
pl2 = plistlib.readPlistFromBytes(TESTDATA)
148148
self.assertEqual(dict(pl), dict(pl2),
149149
"generated data was not identical to Apple's output")
150150

151-
def test_stringio(self):
152-
from StringIO import StringIO
153-
f = StringIO()
151+
def test_bytesio(self):
152+
from io import BytesIO
153+
b = BytesIO()
154154
pl = self._create()
155-
plistlib.writePlist(pl, f)
156-
pl2 = plistlib.readPlist(StringIO(f.getvalue()))
157-
self.assertEqual(dict(pl), dict(pl2))
158-
159-
def test_cstringio(self):
160-
from cStringIO import StringIO
161-
f = StringIO()
162-
pl = self._create()
163-
plistlib.writePlist(pl, f)
164-
pl2 = plistlib.readPlist(StringIO(f.getvalue()))
155+
plistlib.writePlist(pl, b)
156+
pl2 = plistlib.readPlist(BytesIO(b.getvalue()))
165157
self.assertEqual(dict(pl), dict(pl2))
166158

167159
def test_controlcharacters(self):
@@ -170,17 +162,17 @@ def test_controlcharacters(self):
170162
testString = "string containing %s" % c
171163
if i >= 32 or c in "\r\n\t":
172164
# \r, \n and \t are the only legal control chars in XML
173-
plistlib.writePlistToString(testString)
165+
plistlib.writePlistToBytes(testString)
174166
else:
175167
self.assertRaises(ValueError,
176-
plistlib.writePlistToString,
168+
plistlib.writePlistToBytes,
177169
testString)
178170

179171
def test_nondictroot(self):
180172
test1 = "abc"
181173
test2 = [1, 2, 3, "abc"]
182-
result1 = plistlib.readPlistFromString(plistlib.writePlistToString(test1))
183-
result2 = plistlib.readPlistFromString(plistlib.writePlistToString(test2))
174+
result1 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test1))
175+
result2 = plistlib.readPlistFromBytes(plistlib.writePlistToBytes(test2))
184176
self.assertEqual(test1, result1)
185177
self.assertEqual(test2, result2)
186178

0 commit comments

Comments
 (0)