astral-sh/uv
uv-workspace
crates/uv-workspace/ parses pyproject.toml files (including uv's extensions), discovers
workspace members across multiple pyproject.toml files, and provides a mutable TOML model
used by uv add, uv remove, and uv version to keep formatting/comments intact.
Purpose
uv is a project manager, which means most of its commands start by:
- Walking up from the current directory to find a
pyproject.toml(and optionally a parent[tool.uv.workspace]root). - Parsing it into typed Rust structs.
- Resolving its dependencies (with markers, extras, dependency groups), build system, indexes, and uv-specific configuration.
- For mutating commands, editing the file while preserving the user's exact formatting.
This crate handles all four steps.
Directory layout
crates/uv-workspace/src/
├── lib.rs # Re-exports
├── pyproject.rs # 69k chars: PyProjectToml + ToolUv + every typed view
├── pyproject_mut.rs # 78k chars: toml_edit-based mutation API for uv add/remove/version
├── workspace.rs # 108k chars: Workspace discovery and member resolution
└── dependency_groups.rs # PEP 735 dependency groups parsingKey abstractions
| Type | File | Role |
|---|---|---|
PyProjectToml |
pyproject.rs |
The full typed view of pyproject.toml: [project], [build-system], [tool.uv], dependency groups, sources, indexes, conflicts. |
ToolUv |
pyproject.rs |
The [tool.uv] table: dependency overrides, constraints, sources, indexes, environments, build settings, conflicts, dev-dependencies. |
PyProjectTomlMut |
pyproject_mut.rs |
A toml_edit document plus typed accessors. Used by uv add to insert dependencies, by uv remove to delete them, and by uv version to bump versions while preserving formatting. |
AddBoundsKind |
pyproject_mut.rs |
The bounds style for added dependencies (>=, ~=, ==, none). |
Workspace |
workspace.rs |
The discovered project + workspace tree: root, members (each a Package with its own pyproject.toml), and all configuration. |
WorkspaceCache |
workspace.rs |
Per-process cache of discovered workspaces keyed by root path. |
DiscoveryOptions |
workspace.rs |
Knobs for workspace discovery: members, exclusions, source patterns. |
DependencyGroups |
dependency_groups.rs |
The PEP 735 groups (default groups, group inclusions, transitive group expansion). |
How it works
Discovery
Workspace::discover (workspace.rs) walks up from a given directory looking for a
pyproject.toml. If the file declares [tool.uv.workspace], it's the workspace root; if it
declares membership in a different workspace (via being inside a parent's members glob),
the parent becomes the root. The discovery rules also support:
- Standalone projects (no workspace).
- Workspaces with a single root member.
- Workspaces with explicit member globs (
members = ["packages/*"]) and exclusions. - Source overrides (
[tool.uv.sources]mapping a dependency to a path/URL/git source).
Parsing
pyproject.rs defines PyProjectToml and every typed sub-struct. The deserialization is
serde-based but goes to extremes for diagnostics — for example, serde_verbatim (in
uv-build-backend/src/serde_verbatim.rs) records original byte spans so error messages can
underline exactly the offending token in the source TOML.
uv-specific extensions live under [tool.uv] and [tool.uv.workspace]. Examples:
[tool.uv.sources]— override where a package comes from (path, git, URL).[[tool.uv.index]]— named indexes with priority.[tool.uv.dependency-groups]— defaults, group inclusions.[tool.uv.environments]/[tool.uv.required-environments]— required marker environments.[tool.uv.conflicts]— extras / groups that cannot be combined.[tool.uv.constraint-dependencies]/[tool.uv.override-dependencies].[tool.uv.no-build-isolation-package]and friends.
Mutation
pyproject_mut.rs is the surprising part: editing TOML files while preserving formatting,
comments, and quoting style. It uses toml_edit (which keeps the exact source representation
in its DOM) plus a typed wrapper that knows about uv's table layout. Operations include:
- Add a dependency — insert into
[project.dependencies],[project.optional-dependencies.<extra>], or[dependency-groups.<group>]. If the dependency already exists, update or split it based on markers. - Remove a dependency — find every entry that matches and delete it.
- Edit
[tool.uv.sources]— when a user adds a path/git/URL dependency. - Bump version —
uv version. - Bump bounds —
uv lock --upgrade-packagemay rewrite specifiers if needed.
Mutations are atomic: the new TOML is serialized to a temp file and fs-err::renamed into
place after a successful write.
Dependency groups
dependency_groups.rs implements PEP 735. Groups can include other groups ({include-group = "dev"}); the implementation does cycle detection and topological expansion. The dev group
is a default and is enabled by uv sync unless --no-dev is passed.
Integration points
uv-cli+uv-settingsconsumePyProjectTomlvia the binary's settings layer.uv-resolveruses the discovered workspace's members and constraints during resolution.uv-installerreads workspace member metadata to install local paths.uv-build-frontendreads[build-system]from the same parsed type.uv-scriptsreuses parts ofPyProjectTomlfor PEP 723 inline metadata.
Entry points for modification
- A new
[tool.uv]field — extendToolUvinpyproject.rs. Update the JSON schema generation incrates/uv-options-metadata/. - A new mutation —
pyproject_mut.rs. Keep the existing patterns: read → mutate → reserialize viatoml_editand avoid touching unrelated tables. - A new workspace-discovery rule —
workspace.rs. Be careful with the discovery walk — this is the most subtle code in the crate.
Key source files
| File | Purpose |
|---|---|
crates/uv-workspace/src/pyproject.rs |
The 69k-character typed view of pyproject.toml. |
crates/uv-workspace/src/pyproject_mut.rs |
The mutable model used by uv add/remove/version. |
crates/uv-workspace/src/workspace.rs |
The 108k-character discovery / member resolver. |
crates/uv-workspace/src/dependency_groups.rs |
PEP 735 dependency-group expansion. |
See also
uv-settingsfor theuv.tomlparallel surface.- features/project-workflow for an end-to-end walk-through.
uv-scriptsfor PEP 723 (inlinepyproject-like metadata).
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.