Skip to content

Commit

Permalink
Update workspace documentation to remove legacy virtual projects
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Aug 27, 2024
1 parent ffb0c30 commit ca52c91
Showing 1 changed file with 15 additions and 76 deletions.
91 changes: 15 additions & 76 deletions docs/concepts/workspaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,6 @@ In defining a workspace, you must specify the `members` (required) and `exclude`
which direct the workspace to include or exclude specific directories as members respectively, and
accept lists of globs:

```toml title="pyproject.toml"
[tool.uv.workspace]
members = ["packages/*", "examples/*"]
exclude = ["example/excluded_example"]
```

In this example, the workspace includes all packages in the `packages` directory and all examples in
the `examples` directory, with the exception of the `example/excluded_example` directory.

Every directory included by the `members` globs (and not excluded by the `exclude` globs) must
contain a `pyproject.toml` file; in other words, every member must be a valid Python package, or
workspace discovery will raise an error.

## Workspace roots

Every workspace needs a workspace root, which can either be explicit or "virtual".

An explicit root is a directory that is itself a valid Python package, and thus a valid workspace
member, as in:

```toml title="pyproject.toml"
[project]
name = "albatross"
Expand All @@ -60,37 +40,24 @@ bird-feeder = { workspace = true }

[tool.uv.workspace]
members = ["packages/*"]
exclude = ["packages/seeds"]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```

A virtual root is a directory that is _not_ a valid Python package, but contains a `pyproject.toml`
with a `tool.uv.workspace` table. In other words, the `pyproject.toml` exists to define the
workspace, but does not itself define a package, as in:

```toml title="pyproject.toml"
[tool.uv.workspace]
members = ["packages/*"]
```

A virtual root _must not_ contain a `[project]` table, as the inclusion of a `[project]` table
implies the directory is a package, and thus an explicit root. As such, virtual roots cannot define
their own dependencies; however, they _can_ define development dependencies as in:
Every directory included by the `members` globs (and not excluded by the `exclude` globs) must
contain a `pyproject.toml` file; in other words, every member must be a valid Python package, or
workspace discovery will raise an error.

```toml title="pyproject.toml"
[tool.uv.workspace]
members = ["packages/*"]

[tool.uv]
dev-dependencies = ["ruff==0.5.0"]
```
In this example, the workspace includes all packages in the `packages` directory, with the exception
of the `seeds` directory. Every workspace needs a workspace root, like `albatross` above. And the
workspace root is _also_ a workspace member.

By default, `uv run` and `uv sync` operates on the workspace root, if it's explicit. For example, in
the above example, `uv run` and `uv run --package albatross` would be equivalent. For virtual
workspaces, `uv run` and `uv sync` instead sync all workspace members, since the root is not a
member itself.
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

Expand Down Expand Up @@ -147,13 +114,11 @@ overrides the `tqdm` entry in its own `tool.uv.sources` table.

## Workspace layouts

In general, there are two common layouts for workspaces, which map to the two kinds of workspace
roots: a **root package with helpers** (for explicit roots) and a **flat workspace** (for virtual
roots).
The most common workspace layout can be thought of as a root package with a series of accompanying
libraries, each in its own subdirectory.

In the former case, the workspace includes an explicit workspace root, with peripheral packages or
libraries defined in `packages`. For example, here, `albatross` is an explicit workspace root, and
`bird-feeder` and `seeds` are workspace members:
For example, continuing with the above example, this workspace has an explicit root at `albatross`,
with two packages (`bird-feeder` and `seeds`) in the `packages` directory:

```text
albatross
Expand All @@ -178,34 +143,8 @@ albatross
└── main.py
```

In the latter case, _all_ members are located in the `packages` directory, and the root
`pyproject.toml` comprises a virtual root:

```text
albatross
├── packages
│ ├── albatross
│ │ ├── pyproject.toml
│ │ └── src
│ │ └── albatross
│ │ ├── __init__.py
│ │ └── foo.py
│ ├── 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
```
Since `seeds` was excluded in the `pyproject.toml`, the workspace has two members: `albatross` (the
root) and `bird-feeder`.

## When (not) to use workspaces

Expand Down

0 comments on commit ca52c91

Please sign in to comment.