diff --git a/Lib/plistlib.py b/Lib/plistlib.py index 655c51eea3..c3aee1e15c 100644 --- a/Lib/plistlib.py +++ b/Lib/plistlib.py @@ -21,7 +21,7 @@ Generate Plist example: - import datetime + import datetime as dt import plistlib pl = dict( @@ -37,7 +37,7 @@ ), someData = b"", someMoreData = b"" * 10, - aDate = datetime.datetime.now() + aDate = dt.datetime.now() ) print(plistlib.dumps(pl).decode()) @@ -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: diff --git a/Lib/test/test_plistlib.py b/Lib/test/test_plistlib.py index 389da145e6..c49557ec37 100644 --- a/Lib/test/test_plistlib.py +++ b/Lib/test/test_plistlib.py @@ -1,4 +1,4 @@ -# Copyright (C) 2003-2013 Python Software Foundation +# Copyright (C) 2003 Python Software Foundation import copy import operator import pickle @@ -13,7 +13,6 @@ import subprocess import binascii import collections -import time import zoneinfo from test import support from test.support import os_helper @@ -510,6 +509,69 @@ def test_bytes(self): data2 = plistlib.dumps(pl2) self.assertEqual(data, data2) + def test_bytes_indent(self): + header = ( + b'\n' + b'\n' + b'\n') + data = [{'bytes': bytes(range(50))}] + pl = plistlib.dumps(data) + self.assertEqual(pl, header + + b'\n' + b'\t\n' + b'\t\tbytes\n' + b'\t\t\n' + b'\t\tAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKiss\n' + b'\t\tLS4vMDE=\n' + b'\t\t\n' + b'\t\n' + b'\n' + b'\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'\n' + b' \n' + b' bytes\n' + b' \n' + b' AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDE=\n' + b' \n' + b' \n' + b'\n' + b'\n') + + pl = dumps_with_indent(data, b' \t') + self.assertEqual(pl, header + + b'\n' + b' \t\n' + b' \t \tbytes\n' + b' \t \t\n' + b' \t \tAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKiss\n' + b' \t \tLS4vMDE=\n' + b' \t \t\n' + b' \t\n' + b'\n' + b'\n') + + pl = dumps_with_indent(data, b'\t ') + self.assertEqual(pl, header + + b'\n' + b'\t \n' + b'\t \t bytes\n' + b'\t \t \n' + b'\t \t AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygp\n' + b'\t \t KissLS4vMDE=\n' + b'\t \t \n' + b'\t \n' + b'\n' + b'\n') + def test_loads_str_with_xml_fmt(self): pl = self._create() b = plistlib.dumps(pl) @@ -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: @@ -770,7 +831,7 @@ 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 inside an array", "key inside an array23", @@ -778,7 +839,7 @@ def test_invalidarray(self): self.assertRaises(ValueError, plistlib.loads, ("%s"%i).encode()) - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_invaliddict(self): for i in ["kcompound key", "single key", @@ -790,12 +851,12 @@ def test_invaliddict(self): self.assertRaises(ValueError, plistlib.loads, ("%s"%i).encode()) - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_invalidinteger(self): self.assertRaises(ValueError, plistlib.loads, b"not integer") - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_invalidreal(self): self.assertRaises(ValueError, plistlib.loads, b"not real") @@ -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"): @@ -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"