Skip to content

workspace

_workspace

Workspace context detection for UV workspaces.

Detects whether a project path is a standalone package, a UV workspace root, or a member of a UV workspace. Used by the check engine to filter checks by context.

ProjectContext

Bases: StrEnum

Project context within a UV workspace layout.

Source code in packages/axm-init/src/axm_init/checks/_workspace.py
class ProjectContext(StrEnum):
    """Project context within a UV workspace layout."""

    STANDALONE = "standalone"
    WORKSPACE = "workspace"
    MEMBER = "member"

detect_context(path)

Detect whether path is a standalone package, workspace, or member.

Detection logic:

  1. If path/pyproject.toml has [tool.uv.workspace]WORKSPACE
  2. If a parent directory is a workspace root → MEMBER
  3. Otherwise → STANDALONE

Gracefully falls back to STANDALONE on missing or corrupt TOML.

Parameters:

Name Type Description Default
path Path

Project root directory to inspect.

required

Returns:

Type Description
ProjectContext

The detected ProjectContext.

Source code in packages/axm-init/src/axm_init/checks/_workspace.py
def detect_context(path: Path) -> ProjectContext:
    """Detect whether *path* is a standalone package, workspace, or member.

    Detection logic:

    1. If *path*/pyproject.toml has ``[tool.uv.workspace]`` → ``WORKSPACE``
    2. If a parent directory is a workspace root → ``MEMBER``
    3. Otherwise → ``STANDALONE``

    Gracefully falls back to ``STANDALONE`` on missing or corrupt TOML.

    Args:
        path: Project root directory to inspect.

    Returns:
        The detected ``ProjectContext``.
    """
    data = _load_pyproject(path)

    # Case 1: this path IS a workspace root
    if data is not None and _has_workspace_section(data):
        return ProjectContext.WORKSPACE

    # Case 2: check if a parent is a workspace root
    root = find_workspace_root(path)
    if root is not None:
        return ProjectContext.MEMBER

    # Case 3: standalone (including missing/corrupt TOML)
    return ProjectContext.STANDALONE

find_workspace_root(path)

Walk parent directories looking for a UV workspace root.

A workspace root is a directory whose pyproject.toml contains a [tool.uv.workspace] section.

Parameters:

Name Type Description Default
path Path

Starting directory (typically a member package).

required

Returns:

Type Description
Path | None

The workspace root Path, or None if not found.

Source code in packages/axm-init/src/axm_init/checks/_workspace.py
def find_workspace_root(path: Path) -> Path | None:
    """Walk parent directories looking for a UV workspace root.

    A workspace root is a directory whose ``pyproject.toml`` contains a
    ``[tool.uv.workspace]`` section.

    Args:
        path: Starting directory (typically a member package).

    Returns:
        The workspace root ``Path``, or ``None`` if not found.
    """
    for parent in path.resolve().parents:
        data = _load_pyproject(parent)
        if data is not None and _has_workspace_section(data):
            return parent
    return None

get_workspace_members(path)

Resolve workspace member package names from path.

Reads the members globs from [tool.uv.workspace] in the pyproject.toml at path, resolves them via Path.glob(), and filters out directories matching exclude globs.

Each resolved directory must contain a pyproject.toml to be considered a valid member.

Parameters:

Name Type Description Default
path Path

Workspace root directory.

required

Returns:

Type Description
list[str]

Sorted list of member directory names (relative to path).

Source code in packages/axm-init/src/axm_init/checks/_workspace.py
def get_workspace_members(path: Path) -> list[str]:
    """Resolve workspace member package names from *path*.

    Reads the ``members`` globs from ``[tool.uv.workspace]`` in the
    pyproject.toml at *path*, resolves them via ``Path.glob()``, and
    filters out directories matching ``exclude`` globs.

    Each resolved directory must contain a ``pyproject.toml`` to be
    considered a valid member.

    Args:
        path: Workspace root directory.

    Returns:
        Sorted list of member directory names (relative to *path*).
    """
    data = _load_pyproject(path)
    if data is None:
        return []

    ws_config = _get_workspace_config(data)
    if not ws_config:
        return []

    resolved = path.resolve()
    member_dirs = _resolve_glob_dirs(
        resolved,
        ws_config.get("members", []),
        require_pyproject=True,
    )
    exclude_dirs = _resolve_glob_dirs(
        resolved,
        ws_config.get("exclude", []),
    )

    return sorted(m.name for m in member_dirs - exclude_dirs)