Source code for ooodev.io.json.json_custom_props

from __future__ import annotations
from typing import Any, TYPE_CHECKING
import contextlib
from ooodev.utils.gen_util import NULL_OBJ
from ooodev.utils.helper.dot_dict import DotDict
from ooodev.io.json.doc_json_file import DocJsonFile
from ooodev.io.log.named_logger import NamedLogger
from ooodev import get_version


if TYPE_CHECKING:
    from ooodev.proto.office_document_t import OfficeDocumentT


[docs]class JsonCustomProps: """ Class to add custom properties to a document. The properties are stored in a json file embedded in the document. Allows custom properties to be added to a document. Note: Any value that can be serialized to JSON can be stored as a custom property. Classes can implement the :py:class:`ooodev.io.json.json_encoder.JsonEncoder` class to provide custom serialization by overriding the ``on_json_encode()`` method. """
[docs] def __init__(self, doc: OfficeDocumentT, file_name: str = "DocumentCustomProperties.json"): """ Constructor. Args: doc (Any): The document. file_name (str, optional): The name of the file to store the properties. Defaults to "DocumentCustomProperties.json". """ self._log = NamedLogger(self.__class__.__name__) self._json_doc = DocJsonFile(doc, "json") if not file_name.endswith(".json"): file_name = f"{file_name}.json" self._name = file_name self._props = self._get_custom_properties()
# please the type checker def _get_custom_properties(self) -> dict: """ Loads custom properties from the hidden control. """ if not self._json_doc.file_exist(self._name): self._log.debug(f"File does not exist: {self._name}. Creating empty dictionary.") return {} try: result = self._json_doc.read_json(self._name) return result.get("data", {}) except Exception: self._log.error(f"Error reading JSON file: {self._name}. Returning empty dictionary.", exc_info=True) return {} def _save_properties(self, data: dict) -> None: """ Saves custom properties to the hidden control. Args: properties (dict): The properties to save. """ try: json_data = { "id": "ooodev.io.json.json_custom_props.JsonCustomProps", "version": get_version(), "data": data, } self._json_doc.write_json(self._name, json_data) except Exception: self._log.error(f"Error writing JSON file: {self._name}", exc_info=True)
[docs] def get_custom_property(self, name: str, default: Any = NULL_OBJ) -> Any: """ Gets a custom property. Args: name (str): The name of the property. default (Any, optional): The default value to return if the property does not exist. Raises: AttributeError: If the property is not found. Returns: Any: The value of the property. """ result = self._props.get(name, default) if result is NULL_OBJ: self._log.error(f"Property '{name}' not found.") raise AttributeError(f"Property '{name}' not found.") return result
[docs] def set_custom_property(self, name: str, value: Any): """ Sets a custom property. Args: name (str): The name of the property. value (Any): The value of the property. Raises: AttributeError: If the property is a forbidden key. """ with contextlib.suppress(Exception): props = self._props.copy() props[name] = value self._save_properties(props) self._props = props
[docs] def get_custom_properties(self) -> DotDict: """ Gets custom properties. Returns: DotDict: custom properties. Hint: DotDict is a class that allows you to access dictionary keys as attributes or keys. DotDict can be imported from ``ooodev.utils.helper.dot_dict.DotDict``. """ dd = DotDict() dd.update(self._props) return dd
[docs] def set_custom_properties(self, properties: DotDict) -> None: """ Sets custom properties. Args: properties (DotDict): custom properties to set. Hint: DotDict is a class that allows you to access dictionary keys as attributes or keys. DotDict can be imported from ``ooodev.utils.helper.dot_dict.DotDict``. """ with contextlib.suppress(Exception): props = self._props.copy() props.update(properties.copy_dict()) self._save_properties(props) self._props = props
[docs] def remove_custom_property(self, name: str) -> None: """ Removes a custom property. Args: name (str): The name of the property to remove. Raises: AttributeError: If the property is a forbidden key. Returns: None: """ with contextlib.suppress(Exception): props = self._props.copy() if name in props: del props[name] self._save_properties(props) self._props = props
[docs] def has_custom_property(self, name: str) -> bool: """ Gets if a custom property exists. Args: name (str): The name of the property to check. Returns: bool: ``True`` if the property exists, otherwise ``False``. """ return name in self._props