Source code for ds_provider_tripletex_py_lib.read_info
"""
**File:** ``read_info.py``
**Region:** ``ds_provider_tripletex_py_lib/read_info``
Read and field-projection information for Tripletex products.
Each :class:`~ds_provider_tripletex_py_lib.enums.TripletexProductName` has a
packaged ``assets/<product_name>/read/metadata.json`` declaring ``path``,
``pagination`` (``"date_window"`` if the endpoint has ``dateFrom``/``dateTo``,
else ``"offset"``), ``changed_since`` (use Tripletex's ``changedSince``
filter instead of ``versionDigest``/``If-None-Match``), a field selector
(``str``, or a one-key ``dict`` for a nested group, e.g. ``{"account": ["id"]}``),
and an optional ``explode_columns`` (fields that are a list of objects,
needing one row per element rather than in-place flattening). ``_lite``
products reuse a full product's path with fewer fields.
"""
import json
from dataclasses import dataclass, field
from importlib.resources import files
from typing import Any, cast
from ds_resource_plugin_py_lib.common.resource.errors import ValidationError
from .enums import OperationType, PaginationKind, TripletexProductName
[docs]
@dataclass(frozen=True)
class ReadInfo:
"""
Read information for a single Tripletex product.
Attributes:
path: API path segment appended to the linked service host, e.g. ``"ledger/posting"``.
fields: Field selector list used to build the ``fields`` query parameter.
changed_since: Whether this product supports Tripletex's ``changedSince``
filter (replaces ``versionDigest``/``If-None-Match`` when ``True``).
pagination: How ``read()`` requests are paginated for this product.
explode_columns: Field names that are a list of objects and should be
exploded into one row per element, e.g. ``["bankAccountPresentation"]``.
"""
path: str
fields: list[Any]
changed_since: bool
pagination: PaginationKind = PaginationKind.OFFSET
explode_columns: list[str] = field(default_factory=list)
[docs]
def get_read_info(product_name: TripletexProductName) -> ReadInfo:
"""
Load packaged read metadata for a Tripletex product.
Every :class:`TripletexProductName` member must ship read assets, so a
missing file is treated the same as a malformed one -- a packaging bug,
not a condition to degrade gracefully from.
Args:
product_name: Tripletex product to load.
Returns:
ReadInfo: Read info built from ``assets/<product_name>/read/metadata.json``.
Raises:
ValidationError: If the metadata file is missing, or exists but is
missing a required key (``path``, ``fields``, ``pagination``,
``changed_since``) or ``pagination`` is not a recognized
:class:`PaginationKind` value.
"""
try:
payload = _load_metadata(product_name, OperationType.READ)
except FileNotFoundError as exc:
raise ValidationError(
message=f"Missing read metadata for Tripletex product '{product_name.value}'",
details={"product_name": product_name.value, "operation": OperationType.READ.value},
) from exc
try:
return ReadInfo(
path=payload["path"],
fields=payload["fields"],
pagination=PaginationKind(payload["pagination"]),
changed_since=payload["changed_since"],
explode_columns=payload.get("explode_columns", []),
)
except (KeyError, ValueError) as exc:
raise ValidationError(
message=f"Invalid read metadata for Tripletex product '{product_name.value}': {exc}",
details={"product_name": product_name.value, "operation": OperationType.READ.value},
) from exc