"""Installed-vs-checkout detection and the platform user-data storage root.
The central settings facade (:class:`~core.config.Settings`) roots the
encrypted profile store at ``aeat_local_storage_root``, from which the token,
log, secret, blob and audit roots derive. Historically that root defaulted to
``PROJECT_ROOT / "var" / "storage"``, which is correct for a source checkout
but wrong for an installed distribution: under a wheel it resolves *inside* the
virtualenv, and under ``uvx`` inside uv's ephemeral cache, where a cache prune
could silently destroy the taxpayer's encrypted store.
This module owns the two decisions that fix that defect without disturbing the
dev loop: whether the process runs from a source checkout or an installed
distribution (:func:`detect_run_mode`), and where the platform user-data base
lives per operating system (:func:`platform_user_data_root`). A checkout keeps
the ``PROJECT_ROOT / "var" / "storage"`` default; an installed run lands under
the platform user-data directory (``%LOCALAPPDATA%`` on Windows,
``$XDG_DATA_HOME`` with the ``~/.local/share`` fallback on Linux,
``~/Library/Application Support`` on macOS).
Every input the resolution reads — the project-root candidate, the platform
string, the environment mapping, and the home directory — is captured in the
frozen :class:`StateRootInputs` seam so the detection is deterministic and
testable without mutating the ambient process. :func:`default_storage_root` is
the live entry point :class:`~core.config.Settings` binds as its
``aeat_local_storage_root`` default factory.
See Also:
:class:`~core.config.Settings`
Central settings aggregate whose storage-root default is resolved here.
:data:`~core.config.PROJECT_ROOT`
Checkout-root anchor mirrored when source-tree defaults are preserved.
:class:`StateRootInputs`
Frozen seam that captures every environmental input used by resolution.
:func:`detect_run_mode`
Checkout-versus-installed classifier used before selecting a root.
:func:`resolve_state_root`
Pure resolver that returns the effective storage root.
:func:`default_storage_root`
Live default factory bound into the settings model.
"""
from __future__ import annotations
import os
import sys
from enum import StrEnum
from pathlib import Path
from pydantic import BaseModel
from ._models import STRICT_FROZEN_CONFIG
# Project-root candidate: four levels up from this module
# (file → core/ → aeat/ → src/ → REPO_ROOT), mirroring
# :data:`~core.config.PROJECT_ROOT` exactly so the checkout default is
# byte-identical to the historical value.
_MODULE_PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent.parent
_WINDOWS_PLATFORM = "win32"
_MACOS_PLATFORM = "darwin"
#: Vendor/application directory name appended to the platform user-data base.
_APP_DIRNAME = "aeat"
#: Storage substrate subdirectory under the resolved installed state root.
_STORAGE_DIRNAME = "storage"
#: Checkout state-root layout: ``PROJECT_ROOT / "var" / "storage"``.
_CHECKOUT_STATE_SUBDIRS = ("var", "storage")
[docs]
class RunMode(StrEnum):
"""Whether the process runs from a source checkout or an installed build.
:func:`detect_run_mode` returns a member; :func:`resolve_state_root`
branches on it to pick the checkout ``var/storage`` default or the
platform user-data directory.
"""
CHECKOUT = "checkout"
INSTALLED = "installed"
[docs]
class StateRootResolution(BaseModel):
"""Typed outcome of resolving the storage state root.
Carries the decided :class:`RunMode`, the project-root candidate it was
decided from, the platform user-data base, and the effective
``storage_root`` that :class:`~core.config.Settings` should default
``aeat_local_storage_root`` to.
"""
model_config = STRICT_FROZEN_CONFIG
run_mode: RunMode
project_root: Path
platform_user_data_root: Path
storage_root: Path
[docs]
def detect_run_mode(inputs: StateRootInputs) -> RunMode:
"""Classify the run as a source checkout or an installed distribution.
A source checkout carries the repository markers at its project root: a
``pyproject.toml`` file and a ``.git`` entry (a directory in a normal
clone, a pointer *file* inside a git worktree — so presence, not
directory-ness, is the test). An installed wheel resolves the candidate
under ``site-packages`` where neither marker exists, so the absence of
either marker classifies the run as installed.
"""
root = inputs.project_root_candidate
has_pyproject = (root / "pyproject.toml").is_file()
has_git_marker = (root / ".git").exists()
if has_pyproject and has_git_marker:
return RunMode.CHECKOUT
return RunMode.INSTALLED
def _env_absolute_path(environ: dict[str, str], name: str) -> Path | None:
"""Return an absolute :class:`~pathlib.Path` from ``environ[name]``, or ``None``.
A blank, unset, or non-absolute value yields ``None`` so the caller falls
back to the platform default. The absolute-only rule matches the XDG Base
Directory specification (a relative ``$XDG_DATA_HOME`` is ignored) and is
applied uniformly to ``%LOCALAPPDATA%`` for the same robustness.
"""
raw = environ.get(name, "").strip()
if not raw:
return None
candidate = Path(raw)
return candidate if candidate.is_absolute() else None
[docs]
def resolve_state_root(inputs: StateRootInputs) -> StateRootResolution:
"""Resolve the effective storage state root for the given inputs.
A checkout keeps the historical ``PROJECT_ROOT / "var" / "storage"``
default; an installed run lands at ``<platform-user-data>/aeat/storage`` so
the encrypted store never resolves inside a virtualenv or uv cache.
"""
run_mode = detect_run_mode(inputs)
user_data_root = platform_user_data_root(inputs)
if run_mode is RunMode.CHECKOUT:
storage_root = inputs.project_root_candidate.joinpath(*_CHECKOUT_STATE_SUBDIRS)
else:
storage_root = user_data_root / _STORAGE_DIRNAME
return StateRootResolution(
run_mode=run_mode,
project_root=inputs.project_root_candidate,
platform_user_data_root=user_data_root,
storage_root=storage_root,
)
[docs]
def default_storage_root() -> Path:
"""Return the ``aeat_local_storage_root`` default for the live process.
Bound as the :class:`~core.config.Settings` ``aeat_local_storage_root``
default factory: a checkout resolves to ``PROJECT_ROOT / "var" / "storage"``
(unchanged), an installed run to the platform user-data storage directory.
"""
return resolve_state_root(live_state_root_inputs()).storage_root