Source code for pycsamt.api.view.config
"""Global configuration for pyCSAMT API view wrappers."""
from __future__ import annotations
import copy
import os
from collections.abc import Callable, Generator
from contextlib import contextmanager
from typing import Any
__all__ = [
"APIViewConfig",
"PYCSAMT_API_VIEW",
"configure_api_view",
"reset_api_view",
]
ViewWrapper = Callable[..., Any]
_PYCSAMT_BACKENDS = {"api", "apiframe", "pycsamt", "view"}
_PANDAS_BACKENDS = {"false", "none", "off", "pandas", "raw"}
def _normalise_backend(value: Any) -> str | ViewWrapper:
if callable(value):
return value
if isinstance(value, bool):
return "pycsamt" if value else "pandas"
if value is None:
return "pandas"
name = str(value).strip().lower()
if name in _PYCSAMT_BACKENDS:
return "pycsamt"
if name in _PANDAS_BACKENDS:
return "pandas"
msg = (
"api view backend must be 'pycsamt', 'pandas'/False, "
"or a callable wrapper."
)
raise ValueError(msg)
[docs]
class APIViewConfig:
"""Package-wide policy for dataframe-like public API views.
The backend controls what :func:`pycsamt.api.view.wrap_frame` returns:
* ``"pycsamt"`` / ``True``: return the built-in ``APIFrame``.
* ``"pandas"`` / ``False``: return the original dataframe-like object.
* callable: call ``wrapper(data, **metadata)`` and return its result.
"""
def __init__(self) -> None:
self._init_defaults()
def _init_defaults(self) -> None:
self.backend: str | ViewWrapper = _normalise_backend(
os.environ.get("PYCSAMT_API_VIEW", "pycsamt")
)
[docs]
@contextmanager
def context(self, **kw: Any) -> Generator[APIViewConfig, None, None]:
"""Temporarily override API view settings."""
snapshot = copy.copy(self.backend)
try:
if kw:
self.configure(**kw)
yield self
finally:
self.backend = snapshot
[docs]
def reset(self) -> None:
"""Reset to defaults."""
self._init_defaults()
[docs]
def wrap_frame(self, data: Any, **metadata: Any) -> Any:
"""Apply the configured dataframe wrapper."""
backend = self.backend
if backend == "pandas":
return data
if callable(backend):
return backend(data, **metadata)
from .frame import _default_wrap_frame
return _default_wrap_frame(data, **metadata)
[docs]
def enabled(self) -> bool:
"""Return whether API view wrapping is enabled."""
return self.backend != "pandas"
[docs]
def summary(self) -> str:
"""Return a compact configuration summary."""
backend = self.backend
if callable(backend):
name = getattr(backend, "__name__", backend.__class__.__name__)
else:
name = str(backend)
return f"APIViewConfig(backend={name!r})"
def __repr__(self) -> str:
return self.summary()
PYCSAMT_API_VIEW = APIViewConfig()
[docs]
def reset_api_view() -> None:
"""Reset the global API view backend."""
PYCSAMT_API_VIEW.reset()