Source code for pycsamt.emtf.xml.writer

# Author: LKouadio <etanoyau@gmail.com>
# License: LGPL-3.0

"""Filesystem/stream writer for the EMTF XML serializer."""

from __future__ import annotations

from os import PathLike
from pathlib import Path
from typing import IO
import xml.etree.ElementTree as ET

from ...api.property import PyCSAMTObject
from ..document import EMTF
from .serializer import EMTFXMLSerializer

__all__ = ["EMTFXMLWriter", "write_emtf_xml"]


[docs] class EMTFXMLWriter(PyCSAMTObject): """Serialize :class:`~pycsamt.emtf.EMTF` documents as EMTF XML. Parameters ---------- strict : bool, default=True Reject unsupported/ambiguous scientific content rather than silently dropping it. precision : int, default=17 Significant digits used for floating-point response data. pretty : bool, default=True Indent the generated XML for human readability. """ def __init__( self, *, strict: bool = True, precision: int = 17, pretty: bool = True, ) -> None: self.serializer = EMTFXMLSerializer( strict=strict, precision=precision, ) self.pretty = bool(pretty)
[docs] def to_element(self, document: EMTF) -> ET.Element: """Return a serialized root element.""" root = self.serializer.to_element(document) if self.pretty: ET.indent(root, space=" ") return root
[docs] def dumps( self, document: EMTF, *, xml_declaration: bool = True, encoding: str = "utf-8", ) -> str: """Return a Unicode EMTF XML document.""" root = self.to_element(document) body = ET.tostring(root, encoding="unicode", short_empty_elements=True) if not xml_declaration: return body label = str(encoding).replace("_", "-").upper() return f'<?xml version="1.0" encoding="{label}"?>\n' + body
[docs] def write( self, document: EMTF, target: str | PathLike[str] | IO[str] | IO[bytes], *, xml_declaration: bool = True, encoding: str = "utf-8", ) -> Path | IO[str] | IO[bytes]: """Write *document* to a filesystem path or writable stream.""" text = self.dumps( document, xml_declaration=xml_declaration, encoding=encoding, ) if isinstance(target, (str, PathLike)): path = Path(target).expanduser() path.parent.mkdir(parents=True, exist_ok=True) path.write_text(text, encoding=encoding) return path write = getattr(target, "write", None) if not callable(write): raise TypeError("target must be a path or writable file object") try: write(text) except TypeError: write(text.encode(encoding)) return target
[docs] def write_emtf_xml( document: EMTF, target: str | PathLike[str] | IO[str] | IO[bytes], *, strict: bool = True, precision: int = 17, pretty: bool = True, xml_declaration: bool = True, encoding: str = "utf-8", ) -> Path | IO[str] | IO[bytes]: """Convenience wrapper around :class:`EMTFXMLWriter`.""" return EMTFXMLWriter( strict=strict, precision=precision, pretty=pretty, ).write( document, target, xml_declaration=xml_declaration, encoding=encoding, )