def test_pretty_print(): root = etree.Element("root") attrs = OrderedDict([("c", "2"), ("b", "1"), ("a", "0")]) etree.SubElement(root, "element", attrs).text = "text" etree.SubElement(root, "element").text = "text" root.append(etree.Element("empty-element")) result = etree.tostring(root, encoding="unicode", pretty_print=True) assert result == ("<root>\n" ' <element c="2" b="1" a="0">text</element>\n' " <element>text</element>\n" " <empty-element/>\n" "</root>\n")
def dump( value, fp, sort_keys=True, skipkeys=False, use_builtin_types=None, pretty_print=True, ): if not hasattr(fp, "write"): raise AttributeError("'%s' object has no attribute 'write'" % type(fp).__name__) root = etree.Element("plist", version="1.0") el = totree( value, sort_keys=sort_keys, skipkeys=skipkeys, use_builtin_types=use_builtin_types, pretty_print=pretty_print, ) root.append(el) tree = etree.ElementTree(root) # we write the doctype ourselves instead of using the 'doctype' argument # of 'write' method, becuse lxml will force adding a '\n' even when # pretty_print is False. if pretty_print: header = b"\n".join((XML_DECLARATION, PLIST_DOCTYPE, b"")) else: header = XML_DECLARATION + PLIST_DOCTYPE fp.write(header) tree.write(fp, encoding="utf-8", pretty_print=pretty_print, xml_declaration=False)
def _integer_element(value, ctx): if -1 << 63 <= value < 1 << 64: el = etree.Element("integer") el.text = "%d" % value return el else: raise OverflowError(value)
def dump( value: PlistEncodable, fp: IO[bytes], sort_keys: bool = True, skipkeys: bool = False, use_builtin_types: Optional[bool] = None, pretty_print: bool = True, ) -> None: """Write a Python object to a plist file. Args: value: An object to write. fp: A file opened for writing. sort_keys (bool): Whether keys of dictionaries should be sorted. skipkeys (bool): Whether to silently skip non-string dictionary keys. use_builtin_types (bool): If true, byte strings will be encoded in Base-64 and wrapped in a ``data`` tag; if false, they will be either stored as ASCII strings or an exception raised if they cannot be represented. Defaults pretty_print (bool): Whether to indent the output. indent_level (int): Level of indentation when serializing. Raises: ``TypeError`` if non-string dictionary keys are serialized and ``skipkeys`` is false. ``ValueError`` if non-representable binary data is present and `use_builtin_types` is false. """ if not hasattr(fp, "write"): raise AttributeError("'%s' object has no attribute 'write'" % type(fp).__name__) root = etree.Element("plist", version="1.0") el = totree( value, sort_keys=sort_keys, skipkeys=skipkeys, use_builtin_types=use_builtin_types, pretty_print=pretty_print, ) root.append(el) tree = etree.ElementTree(root) # we write the doctype ourselves instead of using the 'doctype' argument # of 'write' method, becuse lxml will force adding a '\n' even when # pretty_print is False. if pretty_print: header = b"\n".join((XML_DECLARATION, PLIST_DOCTYPE, b"")) else: header = XML_DECLARATION + PLIST_DOCTYPE fp.write(header) tree.write( # type: ignore fp, encoding="utf-8", pretty_print=pretty_print, xml_declaration=False, )
def _data_element(data, ctx): el = etree.Element("data") el.text = _encode_base64( data, maxlinelength=(76 if ctx.pretty_print else None), indent_level=ctx.indent_level, ) return el
def _array_element(array, ctx): el = etree.Element("array") if len(array) == 0: return el ctx.indent_level += 1 for value in array: el.append(_make_element(value, ctx)) ctx.indent_level -= 1 return el
def _array_element(array: Sequence[PlistEncodable], ctx: SimpleNamespace) -> etree.Element: el = etree.Element("array") if len(array) == 0: return el ctx.indent_level += 1 for value in array: el.append(_make_element(value, ctx)) ctx.indent_level -= 1 return el
def _data_element(data: bytes, ctx: SimpleNamespace) -> etree.Element: el = etree.Element("data") # NOTE: mypy is confused about whether el.text should be str or bytes. el.text = _encode_base64( # type: ignore data, maxlinelength=(76 if ctx.pretty_print else None), indent_level=ctx.indent_level, ) return el
def _dict_element(d, ctx): el = etree.Element("dict") items = d.items() if ctx.sort_keys: items = sorted(items) ctx.indent_level += 1 for key, value in items: if not isinstance(key, basestring): if ctx.skipkeys: continue raise TypeError("keys must be strings") k = etree.SubElement(el, "key") k.text = tounicode(key, "utf-8") el.append(_make_element(value, ctx)) ctx.indent_level -= 1 return el
def _dict_element(d: Mapping[str, PlistEncodable], ctx: SimpleNamespace) -> etree.Element: el = etree.Element("dict") items = d.items() if ctx.sort_keys: items = sorted(items) # type: ignore ctx.indent_level += 1 for key, value in items: if not isinstance(key, str): if ctx.skipkeys: continue raise TypeError("keys must be strings") k = etree.SubElement(el, "key") k.text = tounicode(key, "utf-8") el.append(_make_element(value, ctx)) ctx.indent_level -= 1 return el
def _date_element(date, ctx): el = etree.Element("date") el.text = _date_to_string(date) return el
def _real_element(value, ctx): el = etree.Element("real") el.text = repr(value) return el
def _bool_element(value, ctx): if value: return etree.Element("true") else: return etree.Element("false")
def _bool_element(value: bool, ctx: SimpleNamespace) -> etree.Element: if value: return etree.Element("true") return etree.Element("false")
def _date_element(date: datetime, ctx: SimpleNamespace) -> etree.Element: el = etree.Element("date") el.text = _date_to_string(date) return el
def _real_element(value: float, ctx: SimpleNamespace) -> etree.Element: el = etree.Element("real") el.text = repr(value) return el
def _integer_element(value: int, ctx: SimpleNamespace) -> etree.Element: if -1 << 63 <= value < 1 << 64: el = etree.Element("integer") el.text = "%d" % value return el raise OverflowError(value)
def _string_element(value, ctx): el = etree.Element("string") el.text = value return el
def _string_element(value: str, ctx: SimpleNamespace) -> etree.Element: el = etree.Element("string") el.text = value return el