From a4d880ce5d30ee4b11ece67afc4e0cb9e77c0a5b Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sat, 7 Dec 2024 09:09:37 -0500 Subject: [PATCH] Reverts --- .../uv-resolver/src/pubgrub/dependencies.rs | 26 +- crates/uv-resolver/src/resolver/mod.rs | 10 +- crates/uv/tests/it/lock.rs | 493 ++++++++++++++++++ foo/README.md | 0 foo/bar.egg-info/PKG-INFO | 7 - foo/bar.egg-info/SOURCES.txt | 8 - foo/bar.egg-info/dependency_links.txt | 1 - foo/bar.egg-info/requires.txt | 1 - foo/bar.egg-info/top_level.txt | 1 - foo/foo.egg-info/PKG-INFO | 7 - foo/foo.egg-info/SOURCES.txt | 8 - foo/foo.egg-info/dependency_links.txt | 1 - foo/foo.egg-info/requires.txt | 1 - foo/foo.egg-info/top_level.txt | 1 - foo/hello.py | 6 - foo/pyproject.toml | 9 - foo/uv.lock | 13 - 17 files changed, 509 insertions(+), 84 deletions(-) delete mode 100644 foo/README.md delete mode 100644 foo/bar.egg-info/PKG-INFO delete mode 100644 foo/bar.egg-info/SOURCES.txt delete mode 100644 foo/bar.egg-info/dependency_links.txt delete mode 100644 foo/bar.egg-info/requires.txt delete mode 100644 foo/bar.egg-info/top_level.txt delete mode 100644 foo/foo.egg-info/PKG-INFO delete mode 100644 foo/foo.egg-info/SOURCES.txt delete mode 100644 foo/foo.egg-info/dependency_links.txt delete mode 100644 foo/foo.egg-info/requires.txt delete mode 100644 foo/foo.egg-info/top_level.txt delete mode 100644 foo/hello.py delete mode 100644 foo/pyproject.toml delete mode 100644 foo/uv.lock diff --git a/crates/uv-resolver/src/pubgrub/dependencies.rs b/crates/uv-resolver/src/pubgrub/dependencies.rs index eada0f0c3951e..5b97c7aa5c178 100644 --- a/crates/uv-resolver/src/pubgrub/dependencies.rs +++ b/crates/uv-resolver/src/pubgrub/dependencies.rs @@ -2,7 +2,6 @@ use std::iter; use either::Either; use pubgrub::Ranges; -use tracing::warn; use uv_normalize::{ExtraName, GroupName, PackageName}; use uv_pep440::{Version, VersionSpecifiers}; @@ -98,21 +97,16 @@ impl PubGrubDependency { url, } = requirement; match &*package { - PubGrubPackageInner::Package { name, .. } => { - - Some(PubGrubDependency { - package: package.clone(), - version: version.clone(), - url, - }) - } - PubGrubPackageInner::Marker { name, .. } => { - Some(PubGrubDependency { - package: package.clone(), - version: version.clone(), - url, - }) - } + PubGrubPackageInner::Package { .. } => Some(PubGrubDependency { + package: package.clone(), + version: version.clone(), + url, + }), + PubGrubPackageInner::Marker { .. } => Some(PubGrubDependency { + package: package.clone(), + version: version.clone(), + url, + }), PubGrubPackageInner::Extra { name, .. } => { // Detect self-dependencies. if dev.is_none() { diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index f8ee9441f0d3e..0bdd03d5f170b 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -2453,7 +2453,6 @@ impl ForkState { extra: ref dependency_extra, dev: ref dependency_dev, marker: ref dependency_marker, - .. } => { let to_url = self.fork_urls.get(dependency_name); let to_index = self.fork_indexes.get(dependency_name); @@ -2478,8 +2477,13 @@ impl ForkState { PubGrubPackageInner::Marker { name: ref dependency_name, marker: ref dependency_marker, - .. } => { + // Ignore self-dependencies. For example, `tensorflow-macos` depends on + // `tensorflow-macos ; platform_machine == 'arm64' and platform_system == 'Darwin'. + if self_name == Some(dependency_name) { + continue; + } + let to_url = self.fork_urls.get(dependency_name); let to_index = self.fork_indexes.get(dependency_name); let edge = ResolutionDependencyEdge { @@ -2504,7 +2508,6 @@ impl ForkState { name: ref dependency_name, extra: ref dependency_extra, marker: ref dependency_marker, - .. } => { // Insert an edge from the dependent package to the extra package. let to_url = self.fork_urls.get(dependency_name); @@ -2551,7 +2554,6 @@ impl ForkState { name: ref dependency_name, dev: ref dependency_dev, marker: ref dependency_marker, - .. } => { // Add an edge from the dependent package to the dev package, but _not_ the // base package. diff --git a/crates/uv/tests/it/lock.rs b/crates/uv/tests/it/lock.rs index 67bcdc03741dd..36963a354b26f 100644 --- a/crates/uv/tests/it/lock.rs +++ b/crates/uv/tests/it/lock.rs @@ -19029,3 +19029,496 @@ fn no_lowest_warning_with_name_and_url() -> Result<()> { Ok(()) } + +#[test] +fn lock_self_compatible() -> 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 = ["typing-extensions", "project"] + "#, + )?; + + uv_snapshot!(context.filters(), context.lock(), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 packages in [TIME] + "###); + + let lock = context.read("uv.lock"); + + 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 = "project" + version = "0.1.0" + source = { virtual = "." } + dependencies = [ + { name = "project" }, + { name = "typing-extensions" }, + ] + + [package.metadata] + requires-dist = [ + { name = "project" }, + { name = "typing-extensions" }, + ] + + [[package]] + name = "typing-extensions" + version = "4.10.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/16/3a/0d26ce356c7465a19c9ea8814b960f8a36c3b0d07c323176620b7b483e44/typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb", size = 77558 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/de/dc04a3ea60b22624b51c703a84bbe0184abcd1d0b9bc8074b5d6b7ab90bb/typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475", size = 33926 }, + ] + "### + ); + }); + + // Re-run with `--locked`. + uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 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 2 packages in [TIME] + "###); + + // Install from the lockfile. + uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Prepared 1 package in [TIME] + Installed 1 package in [TIME] + + typing-extensions==4.10.0 + "###); + + Ok(()) +} + +#[test] +fn lock_self_exact() -> 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 = ["typing-extensions", "project==0.1.0"] + "#, + )?; + + uv_snapshot!(context.filters(), context.lock(), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 packages in [TIME] + "###); + + let lock = context.read("uv.lock"); + + 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 = "project" + version = "0.1.0" + source = { virtual = "." } + dependencies = [ + { name = "project" }, + { name = "typing-extensions" }, + ] + + [package.metadata] + requires-dist = [ + { name = "project", specifier = "==0.1.0" }, + { name = "typing-extensions" }, + ] + + [[package]] + name = "typing-extensions" + version = "4.10.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/16/3a/0d26ce356c7465a19c9ea8814b960f8a36c3b0d07c323176620b7b483e44/typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb", size = 77558 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/de/dc04a3ea60b22624b51c703a84bbe0184abcd1d0b9bc8074b5d6b7ab90bb/typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475", size = 33926 }, + ] + "### + ); + }); + + // Re-run with `--locked`. + uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 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 2 packages in [TIME] + "###); + + // Install from the lockfile. + uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Prepared 1 package in [TIME] + Installed 1 package in [TIME] + + typing-extensions==4.10.0 + "###); + + Ok(()) +} + +#[test] +fn lock_self_incompatible() -> 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 = ["typing-extensions", "project==0.2.0"] + "#, + )?; + + uv_snapshot!(context.filters(), context.lock(), @r###" + success: false + exit_code: 1 + ----- stdout ----- + + ----- stderr ----- + × No solution found when resolving dependencies: + ╰─▶ Because your project depends on your project and your project requires your project, we can conclude that your projects's requirements are unsatisfiable. + "###); + + Ok(()) +} + +#[test] +fn lock_self_extra_compatible() -> 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 = ["typing-extensions"] + + [project.optional-dependencies] + foo = ["project"] + "#, + )?; + + uv_snapshot!(context.filters(), context.lock(), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 packages in [TIME] + "###); + + let lock = context.read("uv.lock"); + + 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 = "project" + version = "0.1.0" + source = { virtual = "." } + dependencies = [ + { name = "typing-extensions" }, + ] + + [package.optional-dependencies] + foo = [ + { name = "project" }, + ] + + [package.metadata] + requires-dist = [ + { name = "project", marker = "extra == 'foo'" }, + { name = "typing-extensions" }, + ] + + [[package]] + name = "typing-extensions" + version = "4.10.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/16/3a/0d26ce356c7465a19c9ea8814b960f8a36c3b0d07c323176620b7b483e44/typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb", size = 77558 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/de/dc04a3ea60b22624b51c703a84bbe0184abcd1d0b9bc8074b5d6b7ab90bb/typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475", size = 33926 }, + ] + "### + ); + }); + + // Re-run with `--locked`. + uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 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 2 packages in [TIME] + "###); + + // Install from the lockfile. + uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Prepared 1 package in [TIME] + Installed 1 package in [TIME] + + typing-extensions==4.10.0 + "###); + + Ok(()) +} + +#[test] +fn lock_self_extra_incompatible() -> 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 = ["typing-extensions"] + + [project.optional-dependencies] + foo = ["project==0.2.0"] + "#, + )?; + + uv_snapshot!(context.filters(), context.lock(), @r###" + success: false + exit_code: 1 + ----- stdout ----- + + ----- stderr ----- + × No solution found when resolving dependencies: + ╰─▶ Because project[foo] depends on your project and your project requires project[foo], we can conclude that your projects's requirements are unsatisfiable. + "###); + + Ok(()) +} + +#[test] +fn lock_self_marker_compatible() -> 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 = ["typing-extensions", "project ; sys_platform == 'win32'"] + "#, + )?; + + uv_snapshot!(context.filters(), context.lock(), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 packages in [TIME] + "###); + + let lock = context.read("uv.lock"); + + 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 = "project" + version = "0.1.0" + source = { virtual = "." } + dependencies = [ + { name = "typing-extensions" }, + ] + + [package.metadata] + requires-dist = [ + { name = "project", marker = "sys_platform == 'win32'" }, + { name = "typing-extensions" }, + ] + + [[package]] + name = "typing-extensions" + version = "4.10.0" + source = { registry = "https://pypi.org/simple" } + sdist = { url = "https://files.pythonhosted.org/packages/16/3a/0d26ce356c7465a19c9ea8814b960f8a36c3b0d07c323176620b7b483e44/typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb", size = 77558 } + wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/de/dc04a3ea60b22624b51c703a84bbe0184abcd1d0b9bc8074b5d6b7ab90bb/typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475", size = 33926 }, + ] + "### + ); + }); + + // Re-run with `--locked`. + uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 2 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 2 packages in [TIME] + "###); + + // Install from the lockfile. + uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Prepared 1 package in [TIME] + Installed 1 package in [TIME] + + typing-extensions==4.10.0 + "###); + + Ok(()) +} + +#[test] +fn lock_self_marker_incompatible() -> 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 = ["typing-extensions", "project>0.1 ; sys_platform == 'win32'"] + "#, + )?; + + uv_snapshot!(context.filters(), context.lock(), @r###" + success: false + exit_code: 1 + ----- stdout ----- + + ----- stderr ----- + × No solution found when resolving dependencies: + ╰─▶ Because only project{sys_platform == 'win32'}<=0.1 is available and your project depends on project{sys_platform == 'win32'}>0.1, we can conclude that your project's requirements are unsatisfiable. + "###); + + Ok(()) +} diff --git a/foo/README.md b/foo/README.md deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/foo/bar.egg-info/PKG-INFO b/foo/bar.egg-info/PKG-INFO deleted file mode 100644 index d5695e63180cb..0000000000000 --- a/foo/bar.egg-info/PKG-INFO +++ /dev/null @@ -1,7 +0,0 @@ -Metadata-Version: 2.1 -Name: bar -Version: 0.0.0 -Summary: Add your description here -Requires-Python: >=3.10 -Description-Content-Type: text/markdown -Requires-Dist: anyio==4.7.0 diff --git a/foo/bar.egg-info/SOURCES.txt b/foo/bar.egg-info/SOURCES.txt deleted file mode 100644 index 1b825d24791ef..0000000000000 --- a/foo/bar.egg-info/SOURCES.txt +++ /dev/null @@ -1,8 +0,0 @@ -README.md -hello.py -pyproject.toml -bar.egg-info/PKG-INFO -bar.egg-info/SOURCES.txt -bar.egg-info/dependency_links.txt -bar.egg-info/requires.txt -bar.egg-info/top_level.txt \ No newline at end of file diff --git a/foo/bar.egg-info/dependency_links.txt b/foo/bar.egg-info/dependency_links.txt deleted file mode 100644 index 8b137891791fe..0000000000000 --- a/foo/bar.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/foo/bar.egg-info/requires.txt b/foo/bar.egg-info/requires.txt deleted file mode 100644 index e068e90870e03..0000000000000 --- a/foo/bar.egg-info/requires.txt +++ /dev/null @@ -1 +0,0 @@ -anyio==4.7.0 diff --git a/foo/bar.egg-info/top_level.txt b/foo/bar.egg-info/top_level.txt deleted file mode 100644 index ce013625030ba..0000000000000 --- a/foo/bar.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -hello diff --git a/foo/foo.egg-info/PKG-INFO b/foo/foo.egg-info/PKG-INFO deleted file mode 100644 index 71b94d824e163..0000000000000 --- a/foo/foo.egg-info/PKG-INFO +++ /dev/null @@ -1,7 +0,0 @@ -Metadata-Version: 2.1 -Name: foo -Version: 0.1.0 -Summary: Add your description here -Requires-Python: >=3.13.0 -Description-Content-Type: text/markdown -Requires-Dist: foo@ ./scripts/path diff --git a/foo/foo.egg-info/SOURCES.txt b/foo/foo.egg-info/SOURCES.txt deleted file mode 100644 index aff7df1d3fa2f..0000000000000 --- a/foo/foo.egg-info/SOURCES.txt +++ /dev/null @@ -1,8 +0,0 @@ -README.md -hello.py -pyproject.toml -foo.egg-info/PKG-INFO -foo.egg-info/SOURCES.txt -foo.egg-info/dependency_links.txt -foo.egg-info/requires.txt -foo.egg-info/top_level.txt \ No newline at end of file diff --git a/foo/foo.egg-info/dependency_links.txt b/foo/foo.egg-info/dependency_links.txt deleted file mode 100644 index 8b137891791fe..0000000000000 --- a/foo/foo.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/foo/foo.egg-info/requires.txt b/foo/foo.egg-info/requires.txt deleted file mode 100644 index c868b9c4ea220..0000000000000 --- a/foo/foo.egg-info/requires.txt +++ /dev/null @@ -1 +0,0 @@ -foo@ ./scripts/path diff --git a/foo/foo.egg-info/top_level.txt b/foo/foo.egg-info/top_level.txt deleted file mode 100644 index ce013625030ba..0000000000000 --- a/foo/foo.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -hello diff --git a/foo/hello.py b/foo/hello.py deleted file mode 100644 index f8a203dd42159..0000000000000 --- a/foo/hello.py +++ /dev/null @@ -1,6 +0,0 @@ -def main(): - print("Hello from foo!") - - -if __name__ == "__main__": - main() diff --git a/foo/pyproject.toml b/foo/pyproject.toml deleted file mode 100644 index 311033fee596e..0000000000000 --- a/foo/pyproject.toml +++ /dev/null @@ -1,9 +0,0 @@ -[project] -name = "anyio" -version = "0.1.0" -description = "Add your description here" -readme = "README.md" -requires-python = ">=3.10" -dependencies = [ - "anyio==0.1.0" -] diff --git a/foo/uv.lock b/foo/uv.lock deleted file mode 100644 index 2a2d48fdd70c7..0000000000000 --- a/foo/uv.lock +++ /dev/null @@ -1,13 +0,0 @@ -version = 1 -requires-python = ">=3.10" - -[[package]] -name = "anyio" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "anyio" }, -] - -[package.metadata] -requires-dist = [{ name = "anyio", specifier = "==0.1.0" }]