The property list (``.plist``) file format is a simple serialization supporting
basic object types, like dictionaries, lists, numbers and strings. Usually the
-top level object is a dictionary.
+top level object is a dictionary or a frozen dictionary.
To write out and to parse a plist file, use the :func:`dump` and
:func:`load` functions.
The following standard library modules have been updated to accept
:class:`!frozendict`: :mod:`copy`, :mod:`decimal`, :mod:`json`, :mod:`marshal`,
-:mod:`pickle`, :mod:`pprint` and :mod:`xml.etree.ElementTree`.
+:mod:`plistlib` (only for serialization), :mod:`pickle`, :mod:`pprint` and
+:mod:`xml.etree.ElementTree`.
:func:`eval` and :func:`exec` accept :class:`!frozendict` for *globals*, and
:func:`type` and :meth:`str.maketrans` accept :class:`!frozendict` for *dict*.
The property list (.plist) file format is a simple XML pickle supporting
basic object types, like dictionaries, lists, numbers and strings.
-Usually the top level object is a dictionary.
+Usually the top level object is a dictionary or a frozen dictionary.
To write out a plist file, use the dump(value, file)
function. 'value' is the top level object, 'file' is
elif isinstance(value, float):
self.simple_element("real", repr(value))
- elif isinstance(value, dict):
+ elif isinstance(value, (dict, frozendict)):
self.write_dict(value)
elif isinstance(value, (bytes, bytearray)):
self._objidtable[id(value)] = refnum
# And finally recurse into containers
- if isinstance(value, dict):
+ if isinstance(value, (dict, frozendict)):
keys = []
values = []
items = value.items()
self._write_size(0xA0, s)
self._fp.write(struct.pack('>' + self._ref_format * s, *refs))
- elif isinstance(value, dict):
+ elif isinstance(value, (dict, frozendict)):
keyRefs, valRefs = [], []
if self._sort_keys:
# Generic bits
#
-_FORMATS={
- FMT_XML: dict(
+_FORMATS=frozendict({
+ FMT_XML: frozendict(
detect=_is_fmt_xml,
parser=_PlistParser,
writer=_PlistWriter,
),
- FMT_BINARY: dict(
+ FMT_BINARY: frozendict(
detect=_is_fmt_binary,
parser=_BinaryPlistParser,
writer=_BinaryPlistWriter,
)
-}
+})
def load(fp, *, fmt=None, dict_type=dict, aware_datetime=False):
})
self.assertIsNot(pl2['first'], pl2['second'])
+ def test_frozendict(self):
+ pl = frozendict(
+ aString="Doodah",
+ anInt=728,
+ aDict=frozendict(
+ anotherString="hello",
+ aTrueValue=True,
+ ),
+ aList=["A", "B", 12],
+ )
+
+ for fmt in ALL_FORMATS:
+ with self.subTest(fmt=fmt):
+ data = plistlib.dumps(pl, fmt=fmt)
+ pl2 = plistlib.loads(data)
+ self.assertEqual(pl2, dict(pl))
+ self.assertIsInstance(pl2, dict)
+ self.assertIsInstance(pl2['aDict'], dict)
+
def test_controlcharacters(self):
for i in range(128):
c = chr(i)