mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00

Some checks are pending
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
Closes https://github.com/astral-sh/uv/issues/14093.
206 lines
7.8 KiB
Markdown
206 lines
7.8 KiB
Markdown
# Using workspaces
|
|
|
|
Inspired by the [Cargo](https://doc.rust-lang.org/cargo/reference/workspaces.html) concept of the
|
|
same name, a workspace is "a collection of one or more packages, called _workspace members_, that
|
|
are managed together."
|
|
|
|
Workspaces organize large codebases by splitting them into multiple packages with common
|
|
dependencies. Think: a FastAPI-based web application, alongside a series of libraries that are
|
|
versioned and maintained as separate Python packages, all in the same Git repository.
|
|
|
|
In a workspace, each package defines its own `pyproject.toml`, but the workspace shares a single
|
|
lockfile, ensuring that the workspace operates with a consistent set of dependencies.
|
|
|
|
As such, `uv lock` operates on the entire workspace at once, while `uv run` and `uv sync` operate on
|
|
the workspace root by default, though both accept a `--package` argument, allowing you to run a
|
|
command in a particular workspace member from any workspace directory.
|
|
|
|
## Getting started
|
|
|
|
To create a workspace, add a `tool.uv.workspace` table to a `pyproject.toml`, which will implicitly
|
|
create a workspace rooted at that package.
|
|
|
|
!!! tip
|
|
|
|
By default, running `uv init` inside an existing package will add the newly created member to the workspace, creating a `tool.uv.workspace` table in the workspace root if it doesn't already exist.
|
|
|
|
In defining a workspace, you must specify the `members` (required) and `exclude` (optional) keys,
|
|
which direct the workspace to include or exclude specific directories as members respectively, and
|
|
accept lists of globs:
|
|
|
|
```toml title="pyproject.toml"
|
|
[project]
|
|
name = "albatross"
|
|
version = "0.1.0"
|
|
requires-python = ">=3.12"
|
|
dependencies = ["bird-feeder", "tqdm>=4,<5"]
|
|
|
|
[tool.uv.sources]
|
|
bird-feeder = { workspace = true }
|
|
|
|
[tool.uv.workspace]
|
|
members = ["packages/*"]
|
|
exclude = ["packages/seeds"]
|
|
```
|
|
|
|
Every directory included by the `members` globs (and not excluded by the `exclude` globs) must
|
|
contain a `pyproject.toml` file. However, workspace members can be _either_
|
|
[applications](./init.md#applications) or [libraries](./init.md#libraries); both are supported in
|
|
the workspace context.
|
|
|
|
Every workspace needs a root, which is _also_ a workspace member. In the above example, `albatross`
|
|
is the workspace root, and the workspace members include all projects under the `packages`
|
|
directory, except `seeds`.
|
|
|
|
By default, `uv run` and `uv sync` operates on the workspace root. For example, in the above
|
|
example, `uv run` and `uv run --package albatross` would be equivalent, while
|
|
`uv run --package bird-feeder` would run the command in the `bird-feeder` package.
|
|
|
|
## Workspace sources
|
|
|
|
Within a workspace, dependencies on workspace members are facilitated via
|
|
[`tool.uv.sources`](./dependencies.md), as in:
|
|
|
|
```toml title="pyproject.toml"
|
|
[project]
|
|
name = "albatross"
|
|
version = "0.1.0"
|
|
requires-python = ">=3.12"
|
|
dependencies = ["bird-feeder", "tqdm>=4,<5"]
|
|
|
|
[tool.uv.sources]
|
|
bird-feeder = { workspace = true }
|
|
|
|
[tool.uv.workspace]
|
|
members = ["packages/*"]
|
|
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
```
|
|
|
|
In this example, the `albatross` project depends on the `bird-feeder` project, which is a member of
|
|
the workspace. The `workspace = true` key-value pair in the `tool.uv.sources` table indicates the
|
|
`bird-feeder` dependency should be provided by the workspace, rather than fetched from PyPI or
|
|
another registry.
|
|
|
|
!!! note
|
|
|
|
Dependencies between workspace members are editable.
|
|
|
|
Any `tool.uv.sources` definitions in the workspace root apply to all members, unless overridden in
|
|
the `tool.uv.sources` of a specific member. For example, given the following `pyproject.toml`:
|
|
|
|
```toml title="pyproject.toml"
|
|
[project]
|
|
name = "albatross"
|
|
version = "0.1.0"
|
|
requires-python = ">=3.12"
|
|
dependencies = ["bird-feeder", "tqdm>=4,<5"]
|
|
|
|
[tool.uv.sources]
|
|
bird-feeder = { workspace = true }
|
|
tqdm = { git = "https://github.com/tqdm/tqdm" }
|
|
|
|
[tool.uv.workspace]
|
|
members = ["packages/*"]
|
|
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
```
|
|
|
|
Every workspace member would, by default, install `tqdm` from GitHub, unless a specific member
|
|
overrides the `tqdm` entry in its own `tool.uv.sources` table.
|
|
|
|
!!! note
|
|
|
|
If a workspace member provides `tool.uv.sources` for some dependency, it will ignore any
|
|
`tool.uv.sources` for the same dependency in the workspace root, even if the member's source is
|
|
limited by a [marker](dependencies.md#platform-specific-sources) that doesn't match the current
|
|
platform.
|
|
|
|
## Workspace layouts
|
|
|
|
The most common workspace layout can be thought of as a root project with a series of accompanying
|
|
libraries.
|
|
|
|
For example, continuing with the above example, this workspace has an explicit root at `albatross`,
|
|
with two libraries (`bird-feeder` and `seeds`) in the `packages` directory:
|
|
|
|
```text
|
|
albatross
|
|
├── packages
|
|
│ ├── bird-feeder
|
|
│ │ ├── pyproject.toml
|
|
│ │ └── src
|
|
│ │ └── bird_feeder
|
|
│ │ ├── __init__.py
|
|
│ │ └── foo.py
|
|
│ └── seeds
|
|
│ ├── pyproject.toml
|
|
│ └── src
|
|
│ └── seeds
|
|
│ ├── __init__.py
|
|
│ └── bar.py
|
|
├── pyproject.toml
|
|
├── README.md
|
|
├── uv.lock
|
|
└── src
|
|
└── albatross
|
|
└── main.py
|
|
```
|
|
|
|
Since `seeds` was excluded in the `pyproject.toml`, the workspace has two members total: `albatross`
|
|
(the root) and `bird-feeder`.
|
|
|
|
## When (not) to use workspaces
|
|
|
|
Workspaces are intended to facilitate the development of multiple interconnected packages within a
|
|
single repository. As a codebase grows in complexity, it can be helpful to split it into smaller,
|
|
composable packages, each with their own dependencies and version constraints.
|
|
|
|
Workspaces help enforce isolation and separation of concerns. For example, in uv, we have separate
|
|
packages for the core library and the command-line interface, enabling us to test the core library
|
|
independently of the CLI, and vice versa.
|
|
|
|
Other common use cases for workspaces include:
|
|
|
|
- A library with a performance-critical subroutine implemented in an extension module (Rust, C++,
|
|
etc.).
|
|
- A library with a plugin system, where each plugin is a separate workspace package with a
|
|
dependency on the root.
|
|
|
|
Workspaces are _not_ suited for cases in which members have conflicting requirements, or desire a
|
|
separate virtual environment for each member. In this case, path dependencies are often preferable.
|
|
For example, rather than grouping `albatross` and its members in a workspace, you can always define
|
|
each package as its own independent project, with inter-package dependencies defined as path
|
|
dependencies in `tool.uv.sources`:
|
|
|
|
```toml title="pyproject.toml"
|
|
[project]
|
|
name = "albatross"
|
|
version = "0.1.0"
|
|
requires-python = ">=3.12"
|
|
dependencies = ["bird-feeder", "tqdm>=4,<5"]
|
|
|
|
[tool.uv.sources]
|
|
bird-feeder = { path = "packages/bird-feeder" }
|
|
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
```
|
|
|
|
This approach conveys many of the same benefits, but allows for more fine-grained control over
|
|
dependency resolution and virtual environment management (with the downside that `uv run --package`
|
|
is no longer available; instead, commands must be run from the relevant package directory).
|
|
|
|
Finally, uv's workspaces enforce a single `requires-python` for the entire workspace, taking the
|
|
intersection of all members' `requires-python` values. If you need to support testing a given member
|
|
on a Python version that isn't supported by the rest of the workspace, you may need to use `uv pip`
|
|
to install that member in a separate virtual environment.
|
|
|
|
!!! note
|
|
|
|
As Python does not provide dependency isolation, uv can't ensure that a package uses its declared dependencies and nothing else. For workspaces specifically, uv can't ensure that packages don't import dependencies declared by another workspace member.
|