Use universal resolution in uv lock (#3969)

## Summary

Wires up the optional markers in resolution, and adds
respecting-the-markers to `Lock:: to_resolution`.
This commit is contained in:
Charlie Marsh 2024-06-02 21:33:18 -04:00 committed by GitHub
parent c500b78936
commit a23ca5bab7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 195 additions and 54 deletions

View file

@ -19,7 +19,7 @@ use distribution_types::{
RegistrySourceDist, RemoteSource, Resolution, ResolvedDist, ToUrlError, RegistrySourceDist, RemoteSource, Resolution, ResolvedDist, ToUrlError,
}; };
use pep440_rs::Version; use pep440_rs::Version;
use pep508_rs::{MarkerEnvironment, VerbatimUrl}; use pep508_rs::{MarkerEnvironment, MarkerTree, VerbatimUrl};
use platform_tags::{TagCompatibility, TagPriority, Tags}; use platform_tags::{TagCompatibility, TagPriority, Tags};
use pypi_types::{HashDigest, ParsedArchiveUrl, ParsedGitUrl}; use pypi_types::{HashDigest, ParsedArchiveUrl, ParsedGitUrl};
use uv_git::{GitReference, GitSha, RepositoryReference, ResolvedRepositoryReference}; use uv_git::{GitReference, GitSha, RepositoryReference, ResolvedRepositoryReference};
@ -82,10 +82,16 @@ impl Lock {
while let Some(dist) = queue.pop_front() { while let Some(dist) = queue.pop_front() {
for dep in &dist.dependencies { for dep in &dist.dependencies {
let dep_dist = self.find_by_id(&dep.id); let dep_dist = self.find_by_id(&dep.id);
if dep_dist
.marker
.as_ref()
.map_or(true, |marker| marker.evaluate(marker_env, &[]))
{
queue.push_back(dep_dist); queue.push_back(dep_dist);
} }
}
let name = dist.id.name.clone(); let name = dist.id.name.clone();
let resolved_dist = ResolvedDist::Installable(dist.to_dist(marker_env, tags)); let resolved_dist = ResolvedDist::Installable(dist.to_dist(tags));
map.insert(name, resolved_dist); map.insert(name, resolved_dist);
} }
let diagnostics = vec![]; let diagnostics = vec![];
@ -280,7 +286,7 @@ pub struct Distribution {
#[serde(flatten)] #[serde(flatten)]
pub(crate) id: DistributionId, pub(crate) id: DistributionId,
#[serde(default)] #[serde(default)]
pub(crate) marker: Option<String>, pub(crate) marker: Option<MarkerTree>,
#[serde(default)] #[serde(default)]
pub(crate) sdist: Option<SourceDist>, pub(crate) sdist: Option<SourceDist>,
#[serde(default, skip_serializing_if = "Vec::is_empty")] #[serde(default, skip_serializing_if = "Vec::is_empty")]
@ -294,11 +300,12 @@ impl Distribution {
annotated_dist: &AnnotatedDist, annotated_dist: &AnnotatedDist,
) -> Result<Distribution, LockError> { ) -> Result<Distribution, LockError> {
let id = DistributionId::from_annotated_dist(annotated_dist); let id = DistributionId::from_annotated_dist(annotated_dist);
let wheels = Wheel::from_annotated_dist(annotated_dist)?; let marker = annotated_dist.marker.clone();
let sdist = SourceDist::from_annotated_dist(annotated_dist)?; let sdist = SourceDist::from_annotated_dist(annotated_dist)?;
let wheels = Wheel::from_annotated_dist(annotated_dist)?;
Ok(Distribution { Ok(Distribution {
id, id,
marker: annotated_dist.marker.as_ref().map(ToString::to_string), marker,
sdist, sdist,
wheels, wheels,
dependencies: vec![], dependencies: vec![],
@ -311,7 +318,7 @@ impl Distribution {
} }
/// Convert the [`Distribution`] to a [`Dist`] that can be used in installation. /// Convert the [`Distribution`] to a [`Dist`] that can be used in installation.
fn to_dist(&self, _marker_env: &MarkerEnvironment, tags: &Tags) -> Dist { fn to_dist(&self, tags: &Tags) -> Dist {
if let Some(best_wheel_index) = self.find_best_wheel(tags) { if let Some(best_wheel_index) = self.find_best_wheel(tags) {
return match &self.id.source.kind { return match &self.id.source.kind {
SourceKind::Registry => { SourceKind::Registry => {

View file

@ -12,15 +12,18 @@ pub struct PythonRequirement {
} }
impl PythonRequirement { impl PythonRequirement {
pub fn new(interpreter: &Interpreter, target: &StringVersion) -> Self { pub fn from_marker_environment(interpreter: &Interpreter, env: &MarkerEnvironment) -> Self {
Self { Self {
installed: interpreter.python_full_version().clone(), installed: interpreter.python_full_version().clone(),
target: target.clone(), target: env.python_full_version().clone(),
} }
} }
pub fn from_marker_environment(interpreter: &Interpreter, env: &MarkerEnvironment) -> Self { pub fn from_interpreter(interpreter: &Interpreter) -> Self {
Self::new(interpreter, env.python_full_version()) Self {
installed: interpreter.python_full_version().clone(),
target: interpreter.python_full_version().clone(),
}
} }
/// Return the installed version of Python. /// Return the installed version of Python.

View file

@ -352,7 +352,7 @@ pub(crate) async fn pip_install(
&upgrade, &upgrade,
&interpreter, &interpreter,
&tags, &tags,
&markers, Some(&markers),
&client, &client,
&flat_index, &flat_index,
&index, &index,

View file

@ -88,7 +88,7 @@ pub(crate) async fn resolve<InstalledPackages: InstalledPackagesProvider>(
upgrade: &Upgrade, upgrade: &Upgrade,
interpreter: &Interpreter, interpreter: &Interpreter,
tags: &Tags, tags: &Tags,
markers: &MarkerEnvironment, markers: Option<&MarkerEnvironment>,
client: &RegistryClient, client: &RegistryClient,
flat_index: &FlatIndex, flat_index: &FlatIndex,
index: &InMemoryIndex, index: &InMemoryIndex,
@ -182,7 +182,11 @@ pub(crate) async fn resolve<InstalledPackages: InstalledPackagesProvider>(
// Collect constraints and overrides. // Collect constraints and overrides.
let constraints = Constraints::from_requirements(constraints); let constraints = Constraints::from_requirements(constraints);
let overrides = Overrides::from_requirements(overrides); let overrides = Overrides::from_requirements(overrides);
let python_requirement = PythonRequirement::from_marker_environment(interpreter, markers); let python_requirement = if let Some(markers) = markers {
PythonRequirement::from_marker_environment(interpreter, markers)
} else {
PythonRequirement::from_interpreter(interpreter)
};
// Determine any lookahead requirements. // Determine any lookahead requirements.
let lookaheads = match options.dependency_mode { let lookaheads = match options.dependency_mode {
@ -196,7 +200,7 @@ pub(crate) async fn resolve<InstalledPackages: InstalledPackagesProvider>(
DistributionDatabase::new(client, build_dispatch, concurrency.downloads, preview), DistributionDatabase::new(client, build_dispatch, concurrency.downloads, preview),
) )
.with_reporter(ResolverReporter::from(printer)) .with_reporter(ResolverReporter::from(printer))
.resolve(Some(markers)) .resolve(markers)
.await? .await?
} }
DependencyMode::Direct => Vec::new(), DependencyMode::Direct => Vec::new(),
@ -230,7 +234,7 @@ pub(crate) async fn resolve<InstalledPackages: InstalledPackagesProvider>(
manifest, manifest,
options, options,
&python_requirement, &python_requirement,
Some(markers), markers,
tags, tags,
flat_index, flat_index,
index, index,

View file

@ -302,7 +302,7 @@ pub(crate) async fn pip_sync(
&upgrade, &upgrade,
interpreter, interpreter,
&tags, &tags,
&markers, Some(&markers),
&client, &client,
&flat_index, &flat_index,
&index, &index,

View file

@ -158,7 +158,7 @@ pub(super) async fn do_lock(
&upgrade, &upgrade,
&interpreter, &interpreter,
tags, tags,
markers, None,
&client, &client,
&flat_index, &flat_index,
&index, &index,

View file

@ -217,7 +217,7 @@ pub(crate) async fn update_environment(
&upgrade, &upgrade,
&interpreter, &interpreter,
tags, tags,
markers, Some(markers),
&client, &client,
&flat_index, &flat_index,
&index, &index,

View file

@ -514,6 +514,12 @@ pub fn python_path_with_versions(
Ok(env::join_paths(selected_pythons)?) Ok(env::join_paths(selected_pythons)?)
} }
#[derive(Debug, Copy, Clone)]
pub enum WindowsFilters {
Platform,
Universal,
}
/// Execute the command and format its output status, stdout and stderr into a snapshot string. /// Execute the command and format its output status, stdout and stderr into a snapshot string.
/// ///
/// This function is derived from `insta_cmd`s `spawn_with_info`. /// This function is derived from `insta_cmd`s `spawn_with_info`.
@ -521,7 +527,7 @@ pub fn run_and_format<T: AsRef<str>>(
mut command: impl BorrowMut<std::process::Command>, mut command: impl BorrowMut<std::process::Command>,
filters: impl AsRef<[(T, T)]>, filters: impl AsRef<[(T, T)]>,
function_name: &str, function_name: &str,
windows_filters: bool, windows_filters: Option<WindowsFilters>,
) -> (String, Output) { ) -> (String, Output) {
let program = command let program = command
.borrow_mut() .borrow_mut()
@ -566,7 +572,8 @@ pub fn run_and_format<T: AsRef<str>>(
// pass whether it's on Windows or Unix. In particular, there are some very // pass whether it's on Windows or Unix. In particular, there are some very
// common Windows-only dependencies that, when removed from a resolution, // common Windows-only dependencies that, when removed from a resolution,
// cause the set of dependencies to be the same across platforms. // cause the set of dependencies to be the same across platforms.
if cfg!(windows) && windows_filters { if cfg!(windows) {
if let Some(windows_filters) = windows_filters {
// The optional leading +/- is for install logs, the optional next line is for lock files // The optional leading +/- is for install logs, the optional next line is for lock files
let windows_only_deps = [ let windows_only_deps = [
("( [+-] )?colorama==\\d+(\\.[\\d+])+\n( # via .*\n)?"), ("( [+-] )?colorama==\\d+(\\.[\\d+])+\n( # via .*\n)?"),
@ -585,13 +592,23 @@ pub fn run_and_format<T: AsRef<str>>(
} }
if removed_packages > 0 { if removed_packages > 0 {
for i in 1..20 { for i in 1..20 {
for verb in match windows_filters {
WindowsFilters::Platform => {
["Resolved", "Downloaded", "Installed", "Uninstalled"].iter()
}
WindowsFilters::Universal => {
["Downloaded", "Installed", "Uninstalled"].iter()
}
} {
snapshot = snapshot.replace( snapshot = snapshot.replace(
&format!("{} packages", i + removed_packages), &format!("{verb} {} packages", i + removed_packages),
&format!("{} package{}", i, if i > 1 { "s" } else { "" }), &format!("{verb} {} package{}", i, if i > 1 { "s" } else { "" }),
); );
} }
} }
} }
}
}
(snapshot, output) (snapshot, output)
} }
@ -641,13 +658,19 @@ macro_rules! uv_snapshot {
}}; }};
($filters:expr, $spawnable:expr, @$snapshot:literal) => {{ ($filters:expr, $spawnable:expr, @$snapshot:literal) => {{
// Take a reference for backwards compatibility with the vec-expecting insta filters. // Take a reference for backwards compatibility with the vec-expecting insta filters.
let (snapshot, output) = $crate::common::run_and_format($spawnable, &$filters, function_name!(), true); let (snapshot, output) = $crate::common::run_and_format($spawnable, &$filters, function_name!(), Some($crate::common::WindowsFilters::Platform));
::insta::assert_snapshot!(snapshot, @$snapshot); ::insta::assert_snapshot!(snapshot, @$snapshot);
output output
}}; }};
($filters:expr, windows_filters=false, $spawnable:expr, @$snapshot:literal) => {{ ($filters:expr, windows_filters=false, $spawnable:expr, @$snapshot:literal) => {{
// Take a reference for backwards compatibility with the vec-expecting insta filters. // Take a reference for backwards compatibility with the vec-expecting insta filters.
let (snapshot, output) = $crate::common::run_and_format($spawnable, &$filters, function_name!(), false); let (snapshot, output) = $crate::common::run_and_format($spawnable, &$filters, function_name!(), None);
::insta::assert_snapshot!(snapshot, @$snapshot);
output
}};
($filters:expr, universal_windows_filters=true, $spawnable:expr, @$snapshot:literal) => {{
// Take a reference for backwards compatibility with the vec-expecting insta filters.
let (snapshot, output) = $crate::common::run_and_format($spawnable, &$filters, function_name!(), Some($crate::common::WindowsFilters::Universal));
::insta::assert_snapshot!(snapshot, @$snapshot); ::insta::assert_snapshot!(snapshot, @$snapshot);
output output
}}; }};

View file

@ -30,7 +30,7 @@ fn lock_wheel_registry() -> Result<()> {
----- stderr ----- ----- stderr -----
warning: `uv lock` is experimental and may change without warning. warning: `uv lock` is experimental and may change without warning.
Resolved 4 packages in [TIME] Resolved 6 packages in [TIME]
"###); "###);
let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?;
@ -49,6 +49,11 @@ fn lock_wheel_registry() -> Result<()> {
sdist = { url = "https://files.pythonhosted.org/packages/c6/b3/fefbf7e78ab3b805dec67d698dc18dd505af7a18a8dd08868c9b4fa736b5/anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce", size = 142737 } sdist = { url = "https://files.pythonhosted.org/packages/c6/b3/fefbf7e78ab3b805dec67d698dc18dd505af7a18a8dd08868c9b4fa736b5/anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce", size = 142737 }
wheels = [{ url = "https://files.pythonhosted.org/packages/68/fe/7ce1926952c8a403b35029e194555558514b365ad77d75125f521a2bec62/anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0", size = 80873 }] wheels = [{ url = "https://files.pythonhosted.org/packages/68/fe/7ce1926952c8a403b35029e194555558514b365ad77d75125f521a2bec62/anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0", size = 80873 }]
[[distribution.dependencies]]
name = "exceptiongroup"
version = "1.2.0"
source = "registry+https://pypi.org/simple"
[[distribution.dependencies]] [[distribution.dependencies]]
name = "idna" name = "idna"
version = "3.6" version = "3.6"
@ -59,6 +64,19 @@ fn lock_wheel_registry() -> Result<()> {
version = "1.3.1" version = "1.3.1"
source = "registry+https://pypi.org/simple" source = "registry+https://pypi.org/simple"
[[distribution.dependencies]]
name = "typing-extensions"
version = "4.10.0"
source = "registry+https://pypi.org/simple"
[[distribution]]
name = "exceptiongroup"
version = "1.2.0"
source = "registry+https://pypi.org/simple"
marker = "python_version < '3.11'"
sdist = { url = "https://files.pythonhosted.org/packages/8e/1c/beef724eaf5b01bb44b6338c8c3494eff7cab376fab4904cfbbc3585dc79/exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68", size = 26264 }
wheels = [{ url = "https://files.pythonhosted.org/packages/b8/9a/5028fd52db10e600f1c4674441b968cf2ea4959085bfb5b99fb1250e5f68/exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14", size = 16210 }]
[[distribution]] [[distribution]]
name = "idna" name = "idna"
version = "3.6" version = "3.6"
@ -83,6 +101,14 @@ fn lock_wheel_registry() -> Result<()> {
source = "registry+https://pypi.org/simple" 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 } 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 }] wheels = [{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }]
[[distribution]]
name = "typing-extensions"
version = "4.10.0"
source = "registry+https://pypi.org/simple"
marker = "python_version < '3.8'"
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 }]
"### "###
); );
}); });
@ -430,7 +456,7 @@ fn lock_wheel_url() -> Result<()> {
----- stderr ----- ----- stderr -----
warning: `uv lock` is experimental and may change without warning. warning: `uv lock` is experimental and may change without warning.
Resolved 4 packages in [TIME] Resolved 6 packages in [TIME]
"###); "###);
let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?;
@ -448,6 +474,11 @@ fn lock_wheel_url() -> Result<()> {
source = "direct+https://files.pythonhosted.org/packages/14/fd/2f20c40b45e4fb4324834aea24bd4afdf1143390242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl" source = "direct+https://files.pythonhosted.org/packages/14/fd/2f20c40b45e4fb4324834aea24bd4afdf1143390242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl"
wheels = [{ url = "https://files.pythonhosted.org/packages/14/fd/2f20c40b45e4fb4324834aea24bd4afdf1143390242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8" }] wheels = [{ url = "https://files.pythonhosted.org/packages/14/fd/2f20c40b45e4fb4324834aea24bd4afdf1143390242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8" }]
[[distribution.dependencies]]
name = "exceptiongroup"
version = "1.2.0"
source = "registry+https://pypi.org/simple"
[[distribution.dependencies]] [[distribution.dependencies]]
name = "idna" name = "idna"
version = "3.6" version = "3.6"
@ -458,6 +489,19 @@ fn lock_wheel_url() -> Result<()> {
version = "1.3.1" version = "1.3.1"
source = "registry+https://pypi.org/simple" source = "registry+https://pypi.org/simple"
[[distribution.dependencies]]
name = "typing-extensions"
version = "4.10.0"
source = "registry+https://pypi.org/simple"
[[distribution]]
name = "exceptiongroup"
version = "1.2.0"
source = "registry+https://pypi.org/simple"
marker = "python_version < '3.11'"
sdist = { url = "https://files.pythonhosted.org/packages/8e/1c/beef724eaf5b01bb44b6338c8c3494eff7cab376fab4904cfbbc3585dc79/exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68", size = 26264 }
wheels = [{ url = "https://files.pythonhosted.org/packages/b8/9a/5028fd52db10e600f1c4674441b968cf2ea4959085bfb5b99fb1250e5f68/exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14", size = 16210 }]
[[distribution]] [[distribution]]
name = "idna" name = "idna"
version = "3.6" version = "3.6"
@ -482,6 +526,14 @@ fn lock_wheel_url() -> Result<()> {
source = "registry+https://pypi.org/simple" 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 } 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 }] wheels = [{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }]
[[distribution]]
name = "typing-extensions"
version = "4.10.0"
source = "registry+https://pypi.org/simple"
marker = "python_version < '3.11'"
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 }]
"### "###
); );
}); });
@ -527,7 +579,7 @@ fn lock_sdist_url() -> Result<()> {
----- stderr ----- ----- stderr -----
warning: `uv lock` is experimental and may change without warning. warning: `uv lock` is experimental and may change without warning.
Resolved 4 packages in [TIME] Resolved 6 packages in [TIME]
"###); "###);
let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?;
@ -545,6 +597,11 @@ fn lock_sdist_url() -> Result<()> {
source = "direct+https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz" source = "direct+https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz"
sdist = { url = "https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6" } sdist = { url = "https://files.pythonhosted.org/packages/db/4d/3970183622f0330d3c23d9b8a5f52e365e50381fd484d08e3285104333d3/anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6" }
[[distribution.dependencies]]
name = "exceptiongroup"
version = "1.2.0"
source = "registry+https://pypi.org/simple"
[[distribution.dependencies]] [[distribution.dependencies]]
name = "idna" name = "idna"
version = "3.6" version = "3.6"
@ -555,6 +612,19 @@ fn lock_sdist_url() -> Result<()> {
version = "1.3.1" version = "1.3.1"
source = "registry+https://pypi.org/simple" source = "registry+https://pypi.org/simple"
[[distribution.dependencies]]
name = "typing-extensions"
version = "4.10.0"
source = "registry+https://pypi.org/simple"
[[distribution]]
name = "exceptiongroup"
version = "1.2.0"
source = "registry+https://pypi.org/simple"
marker = "python_version < '3.11'"
sdist = { url = "https://files.pythonhosted.org/packages/8e/1c/beef724eaf5b01bb44b6338c8c3494eff7cab376fab4904cfbbc3585dc79/exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68", size = 26264 }
wheels = [{ url = "https://files.pythonhosted.org/packages/b8/9a/5028fd52db10e600f1c4674441b968cf2ea4959085bfb5b99fb1250e5f68/exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14", size = 16210 }]
[[distribution]] [[distribution]]
name = "idna" name = "idna"
version = "3.6" version = "3.6"
@ -579,6 +649,14 @@ fn lock_sdist_url() -> Result<()> {
source = "registry+https://pypi.org/simple" 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 } 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 }] wheels = [{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }]
[[distribution]]
name = "typing-extensions"
version = "4.10.0"
source = "registry+https://pypi.org/simple"
marker = "python_version < '3.11'"
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 }]
"### "###
); );
}); });
@ -627,7 +705,7 @@ fn lock_extra() -> Result<()> {
----- stderr ----- ----- stderr -----
warning: `uv lock` is experimental and may change without warning. warning: `uv lock` is experimental and may change without warning.
Resolved 5 packages in [TIME] Resolved 7 packages in [TIME]
"###); "###);
let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?;
@ -646,6 +724,11 @@ fn lock_extra() -> Result<()> {
sdist = { url = "https://files.pythonhosted.org/packages/c6/b3/fefbf7e78ab3b805dec67d698dc18dd505af7a18a8dd08868c9b4fa736b5/anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce", size = 142737 } sdist = { url = "https://files.pythonhosted.org/packages/c6/b3/fefbf7e78ab3b805dec67d698dc18dd505af7a18a8dd08868c9b4fa736b5/anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce", size = 142737 }
wheels = [{ url = "https://files.pythonhosted.org/packages/68/fe/7ce1926952c8a403b35029e194555558514b365ad77d75125f521a2bec62/anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0", size = 80873 }] wheels = [{ url = "https://files.pythonhosted.org/packages/68/fe/7ce1926952c8a403b35029e194555558514b365ad77d75125f521a2bec62/anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0", size = 80873 }]
[[distribution.dependencies]]
name = "exceptiongroup"
version = "1.2.0"
source = "registry+https://pypi.org/simple"
[[distribution.dependencies]] [[distribution.dependencies]]
name = "idna" name = "idna"
version = "3.6" version = "3.6"
@ -656,6 +739,19 @@ fn lock_extra() -> Result<()> {
version = "1.3.1" version = "1.3.1"
source = "registry+https://pypi.org/simple" source = "registry+https://pypi.org/simple"
[[distribution.dependencies]]
name = "typing-extensions"
version = "4.10.0"
source = "registry+https://pypi.org/simple"
[[distribution]]
name = "exceptiongroup"
version = "1.2.0"
source = "registry+https://pypi.org/simple"
marker = "python_version < '3.11'"
sdist = { url = "https://files.pythonhosted.org/packages/8e/1c/beef724eaf5b01bb44b6338c8c3494eff7cab376fab4904cfbbc3585dc79/exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68", size = 26264 }
wheels = [{ url = "https://files.pythonhosted.org/packages/b8/9a/5028fd52db10e600f1c4674441b968cf2ea4959085bfb5b99fb1250e5f68/exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14", size = 16210 }]
[[distribution]] [[distribution]]
name = "idna" name = "idna"
version = "3.6" version = "3.6"
@ -704,6 +800,14 @@ fn lock_extra() -> Result<()> {
source = "registry+https://pypi.org/simple" 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 } 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 }] wheels = [{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }]
[[distribution]]
name = "typing-extensions"
version = "4.10.0"
source = "registry+https://pypi.org/simple"
marker = "python_version < '3.8'"
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 }]
"### "###
); );
}); });

