diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index 729a93c09831..2148ec1c49e2 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -2049,11 +2049,12 @@ pub struct InitArgs { #[arg(long)] pub name: Option, - /// Create a virtual workspace instead of a project. + /// Create a virtual project, rather than a package. /// - /// A virtual workspace does not define project dependencies and cannot be - /// published. Instead, workspace members declare project dependencies. - /// Development dependencies may still be declared. + /// A virtual project is a project that is not intended to be built as a Python package, + /// such as a project that only contains scripts or other application code. + /// + /// Virtual projects themselves are not installed into the Python environment. #[arg(long)] pub r#virtual: bool, diff --git a/crates/uv-settings/src/settings.rs b/crates/uv-settings/src/settings.rs index 8f580b9d6844..ff6b7a83fd23 100644 --- a/crates/uv-settings/src/settings.rs +++ b/crates/uv-settings/src/settings.rs @@ -71,6 +71,10 @@ pub struct Options { #[serde(default, skip_serializing)] #[cfg_attr(feature = "schemars", schemars(skip))] managed: serde::de::IgnoredAny, + + #[serde(default, skip_serializing)] + #[cfg_attr(feature = "schemars", schemars(skip))] + r#virtual: serde::de::IgnoredAny, } impl Options { diff --git a/crates/uv-workspace/src/pyproject.rs b/crates/uv-workspace/src/pyproject.rs index f4d86ae3b390..640414e19f64 100644 --- a/crates/uv-workspace/src/pyproject.rs +++ b/crates/uv-workspace/src/pyproject.rs @@ -32,6 +32,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, } impl PyProjectToml { @@ -40,6 +44,27 @@ impl PyProjectToml { let pyproject = toml::from_str(&raw)?; Ok(PyProjectToml { raw, ..pyproject }) } + + /// Returns `true` if the project should be considered "virtual". + pub fn is_virtual(&self) -> bool { + // A project is virtual if `virtual = true` is set... + if self + .tool + .as_ref() + .and_then(|tool| tool.uv.as_ref()) + .and_then(|uv| uv.r#virtual) + == Some(true) + { + return true; + } + + // Or if `build-system` is not present. + if self.build_system.is_none() { + return true; + } + + false + } } // Ignore raw document in comparison. @@ -99,6 +124,15 @@ pub struct ToolUv { "# )] pub managed: Option, + /// Whether the project should be considered "virtual". + #[option( + default = r#"true"#, + value_type = "bool", + example = r#" + virtual = false + "# + )] + pub r#virtual: Option, /// 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( diff --git a/crates/uv-workspace/src/workspace.rs b/crates/uv-workspace/src/workspace.rs index 6a1c69a6afc4..66f3867b142b 100644 --- a/crates/uv-workspace/src/workspace.rs +++ b/crates/uv-workspace/src/workspace.rs @@ -1337,7 +1337,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()), @@ -1345,7 +1345,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(_)) } @@ -1533,6 +1533,7 @@ mod tests { "exclude": null }, "managed": null, + "virtual": null, "dev-dependencies": null, "environments": null, "override-dependencies": null, @@ -1605,6 +1606,7 @@ mod tests { "exclude": null }, "managed": null, + "virtual": null, "dev-dependencies": null, "environments": null, "override-dependencies": null, diff --git a/crates/uv/src/commands/project/init.rs b/crates/uv/src/commands/project/init.rs index b60d2276ec18..681007923808 100644 --- a/crates/uv/src/commands/project/init.rs +++ b/crates/uv/src/commands/project/init.rs @@ -15,7 +15,7 @@ use uv_python::{ }; use uv_resolver::RequiresPython; use uv_workspace::pyproject_mut::{DependencyTarget, PyProjectTomlMut}; -use uv_workspace::{check_nested_workspaces, DiscoveryOptions, Workspace, WorkspaceError}; +use uv_workspace::{DiscoveryOptions, Workspace, WorkspaceError}; use crate::commands::project::find_requires_python; use crate::commands::reporters::PythonDownloadReporter; @@ -69,24 +69,21 @@ pub(crate) async fn init( } }; - if r#virtual { - init_virtual_workspace(&path, no_workspace)?; - } else { - init_project( - &path, - &name, - no_readme, - python, - no_workspace, - python_preference, - python_downloads, - connectivity, - native_tls, - cache, - printer, - ) - .await?; - } + init_project( + &path, + &name, + r#virtual, + no_readme, + python, + no_workspace, + python_preference, + python_downloads, + connectivity, + native_tls, + cache, + printer, + ) + .await?; // Create the `README.md` if it does not already exist. if !no_readme { @@ -126,29 +123,12 @@ pub(crate) async fn init( Ok(ExitStatus::Success) } -/// Initialize a virtual workspace at the given path. -fn init_virtual_workspace(path: &Path, no_workspace: bool) -> Result<()> { - // Ensure that we aren't creating a nested workspace. - if !no_workspace { - check_nested_workspaces(path, &DiscoveryOptions::default()); - } - - // Create the `pyproject.toml`. - let pyproject = indoc::indoc! {r" - [tool.uv.workspace] - members = [] - "}; - - fs_err::create_dir_all(path)?; - fs_err::write(path.join("pyproject.toml"), pyproject)?; - - Ok(()) -} - /// Initialize a project (and, implicitly, a workspace root) at the given path. +#[allow(clippy::fn_params_excessive_bools)] async fn init_project( path: &Path, name: &PackageName, + r#virtual: bool, no_readme: bool, python: Option, no_workspace: bool, @@ -265,38 +245,56 @@ async fn init_project( RequiresPython::greater_than_equal_version(&interpreter.python_minor_version()) }; - // Create the `pyproject.toml`. - let pyproject = indoc::formatdoc! {r#" - [project] - name = "{name}" - version = "0.1.0" - description = "Add your description here"{readme} - requires-python = "{requires_python}" - dependencies = [] + if r#virtual { + // Create the `pyproject.toml`, but omit `[build-system]`. + let pyproject = indoc::formatdoc! {r#" + [project] + name = "{name}" + version = "0.1.0" + description = "Add your description here"{readme} + requires-python = "{requires_python}" + dependencies = [] + "#, + readme = if no_readme { "" } else { "\nreadme = \"README.md\"" }, + requires_python = requires_python.specifiers(), + }; - [build-system] - requires = ["hatchling"] - build-backend = "hatchling.build" - "#, - readme = if no_readme { "" } else { "\nreadme = \"README.md\"" }, - requires_python = requires_python.specifiers(), - }; + fs_err::create_dir_all(path)?; + fs_err::write(path.join("pyproject.toml"), pyproject)?; + } else { + // Create the `pyproject.toml`. + let pyproject = indoc::formatdoc! {r#" + [project] + name = "{name}" + version = "0.1.0" + description = "Add your description here"{readme} + requires-python = "{requires_python}" + dependencies = [] + + [build-system] + requires = ["hatchling"] + build-backend = "hatchling.build" + "#, + readme = if no_readme { "" } else { "\nreadme = \"README.md\"" }, + requires_python = requires_python.specifiers(), + }; - fs_err::create_dir_all(path)?; - fs_err::write(path.join("pyproject.toml"), pyproject)?; + fs_err::create_dir_all(path)?; + fs_err::write(path.join("pyproject.toml"), pyproject)?; - // Create `src/{name}/__init__.py`, if it doesn't exist already. - let src_dir = path.join("src").join(&*name.as_dist_info_name()); - let init_py = src_dir.join("__init__.py"); - if !init_py.try_exists()? { - fs_err::create_dir_all(&src_dir)?; - fs_err::write( - init_py, - indoc::formatdoc! {r#" + // Create `src/{name}/__init__.py`, if it doesn't exist already. + let src_dir = path.join("src").join(&*name.as_dist_info_name()); + let init_py = src_dir.join("__init__.py"); + if !init_py.try_exists()? { + fs_err::create_dir_all(&src_dir)?; + fs_err::write( + init_py, + indoc::formatdoc! {r#" def hello() -> str: return "Hello from {name}!" "#}, - )?; + )?; + } } if let Some(workspace) = workspace { diff --git a/crates/uv/src/commands/project/sync.rs b/crates/uv/src/commands/project/sync.rs index c4b2c766e51e..82e6169480d9 100644 --- a/crates/uv/src/commands/project/sync.rs +++ b/crates/uv/src/commands/project/sync.rs @@ -200,6 +200,9 @@ pub(super) async fn do_sync( // Read the lockfile. let resolution = lock.to_resolution(project, markers, tags, extras, &dev)?; + // Always skip virtual projects, which shouldn't be built or installed. + let resolution = apply_no_virtual_project(resolution, project); + // If `--no-install-project` is set, remove the project itself. let resolution = apply_no_install_project(no_install_project, resolution, project); @@ -297,6 +300,35 @@ pub(super) async fn do_sync( Ok(()) } +/// Filter out any virtual workspace members. +fn apply_no_virtual_project( + resolution: distribution_types::Resolution, + project: &VirtualProject, +) -> distribution_types::Resolution { + let VirtualProject::Project(project) = project else { + // If the project is _only_ a virtual workspace root, we don't need to filter it out. + return resolution; + }; + + let virtual_members = project + .workspace() + .packages() + .iter() + .filter_map(|(name, package)| { + // A project is virtual if it's explicitly marked as virtual, _or_ if it's missing a + // build system. + if package.pyproject_toml().is_virtual() { + Some(name) + } else { + None + } + }) + .collect::>(); + + // Remove any virtual members from the resolution. + resolution.filter(|dist| !virtual_members.contains(dist.name())) +} + fn apply_no_install_project( no_install_project: bool, resolution: distribution_types::Resolution, diff --git a/crates/uv/tests/common/mod.rs b/crates/uv/tests/common/mod.rs index d8e4f8daa7d8..ec187573b318 100644 --- a/crates/uv/tests/common/mod.rs +++ b/crates/uv/tests/common/mod.rs @@ -1110,8 +1110,9 @@ pub fn make_project(dir: &Path, name: &str, body: &str) -> anyhow::Result<()> { {body} [build-system] - requires = ["flit_core>=3.8,<4"] - build-backend = "flit_core.buildapi" + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + "# }; fs_err::create_dir_all(dir)?; diff --git a/crates/uv/tests/edit.rs b/crates/uv/tests/edit.rs index 6dc2251909eb..2e0e735eb63a 100644 --- a/crates/uv/tests/edit.rs +++ b/crates/uv/tests/edit.rs @@ -20,9 +20,12 @@ fn add_registry() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&["anyio==3.7.0"]), @r###" @@ -50,11 +53,14 @@ fn add_registry() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [ "anyio==3.7.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -143,6 +149,10 @@ fn add_git() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.lock(), @r###" @@ -212,6 +222,10 @@ fn add_git() -> Result<()> { "uv-public-pypackage", ] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", tag = "0.0.1" } "### @@ -313,6 +327,10 @@ fn add_git_private_source() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&[&format!("uv-private-pypackage @ git+https://{token}@github.com/astral-test/uv-private-pypackage")]), @r###" @@ -343,6 +361,10 @@ fn add_git_private_source() -> Result<()> { "uv-private-pypackage", ] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] uv-private-pypackage = { git = "https://github.com/astral-test/uv-private-pypackage" } "### @@ -409,6 +431,10 @@ fn add_git_private_raw() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&[&format!("uv-private-pypackage @ git+https://{token}@github.com/astral-test/uv-private-pypackage")]).arg("--raw-sources"), @r###" @@ -443,6 +469,10 @@ fn add_git_private_raw() -> Result<()> { dependencies = [ "uv-private-pypackage @ git+https://***@github.com/astral-test/uv-private-pypackage", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -504,6 +534,10 @@ fn add_git_error() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.lock(), @r###" @@ -562,6 +596,10 @@ fn add_git_raw() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.lock(), @r###" @@ -617,6 +655,10 @@ fn add_git_raw() -> Result<()> { "anyio==3.7.0", "uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@0.0.1", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -714,6 +756,10 @@ fn add_git_implicit() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.lock(), @r###" @@ -770,6 +816,10 @@ fn add_raw_error() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; // Provide a tag without a Git source. @@ -800,9 +850,12 @@ fn add_unnamed() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&["git+https://github.com/astral-test/uv-public-pypackage"]).arg("--tag=0.0.1"), @r###" @@ -828,12 +881,15 @@ fn add_unnamed() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [ "uv-public-pypackage", ] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", tag = "0.0.1" } "### @@ -897,6 +953,10 @@ fn add_remove_dev() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&["anyio==3.7.0"]).arg("--dev"), @r###" @@ -927,6 +987,10 @@ fn add_remove_dev() -> Result<()> { requires-python = ">=3.12" dependencies = [] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] dev-dependencies = [ "anyio==3.7.0", @@ -1049,6 +1113,10 @@ fn add_remove_dev() -> Result<()> { requires-python = ">=3.12" dependencies = [] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] dev-dependencies = [] "### @@ -1101,6 +1169,10 @@ fn add_remove_optional() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&["anyio==3.7.0"]).arg("--optional=io"), @r###" @@ -1135,6 +1207,10 @@ fn add_remove_optional() -> Result<()> { io = [ "anyio==3.7.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -1254,6 +1330,10 @@ fn add_remove_optional() -> Result<()> { [project.optional-dependencies] io = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -1310,6 +1390,10 @@ fn add_remove_workspace() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; let pyproject_toml = context.temp_dir.child("child2/pyproject.toml"); @@ -1319,6 +1403,10 @@ fn add_remove_workspace() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; // Adding a workspace package with a mismatched source should error. @@ -1374,6 +1462,10 @@ fn add_remove_workspace() -> Result<()> { "child2", ] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] child2 = { workspace = true } "### @@ -1457,6 +1549,10 @@ fn add_remove_workspace() -> Result<()> { requires-python = ">=3.12" dependencies = [] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] "### ); @@ -1525,6 +1621,10 @@ fn add_workspace_editable() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; let pyproject_toml = context.temp_dir.child("child2/pyproject.toml"); @@ -1534,6 +1634,10 @@ fn add_workspace_editable() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; let child1 = context.temp_dir.join("child1"); @@ -1568,6 +1672,10 @@ fn add_workspace_editable() -> Result<()> { "child2", ] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] child2 = { workspace = true } "### @@ -1638,9 +1746,11 @@ fn update() -> Result<()> { name = "project" version = "0.1.0" requires-python = ">=3.12" - dependencies = [ - "requests==2.31.0" - ] + dependencies = ["requests==2.31.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.lock(), @r###" @@ -1696,6 +1806,10 @@ fn update() -> Result<()> { dependencies = [ "requests[security]==2.31.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -1731,6 +1845,10 @@ fn update() -> Result<()> { "requests[security]==2.31.0", "requests[socks,use-chardet-on-py3]>=2.31.0 ; python_full_version >= '3.8'", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -1768,6 +1886,10 @@ fn update() -> Result<()> { "requests[socks,use-chardet-on-py3]>=2.31.0 ; python_full_version >= '3.8'", ] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] requests = { git = "https://github.com/psf/requests", tag = "v2.32.3" } "### @@ -1916,9 +2038,11 @@ fn add_update_marker() -> Result<()> { name = "project" version = "0.1.0" requires-python = ">=3.8" - dependencies = [ - "requests>=2.30; python_version >= '3.11'" - ] + dependencies = ["requests>=2.30; python_version >= '3.11'"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.lock(), @r###" success: true @@ -1975,6 +2099,10 @@ fn add_update_marker() -> Result<()> { "requests>=2.30; python_version >= '3.11'", "requests>=2.0,<2.29 ; python_full_version < '3.11'", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2009,6 +2137,10 @@ fn add_update_marker() -> Result<()> { "requests>=2.30; python_version >= '3.11'", "requests>=2.0,<2.20 ; python_full_version < '3.11'", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2048,6 +2180,10 @@ fn add_update_marker() -> Result<()> { "requests>=2.0,<2.20 ; python_full_version < '3.11'", "requests>=2.31 ; python_full_version >= '3.12' and sys_platform == 'win32'", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2085,6 +2221,10 @@ fn add_update_marker() -> Result<()> { "requests>=2.31 ; python_full_version >= '3.12' and sys_platform == 'win32'", "requests>=2.10 ; sys_platform == 'win32'", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2121,6 +2261,10 @@ fn add_update_marker() -> Result<()> { version = "0.1.0" requires-python = ">=3.8" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2142,6 +2286,10 @@ fn update_source_replace_url() -> Result<()> { dependencies = [ "requests[security] @ https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl" ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; // Change the source. The existing URL should be removed. @@ -2177,6 +2325,10 @@ fn update_source_replace_url() -> Result<()> { "requests[security]", ] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] requests = { git = "https://github.com/psf/requests", tag = "v2.32.3" } "### @@ -2197,9 +2349,11 @@ fn add_inexact() -> Result<()> { name = "project" version = "0.1.0" requires-python = ">=3.12" - dependencies = [ - "anyio == 3.7.0", - ] + dependencies = ["anyio == 3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.lock(), @r###" @@ -2232,6 +2386,10 @@ fn add_inexact() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&["iniconfig==2.0.0"]), @r###" @@ -2262,6 +2420,10 @@ fn add_inexact() -> Result<()> { dependencies = [ "iniconfig==2.0.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2340,6 +2502,10 @@ fn remove_registry() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.lock(), @r###" @@ -2393,6 +2559,10 @@ fn remove_registry() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2440,11 +2610,12 @@ fn add_preserves_indentation_in_pyproject_toml() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" - dependencies = [ - "anyio==3.7.0" - ] + dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&["requests==2.31.0"]), @r###" @@ -2476,12 +2647,15 @@ fn add_preserves_indentation_in_pyproject_toml() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [ - "anyio==3.7.0", - "requests==2.31.0", + "anyio==3.7.0", + "requests==2.31.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2497,9 +2671,12 @@ fn add_puts_default_indentation_in_pyproject_toml_if_not_observed() -> Result<() [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&["requests==2.31.0"]), @r###" @@ -2531,12 +2708,15 @@ fn add_puts_default_indentation_in_pyproject_toml_if_not_observed() -> Result<() [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [ "anyio==3.7.0", "requests==2.31.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2553,9 +2733,12 @@ fn add_frozen() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&["anyio==3.7.0"]).arg("--frozen"), @r###" @@ -2576,11 +2759,14 @@ fn add_frozen() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [ "anyio==3.7.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2600,9 +2786,12 @@ fn add_no_sync() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&["anyio==3.7.0"]).arg("--no-sync"), @r###" @@ -2624,11 +2813,14 @@ fn add_no_sync() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [ "anyio==3.7.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2716,9 +2908,12 @@ fn add_error() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&["xyz"]), @r###" @@ -2758,6 +2953,10 @@ fn add_lower_bound() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; // Adding `anyio` should include a lower-bound. @@ -2790,6 +2989,10 @@ fn add_lower_bound() -> Result<()> { dependencies = [ "anyio>=4.3.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2809,6 +3012,10 @@ fn add_lower_bound_existing() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; // Adding `anyio` should _not_ set a lower-bound, since it's already present (even if @@ -2842,6 +3049,10 @@ fn add_lower_bound_existing() -> Result<()> { dependencies = [ "anyio", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2861,6 +3072,10 @@ fn add_lower_bound_raw() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; // Adding `anyio` should _not_ set a lower-bound when using `--raw-sources`. @@ -2893,6 +3108,10 @@ fn add_lower_bound_raw() -> Result<()> { dependencies = [ "anyio", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -2912,6 +3131,10 @@ fn add_lower_bound_dev() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; // Adding `anyio` should include a lower-bound. @@ -2943,6 +3166,10 @@ fn add_lower_bound_dev() -> Result<()> { requires-python = ">=3.12" dependencies = [] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] dev-dependencies = [ "anyio>=4.3.0", @@ -2966,6 +3193,10 @@ fn add_lower_bound_optional() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; // Adding `anyio` should include a lower-bound. @@ -3001,6 +3232,10 @@ fn add_lower_bound_optional() -> Result<()> { io = [ "anyio>=4.3.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -3080,6 +3315,10 @@ fn add_lower_bound_local() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; // Adding `torch` should include a lower-bound, but no local segment. @@ -3110,6 +3349,10 @@ fn add_lower_bound_local() -> Result<()> { dependencies = [ "local-simple-a>=1.2.3", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -3254,9 +3497,12 @@ fn add_repeat() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; uv_snapshot!(context.filters(), context.add(&["anyio"]), @r###" @@ -3284,11 +3530,14 @@ fn add_repeat() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [ "anyio>=4.3.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -3313,11 +3562,14 @@ fn add_repeat() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [ "anyio>=4.3.0", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); @@ -3335,9 +3587,12 @@ fn add_requirements_file() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; let requirements_txt = context.temp_dir.child("requirements.txt"); @@ -3376,13 +3631,16 @@ fn add_requirements_file() -> Result<()> { [project] name = "project" version = "0.1.0" - # ... requires-python = ">=3.12" dependencies = [ "flask==2.3.2", "anyio", ] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] anyio = { git = "https://github.com/agronholm/anyio.git", rev = "4.4.0" } "### @@ -3880,6 +4138,10 @@ fn fail_to_add_revert_project() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; // Adding `pytorch==1.0.2` should produce an error @@ -3927,6 +4189,10 @@ fn fail_to_add_revert_project() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "### ); }); diff --git a/crates/uv/tests/init.rs b/crates/uv/tests/init.rs index e36c417cac4f..bb5cb58aa856 100644 --- a/crates/uv/tests/init.rs +++ b/crates/uv/tests/init.rs @@ -882,9 +882,9 @@ fn init_explicit_workspace() -> Result<()> { Ok(()) } -/// Run `uv init` from within a virtual workspace. +/// Run `uv init --virtual` to create a virtual project. #[test] -fn init_virtual_workspace() -> Result<()> { +fn init_virtual_project() -> Result<()> { let context = TestContext::new("3.12"); let child = context.temp_dir.child("foo"); @@ -907,12 +907,67 @@ fn init_virtual_workspace() -> Result<()> { }, { assert_snapshot!( pyproject, @r###" + [project] + name = "foo" + version = "0.1.0" + description = "Add your description here" + readme = "README.md" + requires-python = ">=3.12" + dependencies = [] + "### + ); + }); + + uv_snapshot!(context.filters(), context.init().current_dir(&child).arg("bar"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Adding `bar` as member of workspace `[TEMP_DIR]/foo` + Initialized project `bar` at `[TEMP_DIR]/foo/bar` + "###); + + let pyproject = fs_err::read_to_string(pyproject_toml)?; + insta::with_settings!({ + filters => context.filters(), + }, { + assert_snapshot!( + pyproject, @r###" + [project] + name = "foo" + version = "0.1.0" + description = "Add your description here" + readme = "README.md" + requires-python = ">=3.12" + dependencies = [] + [tool.uv.workspace] - members = [] + members = ["bar"] "### ); }); + Ok(()) +} + +/// Run `uv init` from within a virtual workspace. +#[test] +fn init_virtual_workspace() -> Result<()> { + let context = TestContext::new("3.12"); + + let child = context.temp_dir.child("foo"); + child.create_dir_all()?; + + // Create a virtual workspace. + let pyproject_toml = child.child("pyproject.toml"); + pyproject_toml.write_str(indoc! { + r" + [tool.uv.workspace] + members = [] + ", + })?; + uv_snapshot!(context.filters(), context.init().current_dir(&child).arg("bar"), @r###" success: true exit_code: 0 @@ -957,7 +1012,7 @@ fn init_nested_virtual_workspace() -> Result<()> { ----- stdout ----- ----- stderr ----- - warning: Nested workspaces are not supported, but outer workspace (`[TEMP_DIR]/`) includes `[TEMP_DIR]/foo` + Adding `foo` as member of workspace `[TEMP_DIR]/` Initialized workspace `foo` at `[TEMP_DIR]/foo` "###); @@ -967,8 +1022,13 @@ fn init_nested_virtual_workspace() -> Result<()> { }, { assert_snapshot!( pyproject, @r###" - [tool.uv.workspace] - members = [] + [project] + name = "foo" + version = "0.1.0" + description = "Add your description here" + readme = "README.md" + requires-python = ">=3.12" + dependencies = [] "### ); }); @@ -980,7 +1040,7 @@ fn init_nested_virtual_workspace() -> Result<()> { assert_snapshot!( workspace, @r###" [tool.uv.workspace] - members = [] + members = ["foo"] "### ); }); diff --git a/crates/uv/tests/lock.rs b/crates/uv/tests/lock.rs index 71b8bffba003..46ed6fa47dc1 100644 --- a/crates/uv/tests/lock.rs +++ b/crates/uv/tests/lock.rs @@ -28,6 +28,10 @@ fn lock_wheel_registry() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -150,6 +154,10 @@ fn lock_sdist_registry() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["source-distribution==0.0.1"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -233,6 +241,10 @@ fn lock_sdist_git() -> Result<()> { requires-python = ">=3.12" dependencies = ["uv-public-pypackage"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", tag = "0.0.1" } "#, @@ -323,6 +335,10 @@ fn lock_sdist_git() -> Result<()> { requires-python = ">=3.12" dependencies = ["uv-public-pypackage"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", rev = "0dacfd662c64cb4ceb16e6cf65a157a8b715b979" } "#, @@ -379,6 +395,10 @@ fn lock_sdist_git() -> Result<()> { requires-python = ">=3.12" dependencies = ["uv-public-pypackage"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", rev = "b270df1a2fb5d012294e9aaf05e7e0bab1e6a389" } "#, @@ -435,6 +455,10 @@ fn lock_sdist_git() -> Result<()> { requires-python = ">=3.12" dependencies = ["uv-public-pypackage"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", tag = "0.0.2" } "#, @@ -498,6 +522,10 @@ fn lock_sdist_git_subdirectory() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["example-pkg-a @ git+https://github.com/pypa/sample-namespace-packages.git@df7530eeb8fa0cb7dbb8ecb28363e8e36bfa2f45#subdirectory=pkg_resources/pkg_a"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -582,6 +610,10 @@ fn lock_sdist_git_pep508() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage.git@0.0.1"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -645,6 +677,10 @@ fn lock_sdist_git_pep508() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage.git@0dacfd662c64cb4ceb16e6cf65a157a8b715b979"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -698,6 +734,10 @@ fn lock_sdist_git_pep508() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage.git@b270df1a2fb5d012294e9aaf05e7e0bab1e6a389"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -751,6 +791,10 @@ fn lock_sdist_git_pep508() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage.git@0.0.2"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -813,6 +857,10 @@ fn lock_sdist_git_short_rev() -> Result<()> { requires-python = ">=3.12" dependencies = ["uv-public-pypackage"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", rev = "0dacfd6" } "#, @@ -909,6 +957,10 @@ fn lock_wheel_url() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio @ https://files.pythonhosted.org/packages/14/fd/2f20c40b45e4fb4324834aea24bd4afdf1143390242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -1052,6 +1104,10 @@ fn lock_sdist_url() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio @ https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -1183,6 +1239,10 @@ fn lock_project_extra() -> Result<()> { requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [project.optional-dependencies] test = ["iniconfig"] "#, @@ -1325,6 +1385,10 @@ fn lock_project_with_overrides() -> Result<()> { requires-python = ">=3.12" dependencies = ["flask==3.0.0"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] override-dependencies = ["werkzeug==2.3.8"] "#, @@ -1371,7 +1435,7 @@ fn lock_project_with_overrides() -> Result<()> { Ok(()) } -/// Lock a project with a uv.tool.constraint-dependencies. +/// Lock a project with `uv.tool.constraint-dependencies`. #[test] fn lock_project_with_constraints() -> Result<()> { let context = TestContext::new("3.12"); @@ -1385,6 +1449,10 @@ fn lock_project_with_constraints() -> Result<()> { requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] constraint-dependencies = ["idna<3.4"] "#, @@ -1440,6 +1508,10 @@ fn lock_dependency_extra() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["flask[dotenv]"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -1636,6 +1708,10 @@ fn lock_conditional_dependency_extra() -> Result<()> { version = "0.1.0" requires-python = ">=3.7" dependencies = ["requests", "requests[socks] ; python_version < '3.10'"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -1918,6 +1994,10 @@ fn lock_dependency_non_existent_extra() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["flask[foo]"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -2100,6 +2180,10 @@ fn lock_upgrade_log() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["markupsafe<2", "iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -2177,6 +2261,10 @@ fn lock_upgrade_log() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["markupsafe", "typing-extensions"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -2268,6 +2356,10 @@ fn lock_upgrade_log_multi_version() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["markupsafe<2 ; sys_platform != 'win32'", "markupsafe==2.0.0 ; sys_platform == 'win32'"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -2351,6 +2443,10 @@ fn lock_upgrade_log_multi_version() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["markupsafe"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -2426,6 +2522,10 @@ fn lock_preference() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig<2"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -2482,6 +2582,10 @@ fn lock_preference() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -2597,6 +2701,10 @@ fn lock_git_sha() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@main"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -2636,6 +2744,10 @@ fn lock_git_sha() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["uv-public-pypackage @ git+https://github.com/astral-test/uv-public-pypackage@main"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -2712,6 +2824,10 @@ fn lock_requires_python() -> Result<()> { version = "0.1.0" requires-python = ">=3.7" dependencies = ["pygls>=1.1.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -2746,6 +2862,10 @@ fn lock_requires_python() -> Result<()> { version = "0.1.0" requires-python = ">=3.7" dependencies = ["pygls"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -2897,6 +3017,10 @@ fn lock_requires_python() -> Result<()> { version = "0.1.0" requires-python = ">=3.7.9" dependencies = ["pygls"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -3038,6 +3162,10 @@ fn lock_requires_python() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["pygls"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -3178,6 +3306,10 @@ fn lock_requires_python_wheels() -> Result<()> { version = "0.1.0" requires-python = "==3.12.*" dependencies = ["frozenlist"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -3261,6 +3393,10 @@ fn lock_requires_python_wheels() -> Result<()> { version = "0.1.0" requires-python = "==3.11.*" dependencies = ["frozenlist"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -3370,6 +3506,10 @@ fn lock_requires_python_star() -> Result<()> { version = "0.1.0" requires-python = "==3.11.*" dependencies = ["linehaul"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -3492,6 +3632,10 @@ fn lock_requires_python_pre() -> Result<()> { version = "0.1.0" requires-python = ">=3.11b1" dependencies = ["linehaul"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -3612,6 +3756,10 @@ fn lock_requires_python_unbounded() -> Result<()> { version = "0.1.0" requires-python = "<=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -3813,6 +3961,10 @@ fn lock_dev() -> Result<()> { [tool.uv] dev-dependencies = ["typing-extensions @ https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -3927,6 +4079,10 @@ fn lock_conditional_unconditional() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig", "iniconfig ; python_version < '3.12'"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -4004,6 +4160,10 @@ fn lock_multiple_markers() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig ; implementation_name == 'cpython'", "iniconfig ; python_version < '3.12'"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -4086,8 +4246,8 @@ fn lock_relative_and_absolute_paths() -> Result<()> { c = {{ path = '{}' }} [build-system] - requires = ["hatchling"] - build-backend = "hatchling.build" + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, context.temp_dir.join("c").display() })?; @@ -4104,8 +4264,9 @@ fn lock_relative_and_absolute_paths() -> Result<()> { license = {text = "MIT"} [build-system] - requires = ["hatchling"] - build-backend = "hatchling.build" + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + "#})?; context.temp_dir.child("b/b/__init__.py").touch()?; context @@ -4120,8 +4281,9 @@ fn lock_relative_and_absolute_paths() -> Result<()> { license = {text = "MIT"} [build-system] - requires = ["hatchling"] - build-backend = "hatchling.build" + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + "#})?; context.temp_dir.child("c/c/__init__.py").touch()?; @@ -4201,6 +4363,10 @@ fn lock_cycles() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["testtools==2.3.0", "fixtures==3.0.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -4404,6 +4570,11 @@ fn lock_new_extras() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["requests==2.31.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + "#, )?; @@ -4527,6 +4698,11 @@ fn lock_new_extras() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["requests[socks]==2.31.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + "#, )?; @@ -4675,6 +4851,10 @@ fn lock_invalid_hash() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -4771,6 +4951,10 @@ fn lock_resolution_mode() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio>=3"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -4949,6 +5133,10 @@ fn lock_requires_python_no_wheels() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["dearpygui==1.9.1"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -4981,6 +5169,10 @@ fn lock_same_version_multiple_urls() -> Result<()> { version = "0.0.1" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -4994,6 +5186,10 @@ fn lock_same_version_multiple_urls() -> Result<()> { version = "0.0.1" requires-python = ">=3.12" dependencies = ["anyio==3.0.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -5166,6 +5362,10 @@ fn lock_unsafe_lowest() -> Result<()> { [project.optional-dependencies] dev = ["iniconfig"] all = ["project[dev]"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -5205,6 +5405,10 @@ fn lock_exclusion() -> Result<()> { requires-python = ">=3.12" dependencies = [] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = [] exclude = ["child"] @@ -5223,6 +5427,10 @@ fn lock_exclusion() -> Result<()> { requires-python = ">=3.12" dependencies = ["project"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] project = { path = ".." } "#, @@ -5303,6 +5511,10 @@ fn lock_dev_transitive() -> Result<()> { [tool.uv] dev-dependencies = ["anyio"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -5318,6 +5530,10 @@ fn lock_dev_transitive() -> Result<()> { requires-python = ">=3.12" dependencies = ["foo", "baz", "iniconfig>1"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] foo = { path = "../foo" } baz = { workspace = true } @@ -5339,6 +5555,10 @@ fn lock_dev_transitive() -> Result<()> { requires-python = ">=3.12" dependencies = [] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] dev-dependencies = ["typing-extensions>4"] "#, @@ -5462,6 +5682,10 @@ fn lock_redact_https() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -5608,6 +5832,10 @@ fn lock_redact_https() -> Result<()> { requires-python = ">=3.12" dependencies = ["iniconfig"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] index-url = "https://public:heron@pypi-proxy.fly.dev/basic-auth/simple" "#, @@ -5650,6 +5878,10 @@ fn lock_redact_git() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["uv-private-pypackage @ git+https://{token}@github.com/astral-test/uv-private-pypackage"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, token = token, })?; @@ -5735,6 +5967,10 @@ fn lock_relative_index() -> Result<()> { requires-python = ">=3.12" dependencies = ["iniconfig"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] index-url = "https://pypi-proxy.fly.dev/relative/simple" "#, @@ -5824,6 +6060,11 @@ fn lock_no_sources() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] anyio = { path = "./anyio" } "#, @@ -5840,6 +6081,10 @@ fn lock_no_sources() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -6008,6 +6253,10 @@ fn lock_migrate() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -6150,6 +6399,10 @@ fn lock_upgrade_package() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio<=2", "idna<=3"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -6244,6 +6497,10 @@ fn lock_upgrade_package() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio", "idna"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -6426,6 +6683,10 @@ fn lock_upgrade_drop_fork_markers() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["fork-upgrade-foo==1"] + + [build-system] + requires = ["flit_core>=3.8,<4"] + build-backend = "flit_core.buildapi" "#; let pyproject_toml = context.temp_dir.child("pyproject.toml"); @@ -6468,6 +6729,10 @@ fn lock_warn_missing_transitive_lower_bounds() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["pytest>8"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -6499,6 +6764,10 @@ fn lock_find_links_local_wheel() -> Result<()> { requires-python = ">=3.12" dependencies = ["tqdm==1000.0.0"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] find-links = ["{}"] "#, @@ -6588,6 +6857,10 @@ fn lock_find_links_local_sdist() -> Result<()> { requires-python = ">=3.12" dependencies = ["tqdm==999.0.0"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] find-links = ["{}"] "#, @@ -6675,6 +6948,10 @@ fn lock_find_links_http_wheel() -> Result<()> { requires-python = ">=3.12" dependencies = ["packaging==23.2"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] find-links = ["{}"] no-build-package = ["packaging"] @@ -6766,6 +7043,10 @@ fn lock_find_links_http_sdist() -> Result<()> { requires-python = ">=3.12" dependencies = ["packaging==23.2"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] find-links = ["{}"] no-binary-package = ["packaging"] @@ -6884,6 +7165,10 @@ fn lock_local_index() -> Result<()> { requires-python = ">=3.12" dependencies = ["tqdm"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] extra-index-url = ["{}"] "#, @@ -6980,6 +7265,10 @@ fn lock_sources_url() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["workspace @ https://github.com/user-attachments/files/16592193/workspace.zip"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -7115,6 +7404,10 @@ fn lock_sources_archive() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["workspace @ {}"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, Url::from_file_path(&workspace_archive).unwrap(), })?; @@ -7365,6 +7658,10 @@ fn lock_editable() -> Result<()> { dependencies = ["library"] requires-python = ">=3.12" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] library = { path = "./library" } @@ -7381,6 +7678,10 @@ fn lock_editable() -> Result<()> { version = "0.1.0" dependencies = ["library"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] library = { path = "../../library" } "#})?; @@ -7472,6 +7773,10 @@ fn lock_editable() -> Result<()> { version = "0.1.0" dependencies = ["library"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] library = { path = "../../library", editable = true } "#})?; @@ -7575,6 +7880,10 @@ fn lock_mixed_extras() -> Result<()> { requires-python = ">=3.12" dependencies = ["leaf1", "workspace2"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [project.optional-dependencies] async = ["typing-extensions>=4"] @@ -7597,6 +7906,10 @@ fn lock_mixed_extras() -> Result<()> { [project.optional-dependencies] async = ["iniconfig>=2"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; leaf1.child("src/__init__.py").touch()?; @@ -7609,6 +7922,10 @@ fn lock_mixed_extras() -> Result<()> { requires-python = ">=3.12" dependencies = ["leaf2"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] leaf2 = { workspace = true } @@ -7627,6 +7944,10 @@ fn lock_mixed_extras() -> Result<()> { [project.optional-dependencies] async = ["packaging>=24"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; leaf2.child("src/__init__.py").touch()?; @@ -7795,6 +8116,10 @@ fn lock_transitive_extra() -> Result<()> { requires-python = ">=3.12" dependencies = ["leaf"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [project.optional-dependencies] async = ["typing-extensions>=4", "leaf[async]"] @@ -7817,6 +8142,10 @@ fn lock_transitive_extra() -> Result<()> { [project.optional-dependencies] async = ["iniconfig>=2"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; leaf.child("src/__init__.py").touch()?; @@ -8000,9 +8329,11 @@ fn lock_mismatched_versions() -> Result<()> { name = "project" version = "0.1.0" requires-python = ">=3.12" - dependencies = [ - "uv-public-pypackage==0.0.2", - ] + dependencies = ["uv-public-pypackage==0.0.2"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" [tool.uv.sources] uv-public-pypackage = { git = "https://github.com/astral-test/uv-public-pypackage", tag = "0.0.1" } @@ -8093,6 +8424,10 @@ fn unconditional_overlapping_marker_disjoint_version_constraints() -> Result<()> "datasets < 2.19", "datasets >= 2.19 ; python_version > '3.10'" ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -8122,6 +8457,10 @@ fn lock_change_index() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -8244,6 +8583,10 @@ fn lock_remove_member() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio>3"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -8256,6 +8599,10 @@ fn lock_remove_member() -> Result<()> { requires-python = ">=3.12" dependencies = ["leaf"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = ["leaf"] @@ -8437,6 +8784,10 @@ fn lock_add_member() -> Result<()> { requires-python = ">=3.12" dependencies = [] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = [] "#, @@ -8491,6 +8842,10 @@ fn lock_add_member() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio>3"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -8503,6 +8858,10 @@ fn lock_add_member() -> Result<()> { requires-python = ">=3.12" dependencies = [] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = ["leaf"] "#, @@ -8646,6 +9005,10 @@ fn lock_redundant_add_member() -> Result<()> { requires-python = ">=3.12" dependencies = ["anyio"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = [] "#, @@ -8737,6 +9100,10 @@ fn lock_redundant_add_member() -> Result<()> { requires-python = ">=3.12" dependencies = ["anyio", "idna"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = [] "#, @@ -8843,6 +9210,10 @@ fn lock_new_constraints() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -8932,6 +9303,10 @@ fn lock_new_constraints() -> Result<()> { requires-python = ">=3.12" dependencies = ["anyio"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] constraint-dependencies = [ "anyio < 4.3", @@ -9037,6 +9412,10 @@ fn lock_remove_member_virtual() -> Result<()> { r#" [tool.uv.workspace] members = ["leaf"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -9049,6 +9428,10 @@ fn lock_remove_member_virtual() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio>3"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -9201,6 +9584,10 @@ fn lock_rename_project() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -9267,6 +9654,10 @@ fn lock_rename_project() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -9345,6 +9736,10 @@ fn lock_missing_metadata() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -9483,6 +9878,10 @@ fn lock_reorder() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio", "iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -9584,6 +9983,10 @@ fn lock_reorder() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig", "anyio"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -9612,6 +10015,10 @@ fn lock_narrowed_python_version() -> Result<()> { version = "0.1.0" requires-python = ">=3.7" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -9623,6 +10030,11 @@ fn lock_narrowed_python_version() -> Result<()> { version = "0.1.0" requires-python = ">=3.7" dependencies = ["dependency ; python_version < '3.9'", "dependency ; python_version > '3.10'"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] dependency = { path = "./dependency" } "#, @@ -9727,8 +10139,8 @@ fn lock_exclude_unnecessary_python_forks() -> Result<()> { "anyio ; python_version > '3.10'" ] [build-system] - requires = ["hatchling"] - build-backend = "hatchling.build" + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -9833,6 +10245,10 @@ fn lock_constrained_environment() -> Result<()> { requires-python = ">=3.12" dependencies = ["black"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] environments = "platform_system != 'Windows'" "#, @@ -9977,6 +10393,10 @@ fn lock_constrained_environment() -> Result<()> { requires-python = ">=3.12" dependencies = ["black"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] environments = ["platform_system != 'Windows'"] "#, @@ -10001,6 +10421,10 @@ fn lock_constrained_environment() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["black"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -10149,6 +10573,10 @@ fn lock_overlapping_environment() -> Result<()> { requires-python = ">=3.8" dependencies = ["black"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] environments = ["platform_system != 'Windows'", "python_version > '3.10'"] "#, @@ -10320,6 +10748,10 @@ fn lock_dropped_dev_extra() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] dev-dependencies = [ "coverage[toml]" @@ -10421,3 +10853,442 @@ fn lock_dropped_dev_extra() -> Result<()> { Ok(()) } + +/// Lock a project with `virtual = true`. +#[test] +fn lock_explicit_virtual_project() -> Result<()> { + let context = TestContext::new("3.12"); + + let pyproject_toml = context.temp_dir.child("pyproject.toml"); + pyproject_toml.write_str( + r#" + [project] + name = "project" + version = "0.1.0" + requires-python = ">=3.12" + dependencies = ["black"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + + [tool.uv] + virtual = true + dev-dependencies = [ + "anyio" + ] + "#, + )?; + + uv_snapshot!(context.filters(), context.lock(), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 11 packages in [TIME] + "###); + + let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock")).unwrap(); + + insta::with_settings!({ + filters => context.filters(), + }, { + assert_snapshot!( + lock, @r###" + version = 1 + requires-python = ">=3.12" + + [options] + exclude-newer = "2024-03-25T00:00:00Z" + + [[package]] + name = "anyio" + version = "4.3.0" + source = { registry = "https://pypi.org/simple" } + dependencies = [ + { name = "idna" }, + { name = "sniffio" }, + ] + sdist = { url = "https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6", size = 159642 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/14/fd/2f20c40b45e4fb4324834aea24bd4afdf1143390242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8", size = 85584 }, + ] + + [[package]] + name = "black" + version = "24.3.0" + source = { registry = "https://pypi.org/simple" } + dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + ] + sdist = { url = "https://files.pythonhosted.org/packages/8f/5f/bac24a952668c7482cfdb4ebf91ba57a796c9da8829363a772040c1a3312/black-24.3.0.tar.gz", hash = "sha256:a0c9c4a0771afc6919578cec71ce82a3e31e054904e7197deacbc9382671c41f", size = 634292 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/c6/1d174efa9ff02b22d0124c73fc5f4d4fb006d0d9a081aadc354d05754a13/black-24.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2818cf72dfd5d289e48f37ccfa08b460bf469e67fb7c4abb07edc2e9f16fb63f", size = 1600822 }, + { url = "https://files.pythonhosted.org/packages/d9/ed/704731afffe460b8ff0672623b40fce9fe569f2ee617c15857e4d4440a3a/black-24.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4acf672def7eb1725f41f38bf6bf425c8237248bb0804faa3965c036f7672d11", size = 1429987 }, + { url = "https://files.pythonhosted.org/packages/a8/05/8dd038e30caadab7120176d4bc109b7ca2f4457f12eef746b0560a583458/black-24.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7ed6668cbbfcd231fa0dc1b137d3e40c04c7f786e626b405c62bcd5db5857e4", size = 1755319 }, + { url = "https://files.pythonhosted.org/packages/71/9d/e5fa1ff4ef1940be15a64883c0bb8d2fcf626efec996eab4ae5a8c691d2c/black-24.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:56f52cfbd3dabe2798d76dbdd299faa046a901041faf2cf33288bc4e6dae57b5", size = 1385180 }, + { url = "https://files.pythonhosted.org/packages/4d/ea/31770a7e49f3eedfd8cd7b35e78b3a3aaad860400f8673994bc988318135/black-24.3.0-py3-none-any.whl", hash = "sha256:41622020d7120e01d377f74249e677039d20e6344ff5851de8a10f11f513bf93", size = 201493 }, + ] + + [[package]] + name = "click" + version = "8.1.7" + source = { registry = "https://pypi.org/simple" } + dependencies = [ + { name = "colorama", marker = "platform_system == 'Windows'" }, + ] + sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941 }, + ] + + [[package]] + name = "colorama" + version = "0.4.6" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, + ] + + [[package]] + name = "idna" + version = "3.6" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/bf/3f/ea4b9117521a1e9c50344b909be7886dd00a519552724809bb1f486986c2/idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", size = 175426 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f", size = 61567 }, + ] + + [[package]] + name = "mypy-extensions" + version = "1.0.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, + ] + + [[package]] + name = "packaging" + version = "24.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/ee/b5/b43a27ac7472e1818c4bafd44430e69605baefe1f34440593e0332ec8b4d/packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9", size = 147882 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", size = 53488 }, + ] + + [[package]] + name = "pathspec" + version = "0.12.1" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, + ] + + [[package]] + name = "platformdirs" + version = "4.2.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/96/dc/c1d911bf5bb0fdc58cc05010e9f3efe3b67970cef779ba7fbc3183b987a8/platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768", size = 20055 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068", size = 17717 }, + ] + + [[package]] + name = "project" + version = "0.1.0" + source = { editable = "." } + dependencies = [ + { name = "black" }, + ] + + [package.dev-dependencies] + dev = [ + { name = "anyio" }, + ] + + [package.metadata] + requires-dist = [{ name = "black" }] + + [package.metadata.requires-dev] + dev = [{ name = "anyio" }] + + [[package]] + name = "sniffio" + version = "1.3.1" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, + ] + "### + ); + }); + + // Re-run with `--locked`. + uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 11 packages in [TIME] + "###); + + // Re-run with `--offline`. We shouldn't need a network connection to validate an + // already-correct lockfile with immutable metadata. + uv_snapshot!(context.filters(), context.lock().arg("--locked").arg("--offline").arg("--no-cache"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 11 packages in [TIME] + "###); + + // Install from the lockfile. The virtual project should _not_ be installed. + uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Prepared 9 packages in [TIME] + Installed 9 packages in [TIME] + + anyio==4.3.0 + + black==24.3.0 + + click==8.1.7 + + idna==3.6 + + mypy-extensions==1.0.0 + + packaging==24.0 + + pathspec==0.12.1 + + platformdirs==4.2.0 + + sniffio==1.3.1 + "###); + + Ok(()) +} + +/// Lock a project that is implicitly virtual (by way of omitting `build-system`0> +#[test] +fn lock_implicit_virtual_project() -> Result<()> { + let context = TestContext::new("3.12"); + + let pyproject_toml = context.temp_dir.child("pyproject.toml"); + pyproject_toml.write_str( + r#" + [project] + name = "project" + version = "0.1.0" + requires-python = ">=3.12" + dependencies = ["black"] + + [tool.uv] + dev-dependencies = [ + "anyio" + ] + "#, + )?; + + uv_snapshot!(context.filters(), context.lock(), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 11 packages in [TIME] + "###); + + let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock")).unwrap(); + + insta::with_settings!({ + filters => context.filters(), + }, { + assert_snapshot!( + lock, @r###" + version = 1 + requires-python = ">=3.12" + + [options] + exclude-newer = "2024-03-25T00:00:00Z" + + [[package]] + name = "anyio" + version = "4.3.0" + source = { registry = "https://pypi.org/simple" } + dependencies = [ + { name = "idna" }, + { name = "sniffio" }, + ] + sdist = { url = "https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6", size = 159642 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/14/fd/2f20c40b45e4fb4324834aea24bd4afdf1143390242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8", size = 85584 }, + ] + + [[package]] + name = "black" + version = "24.3.0" + source = { registry = "https://pypi.org/simple" } + dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + ] + sdist = { url = "https://files.pythonhosted.org/packages/8f/5f/bac24a952668c7482cfdb4ebf91ba57a796c9da8829363a772040c1a3312/black-24.3.0.tar.gz", hash = "sha256:a0c9c4a0771afc6919578cec71ce82a3e31e054904e7197deacbc9382671c41f", size = 634292 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/c6/1d174efa9ff02b22d0124c73fc5f4d4fb006d0d9a081aadc354d05754a13/black-24.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2818cf72dfd5d289e48f37ccfa08b460bf469e67fb7c4abb07edc2e9f16fb63f", size = 1600822 }, + { url = "https://files.pythonhosted.org/packages/d9/ed/704731afffe460b8ff0672623b40fce9fe569f2ee617c15857e4d4440a3a/black-24.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4acf672def7eb1725f41f38bf6bf425c8237248bb0804faa3965c036f7672d11", size = 1429987 }, + { url = "https://files.pythonhosted.org/packages/a8/05/8dd038e30caadab7120176d4bc109b7ca2f4457f12eef746b0560a583458/black-24.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7ed6668cbbfcd231fa0dc1b137d3e40c04c7f786e626b405c62bcd5db5857e4", size = 1755319 }, + { url = "https://files.pythonhosted.org/packages/71/9d/e5fa1ff4ef1940be15a64883c0bb8d2fcf626efec996eab4ae5a8c691d2c/black-24.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:56f52cfbd3dabe2798d76dbdd299faa046a901041faf2cf33288bc4e6dae57b5", size = 1385180 }, + { url = "https://files.pythonhosted.org/packages/4d/ea/31770a7e49f3eedfd8cd7b35e78b3a3aaad860400f8673994bc988318135/black-24.3.0-py3-none-any.whl", hash = "sha256:41622020d7120e01d377f74249e677039d20e6344ff5851de8a10f11f513bf93", size = 201493 }, + ] + + [[package]] + name = "click" + version = "8.1.7" + source = { registry = "https://pypi.org/simple" } + dependencies = [ + { name = "colorama", marker = "platform_system == 'Windows'" }, + ] + sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941 }, + ] + + [[package]] + name = "colorama" + version = "0.4.6" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, + ] + + [[package]] + name = "idna" + version = "3.6" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/bf/3f/ea4b9117521a1e9c50344b909be7886dd00a519552724809bb1f486986c2/idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", size = 175426 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f", size = 61567 }, + ] + + [[package]] + name = "mypy-extensions" + version = "1.0.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, + ] + + [[package]] + name = "packaging" + version = "24.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/ee/b5/b43a27ac7472e1818c4bafd44430e69605baefe1f34440593e0332ec8b4d/packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9", size = 147882 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", size = 53488 }, + ] + + [[package]] + name = "pathspec" + version = "0.12.1" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, + ] + + [[package]] + name = "platformdirs" + version = "4.2.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/96/dc/c1d911bf5bb0fdc58cc05010e9f3efe3b67970cef779ba7fbc3183b987a8/platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768", size = 20055 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068", size = 17717 }, + ] + + [[package]] + name = "project" + version = "0.1.0" + source = { editable = "." } + dependencies = [ + { name = "black" }, + ] + + [package.dev-dependencies] + dev = [ + { name = "anyio" }, + ] + + [package.metadata] + requires-dist = [{ name = "black" }] + + [package.metadata.requires-dev] + dev = [{ name = "anyio" }] + + [[package]] + name = "sniffio" + version = "1.3.1" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, + ] + "### + ); + }); + + // Re-run with `--locked`. + uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 11 packages in [TIME] + "###); + + // Re-run with `--offline`. We shouldn't need a network connection to validate an + // already-correct lockfile with immutable metadata. + uv_snapshot!(context.filters(), context.lock().arg("--locked").arg("--offline").arg("--no-cache"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 11 packages in [TIME] + "###); + + // Install from the lockfile. The virtual project should _not_ be installed. + uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Prepared 9 packages in [TIME] + Installed 9 packages in [TIME] + + anyio==4.3.0 + + black==24.3.0 + + click==8.1.7 + + idna==3.6 + + mypy-extensions==1.0.0 + + packaging==24.0 + + pathspec==0.12.1 + + platformdirs==4.2.0 + + sniffio==1.3.1 + "###); + + Ok(()) +} diff --git a/crates/uv/tests/run.rs b/crates/uv/tests/run.rs index d6e04fa99f01..6e0f59858d69 100644 --- a/crates/uv/tests/run.rs +++ b/crates/uv/tests/run.rs @@ -27,6 +27,10 @@ fn run_with_python_version() -> Result<()> { "anyio==3.6.0 ; python_version == '3.11'", "anyio==3.7.0 ; python_version == '3.12'", ] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; let test_script = context.temp_dir.child("main.py"); @@ -146,6 +150,10 @@ fn run_args() -> Result<()> { version = "1.0.0" requires-python = ">=3.8" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; @@ -201,6 +209,10 @@ fn run_pep723_script() -> Result<()> { version = "1.0.0" requires-python = ">=3.8" dependencies = ["anyio"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; @@ -363,6 +375,10 @@ fn run_pythonw_script() -> Result<()> { version = "1.0.0" requires-python = ">=3.8" dependencies = ["anyio"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; @@ -473,6 +489,10 @@ fn run_managed_false() -> Result<()> { requires-python = ">=3.8" dependencies = ["anyio"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] managed = false "# @@ -501,6 +521,10 @@ fn run_with() -> Result<()> { version = "1.0.0" requires-python = ">=3.8" dependencies = ["anyio", "sniffio==1.3.1"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; @@ -597,6 +621,10 @@ fn run_with_editable() -> Result<()> { version = "1.0.0" requires-python = ">=3.8" dependencies = ["anyio", "sniffio==1.3.1"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; @@ -660,6 +688,10 @@ fn run_with_editable() -> Result<()> { requires-python = ">=3.8" dependencies = ["anyio", "sniffio==1.3.1"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] anyio = { path = "./src/anyio_local", editable = true } "# @@ -719,6 +751,10 @@ fn run_locked() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -745,6 +781,10 @@ fn run_locked() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -797,6 +837,10 @@ fn run_frozen() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -820,6 +864,10 @@ fn run_frozen() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -853,6 +901,10 @@ fn run_empty_requirements_txt() -> Result<()> { version = "1.0.0" requires-python = ">=3.8" dependencies = ["anyio", "sniffio==1.3.1"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; @@ -909,6 +961,10 @@ fn run_requirements_txt() -> Result<()> { version = "1.0.0" requires-python = ">=3.8" dependencies = ["anyio", "sniffio==1.3.1"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; @@ -1024,6 +1080,10 @@ fn run_requirements_txt_arguments() -> Result<()> { version = "1.0.0" requires-python = ">=3.8" dependencies = ["typing_extensions"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; @@ -1069,15 +1129,15 @@ fn run_editable() -> Result<()> { let pyproject_toml = context.temp_dir.child("pyproject.toml"); pyproject_toml.write_str(indoc! { r#" - [build-system] - requires = ["hatchling"] - build-backend = "hatchling.build" - [project] name = "foo" version = "1.0.0" requires-python = ">=3.8" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; @@ -1136,6 +1196,10 @@ fn run_from_directory() -> Result<()> { [project.scripts] main = "main:main" + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; let main_script = project_dir.child("main.py"); @@ -1180,6 +1244,10 @@ fn run_without_output() -> Result<()> { version = "1.0.0" requires-python = ">=3.8" dependencies = ["anyio", "sniffio==1.3.1"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; @@ -1219,15 +1287,15 @@ fn run_isolated_python_version() -> Result<()> { let pyproject_toml = context.temp_dir.child("pyproject.toml"); pyproject_toml.write_str(indoc! { r#" - [build-system] - requires = ["hatchling"] - build-backend = "hatchling.build" - [project] name = "foo" version = "1.0.0" requires-python = ">=3.8" dependencies = ["anyio"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; @@ -1318,15 +1386,15 @@ fn run_no_project() -> Result<()> { let pyproject_toml = context.temp_dir.child("pyproject.toml"); pyproject_toml.write_str(indoc! { r#" - [build-system] - requires = ["hatchling"] - build-backend = "hatchling.build" - [project] name = "foo" version = "1.0.0" requires-python = ">=3.8" dependencies = ["anyio"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "# })?; diff --git a/crates/uv/tests/sync.rs b/crates/uv/tests/sync.rs index 2ea551facf0f..5de42004c01b 100644 --- a/crates/uv/tests/sync.rs +++ b/crates/uv/tests/sync.rs @@ -21,6 +21,10 @@ fn sync() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -55,6 +59,10 @@ fn locked() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -81,6 +89,10 @@ fn locked() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -115,6 +127,10 @@ fn frozen() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -138,6 +154,10 @@ fn frozen() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -212,6 +232,10 @@ fn package() -> Result<()> { requires-python = ">=3.12" dependencies = ["child", "anyio>3"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] child = { workspace = true } @@ -237,6 +261,10 @@ fn package() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig>1"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -312,6 +340,10 @@ fn mixed_requires_python() -> Result<()> { name = "bird-feeder" version = "0.1.0" requires-python = ">=3.8" + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -381,6 +413,10 @@ fn virtual_workspace_dev_dependencies() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig>1"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -434,6 +470,10 @@ fn sync_build_isolation() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig @ https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -579,10 +619,9 @@ fn sync_build_isolation_package() -> Result<()> { dependencies = [ "iniconfig @ https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", ] + [build-system] - requires = [ - "setuptools >= 40.9.0", - ] + requires = ["setuptools>=42", "wheel"] build-backend = "setuptools.build_meta" "#, )?; @@ -772,6 +811,10 @@ fn sync_environment() -> Result<()> { requires-python = ">=3.10" dependencies = ["iniconfig"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] environments = ["python_version < '3.11'"] "#, @@ -811,6 +854,10 @@ fn read_metadata_statically_over_the_cache() -> Result<()> { requires-python = ">=3.12" # Python string sorting is the other way round. dependencies = ["anyio>=4,<5"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -840,6 +887,10 @@ fn no_install_project() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; @@ -891,6 +942,10 @@ fn no_install_workspace() -> Result<()> { requires-python = ">=3.12" dependencies = ["anyio==3.7.0", "child"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = ["child"] @@ -910,8 +965,8 @@ fn no_install_workspace() -> Result<()> { dependencies = ["iniconfig>1"] [build-system] - requires = ["hatchling"] - build-backend = "hatchling.build" + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; child @@ -968,6 +1023,10 @@ fn no_install_package() -> Result<()> { version = "0.1.0" requires-python = ">=3.12" dependencies = ["anyio==3.7.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#, )?; diff --git a/crates/uv/tests/workspace.rs b/crates/uv/tests/workspace.rs index b3607331d279..7f452ba05a6f 100644 --- a/crates/uv/tests/workspace.rs +++ b/crates/uv/tests/workspace.rs @@ -965,6 +965,10 @@ fn workspace_inherit_sources() -> Result<()> { dependencies = [] requires-python = ">=3.12" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = ["packages/*"] "#})?; @@ -977,6 +981,10 @@ fn workspace_inherit_sources() -> Result<()> { name = "leaf" version = "0.1.0" dependencies = ["library"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; leaf.child("src/__init__.py").touch()?; @@ -987,6 +995,10 @@ fn workspace_inherit_sources() -> Result<()> { name = "library" version = "0.1.0" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; library.child("src/__init__.py").touch()?; @@ -1013,6 +1025,10 @@ fn workspace_inherit_sources() -> Result<()> { version = "0.1.0" dependencies = ["library"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] library = { path = "../../../library", editable = true } "#})?; @@ -1036,6 +1052,10 @@ fn workspace_inherit_sources() -> Result<()> { name = "leaf" version = "0.1.0" dependencies = ["library"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; // Update the root to include the source. @@ -1046,6 +1066,10 @@ fn workspace_inherit_sources() -> Result<()> { dependencies = [] requires-python = ">=3.12" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] library = { path = "../library", editable = true } @@ -1117,6 +1141,10 @@ fn workspace_inherit_sources() -> Result<()> { dependencies = [] requires-python = ">=3.12" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] library = { path = "../library", editable = true } @@ -1131,9 +1159,12 @@ fn workspace_inherit_sources() -> Result<()> { version = "0.1.0" dependencies = ["library"] + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.sources] application = { path = "../application", editable = true } - "#})?; // Resolving should succeed; the member should still use the root's source, despite defining @@ -1167,6 +1198,10 @@ fn workspace_unsatisfiable_member_dependencies() -> Result<()> { dependencies = [] requires-python = ">=3.12" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = ["packages/*"] "#})?; @@ -1179,6 +1214,10 @@ fn workspace_unsatisfiable_member_dependencies() -> Result<()> { name = "leaf" version = "0.1.0" dependencies = ["httpx>9999"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; leaf.child("src/__init__.py").touch()?; @@ -1215,6 +1254,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting() -> Result<()> { dependencies = [] requires-python = ">=3.12" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = ["packages/*"] "#})?; @@ -1227,6 +1270,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting() -> Result<()> { name = "foo" version = "0.1.0" dependencies = ["anyio==4.1.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; foo.child("src/__init__.py").touch()?; let bar = workspace.child("packages").child("bar"); @@ -1235,6 +1282,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting() -> Result<()> { name = "bar" version = "0.1.0" dependencies = ["anyio==4.2.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; bar.child("src/__init__.py").touch()?; @@ -1271,6 +1322,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting_threeway() -> Result< dependencies = [] requires-python = ">=3.12" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = ["packages/*"] "#})?; @@ -1283,6 +1338,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting_threeway() -> Result< name = "red" version = "0.1.0" dependencies = ["anyio==4.1.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; red.child("src/__init__.py").touch()?; let knot = workspace.child("packages").child("knot"); @@ -1291,6 +1350,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting_threeway() -> Result< name = "knot" version = "0.1.0" dependencies = ["anyio==4.2.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; knot.child("src/__init__.py").touch()?; @@ -1302,6 +1365,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting_threeway() -> Result< name = "bird" version = "0.1.0" dependencies = ["anyio==4.3.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; bird.child("src/__init__.py").touch()?; @@ -1338,6 +1405,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting_extra() -> Result<()> dependencies = [] requires-python = ">=3.12" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = ["packages/*"] "#})?; @@ -1350,6 +1421,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting_extra() -> Result<()> name = "foo" version = "0.1.0" dependencies = ["anyio==4.1.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; foo.child("src/__init__.py").touch()?; let bar = workspace.child("packages").child("bar"); @@ -1360,6 +1435,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting_extra() -> Result<()> [project.optional-dependencies] some_extra = ["anyio==4.2.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; bar.child("src/__init__.py").touch()?; @@ -1396,6 +1475,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting_dev() -> Result<()> { dependencies = [] requires-python = ">=3.12" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = ["packages/*"] "#})?; @@ -1408,6 +1491,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting_dev() -> Result<()> { name = "foo" version = "0.1.0" dependencies = ["anyio==4.1.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; foo.child("src/__init__.py").touch()?; let bar = workspace.child("packages").child("bar"); @@ -1416,6 +1503,10 @@ fn workspace_unsatisfiable_member_dependencies_conflicting_dev() -> Result<()> { name = "bar" version = "0.1.0" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv] dev-dependencies = ["anyio==4.2.0"] "#})?; @@ -1455,6 +1546,10 @@ fn workspace_member_name_shadows_dependencies() -> Result<()> { dependencies = [] requires-python = ">=3.12" + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" + [tool.uv.workspace] members = ["packages/*"] "#})?; @@ -1467,6 +1562,10 @@ fn workspace_member_name_shadows_dependencies() -> Result<()> { name = "foo" version = "0.1.0" dependencies = ["anyio==4.1.0"] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; foo.child("src/__init__.py").touch()?; @@ -1477,6 +1576,10 @@ fn workspace_member_name_shadows_dependencies() -> Result<()> { name = "anyio" version = "0.1.0" dependencies = [] + + [build-system] + requires = ["setuptools>=42", "wheel"] + build-backend = "setuptools.build_meta" "#})?; anyio.child("src/__init__.py").touch()?; diff --git a/docs/reference/cli.md b/docs/reference/cli.md index f93621a709a8..51aaa8ec368b 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -447,9 +447,11 @@ uv init [OPTIONS] [PATH]
--version, -V

Display the uv version

-
--virtual

Create a virtual workspace instead of a project.

+
--virtual

Create a virtual project, rather than a package.

-

A virtual workspace does not define project dependencies and cannot be published. Instead, workspace members declare project dependencies. Development dependencies may still be declared.

+

A virtual project is a project that is not intended to be built as a Python package, such as a project that only contains scripts or other application code.

+ +

Virtual projects themselves are not installed into the Python environment.

diff --git a/docs/reference/settings.md b/docs/reference/settings.md index 25f80f258d55..140678073ed8 100644 --- a/docs/reference/settings.md +++ b/docs/reference/settings.md @@ -892,6 +892,31 @@ those that are downloaded and installed by uv. --- +#### [`r#virtual`](#r#virtual) {: #r#virtual } + +Whether the project should be considered "virtual". + +**Default value**: `true` + +**Type**: `bool` + +**Example usage**: + +=== "pyproject.toml" + + ```toml + [tool.uv] + virtual = false + ``` +=== "uv.toml" + + ```toml + + virtual = false + ``` + +--- + #### [`reinstall`](#reinstall) {: #reinstall } Reinstall all packages, regardless of whether they're already installed. Implies `refresh`. diff --git a/uv.schema.json b/uv.schema.json index 6fe0959f999b..e1b2fb24ec5d 100644 --- a/uv.schema.json +++ b/uv.schema.json @@ -368,6 +368,13 @@ "$ref": "#/definitions/Requirement" } }, + "virtual": { + "description": "Whether the project should be considered \"virtual\".", + "type": [ + "boolean", + "null" + ] + }, "workspace": { "description": "The workspace definition for the project, if any.", "anyOf": [