Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Lib/plistlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

Generate Plist example:

import datetime
import datetime as dt
import plistlib

pl = dict(
Expand All @@ -37,7 +37,7 @@
),
someData = b"<binary gunk>",
someMoreData = b"<lots of binary gunk>" * 10,
aDate = datetime.datetime.now()
aDate = dt.datetime.now()
)
print(plistlib.dumps(pl).decode())

Expand Down Expand Up @@ -384,7 +384,7 @@ def write_bytes(self, data):
self._indent_level -= 1
maxlinelength = max(
16,
76 - len(self.indent.replace(b"\t", b" " * 8) * self._indent_level))
76 - len((self.indent * self._indent_level).expandtabs()))

for line in _encode_base64(data, maxlinelength).split(b"\n"):
if line:
Expand Down
82 changes: 70 additions & 12 deletions Lib/test/test_plistlib.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2003-2013 Python Software Foundation
# Copyright (C) 2003 Python Software Foundation
import copy
import operator
import pickle
Expand All @@ -13,7 +13,6 @@
import subprocess
import binascii
import collections
import time
import zoneinfo
from test import support
from test.support import os_helper
Expand Down Expand Up @@ -510,6 +509,69 @@ def test_bytes(self):
data2 = plistlib.dumps(pl2)
self.assertEqual(data, data2)

def test_bytes_indent(self):
header = (
b'<?xml version="1.0" encoding="UTF-8"?>\n'
b'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
b'<plist version="1.0">\n')
data = [{'bytes': bytes(range(50))}]
pl = plistlib.dumps(data)
self.assertEqual(pl, header +
b'<array>\n'
b'\t<dict>\n'
b'\t\t<key>bytes</key>\n'
b'\t\t<data>\n'
b'\t\tAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKiss\n'
b'\t\tLS4vMDE=\n'
b'\t\t</data>\n'
b'\t</dict>\n'
b'</array>\n'
b'</plist>\n')

def dumps_with_indent(data, indent):
fp = BytesIO()
writer = plistlib._PlistWriter(fp, indent=indent)
writer.write(data)
return fp.getvalue()

pl = dumps_with_indent(data, b' ')
self.assertEqual(pl, header +
b'<array>\n'
b' <dict>\n'
b' <key>bytes</key>\n'
b' <data>\n'
b' AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDE=\n'
b' </data>\n'
b' </dict>\n'
b'</array>\n'
b'</plist>\n')

pl = dumps_with_indent(data, b' \t')
self.assertEqual(pl, header +
b'<array>\n'
b' \t<dict>\n'
b' \t \t<key>bytes</key>\n'
b' \t \t<data>\n'
b' \t \tAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKiss\n'
b' \t \tLS4vMDE=\n'
b' \t \t</data>\n'
b' \t</dict>\n'
b'</array>\n'
b'</plist>\n')

pl = dumps_with_indent(data, b'\t ')
self.assertEqual(pl, header +
b'<array>\n'
b'\t <dict>\n'
b'\t \t <key>bytes</key>\n'
b'\t \t <data>\n'
b'\t \t AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygp\n'
b'\t \t KissLS4vMDE=\n'
b'\t \t </data>\n'
b'\t </dict>\n'
b'</array>\n'
b'</plist>\n')

def test_loads_str_with_xml_fmt(self):
pl = self._create()
b = plistlib.dumps(pl)
Expand Down Expand Up @@ -582,7 +644,6 @@ def test_appleformatting(self):
self.assertEqual(data, TESTDATA[fmt],
"generated data was not identical to Apple's output")


def test_appleformattingfromliteral(self):
self.maxDiff = None
for fmt in ALL_FORMATS:
Expand Down Expand Up @@ -770,15 +831,15 @@ def test_nondictroot(self):
self.assertEqual(test1, result1)
self.assertEqual(test2, result2)

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_invalidarray(self):
for i in ["<key>key inside an array</key>",
"<key>key inside an array2</key><real>3</real>",
"<true/><key>key inside an array3</key>"]:
self.assertRaises(ValueError, plistlib.loads,
("<plist><array>%s</array></plist>"%i).encode())

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_invaliddict(self):
for i in ["<key><true/>k</key><string>compound key</string>",
"<key>single key</key>",
Expand All @@ -790,12 +851,12 @@ def test_invaliddict(self):
self.assertRaises(ValueError, plistlib.loads,
("<plist><array><dict>%s</dict></array></plist>"%i).encode())

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_invalidinteger(self):
self.assertRaises(ValueError, plistlib.loads,
b"<plist><integer>not integer</integer></plist>")

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_invalidreal(self):
self.assertRaises(ValueError, plistlib.loads,
b"<plist><integer>not real</integer></plist>")
Expand Down Expand Up @@ -852,7 +913,7 @@ def test_modified_uid_huge(self):
with self.assertRaises(OverflowError):
plistlib.dumps(huge_uid, fmt=plistlib.FMT_BINARY)

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_xml_plist_with_entity_decl(self):
with self.assertRaisesRegex(plistlib.InvalidFileException,
"XML entity declarations are not supported"):
Expand Down Expand Up @@ -1077,10 +1138,7 @@ def test_dump_aware_datetime_without_aware_datetime_option(self):
with self.assertRaisesRegex(TypeError, msg):
plistlib.dumps(dt, fmt=plistlib.FMT_BINARY, aware_datetime=False)

# TODO: RUSTPYTHON
# The error message is different
# In CPython, there is a separate .c file for datetime, which raises a different error message
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; Wrong error message
def test_dump_utc_aware_datetime_without_aware_datetime_option(self):
dt = datetime.datetime(2345, 6, 7, 8, tzinfo=datetime.UTC)
msg = "can't subtract offset-naive and offset-aware datetimes"
Expand Down
Loading