Skip to content

Index

uv

Canonical uv-workspace resolution surface.

Member dataclass

A single uv-workspace member.

Attributes:

Name Type Description
name str

Basename of the member directory -- not the [project].name declared in the member's pyproject.toml. Two globs resolving to same-named directories (e.g. packages/core and libs/core) therefore yield two members with equal name; callers indexing by name must account for the collision. Read the package name from the member's pyproject.toml (path locates it) when needed.

path Path

Absolute, resolved path to the member directory.

Source code in packages/axm-ingot/src/axm_ingot/uv/models.py
Python
@dataclass(frozen=True)
class Member:
    """A single uv-workspace member.

    Attributes:
        name: Basename of the member *directory* -- not the ``[project].name``
            declared in the member's ``pyproject.toml``. Two globs resolving to
            same-named directories (e.g. ``packages/core`` and ``libs/core``)
            therefore yield two members with equal ``name``; callers indexing by
            ``name`` must account for the collision. Read the package name from
            the member's ``pyproject.toml`` (``path`` locates it) when needed.
        path: Absolute, resolved path to the member directory.
    """

    name: str
    path: Path

ResolvedWorkspace dataclass

A uv workspace with its resolved members.

Attributes:

Name Type Description
root Path

Absolute path to the workspace root (holding the root pyproject).

members tuple[Member, ...]

Members sorted by name.

Source code in packages/axm-ingot/src/axm_ingot/uv/models.py
Python
@dataclass(frozen=True)
class ResolvedWorkspace:
    """A uv workspace with its resolved members.

    Attributes:
        root: Absolute path to the workspace root (holding the root pyproject).
        members: Members sorted by name.
    """

    root: Path
    members: tuple[Member, ...]

find_project_root(start)

Walk parents from start to the first directory holding any pyproject.

Returns the directory of the first ancestor (start included) that contains a pyproject.toml -- any project, not necessarily a uv workspace. start is resolved first; a file start is anchored on its parent directory. Unlike :func:find_workspace_root, this never returns None: with no pyproject.toml in any ancestor it falls back to the (resolved) starting directory.

Source code in packages/axm-ingot/src/axm_ingot/uv/resolve.py
Python
def find_project_root(start: Path) -> Path:
    """Walk parents from ``start`` to the first directory holding any pyproject.

    Returns the directory of the first ancestor (``start`` included) that
    contains a ``pyproject.toml`` -- any project, not necessarily a uv
    workspace. ``start`` is resolved first; a file ``start`` is anchored on its
    parent directory. Unlike :func:`find_workspace_root`, this never returns
    ``None``: with no ``pyproject.toml`` in any ancestor it falls back to the
    (resolved) starting directory.
    """
    current = start.resolve()
    if current.is_file():
        current = current.parent
    for candidate in (current, *current.parents):
        if (candidate / _PYPROJECT).is_file():
            return candidate
    return current

find_workspace_root(path)

Walk parents from path to the first uv-workspace root.

Returns the directory of the first ancestor (path included) whose pyproject.toml carries a [tool.uv.workspace] section, else None.

Source code in packages/axm-ingot/src/axm_ingot/uv/resolve.py
Python
def find_workspace_root(path: Path) -> Path | None:
    """Walk parents from ``path`` to the first uv-workspace root.

    Returns the directory of the first ancestor (``path`` included) whose
    ``pyproject.toml`` carries a ``[tool.uv.workspace]`` section, else ``None``.
    """
    current = path.resolve()
    for directory in (current, *current.parents):
        data = _load_pyproject(directory)
        if data is not None and _get_workspace_config(data) is not None:
            return directory
    return None

parse_workspace_members(text)

Extract the raw [tool.uv.workspace].members from pyproject text.

Pure-string helper: parses text with :func:tomllib.loads and returns the declared string members verbatim -- no glob expansion, no filesystem access, no exclude/require_pyproject filtering. Globs (packages/*) and literal string entries are returned exactly as written; non-string entries (malformed TOML with e.g. integer members) are skipped, matching :func:resolve_workspace. Defensive: malformed TOML or an absent [tool.uv.workspace] table yields [] rather than raising.

Parameters:

Name Type Description Default
text str

Raw pyproject.toml content.

required

Returns:

Type Description
list[str]

The raw member strings declared under [tool.uv.workspace].members,

list[str]

or [] when none are declared.

Source code in packages/axm-ingot/src/axm_ingot/uv/resolve.py
Python
def parse_workspace_members(text: str) -> list[str]:
    """Extract the raw ``[tool.uv.workspace].members`` from pyproject text.

    Pure-string helper: parses ``text`` with :func:`tomllib.loads` and returns
    the declared string members verbatim -- no glob expansion, no filesystem
    access, no ``exclude``/``require_pyproject`` filtering. Globs (``packages/*``)
    and literal string entries are returned exactly as written; non-string
    entries (malformed TOML with e.g. integer members) are skipped, matching
    :func:`resolve_workspace`. Defensive: malformed TOML or an absent
    ``[tool.uv.workspace]`` table yields ``[]`` rather than raising.

    Args:
        text: Raw ``pyproject.toml`` content.

    Returns:
        The raw member strings declared under ``[tool.uv.workspace].members``,
        or ``[]`` when none are declared.
    """
    try:
        data = tomllib.loads(text)
    except ValueError:
        # tomllib.TOMLDecodeError and UnicodeDecodeError are both ValueError.
        return []
    workspace = _get_workspace_config(data)
    if workspace is None:
        return []
    members = workspace.get("members")
    if not isinstance(members, list):
        return []
    return [member for member in members if isinstance(member, str)]

resolve_workspace(pyproject_dir)

Resolve the uv workspace rooted at pyproject_dir.

Parses [tool.uv.workspace].members, resolves the globs to directories, subtracts the exclude globs, keeps only directories that contain a pyproject.toml (require_pyproject), and returns the members sorted by name. Returns None when pyproject_dir is not a uv workspace or its pyproject is missing/malformed.

Source code in packages/axm-ingot/src/axm_ingot/uv/resolve.py
Python
def resolve_workspace(pyproject_dir: Path) -> ResolvedWorkspace | None:
    """Resolve the uv workspace rooted at ``pyproject_dir``.

    Parses ``[tool.uv.workspace].members``, resolves the globs to directories,
    subtracts the ``exclude`` globs, keeps only directories that contain a
    ``pyproject.toml`` (``require_pyproject``), and returns the members sorted
    by name. Returns ``None`` when ``pyproject_dir`` is not a uv workspace or
    its pyproject is missing/malformed.
    """
    root = pyproject_dir.resolve()
    data = _load_pyproject(root)
    if data is None:
        return None
    workspace = _get_workspace_config(data)
    if workspace is None:
        return None

    included = _resolve_glob_dirs(root, workspace.get("members"))
    excluded = _resolve_glob_dirs(root, workspace.get("exclude"))
    members = tuple(
        sorted(
            (
                Member(name=directory.name, path=directory)
                for directory in included - excluded
                if (directory / _PYPROJECT).is_file()
            ),
            key=lambda member: member.name,
        )
    )
    return ResolvedWorkspace(root=root, members=members)