Skip to content

[Bug]: When using uv hub, internal dependencies between pyproject workspaces throw an analysis error #789

@mkanat

Description

@mkanat

What happened?

If you have multiple workspaces declared in your pyproject.toml, and they depend on each other inside of the repo, then you get an analysis error from aspect_rules_py that looks like:

ERROR: /home/runner/.bazel/external/aspect_rules_py++uv+whl_install__pypi__default__define_defcl/BUILD.bazel:23:12: in src attribute of whl_install rule @@aspect_rules_py++uv+whl_install__pypi__default__define_defcl//:actual_install: rule '@@aspect_rules_py++uv+whl_install__pypi__default__define_defcl//:whl' does not exist
ERROR: /home/runner/.bazel/external/aspect_rules_py++uv+whl_install__pypi__default__define_defcl/BUILD.bazel:23:12: Analysis of target '@@aspect_rules_py++uv+whl_install__pypi__default__define_defcl//:actual_install' (config: ab9dc43) failed

In this case, a project called "define" depends on another project called "defcl," both of which are workspaces defined in the repo's root pyproject.toml.

Version

Development (host) and target OS/architectures: WSL 2, and ubuntu-linux on GirHub Actions

Output of bazel --version: 9.0.0

Version of the Aspect rules, or other relevant rules from your
WORKSPACE or MODULE.bazel file:

bazel_dep(name = "aspect_rules_py", version = "1.8.4")

Language(s) and/or frameworks involved: uv 0.10.0

How to reproduce

My agent claims this will reproduce it, although I haven't tested it. I can reproduce it basically by creating two packages that have actual dependencies on each other declared both in the pyproject.toml (with { workspace = true }) and in the BUILD.bazel files. But if you want some instructions to recreate a whole environment that you could just feed to an agent, here you go, maybe these will work:

# Repro: uv extension fails when lock file contains editable/workspace packages

## Steps

1. **Workspace with one member depending on another**

   Root `pyproject.toml`:

   
   [project]
   name = "myapp"
   version = "0.0.1"
   requires-python = ">=3.12"
   dependencies = []

   [tool.uv.workspace]
   members = ["packages/a", "packages/b"]
   

   `packages/a/pyproject.toml`: any package, e.g. `name = "myapp-a"`, no deps.

   `packages/b/pyproject.toml` (add one external dep so the lock has both PyPI and editable entries):

   
   [project]
   name = "myapp-b"
   version = "0.0.1"
   requires-python = ">=3.12"
   dependencies = ["myapp-a", "requests"]

   [tool.uv.sources]
   myapp-a = { workspace = true }
   

   **Root `BUILD.bazel`**:

   
   load("@aspect_rules_py//py:defs.bzl", "py_library")

   exports_files(["uv.lock", "pyproject.toml"])

   py_library(
       name = "lib",
       srcs = ["main.py"],
       deps = ["@pypi//requests"],
   )
   

   Create **`main.py`** at repo root (can be empty or `"""Stub."""`).

   **`packages/a/BUILD.bazel`**:

   
   exports_files(["pyproject.toml"])
   

   **`packages/b/BUILD.bazel`**:

   
   exports_files(["pyproject.toml"])
   

2. **Lock:** `uv lock` at repo root. Lock file will list `myapp-a` / `myapp-b` with `source = { editable = "..." }` and no `wheels`.

3. **Bazel:** In `MODULE.bazel` add (and keep your existing Python toolchain / bazel_deps as needed):

   
   bazel_dep(name = "aspect_rules_py", version = "1.8.4")
   bazel_dep(name = "rules_python", version = "1.8.3")

   python = use_extension("@rules_python//python/extensions:python.bzl", "python")
   python.toolchain(python_version = "3.12")

   pypi = use_extension("@aspect_rules_py//uv/unstable:extension.bzl", "uv")
   pypi.declare_hub(hub_name = "pypi")
   pypi.declare_venv(hub_name = "pypi", venv_name = "default")
   pypi.lockfile(src = "//:uv.lock", hub_name = "pypi", venv_name = "default")
   use_repo(pypi, "pypi")
   

4. **Build:** `bazel build //...`

## Result

Analysis fails with: `rule '...//:whl' does not exist` (for the editable package’s whl_install repo).

## Expected

Editable/workspace entries in the lock file are skipped or handled without requiring a `:whl` target.

Any other information?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions