Source code for modelly.studio.config

"""What one Studio server shows: the model, its portrayal and the panels' settings.

The command line builds a ``StudioConfig`` and hands it to the Solara app through one
environment variable as JSON, so the app module finds it however Solara imports it.
"""

from __future__ import annotations

import json
import os
from dataclasses import asdict, dataclass
from pathlib import Path

ENV_VAR = "MODELLY_STUDIO_CONFIG"
DEFAULT_SEED = 42
DEFAULT_EVERY = 1
DEFAULT_PROFILE_STEPS = 50
DEFAULT_TABLE_ROWS = 100
MEBIBYTE = 2**20
DEFAULT_BUDGET_MIB = 256


[docs] @dataclass(frozen=True) class StudioConfig: """The settings of a Studio session. Attributes: target: ``path/to/model.py:ModelClass`` or ``package.module:ModelClass``. portrayal: ``path/to/app.py:function`` or ``package.module:function`` returning an ``AgentPortrayalStyle`` per agent; one colour per agent class when None. seed: The seed the first run starts from. every: Steps between two checkpoints of the timeline. profile_steps: How many of the last steps the profiler panel sums. table_rows: Rows the agent table shows. memory_budget_mib: Mebibytes the timeline's checkpoints may take. """ target: str portrayal: str | None = None seed: int = DEFAULT_SEED every: int = DEFAULT_EVERY profile_steps: int = DEFAULT_PROFILE_STEPS table_rows: int = DEFAULT_TABLE_ROWS memory_budget_mib: int = DEFAULT_BUDGET_MIB @property def memory_budget(self) -> int: """The checkpoint budget in bytes.""" return self.memory_budget_mib * MEBIBYTE @property def source_file(self) -> Path | None: """The model's ``.py`` file when the target names one, for the lint panel.""" source = self.target.rpartition(":")[0] return Path(source) if source.endswith(".py") else None
[docs] def to_json(self) -> str: """The config as JSON.""" return json.dumps(asdict(self))
[docs] @classmethod def from_json(cls, text: str) -> StudioConfig: """A config from ``to_json`` output.""" return cls(**json.loads(text))
[docs] def export(self) -> None: """Put the config in the environment, for the app module to read.""" os.environ[ENV_VAR] = self.to_json()
[docs] @classmethod def from_environment(cls) -> StudioConfig: """The config ``export`` put in the environment. Raises: RuntimeError: When there is none, i.e. the app was not started by ``modelly studio``. """ text = os.environ.get(ENV_VAR) if not text: raise RuntimeError( f"{ENV_VAR} is not set: start Studio with `modelly studio path/to/model.py:Model`" ) return cls.from_json(text)