View file

@ -405,7 +405,7 @@ fn test_uv_run_with_package_virtual_workspace() -> Result<()> {
Success Success
----- stderr ----- ----- stderr -----
Resolved 5 packages in [TIME] Resolved 7 packages in [TIME]
Downloaded 5 packages in [TIME] Downloaded 5 packages in [TIME]
Installed 5 packages in [TIME] Installed 5 packages in [TIME]
+ anyio==4.3.0 + anyio==4.3.0
@ -416,7 +416,7 @@ fn test_uv_run_with_package_virtual_workspace() -> Result<()> {
"### "###
); );
uv_snapshot!(context.filters(), run_workspace(&context) uv_snapshot!(context.filters(), universal_windows_filters=true, run_workspace(&context)
.arg("--package") .arg("--package")
.arg("albatross") .arg("albatross")
.arg("packages/albatross/check_installed_albatross.py") .arg("packages/albatross/check_installed_albatross.py")
@ -427,7 +427,7 @@ fn test_uv_run_with_package_virtual_workspace() -> Result<()> {
Success Success
----- stderr ----- ----- stderr -----
Resolved 7 packages in [TIME] Resolved 10 packages in [TIME]
Downloaded 2 packages in [TIME] Downloaded 2 packages in [TIME]
Installed 2 packages in [TIME] Installed 2 packages in [TIME]
+ albatross==0.1.0 (from file://[TEMP_DIR]/albatross-virtual-workspace/packages/albatross) + albatross==0.1.0 (from file://[TEMP_DIR]/albatross-virtual-workspace/packages/albatross)
@ -473,7 +473,7 @@ fn test_uv_run_with_package_root_workspace() -> Result<()> {
Success Success
----- stderr ----- ----- stderr -----
Resolved 5 packages in [TIME] Resolved 7 packages in [TIME]
Downloaded 5 packages in [TIME] Downloaded 5 packages in [TIME]
Installed 5 packages in [TIME] Installed 5 packages in [TIME]
+ anyio==4.3.0 + anyio==4.3.0
@ -484,7 +484,7 @@ fn test_uv_run_with_package_root_workspace() -> Result<()> {
"### "###
); );
uv_snapshot!(context.filters(), run_workspace(&context) uv_snapshot!(context.filters(), universal_windows_filters=true, run_workspace(&context)
.arg("--package") .arg("--package")
.arg("albatross") .arg("albatross")
.arg("check_installed_albatross.py") .arg("check_installed_albatross.py")
@ -495,7 +495,7 @@ fn test_uv_run_with_package_root_workspace() -> Result<()> {
Success Success
----- stderr ----- ----- stderr -----
Resolved 7 packages in [TIME] Resolved 10 packages in [TIME]
Downloaded 2 packages in [TIME] Downloaded 2 packages in [TIME]
Installed 2 packages in [TIME] Installed 2 packages in [TIME]
+ albatross==0.1.0 (from file://[TEMP_DIR]/albatross-root-workspace) + albatross==0.1.0 (from file://[TEMP_DIR]/albatross-root-workspace)