diff --git a/crates/uv-distribution/src/metadata/lowering.rs b/crates/uv-distribution/src/metadata/lowering.rs index dd0974a99..7c8219d74 100644 --- a/crates/uv-distribution/src/metadata/lowering.rs +++ b/crates/uv-distribution/src/metadata/lowering.rs @@ -16,7 +16,7 @@ use uv_pep508::{MarkerTree, VerbatimUrl, VersionOrUrl, looks_like_git_repository use uv_pypi_types::{ConflictItem, ParsedUrlError, VerbatimParsedUrl}; use uv_redacted::DisplaySafeUrl; use uv_workspace::Workspace; -use uv_workspace::pyproject::{PyProjectToml, Source, Sources}; +use uv_workspace::pyproject::{Source, Sources}; use crate::metadata::GitWorkspaceMember; @@ -723,14 +723,8 @@ fn path_source( }) } else { // Determine whether the project is a package or virtual. - let is_package = package.unwrap_or_else(|| { - let pyproject_path = install_path.join("pyproject.toml"); - fs_err::read_to_string(&pyproject_path) - .ok() - .and_then(|contents| PyProjectToml::from_string(contents).ok()) - .map(|pyproject_toml| pyproject_toml.is_package()) - .unwrap_or(true) - }); + // Default to `package = true` for path sources. + let is_package = package.unwrap_or(true); Ok(RequirementSource::Directory { install_path: install_path.into_boxed_path(), diff --git a/crates/uv/tests/it/lock.rs b/crates/uv/tests/it/lock.rs index ac20124a0..212fc54f4 100644 --- a/crates/uv/tests/it/lock.rs +++ b/crates/uv/tests/it/lock.rs @@ -7139,12 +7139,12 @@ fn lock_exclusion() -> Result<()> { ] [package.metadata] - requires-dist = [{ name = "project", virtual = "../" }] + requires-dist = [{ name = "project", directory = "../" }] [[package]] name = "project" version = "0.1.0" - source = { virtual = "../" } + source = { directory = "../" } "# ); }); @@ -7727,7 +7727,7 @@ fn lock_dev_transitive() -> Result<()> { [package.metadata] requires-dist = [ { name = "baz", editable = "baz" }, - { name = "foo", virtual = "../foo" }, + { name = "foo", directory = "../foo" }, { name = "iniconfig", specifier = ">1" }, ] @@ -7749,7 +7749,7 @@ fn lock_dev_transitive() -> Result<()> { [[package]] name = "foo" version = "0.1.0" - source = { virtual = "../foo" } + source = { directory = "../foo" } [package.metadata] @@ -13566,7 +13566,7 @@ fn lock_narrowed_python_version_upper() -> Result<()> { [[package]] name = "dependency" version = "0.1.0" - source = { virtual = "dependency" } + source = { directory = "dependency" } dependencies = [ { name = "iniconfig", marker = "python_full_version >= '3.10'" }, ] @@ -13592,7 +13592,7 @@ fn lock_narrowed_python_version_upper() -> Result<()> { ] [package.metadata] - requires-dist = [{ name = "dependency", marker = "python_full_version >= '3.10'", virtual = "dependency" }] + requires-dist = [{ name = "dependency", marker = "python_full_version >= '3.10'", directory = "dependency" }] "# ); }); @@ -16870,9 +16870,9 @@ fn lock_explicit_virtual_project() -> Result<()> { Ok(()) } -/// Lock a project that is implicitly virtual (by way of omitting `build-system`). +/// Lock a project with a dev dependency #[test] -fn lock_implicit_virtual_project() -> Result<()> { +fn lock_project_dev_dependency() -> Result<()> { let context = TestContext::new("3.12"); let pyproject_toml = context.temp_dir.child("pyproject.toml"); @@ -17088,10 +17088,9 @@ fn lock_implicit_virtual_project() -> Result<()> { Ok(()) } -/// Lock a project that has a path dependency that is implicitly virtual (by way of omitting -/// `build-system`). +/// Lock a project that has a path dependency #[test] -fn lock_implicit_virtual_path() -> Result<()> { +fn lock_path_dependency() -> Result<()> { let context = TestContext::new("3.12"); let pyproject_toml = context.temp_dir.child("pyproject.toml"); @@ -17158,7 +17157,7 @@ fn lock_implicit_virtual_path() -> Result<()> { [[package]] name = "child" version = "0.1.0" - source = { virtual = "child" } + source = { directory = "child" } dependencies = [ { name = "iniconfig" }, ] @@ -17196,7 +17195,7 @@ fn lock_implicit_virtual_path() -> Result<()> { [package.metadata] requires-dist = [ { name = "anyio", specifier = ">3" }, - { name = "child", virtual = "child" }, + { name = "child", directory = "child" }, ] [[package]] @@ -17233,19 +17232,20 @@ fn lock_implicit_virtual_path() -> Result<()> { "###); // Install from the lockfile. The virtual project should _not_ be installed. - uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r###" + uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r" success: true exit_code: 0 ----- stdout ----- ----- stderr ----- - Prepared 4 packages in [TIME] - Installed 4 packages in [TIME] + Prepared 5 packages in [TIME] + Installed 5 packages in [TIME] + anyio==4.3.0 + + child==0.1.0 (from file://[TEMP_DIR]/child) + idna==3.6 + iniconfig==2.0.0 + sniffio==1.3.1 - "###); + "); Ok(()) } diff --git a/crates/uv/tests/it/sync.rs b/crates/uv/tests/it/sync.rs index 9da2fb62a..0c5507546 100644 --- a/crates/uv/tests/it/sync.rs +++ b/crates/uv/tests/it/sync.rs @@ -5399,7 +5399,8 @@ fn sync_override_package() -> Result<()> { .child("__init__.py") .touch()?; - // Create a package that depends on it. + // Create a package that depends on it. Mark the source with + // `package = false`. let pyproject_toml = context.temp_dir.child("pyproject.toml"); pyproject_toml.write_str( r#" @@ -5414,7 +5415,7 @@ fn sync_override_package() -> Result<()> { build-backend = "hatchling.build" [tool.uv.sources] - core = { path = "./core" } + core = { path = "./core", package = false } "#, )?; @@ -5438,7 +5439,7 @@ fn sync_override_package() -> Result<()> { + project==0.0.0 (from file://[TEMP_DIR]/) "###); - // Mark the source as `package = true`. + // Remove `package = false` from the source. let pyproject_toml = context.temp_dir.child("pyproject.toml"); pyproject_toml.write_str( r#" @@ -5453,7 +5454,7 @@ fn sync_override_package() -> Result<()> { build-backend = "hatchling.build" [tool.uv.sources] - core = { path = "./core", package = true } + core = { path = "./core" } "#, )?; @@ -5472,69 +5473,6 @@ fn sync_override_package() -> Result<()> { ~ project==0.0.0 (from file://[TEMP_DIR]/) "###); - // Remove `package = false`. - let pyproject_toml = context.temp_dir.child("core").child("pyproject.toml"); - pyproject_toml.write_str( - r#" - [project] - name = "core" - version = "0.1.0" - requires-python = ">=3.12" - - [build-system] - requires = ["hatchling"] - build-backend = "hatchling.build" - "#, - )?; - - // Syncing the project _should_ install `core`. - uv_snapshot!(context.filters(), context.sync(), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - Resolved 2 packages in [TIME] - Prepared 1 package in [TIME] - Uninstalled 1 package in [TIME] - Installed 1 package in [TIME] - ~ core==0.1.0 (from file://[TEMP_DIR]/core) - "###); - - // Mark the source as `package = false`. - let pyproject_toml = context.temp_dir.child("pyproject.toml"); - pyproject_toml.write_str( - r#" - [project] - name = "project" - version = "0.0.0" - requires-python = ">=3.12" - dependencies = ["core"] - - [build-system] - requires = ["hatchling"] - build-backend = "hatchling.build" - - [tool.uv.sources] - core = { path = "./core", package = false } - "#, - )?; - - // Syncing the project should _not_ install `core`. - uv_snapshot!(context.filters(), context.sync(), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - Resolved 2 packages in [TIME] - Prepared 1 package in [TIME] - Uninstalled 2 packages in [TIME] - Installed 1 package in [TIME] - - core==0.1.0 (from file://[TEMP_DIR]/core) - ~ project==0.0.0 (from file://[TEMP_DIR]/) - "###); - Ok(()) }