fleche.config ============= .. py:module:: fleche.config .. autoapi-nested-parse:: Configuration system for fleche. Storage type names ------------------ The ``type`` key in a storage config dict is case-sensitive and uses the following **lowercase** identifiers: ``"memory"`` In-memory dict (:class:`~fleche.storage.ValueMemory` / :class:`~fleche.storage.CallMemory`). No required keys. Optional (value backend): ``remaining_depth`` (int, default ``0``). ``"void"`` No-op — discards all data (:class:`~fleche.storage.ValueVoid` / :class:`~fleche.storage.CallVoid`). No required keys. ``"pickle"`` Filesystem backend serialised with the standard ``pickle`` module (:class:`~fleche.storage.ValuePickleFile` / :class:`~fleche.storage.CallPickleFile`). Required: ``root`` (path to storage directory). Optional: ``compress`` (bool, default ``False``) — gzip-compress files. Optional: ``lock_timeout`` (float, default ``1.0``) — write-lock wait timeout (s). Optional: ``lock_wait_start`` (float, default ``0.001``) — initial lock-poll interval for exponential backoff (s). Optional: ``secret_key`` (list of hex strings) — HMAC-SHA256 signing keys; each element is a hex-encoded byte string (same format as ``FLECHE_SECRET_KEY``). If omitted, falls back to the ``FLECHE_SECRET_KEY`` environment variable. Optional (value backend): ``remaining_depth`` (int, default ``0``). ``"cloudpickle"`` Filesystem backend serialised with ``cloudpickle`` — handles more complex Python objects than ``pickle``. Required: ``root``. Optional: ``compress`` (bool, default ``False``) — gzip-compress files. Optional: ``lock_timeout`` (float, default ``1.0``) — write-lock wait timeout (s). Optional: ``lock_wait_start`` (float, default ``0.001``) — initial lock-poll interval for exponential backoff (s). Optional: ``secret_key`` (list of hex strings) — same as ``"pickle"``. Optional (value backend): ``remaining_depth`` (int, default ``0``). ``"dill"`` Filesystem backend serialised with ``dill``. Required: ``root``. Optional: ``compress`` (bool, default ``False``) — gzip-compress files. Optional: ``lock_timeout`` (float, default ``1.0``) — write-lock wait timeout (s). Optional: ``lock_wait_start`` (float, default ``0.001``) — initial lock-poll interval for exponential backoff (s). Optional: ``secret_key`` (list of hex strings) — same as ``"pickle"``. Optional (value backend): ``remaining_depth`` (int, default ``0``). ``"bagofholding_hdf"`` HDF5-backed storage via the ``bagofholding`` library (:class:`~fleche.storage.ValueBagOfHoldingH5File` / :class:`~fleche.storage.CallBagOfHoldingH5File`). Required: ``root``. Optional: ``lock_timeout`` (float, default ``1.0``) — write-lock wait timeout (s). Optional: ``lock_wait_start`` (float, default ``0.001``) — initial lock-poll interval for exponential backoff (s). Optional: ``version_validator`` (str, default omitted) — version validation strategy passed to :meth:`bagofholding:bagofholding.h5.bag.H5Bag.load`. One of ``"exact"``, ``"semantic-minor"``, ``"semantic-major"``, ``"none"``. When omitted, bagofholding's default applies. Optional (value backend): ``remaining_depth`` (int, default ``0``). ``"sql"`` SQL database via SQLAlchemy (:class:`~fleche.storage.Sql`). *Call storage only.* Required: ``url`` (SQLAlchemy connection URL, e.g. ``"sqlite:///~/.fleche/calls.db"``). Optional: ``echo`` (bool, default ``False``) — log SQL statements. Example fleche.toml ------------------- :: [default] cache = "persistent" metadata = ["Runtime"] [persistent] values.type = "cloudpickle" values.root = "~/.fleche/values" calls.type = "cloudpickle" calls.root = "~/.fleche/calls" [fast] values.type = "memory" calls.type = "memory" [with_sql_calls] values.type = "cloudpickle" values.root = "~/.fleche/values" calls.type = "sql" calls.url = "sqlite:///~/.fleche/calls.db" Attributes ---------- .. autoapisummary:: fleche.config.logger fleche.config._live_caches fleche.config._STORAGE_NAME_MAPPING fleche.config._STORAGE_CLASS_TO_NAME Functions --------- .. autoapisummary:: fleche.config._load_config fleche.config._get_config_path fleche.config.load_default_metadata fleche.config.storage_from_config fleche.config._asdict_init_only fleche.config.storage_to_config fleche.config.cache_from_config fleche.config.cache_to_config fleche.config._create_cache fleche.config._default_memory_cache fleche.config.load_cache_config Module Contents --------------- .. py:data:: logger .. py:data:: _live_caches :type: dict[str | None, fleche.caches.Cache] .. py:function:: _load_config(path: pathlib.Path) -> dict[str, Any] .. py:function:: _get_config_path() -> pathlib.Path | None .. py:function:: load_default_metadata() Load the default metadata from the configuration file. .. py:data:: _STORAGE_NAME_MAPPING .. py:data:: _STORAGE_CLASS_TO_NAME :type: dict[type, str] .. py:function:: storage_from_config(d: dict[str, Any], type: Literal['call']) -> fleche.storage.CallStorage storage_from_config(d: dict[str, Any], type: Literal['value']) -> fleche.storage.ValueStorage Construct a :class:`~fleche.storage.StorageBackend` from a config dict. The dict must contain a ``"type"`` key (case-sensitive, lowercase) and any additional parameters required by that storage backend. The input dict is **not** mutated. Supported type values and their parameters: * ``{"type": "memory"}`` * ``{"type": "void"}`` * ``{"type": "pickle", "root": ""}`` — optional: ``compress``, ``lock_timeout``, ``lock_wait_start``, ``secret_key`` (list of hex strings), ``remaining_depth`` (value only) * ``{"type": "cloudpickle", "root": ""}`` — same optional keys as ``"pickle"`` * ``{"type": "dill", "root": ""}`` — same optional keys as ``"pickle"`` * ``{"type": "bagofholding_hdf", "root": ""}`` — optional: ``lock_timeout``, ``lock_wait_start``, ``version_validator``, ``remaining_depth`` (value only) * ``{"type": "sql", "url": ""}`` *(call storage only)* — optional: ``echo`` See the module docstring for full descriptions of each key. .. py:function:: _asdict_init_only(obj) -> dict[str, Any] Like ``dataclasses.asdict()`` but restricted to ``init=True`` fields. ``init=False`` fields are internal state (locks, caches) that must not appear in serialised config. .. py:function:: storage_to_config(s: fleche.storage.ValueStorage | fleche.storage.CallStorage) -> dict[str, Any] Convert a Storage instance to a config dict (inverse of ``storage_from_config``). The returned dict contains a ``"type"`` key and any additional parameters needed to reconstruct the storage via :func:`storage_from_config`. .. py:function:: cache_from_config(d: dict[str, Any] | list[dict[str, Any]]) -> fleche.caches.BaseCache Construct a :class:`~fleche.caches.BaseCache` from a config dict or list. The cache type is determined **implicitly** from the shape of the input: - A **list** of dicts is treated as a :class:`~fleche.caches.CacheStack`, with each element processed recursively. - A **dict** containing a ``max_size`` key creates a :class:`~fleche.caches.SizeLimitedCache`. - A **dict** containing ``read_only: true`` wraps the resulting cache in a :class:`~fleche.caches.ReadOnlyCache`. - Otherwise a plain :class:`~fleche.caches.Cache` is created. The input dict is **not** mutated. .. rubric:: Examples >>> c = cache_from_config({"values": {"type": "memory"}, "calls": {"type": "memory"}}) >>> type(c).__name__ 'Cache' >>> c = cache_from_config({"values": {"type": "memory"}, "calls": {"type": "memory"}, "max_size": 100}) >>> isinstance(c, caches.SizeLimitedCache) True >>> c = cache_from_config({"values": {"type": "memory"}, "calls": {"type": "memory"}, "read_only": True}) >>> isinstance(c, caches.ReadOnlyCache) True >>> c = cache_from_config([{"values": {"type": "memory"}, "calls": {"type": "memory"}}, {"values": {"type": "void"}, "calls": {"type": "void"}}]) >>> isinstance(c, caches.CacheStack) True .. py:function:: cache_to_config(c: fleche.caches.BaseCache) -> dict[str, Any] | list[dict[str, Any]] Convert a :class:`~fleche.caches.BaseCache` to a config dict or list. This is the inverse of :func:`cache_from_config`. The output can be round-tripped back via ``cache_from_config(cache_to_config(cache))``. - :class:`~fleche.caches.Cache` → dict with ``"values"`` and ``"calls"`` - :class:`~fleche.caches.SizeLimitedCache` → same dict plus ``"max_size"`` - :class:`~fleche.caches.ReadOnlyCache` wrapping a ``Cache`` or ``SizeLimitedCache`` → inner cache dict with ``"read_only": True`` - :class:`~fleche.caches.CacheStack` → list of dicts :raises ValueError: for unsupported cache types or unsupported ``ReadOnlyCache`` inner types. .. py:function:: _create_cache(cache_config: dict[str, Any]) -> fleche.caches.Cache .. py:function:: _default_memory_cache(name: str | None, reason: str | None = None) -> fleche.caches.Cache Return (and intern) a fresh in-memory cache, optionally logging the fallback reason. .. py:function:: load_cache_config(name: str | None = None) -> fleche.caches.Cache Load a cache from the configuration file. If name is None, the default cache is loaded. The names 'memory' and 'void' are special-cased to return a transient in-memory cache and a no-op cache respectively. Note: The `Tags` metadata cannot be configured from the config file.