Skip to content

Sandbox

sandbox

Session sandbox: redirect the six AXM state paths to an ephemeral root.

The sandbox lives entirely in the inherited environment (AXM_SANDBOX_* keys), never in module state, so a child process spawned while a sandbox is active reconstructs the same sandbox and the same launch profile. In any process where AXM_SANDBOX_ROOT is absent, :func:active_sandbox returns None and every resolver behaves exactly as before.

This module must not import :mod:axm_config.paths nor :mod:axm_config.profile: profile.current_profile depends on it.

SandboxEscapeError

Bases: ConfigError

A launch variable points a sandboxed path at the real AXM state.

Source code in packages/axm-config/src/axm_config/sandbox.py
Python
class SandboxEscapeError(ConfigError):
    """A launch variable points a sandboxed path at the real AXM state."""

SessionSandbox dataclass

An active session sandbox and the launch values it was built from.

previous records the AXM_SANDBOX_* and AXM_PROFILE values seen at activation so :func:deactivate_sandbox can restore them exactly (nested in-process sessions). It is empty on a sandbox reconstructed from the environment by :func:active_sandbox.

Source code in packages/axm-config/src/axm_config/sandbox.py
Python
@dataclass(frozen=True)
class SessionSandbox:
    """An active session sandbox and the launch values it was built from.

    ``previous`` records the ``AXM_SANDBOX_*`` and ``AXM_PROFILE`` values seen
    at activation so :func:`deactivate_sandbox` can restore them exactly
    (nested in-process sessions). It is empty on a sandbox reconstructed from
    the environment by :func:`active_sandbox`.
    """

    root: Path
    launch_home: Path
    launch_profile: str | None
    launch_axm_home: str | None
    previous: tuple[tuple[str, str | None], ...] = field(
        default=(), compare=False, repr=False
    )

activate_sandbox(root, environ=None)

Publish a sandbox on root in environ and strip AXM_PROFILE.

Raises :class:SandboxEscapeError when one of the six launch variables resolves at or under <HOME>/axm or <HOME>/.axm. Creates no directory: the caller owns the root.

Source code in packages/axm-config/src/axm_config/sandbox.py
Python
def activate_sandbox(
    root: Path,
    environ: MutableMapping[str, str] | None = None,
) -> SessionSandbox:
    """Publish a sandbox on ``root`` in ``environ`` and strip ``AXM_PROFILE``.

    Raises :class:`SandboxEscapeError` when one of the six launch variables
    resolves at or under ``<HOME>/axm`` or ``<HOME>/.axm``. Creates no
    directory: the caller owns the root.
    """
    env = _environ(environ)
    launch_home = _home_of(env)
    _refuse_escapes(env, launch_home)
    outer = active_sandbox(env)
    launch_profile = env.get(_PROFILE_ENV) or (
        outer.launch_profile if outer is not None else None
    )
    launch_axm_home = env.get("AXM_HOME") or None
    sandbox = SessionSandbox(
        root=Path(root),
        launch_home=launch_home,
        launch_profile=launch_profile,
        launch_axm_home=launch_axm_home,
        previous=tuple((key, env.get(key)) for key in _RESTORED_KEYS),
    )
    env[SANDBOX_ROOT_ENV] = str(root)
    env[_LAUNCH_HOME_ENV] = str(launch_home)
    env[_LAUNCH_PROFILE_ENV] = launch_profile or ""
    env[_LAUNCH_AXM_HOME_ENV] = launch_axm_home or ""
    env.pop(_PROFILE_ENV, None)
    return sandbox

active_sandbox(environ=None)

Return the sandbox published in environ, or None when inactive.

Source code in packages/axm-config/src/axm_config/sandbox.py
Python
def active_sandbox(
    environ: MutableMapping[str, str] | None = None,
) -> SessionSandbox | None:
    """Return the sandbox published in ``environ``, or ``None`` when inactive."""
    env = _environ(environ)
    root = env.get(SANDBOX_ROOT_ENV)
    if not root:
        return None
    launch_home = env.get(_LAUNCH_HOME_ENV)
    return SessionSandbox(
        root=Path(root),
        launch_home=Path(launch_home) if launch_home else Path.home(),
        launch_profile=env.get(_LAUNCH_PROFILE_ENV) or None,
        launch_axm_home=env.get(_LAUNCH_AXM_HOME_ENV) or None,
    )

deactivate_sandbox(sandbox, environ=None)

Restore the environment sandbox replaced at activation.

Source code in packages/axm-config/src/axm_config/sandbox.py
Python
def deactivate_sandbox(
    sandbox: SessionSandbox,
    environ: MutableMapping[str, str] | None = None,
) -> None:
    """Restore the environment ``sandbox`` replaced at activation."""
    env = _environ(environ)
    previous = sandbox.previous or (
        *((key, None) for key in _RESTORED_KEYS[:-1]),
        (_PROFILE_ENV, sandbox.launch_profile),
    )
    for key, value in previous:
        if value is None:
            env.pop(key, None)
        else:
            env[key] = value