mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-22 20:45:25 +00:00
Add support for virtual projects (#6585)
## Summary
The basic idea here is: any project can either be a package, or not
("virtual").
If a project is virtual, we don't build or install it.
A project is virtual if either of the following are true:
- `tool.uv.virtual = true` is set.
- `[build-system]` is absent.
The concept of "virtual projects" only applies to workspace member right
now; it doesn't apply to `path` dependencies which are treated like
arbitrary Python source trees.
TODOs that should be resolved prior to merging:
- [ ] Documentation
- [ ] How do we reconcile this with "virtual workspace roots" which are
a little different -- they omit `[project]` entirely and don't even have
a name?
- [x] `uv init --virtual` should create a virtual project rather than a
virtual workspace.
- [x] Running `uv sync` in a virtual project after `uv init --virtual`
shows `Audited 0 packages in 0.01ms`, which is awkward. (See:
https://github.com/astral-sh/uv/pull/6588.)
Closes https://github.com/astral-sh/uv/issues/6511.
This commit is contained in:
parent
6d38d42b41
commit
eb14056e9c
16 changed files with 1710 additions and 147 deletions
|
|
@ -33,6 +33,10 @@ pub struct PyProjectToml {
|
|||
/// The raw unserialized document.
|
||||
#[serde(skip)]
|
||||
pub raw: String,
|
||||
|
||||
/// Used to determine whether a `build-system` is present.
|
||||
#[serde(default, skip_serializing)]
|
||||
build_system: Option<serde::de::IgnoredAny>,
|
||||
}
|
||||
|
||||
impl PyProjectToml {
|
||||
|
|
@ -41,6 +45,23 @@ impl PyProjectToml {
|
|||
let pyproject = toml::from_str(&raw)?;
|
||||
Ok(PyProjectToml { raw, ..pyproject })
|
||||
}
|
||||
|
||||
/// Returns `true` if the project should be considered a Python package, as opposed to a
|
||||
/// non-package ("virtual") project.
|
||||
pub fn is_package(&self) -> bool {
|
||||
// If `tool.uv.package` is set, defer to that explicit setting.
|
||||
if let Some(is_package) = self
|
||||
.tool
|
||||
.as_ref()
|
||||
.and_then(|tool| tool.uv.as_ref())
|
||||
.and_then(|uv| uv.package)
|
||||
{
|
||||
return is_package;
|
||||
}
|
||||
|
||||
// Otherwise, a project is assumed to be a package if `build-system` is present.
|
||||
self.build_system.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore raw document in comparison.
|
||||
|
|
@ -100,6 +121,24 @@ pub struct ToolUv {
|
|||
"#
|
||||
)]
|
||||
pub managed: Option<bool>,
|
||||
/// Whether the project should be considered a Python package, or a non-package ("virtual")
|
||||
/// project.
|
||||
///
|
||||
/// Packages are built and installed into the virtual environment in editable mode and thus
|
||||
/// require a build backend, while virtual projects are _not_ built or installed; instead, only
|
||||
/// their dependencies are included in the virtual environment.
|
||||
///
|
||||
/// Creating a package requires that a `build-system` is present in the `pyproject.toml`, and
|
||||
/// that the project adheres to a structure that adheres to the build backend's expectations
|
||||
/// (e.g., a `src` layout).
|
||||
#[option(
|
||||
default = r#"true"#,
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
package = false
|
||||
"#
|
||||
)]
|
||||
pub package: Option<bool>,
|
||||
/// The project's development dependencies. Development dependencies will be installed by
|
||||
/// default in `uv run` and `uv sync`, but will not appear in the project's published metadata.
|
||||
#[cfg_attr(
|
||||
|
|
|
|||
|
|
@ -1339,7 +1339,7 @@ impl VirtualProject {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the [`PackageName`] of the project, if it's not a virtual workspace.
|
||||
/// Return the [`PackageName`] of the project, if it's not a virtual workspace root.
|
||||
pub fn project_name(&self) -> Option<&PackageName> {
|
||||
match self {
|
||||
VirtualProject::Project(project) => Some(project.project_name()),
|
||||
|
|
@ -1347,7 +1347,7 @@ impl VirtualProject {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the project is a virtual workspace.
|
||||
/// Returns `true` if the project is a virtual workspace root.
|
||||
pub fn is_virtual(&self) -> bool {
|
||||
matches!(self, VirtualProject::Virtual(_))
|
||||
}
|
||||
|
|
@ -1535,6 +1535,7 @@ mod tests {
|
|||
"exclude": null
|
||||
},
|
||||
"managed": null,
|
||||
"package": null,
|
||||
"dev-dependencies": null,
|
||||
"environments": null,
|
||||
"override-dependencies": null,
|
||||
|
|
@ -1607,6 +1608,7 @@ mod tests {
|
|||
"exclude": null
|
||||
},
|
||||
"managed": null,
|
||||
"package": null,
|
||||
"dev-dependencies": null,
|
||||
"environments": null,
|
||||
"override-dependencies": null,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue