diff --git a/Cargo.lock b/Cargo.lock index f792c612f..a2a514234 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4867,11 +4867,9 @@ dependencies = [ "rayon", "rustc-hash 2.0.0", "same-file", - "serde", "tempfile", "thiserror", "tokio", - "toml", "tracing", "url", "uv-cache", diff --git a/crates/uv-installer/Cargo.toml b/crates/uv-installer/Cargo.toml index 64565d769..8f1663a03 100644 --- a/crates/uv-installer/Cargo.toml +++ b/crates/uv-installer/Cargo.toml @@ -39,11 +39,9 @@ futures = { workspace = true } rayon = { workspace = true } rustc-hash = { workspace = true } same-file = { workspace = true } -serde = { workspace = true } tempfile = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } -toml = { workspace = true } tracing = { workspace = true } url = { workspace = true } walkdir = { workspace = true } diff --git a/crates/uv-installer/src/plan.rs b/crates/uv-installer/src/plan.rs index 6129d9bfd..a8e2f0ab9 100644 --- a/crates/uv-installer/src/plan.rs +++ b/crates/uv-installer/src/plan.rs @@ -123,9 +123,6 @@ impl<'a> Planner<'a> { RequirementSatisfaction::OutOfDate => { debug!("Requirement installed, but not fresh: {distribution}"); } - RequirementSatisfaction::Dynamic => { - debug!("Requirement installed, but dynamic: {distribution}"); - } } reinstalls.push(distribution.clone()); } diff --git a/crates/uv-installer/src/satisfies.rs b/crates/uv-installer/src/satisfies.rs index 101ed788e..a0d83af0a 100644 --- a/crates/uv-installer/src/satisfies.rs +++ b/crates/uv-installer/src/satisfies.rs @@ -1,9 +1,6 @@ use std::fmt::Debug; -use std::path::Path; -use anyhow::Result; use same_file::is_same_file; -use serde::Deserialize; use tracing::{debug, trace}; use url::Url; @@ -17,14 +14,16 @@ pub(crate) enum RequirementSatisfaction { Mismatch, Satisfied, OutOfDate, - Dynamic, } impl RequirementSatisfaction { /// Returns true if a requirement is satisfied by an installed distribution. /// /// Returns an error if IO fails during a freshness check for a local path. - pub(crate) fn check(distribution: &InstalledDist, source: &RequirementSource) -> Result { + pub(crate) fn check( + distribution: &InstalledDist, + source: &RequirementSource, + ) -> anyhow::Result { trace!( "Comparing installed with source: {:?} {:?}", distribution, @@ -250,59 +249,8 @@ impl RequirementSatisfaction { return Ok(Self::OutOfDate); } - // Does the package have dynamic metadata? - if is_dynamic(requested_path) { - trace!("Dependency is dynamic"); - return Ok(Self::Dynamic); - } - Ok(Self::Satisfied) } } } } - -/// Returns `true` if the source tree at the given path contains dynamic metadata. -fn is_dynamic(path: &Path) -> bool { - // If there's no `pyproject.toml`, we assume it's dynamic. - let Ok(contents) = fs_err::read_to_string(path.join("pyproject.toml")) else { - return true; - }; - let Ok(pyproject_toml) = toml::from_str::(&contents) else { - return true; - }; - // If `[project]` is not present, we assume it's dynamic. - let Some(project) = pyproject_toml.project else { - // ...unless it appears to be a Poetry project. - return pyproject_toml - .tool - .map_or(true, |tool| tool.poetry.is_none()); - }; - // `[project.dynamic]` must be present and non-empty. - project.dynamic.is_some_and(|dynamic| !dynamic.is_empty()) -} - -/// A pyproject.toml as specified in PEP 517. -#[derive(Deserialize, Debug)] -#[serde(rename_all = "kebab-case")] -struct PyProjectToml { - project: Option, - tool: Option, -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "kebab-case")] -struct Project { - dynamic: Option>, -} - -#[derive(Deserialize, Debug)] -struct Tool { - poetry: Option, -} - -#[derive(Deserialize, Debug)] -struct ToolPoetry { - #[allow(dead_code)] - name: Option, -} diff --git a/crates/uv-installer/src/site_packages.rs b/crates/uv-installer/src/site_packages.rs index 002657afb..6883bcebe 100644 --- a/crates/uv-installer/src/site_packages.rs +++ b/crates/uv-installer/src/site_packages.rs @@ -311,9 +311,7 @@ impl SitePackages { distribution, entry.requirement.source().as_ref(), )? { - RequirementSatisfaction::Mismatch - | RequirementSatisfaction::OutOfDate - | RequirementSatisfaction::Dynamic => { + RequirementSatisfaction::Mismatch | RequirementSatisfaction::OutOfDate => { return Ok(SatisfiesResult::Unsatisfied(entry.requirement.to_string())) } RequirementSatisfaction::Satisfied => {} @@ -323,8 +321,7 @@ impl SitePackages { for constraint in constraints.get(&distribution.name()).into_iter().flatten() { match RequirementSatisfaction::check(distribution, &constraint.source)? { RequirementSatisfaction::Mismatch - | RequirementSatisfaction::OutOfDate - | RequirementSatisfaction::Dynamic => { + | RequirementSatisfaction::OutOfDate => { return Ok(SatisfiesResult::Unsatisfied( entry.requirement.to_string(), )) diff --git a/crates/uv/tests/pip_install.rs b/crates/uv/tests/pip_install.rs index 593b98f4d..79a5695eb 100644 --- a/crates/uv/tests/pip_install.rs +++ b/crates/uv/tests/pip_install.rs @@ -3051,10 +3051,10 @@ requires-python = ">=3.8" } #[test] -fn invalidate_editable_dynamic() -> Result<()> { +fn editable_dynamic() -> Result<()> { let context = TestContext::new("3.12"); - // Create an editable package with dynamic metadata + // Create an editable package with dynamic metadata. let editable_dir = context.temp_dir.child("editable"); editable_dir.create_dir_all()?; let pyproject_toml = editable_dir.child("pyproject.toml"); @@ -3092,7 +3092,7 @@ dependencies = {file = ["requirements.txt"]} "### ); - // Re-installing should re-install. + // Re-installing should not re-install, as we don't special-case dynamic metadata. uv_snapshot!(context.filters(), context.pip_install() .arg("--editable") .arg(editable_dir.path()), @r###" @@ -3101,35 +3101,7 @@ dependencies = {file = ["requirements.txt"]} ----- stdout ----- ----- stderr ----- - Resolved 4 packages in [TIME] - Prepared 1 package in [TIME] - Uninstalled 1 package in [TIME] - Installed 1 package in [TIME] - - example==0.1.0 (from file://[TEMP_DIR]/editable) - + example==0.1.0 (from file://[TEMP_DIR]/editable) - "### - ); - - // Modify the requirements. - requirements_txt.write_str("anyio==3.7.1")?; - - // Re-installing should update the package. - uv_snapshot!(context.filters(), context.pip_install() - .arg("--editable") - .arg(editable_dir.path()), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - Resolved 4 packages in [TIME] - Prepared 2 packages in [TIME] - Uninstalled 2 packages in [TIME] - Installed 2 packages in [TIME] - - anyio==4.0.0 - + anyio==3.7.1 - - example==0.1.0 (from file://[TEMP_DIR]/editable) - + example==0.1.0 (from file://[TEMP_DIR]/editable) + Audited 1 package in [TIME] "### );