Source code for pycsamt.jones.base

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

"""Minimal bases for the Jones (J-format) subsystem."""

from __future__ import annotations

import io
from collections.abc import Iterable
from pathlib import Path
from typing import Any, ClassVar

from ..utils.validation import has_read
from .config import ENCODING_DEFAULT
from .utils import iter_lines

__all__ = ["BaseJones", "JComponentBase"]


[docs] class BaseJones: """Root base for all Jones objects. Provides a common interface and light I/O hooks. Subclasses must implement ``from_lines``, ``read`` and ``write``. """ _repr_keys: ClassVar[list[str]] = ["path", "encoding"] def __init__(self, *, verbose: int | bool = 0) -> None: self.verbose: int | bool = verbose self.path: Path | None = None self.encoding: str = ENCODING_DEFAULT self._has_read: bool = False
[docs] @classmethod def from_file( cls, obj: io.TextIOBase | str | Path, *, encoding: str = ENCODING_DEFAULT, verbose: int | bool = 0, **kws: Any, ) -> BaseJones: lines = iter_lines(obj, encoding=encoding) inst = cls.from_lines(lines, verbose=verbose, **kws) if isinstance(obj, (str, Path)): inst.path = Path(obj) inst.encoding = encoding return inst
[docs] @classmethod def from_lines( cls, lines: Iterable[str], *, verbose: int | bool = 0, **kws: Any, ) -> BaseJones: raise NotImplementedError( f"{cls.__name__}.from_lines() not implemented" )
[docs] def read(self, *args: Any, **kws: Any) -> BaseJones: raise NotImplementedError( f"{self.__class__.__name__}.read() not implemented" )
[docs] def write( self, obj: io.TextIOBase | str | Path, *, encoding: str | None = None, **kws: Any, ) -> None: raise NotImplementedError( f"{self.__class__.__name__}.write() not implemented" )
def __has_read__(self) -> bool: return bool(self._has_read) def _mark_read(self, state: bool = True) -> None: self._has_read = bool(state)
[docs] def require_read( self, *, attributes: str | list[str] | None = None, msg: str | None = None, ) -> None: has_read(self, attributes=attributes, msg=msg)
[docs] def to_dict(self) -> dict[str, Any]: out: dict[str, Any] = {} for k, v in vars(self).items(): if k.startswith("_"): continue if callable(v): continue out[k] = v return out
[docs] def summary(self) -> str: parts = [] for k in self._repr_keys: if hasattr(self, k): v = getattr(self, k) if v is not None: parts.append(f"{k}={v!r}") return f"{self.__class__.__name__}({', '.join(parts)})"
def __str__(self) -> str: return self.summary() def __repr__(self) -> str: s = self.summary() if s.endswith("())"): return f"{self.__class__.__name__}({self.to_dict()})" return s
[docs] class JComponentBase(BaseJones): """Common base for concrete components. All components must accept ``verbose`` in ``__init__`` and must implement ``from_file``, ``from_lines``, ``read`` and ``write``. """ _repr_keys: ClassVar[list[str]] = [ "name", "station", "kind", "comp", "units", "n", "shape", ]