Source code for exlab_wizard.config.test_bootstrap
"""Starter ``config.yaml`` bootstrap for the ``-test`` sandbox.
Shared by the tray's ``--test`` flag (:mod:`exlab_wizard.tray.main`) and the
standalone dev seeder (:mod:`exlab_wizard.dev.seed`). Lives in the light
``config`` package so the dev command can reuse it without importing the heavy
``tray`` package (whose ``__init__`` pulls in pystray and the server stack).
"""
from __future__ import annotations
from pathlib import Path
from exlab_wizard.logging import get_logger
_log = get_logger(__name__)
[docs]
def write_starter_test_config(config_path: Path) -> None:
"""Write a starter test ``config.yaml`` if one does not already exist.
Pins ``paths.app_root`` to an ``app/`` folder under the test sandbox
(``config_path.parent``) -- rather than the real Documents-folder default --
so the whole working tree stays contained in the suffixed sandbox and the
wizard runs without manual Settings entry. The LIMS endpoint and email are
intentionally left blank so the operator still wires that integration
through the live Settings UI. Equipment is left empty -- sample equipment is
seeded separately by :func:`exlab_wizard.sample_data.generate_samples`.
Idempotent: an existing config is never overwritten. The sandbox is
persistent across launches and the operator resets it by deleting the
suffixed directory.
"""
if config_path.exists():
return
# Lazy imports keep this module's import graph light for callers that only
# need the function lazily (the tray test path and the dev command).
from exlab_wizard.config.loader import save_config
from exlab_wizard.config.models import Config, OrchestratorConfig, PathsConfig
from exlab_wizard.paths import ensure_app_dirs, ensure_dir
sandbox = config_path.parent # e.g. ~/Library/Application Support/exlab-wizard-test
paths_cfg = PathsConfig(app_root=str(sandbox / "app"))
orchestrator_cfg = OrchestratorConfig(
label="test-workstation",
staging_root=str(sandbox / "staging"),
)
cfg = Config(paths=paths_cfg, orchestrator=orchestrator_cfg, equipment=[])
save_config(config_path, cfg)
# Pre-create the app root + derived data/templates/plugins (and the staging
# root) so first-launch path lookups don't fail on a missing tree.
ensure_app_dirs(cfg)
ensure_dir(Path(orchestrator_cfg.staging_root))
_log.info("test mode: wrote starter config [path=%s]", str(config_path))
[docs]
def bootstrap_test_config(config_path: Path, *, include_samples: bool) -> None:
"""Tray ``--test`` bootstrap: write the starter config, optionally seed samples.
No-op when a config already exists -- the sandbox is persistent, so a
repeat ``--test`` boot must neither overwrite the config nor re-seed (and
never wipes). On a fresh sandbox, writes the starter config and, when
``include_samples`` (``--add-test-samples``), expands the declarative
``SAMPLES`` tree through the shared generator in non-destructive mode.
"""
if config_path.exists():
return
write_starter_test_config(config_path)
if include_samples:
from exlab_wizard.sample_data import generate_samples
generate_samples(config_path, wipe=False)