Source code for conda_workspaces.context

"""Workspace context — lazy properties for conda & workspace state.

Provides a namespace of lazily-evaluated properties that downstream
code can use without importing conda at module level.  This keeps
import-time overhead negligible.
"""

from __future__ import annotations

import os
from pathlib import Path
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .models import WorkspaceConfig


[docs] class WorkspaceContext: """Lazy-evaluated context for the current workspace. Properties are resolved on first access and cached. Conda imports are deferred to keep plugin load time under 1 ms. """ def __init__(self, config: WorkspaceConfig | None = None) -> None: self._config = config self._cache: dict[str, object] = {} @property def config(self) -> WorkspaceConfig: """The parsed workspace configuration.""" if self._config is None: from .parsers import detect_and_parse _, self._config = detect_and_parse() return self._config @property def root(self) -> Path: """Workspace root directory.""" return Path(self.config.root) @property def envs_dir(self) -> Path: """Directory where project-local environments are stored.""" return self.root / self.config.envs_dir @property def platform(self) -> str: """Current conda subdir (e.g. ``osx-arm64``).""" if "platform" not in self._cache: from conda.base.context import context self._cache["platform"] = context.subdir return self._cache["platform"] # type: ignore[return-value] @property def root_prefix(self) -> Path: """Conda root prefix (base environment).""" if "root_prefix" not in self._cache: from conda.base.context import context self._cache["root_prefix"] = Path(context.root_prefix) return self._cache["root_prefix"] # type: ignore[return-value]
[docs] def env_prefix(self, env_name: str) -> Path: """Return the prefix path for a named environment.""" return self.envs_dir / env_name
[docs] def env_exists(self, env_name: str) -> bool: """Check whether the prefix is a valid conda environment.""" from conda.core.envs_manager import PrefixData prefix = self.env_prefix(env_name) return PrefixData(str(prefix)).is_environment()
[docs] class CondaContext: """Lazy-evaluated namespace exposed as ``conda.*`` in task templates. Attribute access is deferred so conda internals load only when a template references a variable. """ def __init__(self, manifest_path: Path | None = None) -> None: self._manifest_path = manifest_path @property def platform(self) -> str: """The conda platform/subdir string, e.g. ``linux-64`` or ``osx-arm64``.""" from conda.base.context import context return context.subdir @property def environment_name(self) -> str: """Name of the currently active conda environment, or ``"base"``.""" from conda.base.context import context if context.active_prefix: return Path(context.active_prefix).name return "base" @property def environment(self) -> _EnvironmentProxy: """Allows ``{{ conda.environment.name }}`` in templates.""" return _EnvironmentProxy(self.environment_name) @property def prefix(self) -> str: """Absolute path to the target conda environment prefix.""" from conda.base.context import context return str(context.target_prefix) @property def version(self) -> str: """The installed conda version string.""" from conda import __version__ return __version__ @property def manifest_path(self) -> str: """Path to the task definition file, or empty string if unknown.""" return str(self._manifest_path) if self._manifest_path else "" @property def init_cwd(self) -> str: """The working directory at the time of context creation.""" return os.getcwd() @property def is_win(self) -> bool: """True when running on Windows.""" from conda.base.constants import on_win return on_win @property def is_unix(self) -> bool: """True when running on a Unix-like system (Linux or macOS).""" from conda.base.constants import on_win return not on_win @property def is_osx(self) -> bool: """True when the host platform is macOS.""" from conda.base.context import context return context.platform == "osx" @property def is_linux(self) -> bool: """True when the host platform is Linux.""" from conda.base.context import context return context.platform == "linux"
class _EnvironmentProxy: """Allows ``{{ conda.environment.name }}`` in templates.""" def __init__(self, name: str) -> None: self.name = name
[docs] def build_template_context( manifest_path: Path | None = None, task_args: dict[str, str] | None = None, ) -> dict[str, object]: """Build the full Jinja2 template context dict. The returned dict contains: - ``conda``: a :class:`CondaContext` instance - ``pixi``: alias to the same context (for pixi.toml compatibility) - Any user-supplied task argument values """ ctx = CondaContext(manifest_path=manifest_path) result: dict[str, object] = {"conda": ctx, "pixi": ctx} if task_args: result.update(task_args) return result