autocal layout first design

This commit is contained in:
ykcheungab
2026-09-20 21:15:39 +08:00
parent 07d7c3bad6
commit e276b5de0f
92 changed files with 18071 additions and 64 deletions
+56 -10
View File
@@ -1,34 +1,80 @@
"""Resolve app, config, and output paths for editable and frozen runs."""
"""Resolve app, config, and output paths for editable and frozen runs.
Several desktop products share this package. Which one a process belongs to is
decided once, at start-up:
* ``ORISYS_APP_ID`` — the directory name under ``apps/`` (e.g. ``studio``,
``autocal``). Set it **before** importing anything from this package; an app
that changes it later gets whichever root was resolved first, because these
helpers are called during import of logging/prefs.
* Otherwise the historic behaviour applies, which resolves ``apps/studio``.
That keeps existing callers working without them passing anything.
"""
from __future__ import annotations
import os
import sys
from pathlib import Path
#: Environment variable naming the app directory under ``apps/``.
APP_ID_ENV = "ORISYS_APP_ID"
#: Fallback app when ``ORISYS_APP_ID`` is unset — the first product built here.
DEFAULT_APP_ID = "studio"
def is_frozen() -> bool:
return bool(getattr(sys, "frozen", False))
def _studio_root_from_shared() -> Path:
"""Repo layout: shared/src/orisys_app_shared -> apps/studio."""
def app_id() -> str:
"""The app directory name for this process."""
return os.environ.get(APP_ID_ENV, "").strip() or DEFAULT_APP_ID
def apps_dir() -> Path:
"""The ``apps/`` directory of the source tree."""
here = Path(__file__).resolve()
# .../orisys-app/shared/src/orisys_app_shared/paths.py
# .../orisys-app/shared/src/orisys_app_shared/paths.py -> .../orisys-app
repo_root = here.parents[3]
return repo_root / "apps" / "studio"
return repo_root / "apps"
def _default_app_root_from_shared(app_id_value: str) -> Path:
"""Repo layout: shared/src/orisys_app_shared -> apps/<app>."""
return apps_dir() / app_id_value
def app_root() -> Path:
"""Return the studio app root (editable) or EXE directory (frozen)."""
"""Return this app's root (editable) or the EXE directory (frozen)."""
if is_frozen():
return Path(sys.executable).resolve().parent
# Prefer cwd override when launched from apps/studio
wanted = app_id()
# Launched from inside an app directory (``python apps/<app>/run.py``).
cwd = Path.cwd().resolve()
if (cwd / "config").is_dir() and (cwd / "run.py").is_file():
return cwd
if (cwd / "apps" / "studio" / "config").is_dir():
return cwd / "apps" / "studio"
return _studio_root_from_shared()
# Launched from the repo root.
candidate = cwd / "apps" / wanted
if (candidate / "config").is_dir():
return candidate
# A named app that is not where we expected must not silently fall back to
# another product's config: that would write one app's preferences into
# another's tree.
if wanted == DEFAULT_APP_ID:
return _default_app_root_from_shared(wanted)
unresolved = _default_app_root_from_shared(wanted)
if (unresolved / "config").is_dir():
return unresolved
raise FileNotFoundError(
f"{APP_ID_ENV}={wanted!r} does not name an app with a config directory "
f"(looked in {cwd / 'apps' / wanted} and {unresolved})"
)
def config_dir() -> Path: