bpo-36409: Remove old plistlib API deprecated in 3.4 (GH-15615)
* Remove implementation for old plistlib API deprecated in 3.4
This commit is contained in:
parent
9b51570ffd
commit
ce81a925ef
|
@ -30,7 +30,7 @@ To work with plist data in bytes objects, use :func:`dumps`
|
||||||
and :func:`loads`.
|
and :func:`loads`.
|
||||||
|
|
||||||
Values can be strings, integers, floats, booleans, tuples, lists, dictionaries
|
Values can be strings, integers, floats, booleans, tuples, lists, dictionaries
|
||||||
(but only with string keys), :class:`Data`, :class:`bytes`, :class:`bytesarray`
|
(but only with string keys), :class:`bytes`, :class:`bytearray`
|
||||||
or :class:`datetime.datetime` objects.
|
or :class:`datetime.datetime` objects.
|
||||||
|
|
||||||
.. versionchanged:: 3.4
|
.. versionchanged:: 3.4
|
||||||
|
@ -40,6 +40,9 @@ or :class:`datetime.datetime` objects.
|
||||||
Support added for reading and writing :class:`UID` tokens in binary plists as used
|
Support added for reading and writing :class:`UID` tokens in binary plists as used
|
||||||
by NSKeyedArchiver and NSKeyedUnarchiver.
|
by NSKeyedArchiver and NSKeyedUnarchiver.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.9
|
||||||
|
Old API removed.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
`PList manual page <https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/PropertyLists/>`_
|
`PList manual page <https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/PropertyLists/>`_
|
||||||
|
@ -48,7 +51,7 @@ or :class:`datetime.datetime` objects.
|
||||||
|
|
||||||
This module defines the following functions:
|
This module defines the following functions:
|
||||||
|
|
||||||
.. function:: load(fp, \*, fmt=None, use_builtin_types=True, dict_type=dict)
|
.. function:: load(fp, \*, fmt=None, dict_type=dict)
|
||||||
|
|
||||||
Read a plist file. *fp* should be a readable and binary file object.
|
Read a plist file. *fp* should be a readable and binary file object.
|
||||||
Return the unpacked root object (which usually is a
|
Return the unpacked root object (which usually is a
|
||||||
|
@ -62,10 +65,6 @@ This module defines the following functions:
|
||||||
|
|
||||||
* :data:`FMT_BINARY`: Binary plist format
|
* :data:`FMT_BINARY`: Binary plist format
|
||||||
|
|
||||||
If *use_builtin_types* is true (the default) binary data will be returned
|
|
||||||
as instances of :class:`bytes`, otherwise it is returned as instances of
|
|
||||||
:class:`Data`.
|
|
||||||
|
|
||||||
The *dict_type* is the type used for dictionaries that are read from the
|
The *dict_type* is the type used for dictionaries that are read from the
|
||||||
plist file.
|
plist file.
|
||||||
|
|
||||||
|
@ -80,7 +79,7 @@ This module defines the following functions:
|
||||||
.. versionadded:: 3.4
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
|
|
||||||
.. function:: loads(data, \*, fmt=None, use_builtin_types=True, dict_type=dict)
|
.. function:: loads(data, \*, fmt=None, dict_type=dict)
|
||||||
|
|
||||||
Load a plist from a bytes object. See :func:`load` for an explanation of
|
Load a plist from a bytes object. See :func:`load` for an explanation of
|
||||||
the keyword arguments.
|
the keyword arguments.
|
||||||
|
@ -124,75 +123,6 @@ This module defines the following functions:
|
||||||
|
|
||||||
.. versionadded:: 3.4
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
The following functions are deprecated:
|
|
||||||
|
|
||||||
.. function:: readPlist(pathOrFile)
|
|
||||||
|
|
||||||
Read a plist file. *pathOrFile* may be either a file name or a (readable
|
|
||||||
and binary) file object. Returns the unpacked root object (which usually
|
|
||||||
is a dictionary).
|
|
||||||
|
|
||||||
This function calls :func:`load` to do the actual work, see the documentation
|
|
||||||
of :func:`that function <load>` for an explanation of the keyword arguments.
|
|
||||||
|
|
||||||
.. deprecated:: 3.4 Use :func:`load` instead.
|
|
||||||
|
|
||||||
.. versionchanged:: 3.7
|
|
||||||
Dict values in the result are now normal dicts. You no longer can use
|
|
||||||
attribute access to access items of these dictionaries.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: writePlist(rootObject, pathOrFile)
|
|
||||||
|
|
||||||
Write *rootObject* to an XML plist file. *pathOrFile* may be either a file name
|
|
||||||
or a (writable and binary) file object
|
|
||||||
|
|
||||||
.. deprecated:: 3.4 Use :func:`dump` instead.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: readPlistFromBytes(data)
|
|
||||||
|
|
||||||
Read a plist data from a bytes object. Return the root object.
|
|
||||||
|
|
||||||
See :func:`load` for a description of the keyword arguments.
|
|
||||||
|
|
||||||
.. deprecated:: 3.4 Use :func:`loads` instead.
|
|
||||||
|
|
||||||
.. versionchanged:: 3.7
|
|
||||||
Dict values in the result are now normal dicts. You no longer can use
|
|
||||||
attribute access to access items of these dictionaries.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: writePlistToBytes(rootObject)
|
|
||||||
|
|
||||||
Return *rootObject* as an XML plist-formatted bytes object.
|
|
||||||
|
|
||||||
.. deprecated:: 3.4 Use :func:`dumps` instead.
|
|
||||||
|
|
||||||
|
|
||||||
The following classes are available:
|
|
||||||
|
|
||||||
.. class:: Data(data)
|
|
||||||
|
|
||||||
Return a "data" wrapper object around the bytes object *data*. This is used
|
|
||||||
in functions converting from/to plists to represent the ``<data>`` type
|
|
||||||
available in plists.
|
|
||||||
|
|
||||||
It has one attribute, :attr:`data`, that can be used to retrieve the Python
|
|
||||||
bytes object stored in it.
|
|
||||||
|
|
||||||
.. deprecated:: 3.4 Use a :class:`bytes` object instead.
|
|
||||||
|
|
||||||
.. class:: UID(data)
|
|
||||||
|
|
||||||
Wraps an :class:`int`. This is used when reading or writing NSKeyedArchiver
|
|
||||||
encoded data, which contains UID (see PList manual).
|
|
||||||
|
|
||||||
It has one attribute, :attr:`data` which can be used to retrieve the int value
|
|
||||||
of the UID. :attr:`data` must be in the range `0 <= data <= 2**64`.
|
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
|
||||||
|
|
||||||
|
|
||||||
The following constants are available:
|
The following constants are available:
|
||||||
|
|
||||||
|
|
|
@ -213,6 +213,12 @@ Removed
|
||||||
instead. The ``xml.etree.cElementTree`` module has been removed.
|
instead. The ``xml.etree.cElementTree`` module has been removed.
|
||||||
(Contributed by Serhiy Storchaka in :issue:`36543`.)
|
(Contributed by Serhiy Storchaka in :issue:`36543`.)
|
||||||
|
|
||||||
|
* The old :mod:`plistlib` API has been removed, it was deprecated since Python
|
||||||
|
3.4. Use the :func:`load`, :func:`loads`, :func:`dump`, and :func:`dumps`
|
||||||
|
functions. Additionally, the ``use_builtin_types`` parameter was removed,
|
||||||
|
standard :class:`bytes` objects are always used.
|
||||||
|
(Contributed by Jon Janzen in :issue:`36409`.)
|
||||||
|
|
||||||
|
|
||||||
Porting to Python 3.9
|
Porting to Python 3.9
|
||||||
=====================
|
=====================
|
||||||
|
|
155
Lib/plistlib.py
155
Lib/plistlib.py
|
@ -46,9 +46,7 @@ Parse Plist example:
|
||||||
print(pl["aKey"])
|
print(pl["aKey"])
|
||||||
"""
|
"""
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"readPlist", "writePlist", "readPlistFromBytes", "writePlistToBytes",
|
"InvalidFileException", "FMT_XML", "FMT_BINARY", "load", "dump", "loads", "dumps", "UID"
|
||||||
"Data", "InvalidFileException", "FMT_XML", "FMT_BINARY",
|
|
||||||
"load", "dump", "loads", "dumps", "UID"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
import binascii
|
import binascii
|
||||||
|
@ -69,112 +67,6 @@ PlistFormat = enum.Enum('PlistFormat', 'FMT_XML FMT_BINARY', module=__name__)
|
||||||
globals().update(PlistFormat.__members__)
|
globals().update(PlistFormat.__members__)
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Deprecated functionality
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def _maybe_open(pathOrFile, mode):
|
|
||||||
if isinstance(pathOrFile, str):
|
|
||||||
with open(pathOrFile, mode) as fp:
|
|
||||||
yield fp
|
|
||||||
|
|
||||||
else:
|
|
||||||
yield pathOrFile
|
|
||||||
|
|
||||||
|
|
||||||
def readPlist(pathOrFile):
|
|
||||||
"""
|
|
||||||
Read a .plist from a path or file. pathOrFile should either
|
|
||||||
be a file name, or a readable binary file object.
|
|
||||||
|
|
||||||
This function is deprecated, use load instead.
|
|
||||||
"""
|
|
||||||
warn("The readPlist function is deprecated, use load() instead",
|
|
||||||
DeprecationWarning, 2)
|
|
||||||
|
|
||||||
with _maybe_open(pathOrFile, 'rb') as fp:
|
|
||||||
return load(fp, fmt=None, use_builtin_types=False)
|
|
||||||
|
|
||||||
def writePlist(value, pathOrFile):
|
|
||||||
"""
|
|
||||||
Write 'value' to a .plist file. 'pathOrFile' may either be a
|
|
||||||
file name or a (writable) file object.
|
|
||||||
|
|
||||||
This function is deprecated, use dump instead.
|
|
||||||
"""
|
|
||||||
warn("The writePlist function is deprecated, use dump() instead",
|
|
||||||
DeprecationWarning, 2)
|
|
||||||
with _maybe_open(pathOrFile, 'wb') as fp:
|
|
||||||
dump(value, fp, fmt=FMT_XML, sort_keys=True, skipkeys=False)
|
|
||||||
|
|
||||||
|
|
||||||
def readPlistFromBytes(data):
|
|
||||||
"""
|
|
||||||
Read a plist data from a bytes object. Return the root object.
|
|
||||||
|
|
||||||
This function is deprecated, use loads instead.
|
|
||||||
"""
|
|
||||||
warn("The readPlistFromBytes function is deprecated, use loads() instead",
|
|
||||||
DeprecationWarning, 2)
|
|
||||||
return load(BytesIO(data), fmt=None, use_builtin_types=False)
|
|
||||||
|
|
||||||
|
|
||||||
def writePlistToBytes(value):
|
|
||||||
"""
|
|
||||||
Return 'value' as a plist-formatted bytes object.
|
|
||||||
|
|
||||||
This function is deprecated, use dumps instead.
|
|
||||||
"""
|
|
||||||
warn("The writePlistToBytes function is deprecated, use dumps() instead",
|
|
||||||
DeprecationWarning, 2)
|
|
||||||
f = BytesIO()
|
|
||||||
dump(value, f, fmt=FMT_XML, sort_keys=True, skipkeys=False)
|
|
||||||
return f.getvalue()
|
|
||||||
|
|
||||||
|
|
||||||
class Data:
|
|
||||||
"""
|
|
||||||
Wrapper for binary data.
|
|
||||||
|
|
||||||
This class is deprecated, use a bytes object instead.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, data):
|
|
||||||
if not isinstance(data, bytes):
|
|
||||||
raise TypeError("data must be as bytes")
|
|
||||||
self.data = data
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def fromBase64(cls, data):
|
|
||||||
# base64.decodebytes just calls binascii.a2b_base64;
|
|
||||||
# it seems overkill to use both base64 and binascii.
|
|
||||||
return cls(_decode_base64(data))
|
|
||||||
|
|
||||||
def asBase64(self, maxlinelength=76):
|
|
||||||
return _encode_base64(self.data, maxlinelength)
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if isinstance(other, self.__class__):
|
|
||||||
return self.data == other.data
|
|
||||||
elif isinstance(other, bytes):
|
|
||||||
return self.data == other
|
|
||||||
else:
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "%s(%s)" % (self.__class__.__name__, repr(self.data))
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# End of deprecated functionality
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
class UID:
|
class UID:
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
if not isinstance(data, int):
|
if not isinstance(data, int):
|
||||||
|
@ -202,7 +94,6 @@ class UID:
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.data)
|
return hash(self.data)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# XML support
|
# XML support
|
||||||
#
|
#
|
||||||
|
@ -273,11 +164,10 @@ def _escape(text):
|
||||||
return text
|
return text
|
||||||
|
|
||||||
class _PlistParser:
|
class _PlistParser:
|
||||||
def __init__(self, use_builtin_types, dict_type):
|
def __init__(self, dict_type):
|
||||||
self.stack = []
|
self.stack = []
|
||||||
self.current_key = None
|
self.current_key = None
|
||||||
self.root = None
|
self.root = None
|
||||||
self._use_builtin_types = use_builtin_types
|
|
||||||
self._dict_type = dict_type
|
self._dict_type = dict_type
|
||||||
|
|
||||||
def parse(self, fileobj):
|
def parse(self, fileobj):
|
||||||
|
@ -366,11 +256,7 @@ class _PlistParser:
|
||||||
self.add_object(self.get_data())
|
self.add_object(self.get_data())
|
||||||
|
|
||||||
def end_data(self):
|
def end_data(self):
|
||||||
if self._use_builtin_types:
|
self.add_object(_decode_base64(self.get_data()))
|
||||||
self.add_object(_decode_base64(self.get_data()))
|
|
||||||
|
|
||||||
else:
|
|
||||||
self.add_object(Data.fromBase64(self.get_data()))
|
|
||||||
|
|
||||||
def end_date(self):
|
def end_date(self):
|
||||||
self.add_object(_date_from_string(self.get_data()))
|
self.add_object(_date_from_string(self.get_data()))
|
||||||
|
@ -452,9 +338,6 @@ class _PlistWriter(_DumbXMLWriter):
|
||||||
elif isinstance(value, dict):
|
elif isinstance(value, dict):
|
||||||
self.write_dict(value)
|
self.write_dict(value)
|
||||||
|
|
||||||
elif isinstance(value, Data):
|
|
||||||
self.write_data(value)
|
|
||||||
|
|
||||||
elif isinstance(value, (bytes, bytearray)):
|
elif isinstance(value, (bytes, bytearray)):
|
||||||
self.write_bytes(value)
|
self.write_bytes(value)
|
||||||
|
|
||||||
|
@ -467,9 +350,6 @@ class _PlistWriter(_DumbXMLWriter):
|
||||||
else:
|
else:
|
||||||
raise TypeError("unsupported type: %s" % type(value))
|
raise TypeError("unsupported type: %s" % type(value))
|
||||||
|
|
||||||
def write_data(self, data):
|
|
||||||
self.write_bytes(data.data)
|
|
||||||
|
|
||||||
def write_bytes(self, data):
|
def write_bytes(self, data):
|
||||||
self.begin_element("data")
|
self.begin_element("data")
|
||||||
self._indent_level -= 1
|
self._indent_level -= 1
|
||||||
|
@ -563,8 +443,7 @@ class _BinaryPlistParser:
|
||||||
|
|
||||||
see also: http://opensource.apple.com/source/CF/CF-744.18/CFBinaryPList.c
|
see also: http://opensource.apple.com/source/CF/CF-744.18/CFBinaryPList.c
|
||||||
"""
|
"""
|
||||||
def __init__(self, use_builtin_types, dict_type):
|
def __init__(self, dict_type):
|
||||||
self._use_builtin_types = use_builtin_types
|
|
||||||
self._dict_type = dict_type
|
self._dict_type = dict_type
|
||||||
|
|
||||||
def parse(self, fp):
|
def parse(self, fp):
|
||||||
|
@ -664,10 +543,7 @@ class _BinaryPlistParser:
|
||||||
|
|
||||||
elif tokenH == 0x40: # data
|
elif tokenH == 0x40: # data
|
||||||
s = self._get_size(tokenL)
|
s = self._get_size(tokenL)
|
||||||
if self._use_builtin_types:
|
result = self._fp.read(s)
|
||||||
result = self._fp.read(s)
|
|
||||||
else:
|
|
||||||
result = Data(self._fp.read(s))
|
|
||||||
|
|
||||||
elif tokenH == 0x50: # ascii string
|
elif tokenH == 0x50: # ascii string
|
||||||
s = self._get_size(tokenL)
|
s = self._get_size(tokenL)
|
||||||
|
@ -783,10 +659,6 @@ class _BinaryPlistWriter (object):
|
||||||
if (type(value), value) in self._objtable:
|
if (type(value), value) in self._objtable:
|
||||||
return
|
return
|
||||||
|
|
||||||
elif isinstance(value, Data):
|
|
||||||
if (type(value.data), value.data) in self._objtable:
|
|
||||||
return
|
|
||||||
|
|
||||||
elif id(value) in self._objidtable:
|
elif id(value) in self._objidtable:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -795,8 +667,6 @@ class _BinaryPlistWriter (object):
|
||||||
self._objlist.append(value)
|
self._objlist.append(value)
|
||||||
if isinstance(value, _scalars):
|
if isinstance(value, _scalars):
|
||||||
self._objtable[(type(value), value)] = refnum
|
self._objtable[(type(value), value)] = refnum
|
||||||
elif isinstance(value, Data):
|
|
||||||
self._objtable[(type(value.data), value.data)] = refnum
|
|
||||||
else:
|
else:
|
||||||
self._objidtable[id(value)] = refnum
|
self._objidtable[id(value)] = refnum
|
||||||
|
|
||||||
|
@ -826,8 +696,6 @@ class _BinaryPlistWriter (object):
|
||||||
def _getrefnum(self, value):
|
def _getrefnum(self, value):
|
||||||
if isinstance(value, _scalars):
|
if isinstance(value, _scalars):
|
||||||
return self._objtable[(type(value), value)]
|
return self._objtable[(type(value), value)]
|
||||||
elif isinstance(value, Data):
|
|
||||||
return self._objtable[(type(value.data), value.data)]
|
|
||||||
else:
|
else:
|
||||||
return self._objidtable[id(value)]
|
return self._objidtable[id(value)]
|
||||||
|
|
||||||
|
@ -885,10 +753,6 @@ class _BinaryPlistWriter (object):
|
||||||
f = (value - datetime.datetime(2001, 1, 1)).total_seconds()
|
f = (value - datetime.datetime(2001, 1, 1)).total_seconds()
|
||||||
self._fp.write(struct.pack('>Bd', 0x33, f))
|
self._fp.write(struct.pack('>Bd', 0x33, f))
|
||||||
|
|
||||||
elif isinstance(value, Data):
|
|
||||||
self._write_size(0x40, len(value.data))
|
|
||||||
self._fp.write(value.data)
|
|
||||||
|
|
||||||
elif isinstance(value, (bytes, bytearray)):
|
elif isinstance(value, (bytes, bytearray)):
|
||||||
self._write_size(0x40, len(value))
|
self._write_size(0x40, len(value))
|
||||||
self._fp.write(value)
|
self._fp.write(value)
|
||||||
|
@ -970,7 +834,7 @@ _FORMATS={
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def load(fp, *, fmt=None, use_builtin_types=True, dict_type=dict):
|
def load(fp, *, fmt=None, dict_type=dict):
|
||||||
"""Read a .plist file. 'fp' should be a readable and binary file object.
|
"""Read a .plist file. 'fp' should be a readable and binary file object.
|
||||||
Return the unpacked root object (which usually is a dictionary).
|
Return the unpacked root object (which usually is a dictionary).
|
||||||
"""
|
"""
|
||||||
|
@ -988,17 +852,16 @@ def load(fp, *, fmt=None, use_builtin_types=True, dict_type=dict):
|
||||||
else:
|
else:
|
||||||
P = _FORMATS[fmt]['parser']
|
P = _FORMATS[fmt]['parser']
|
||||||
|
|
||||||
p = P(use_builtin_types=use_builtin_types, dict_type=dict_type)
|
p = P(dict_type=dict_type)
|
||||||
return p.parse(fp)
|
return p.parse(fp)
|
||||||
|
|
||||||
|
|
||||||
def loads(value, *, fmt=None, use_builtin_types=True, dict_type=dict):
|
def loads(value, *, fmt=None, dict_type=dict):
|
||||||
"""Read a .plist file from a bytes object.
|
"""Read a .plist file from a bytes object.
|
||||||
Return the unpacked root object (which usually is a dictionary).
|
Return the unpacked root object (which usually is a dictionary).
|
||||||
"""
|
"""
|
||||||
fp = BytesIO(value)
|
fp = BytesIO(value)
|
||||||
return load(
|
return load(fp, fmt=fmt, dict_type=dict_type)
|
||||||
fp, fmt=fmt, use_builtin_types=use_builtin_types, dict_type=dict_type)
|
|
||||||
|
|
||||||
|
|
||||||
def dump(value, fp, *, fmt=FMT_XML, sort_keys=True, skipkeys=False):
|
def dump(value, fp, *, fmt=FMT_XML, sort_keys=True, skipkeys=False):
|
||||||
|
|
|
@ -263,14 +263,12 @@ class TestPlistlib(unittest.TestCase):
|
||||||
self.assertEqual(copy.deepcopy(UID(1)), UID(1))
|
self.assertEqual(copy.deepcopy(UID(1)), UID(1))
|
||||||
|
|
||||||
def test_appleformatting(self):
|
def test_appleformatting(self):
|
||||||
for use_builtin_types in (True, False):
|
for fmt in ALL_FORMATS:
|
||||||
for fmt in ALL_FORMATS:
|
with self.subTest(fmt=fmt):
|
||||||
with self.subTest(fmt=fmt, use_builtin_types=use_builtin_types):
|
pl = plistlib.loads(TESTDATA[fmt])
|
||||||
pl = plistlib.loads(TESTDATA[fmt],
|
data = plistlib.dumps(pl, fmt=fmt)
|
||||||
use_builtin_types=use_builtin_types)
|
self.assertEqual(data, TESTDATA[fmt],
|
||||||
data = plistlib.dumps(pl, fmt=fmt)
|
"generated data was not identical to Apple's output")
|
||||||
self.assertEqual(data, TESTDATA[fmt],
|
|
||||||
"generated data was not identical to Apple's output")
|
|
||||||
|
|
||||||
|
|
||||||
def test_appleformattingfromliteral(self):
|
def test_appleformattingfromliteral(self):
|
||||||
|
@ -524,8 +522,7 @@ class TestBinaryPlistlib(unittest.TestCase):
|
||||||
# Test effectiveness of saving duplicated objects
|
# Test effectiveness of saving duplicated objects
|
||||||
for x in (None, False, True, 12345, 123.45, 'abcde', b'abcde',
|
for x in (None, False, True, 12345, 123.45, 'abcde', b'abcde',
|
||||||
datetime.datetime(2004, 10, 26, 10, 33, 33),
|
datetime.datetime(2004, 10, 26, 10, 33, 33),
|
||||||
plistlib.Data(b'abcde'), bytearray(b'abcde'),
|
bytearray(b'abcde'), [12, 345], (12, 345), {'12': 345}):
|
||||||
[12, 345], (12, 345), {'12': 345}):
|
|
||||||
with self.subTest(x=x):
|
with self.subTest(x=x):
|
||||||
data = plistlib.dumps([x]*1000, fmt=plistlib.FMT_BINARY)
|
data = plistlib.dumps([x]*1000, fmt=plistlib.FMT_BINARY)
|
||||||
self.assertLess(len(data), 1100, repr(data))
|
self.assertLess(len(data), 1100, repr(data))
|
||||||
|
@ -533,8 +530,7 @@ class TestBinaryPlistlib(unittest.TestCase):
|
||||||
def test_identity(self):
|
def test_identity(self):
|
||||||
for x in (None, False, True, 12345, 123.45, 'abcde', b'abcde',
|
for x in (None, False, True, 12345, 123.45, 'abcde', b'abcde',
|
||||||
datetime.datetime(2004, 10, 26, 10, 33, 33),
|
datetime.datetime(2004, 10, 26, 10, 33, 33),
|
||||||
plistlib.Data(b'abcde'), bytearray(b'abcde'),
|
bytearray(b'abcde'), [12, 345], (12, 345), {'12': 345}):
|
||||||
[12, 345], (12, 345), {'12': 345}):
|
|
||||||
with self.subTest(x=x):
|
with self.subTest(x=x):
|
||||||
data = plistlib.dumps([x]*2, fmt=plistlib.FMT_BINARY)
|
data = plistlib.dumps([x]*2, fmt=plistlib.FMT_BINARY)
|
||||||
a, b = plistlib.loads(data)
|
a, b = plistlib.loads(data)
|
||||||
|
@ -621,95 +617,6 @@ class TestBinaryPlistlib(unittest.TestCase):
|
||||||
plistlib.loads(b'bplist00' + data, fmt=plistlib.FMT_BINARY)
|
plistlib.loads(b'bplist00' + data, fmt=plistlib.FMT_BINARY)
|
||||||
|
|
||||||
|
|
||||||
class TestPlistlibDeprecated(unittest.TestCase):
|
|
||||||
def test_io_deprecated(self):
|
|
||||||
pl_in = {
|
|
||||||
'key': 42,
|
|
||||||
'sub': {
|
|
||||||
'key': 9,
|
|
||||||
'alt': 'value',
|
|
||||||
'data': b'buffer',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pl_out = {
|
|
||||||
'key': 42,
|
|
||||||
'sub': {
|
|
||||||
'key': 9,
|
|
||||||
'alt': 'value',
|
|
||||||
'data': plistlib.Data(b'buffer'),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.addCleanup(support.unlink, support.TESTFN)
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
plistlib.writePlist(pl_in, support.TESTFN)
|
|
||||||
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
pl2 = plistlib.readPlist(support.TESTFN)
|
|
||||||
|
|
||||||
self.assertEqual(pl_out, pl2)
|
|
||||||
|
|
||||||
os.unlink(support.TESTFN)
|
|
||||||
|
|
||||||
with open(support.TESTFN, 'wb') as fp:
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
plistlib.writePlist(pl_in, fp)
|
|
||||||
|
|
||||||
with open(support.TESTFN, 'rb') as fp:
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
pl2 = plistlib.readPlist(fp)
|
|
||||||
|
|
||||||
self.assertEqual(pl_out, pl2)
|
|
||||||
|
|
||||||
def test_bytes_deprecated(self):
|
|
||||||
pl = {
|
|
||||||
'key': 42,
|
|
||||||
'sub': {
|
|
||||||
'key': 9,
|
|
||||||
'alt': 'value',
|
|
||||||
'data': b'buffer',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
data = plistlib.writePlistToBytes(pl)
|
|
||||||
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
pl2 = plistlib.readPlistFromBytes(data)
|
|
||||||
|
|
||||||
self.assertIsInstance(pl2, dict)
|
|
||||||
self.assertEqual(pl2, dict(
|
|
||||||
key=42,
|
|
||||||
sub=dict(
|
|
||||||
key=9,
|
|
||||||
alt='value',
|
|
||||||
data=plistlib.Data(b'buffer'),
|
|
||||||
)
|
|
||||||
))
|
|
||||||
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
data2 = plistlib.writePlistToBytes(pl2)
|
|
||||||
self.assertEqual(data, data2)
|
|
||||||
|
|
||||||
def test_dataobject_deprecated(self):
|
|
||||||
in_data = { 'key': plistlib.Data(b'hello') }
|
|
||||||
out_data = { 'key': b'hello' }
|
|
||||||
|
|
||||||
buf = plistlib.dumps(in_data)
|
|
||||||
|
|
||||||
cur = plistlib.loads(buf)
|
|
||||||
self.assertEqual(cur, out_data)
|
|
||||||
self.assertEqual(cur, in_data)
|
|
||||||
|
|
||||||
cur = plistlib.loads(buf, use_builtin_types=False)
|
|
||||||
self.assertEqual(cur, out_data)
|
|
||||||
self.assertEqual(cur, in_data)
|
|
||||||
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
|
||||||
cur = plistlib.readPlistFromBytes(buf)
|
|
||||||
self.assertEqual(cur, out_data)
|
|
||||||
self.assertEqual(cur, in_data)
|
|
||||||
|
|
||||||
|
|
||||||
class TestKeyedArchive(unittest.TestCase):
|
class TestKeyedArchive(unittest.TestCase):
|
||||||
def test_keyed_archive_data(self):
|
def test_keyed_archive_data(self):
|
||||||
# This is the structure of a NSKeyedArchive packed plist
|
# This is the structure of a NSKeyedArchive packed plist
|
||||||
|
@ -749,7 +656,7 @@ class MiscTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
support.run_unittest(TestPlistlib, TestPlistlibDeprecated, TestKeyedArchive, MiscTestCase)
|
support.run_unittest(TestPlistlib, TestKeyedArchive, MiscTestCase)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Remove the old plistlib API deprecated in Python 3.4
|
Loading…
Reference in New Issue