https://github.com/python/cpython/commit/bbf214df23be3ee5daead119e8a2506d810d7d1f
commit: bbf214df23be3ee5daead119e8a2506d810d7d1f
branch: main
author: AN Long <[email protected]>
committer: ronaldoussoren <[email protected]>
date: 2024-01-06T10:26:59+01:00
summary:
gh-113537: support loads str in plistlib.loads (#113582)
Add support for loading XML plists from a string value instead of a only bytes
value.
files:
A Misc/NEWS.d/next/Library/2023-12-30-20-30-05.gh-issue-113537.v1W5_X.rst
M Doc/library/plistlib.rst
M Lib/plistlib.py
M Lib/test/test_plistlib.py
diff --git a/Doc/library/plistlib.rst b/Doc/library/plistlib.rst
index 10f1a48fc70a72..7416ca2650bab4 100644
--- a/Doc/library/plistlib.rst
+++ b/Doc/library/plistlib.rst
@@ -27,7 +27,7 @@ top level object is a dictionary.
To write out and to parse a plist file, use the :func:`dump` and
:func:`load` functions.
-To work with plist data in bytes objects, use :func:`dumps`
+To work with plist data in bytes or string objects, use :func:`dumps`
and :func:`loads`.
Values can be strings, integers, floats, booleans, tuples, lists, dictionaries
@@ -89,11 +89,13 @@ This module defines the following functions:
.. function:: loads(data, *, fmt=None, dict_type=dict, aware_datetime=False)
- Load a plist from a bytes object. See :func:`load` for an explanation of
- the keyword arguments.
+ Load a plist from a bytes or string object. See :func:`load` for an
+ explanation of the keyword arguments.
.. versionadded:: 3.4
+ .. versionchanged:: 3.13
+ *data* can be a string when *fmt* equals :data:`FMT_XML`.
.. function:: dump(value, fp, *, fmt=FMT_XML, sort_keys=True, skipkeys=False,
aware_datetime=False)
diff --git a/Lib/plistlib.py b/Lib/plistlib.py
index 0fc1b5cbfa8c49..188a0b399b587b 100644
--- a/Lib/plistlib.py
+++ b/Lib/plistlib.py
@@ -906,6 +906,11 @@ def loads(value, *, fmt=None, dict_type=dict,
aware_datetime=False):
"""Read a .plist file from a bytes object.
Return the unpacked root object (which usually is a dictionary).
"""
+ if isinstance(value, str):
+ if fmt == FMT_BINARY:
+ raise TypeError("value must be bytes-like object when fmt is "
+ "FMT_BINARY")
+ value = value.encode()
fp = BytesIO(value)
return load(fp, fmt=fmt, dict_type=dict_type,
aware_datetime=aware_datetime)
diff --git a/Lib/test/test_plistlib.py b/Lib/test/test_plistlib.py
index 1d2e14a30c4e13..f47982907def21 100644
--- a/Lib/test/test_plistlib.py
+++ b/Lib/test/test_plistlib.py
@@ -510,6 +510,19 @@ def test_bytes(self):
data2 = plistlib.dumps(pl2)
self.assertEqual(data, data2)
+ def test_loads_str_with_xml_fmt(self):
+ pl = self._create()
+ b = plistlib.dumps(pl)
+ s = b.decode()
+ self.assertIsInstance(s, str)
+ pl2 = plistlib.loads(s)
+ self.assertEqual(pl, pl2)
+
+ def test_loads_str_with_binary_fmt(self):
+ msg = "value must be bytes-like object when fmt is FMT_BINARY"
+ with self.assertRaisesRegex(TypeError, msg):
+ plistlib.loads('test', fmt=plistlib.FMT_BINARY)
+
def test_indentation_array(self):
data = [[[[[[[[{'test': b'aaaaaa'}]]]]]]]]
self.assertEqual(plistlib.loads(plistlib.dumps(data)), data)
diff --git
a/Misc/NEWS.d/next/Library/2023-12-30-20-30-05.gh-issue-113537.v1W5_X.rst
b/Misc/NEWS.d/next/Library/2023-12-30-20-30-05.gh-issue-113537.v1W5_X.rst
new file mode 100644
index 00000000000000..a6150815b285a9
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-12-30-20-30-05.gh-issue-113537.v1W5_X.rst
@@ -0,0 +1 @@
+Support loads ``str`` in :func:`plistlib.loads`.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]