diff --git a/crates/uv-resolver/src/lock.rs b/crates/uv-resolver/src/lock.rs index 5cea21f08..f20d73b7a 100644 --- a/crates/uv-resolver/src/lock.rs +++ b/crates/uv-resolver/src/lock.rs @@ -9,12 +9,12 @@ use std::str::FromStr; use rustc_hash::FxHashMap; use url::Url; -use distribution_filename::WheelFilename; +use distribution_filename::{SourceDistFilename, WheelFilename}; use distribution_types::{ BuiltDist, DirectUrlBuiltDist, DirectUrlSourceDist, DirectorySourceDist, Dist, FileLocation, GitSourceDist, IndexUrl, ParsedArchiveUrl, ParsedGitUrl, PathBuiltDist, PathSourceDist, - RegistryBuiltDist, RegistryBuiltWheel, RegistrySourceDist, Resolution, ResolvedDist, - ToUrlError, + RegistryBuiltDist, RegistryBuiltWheel, RegistrySourceDist, RemoteSource, Resolution, + ResolvedDist, ToUrlError, }; use pep440_rs::Version; use pep508_rs::{MarkerEnvironment, VerbatimUrl}; @@ -339,7 +339,31 @@ impl Distribution { let source_dist = distribution_types::SourceDist::DirectUrl(direct_dist); Dist::Source(source_dist) } - SourceKind::Registry => todo!(), + SourceKind::Registry => { + // TODO(charlie): Introduce an error type to the conversion functions. + let filename = + SourceDistFilename::parse(&sdist.url.filename().unwrap(), &self.id.name) + .unwrap(); + let file = Box::new(distribution_types::File { + dist_info_metadata: false, + filename: filename.to_string(), + hashes: vec![], + requires_python: None, + size: None, + upload_time_utc_ms: None, + url: FileLocation::AbsoluteUrl(sdist.url.to_string()), + yanked: None, + }); + let index = IndexUrl::Url(VerbatimUrl::from_url(self.id.source.url.clone())); + let reg_dist = RegistrySourceDist { + filename, + file, + index, + wheels: vec![], + }; + let source_dist = distribution_types::SourceDist::Registry(reg_dist); + Dist::Source(source_dist) + } }; } @@ -978,8 +1002,6 @@ impl Wheel { .url .to_url() .map_err(LockError::invalid_file_url)?; - // FIXME: Is it guaranteed that there is at least one hash? - // If not, we probably need to make this fallible. let hash = wheel.file.hashes.first().cloned().map(Hash::from); Ok(Wheel { url, diff --git a/crates/uv/tests/lock.rs b/crates/uv/tests/lock.rs index af8694100..bb6657339 100644 --- a/crates/uv/tests/lock.rs +++ b/crates/uv/tests/lock.rs @@ -11,7 +11,7 @@ mod common; /// Lock a requirement from PyPI. #[test] -fn lock_registry() -> Result<()> { +fn lock_wheel_registry() -> Result<()> { let context = TestContext::new("3.12"); let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("anyio==3.7.0")?; @@ -163,9 +163,67 @@ fn lock_registry() -> Result<()> { Ok(()) } +/// Lock a requirement from PyPI. +#[test] +fn lock_sdist_registry() -> Result<()> { + let context = TestContext::new("3.12"); + let requirements_in = context.temp_dir.child("requirements.in"); + requirements_in.write_str("netwell")?; + + uv_snapshot!(context + .compile() + .arg("requirements.in") + .arg("--no-deps") + .arg("--generate-hashes") + .arg("--unstable-uv-lock-file"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + # This file was autogenerated by uv via the following command: + # uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --no-deps --generate-hashes --unstable-uv-lock-file + netwell==0.4.0 \ + --hash=sha256:cd6940614081790099b8fc1fdcf65cb930d54c647ed8bc9ba90dc781cf33926e + # via -r requirements.in + + ----- stderr ----- + Resolved 1 package in [TIME] + "###); + + let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + + assert_snapshot!( + lock, @r###" + version = 1 + + [[distribution]] + name = "netwell" + version = "0.4.0" + source = "registry+https://pypi.org/simple" + + [distribution.sdist] + url = "https://files.pythonhosted.org/packages/9d/01/4aacc00ffd2ed59595769e233baf1e72b3a4034ddabf65ff4ef34e1d487e/netwell-0.4.0.tar.gz" + hash = "sha256:cd6940614081790099b8fc1fdcf65cb930d54c647ed8bc9ba90dc781cf33926e" + "### + ); + + // Install from the lockfile. + uv_snapshot!(context.install().arg("--unstable-uv-lock-file").arg("netwell"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Downloaded 1 package in [TIME] + Installed 1 package in [TIME] + + netwell==0.4.0 + "###); + + Ok(()) +} + /// Lock a Git requirement. #[test] -fn lock_git() -> Result<()> { +fn lock_sdist_git() -> Result<()> { let context = TestContext::new("3.12"); let requirements_in = context.temp_dir.child("requirements.in"); requirements_in.write_str("anyio @ git+https://github.com/agronholm/anyio@3.7.0")?;