From a23ca5bab72b88ef992f7a0622ef19fb7ff73c74 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sun, 2 Jun 2024 21:33:18 -0400 Subject: [PATCH] Use universal resolution in `uv lock` (#3969) ## Summary Wires up the optional markers in resolution, and adds respecting-the-markers to `Lock:: to_resolution`. --- crates/uv-resolver/src/lock.rs | 21 ++-- crates/uv-resolver/src/python_requirement.rs | 11 +- crates/uv/src/commands/pip/install.rs | 2 +- crates/uv/src/commands/pip/operations.rs | 12 +- crates/uv/src/commands/pip/sync.rs | 2 +- crates/uv/src/commands/project/lock.rs | 2 +- crates/uv/src/commands/project/mod.rs | 2 +- crates/uv/tests/common/mod.rs | 73 +++++++----- crates/uv/tests/lock.rs | 112 ++++++++++++++++++- crates/uv/tests/workspace.rs | 12 +- 10 files changed, 195 insertions(+), 54 deletions(-) diff --git a/crates/uv-resolver/src/lock.rs b/crates/uv-resolver/src/lock.rs index fb0595e33..07bb938e4 100644 --- a/crates/uv-resolver/src/lock.rs +++ b/crates/uv-resolver/src/lock.rs @@ -19,7 +19,7 @@ use distribution_types::{ RegistrySourceDist, RemoteSource, Resolution, ResolvedDist, ToUrlError, }; use pep440_rs::Version; -use pep508_rs::{MarkerEnvironment, VerbatimUrl}; +use pep508_rs::{MarkerEnvironment, MarkerTree, VerbatimUrl}; use platform_tags::{TagCompatibility, TagPriority, Tags}; use pypi_types::{HashDigest, ParsedArchiveUrl, ParsedGitUrl}; use uv_git::{GitReference, GitSha, RepositoryReference, ResolvedRepositoryReference}; @@ -82,10 +82,16 @@ impl Lock { while let Some(dist) = queue.pop_front() { for dep in &dist.dependencies { let dep_dist = self.find_by_id(&dep.id); - queue.push_back(dep_dist); + if dep_dist + .marker + .as_ref() + .map_or(true, |marker| marker.evaluate(marker_env, &[])) + { + queue.push_back(dep_dist); + } } 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); } let diagnostics = vec![]; @@ -280,7 +286,7 @@ pub struct Distribution { #[serde(flatten)] pub(crate) id: DistributionId, #[serde(default)] - pub(crate) marker: Option, + pub(crate) marker: Option, #[serde(default)] pub(crate) sdist: Option, #[serde(default, skip_serializing_if = "Vec::is_empty")] @@ -294,11 +300,12 @@ impl Distribution { annotated_dist: &AnnotatedDist, ) -> Result { 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 wheels = Wheel::from_annotated_dist(annotated_dist)?; Ok(Distribution { id, - marker: annotated_dist.marker.as_ref().map(ToString::to_string), + marker, sdist, wheels, dependencies: vec![], @@ -311,7 +318,7 @@ impl Distribution { } /// 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) { return match &self.id.source.kind { SourceKind::Registry => { diff --git a/crates/uv-resolver/src/python_requirement.rs b/crates/uv-resolver/src/python_requirement.rs index ed5f47e30..84a6dd556 100644 --- a/crates/uv-resolver/src/python_requirement.rs +++ b/crates/uv-resolver/src/python_requirement.rs @@ -12,15 +12,18 @@ pub struct PythonRequirement { } impl PythonRequirement { - pub fn new(interpreter: &Interpreter, target: &StringVersion) -> Self { + pub fn from_marker_environment(interpreter: &Interpreter, env: &MarkerEnvironment) -> Self { Self { 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 { - Self::new(interpreter, env.python_full_version()) + pub fn from_interpreter(interpreter: &Interpreter) -> Self { + Self { + installed: interpreter.python_full_version().clone(), + target: interpreter.python_full_version().clone(), + } } /// Return the installed version of Python. diff --git a/crates/uv/src/commands/pip/install.rs b/crates/uv/src/commands/pip/install.rs index 03712dc6e..d0107f655 100644 --- a/crates/uv/src/commands/pip/install.rs +++ b/crates/uv/src/commands/pip/install.rs @@ -352,7 +352,7 @@ pub(crate) async fn pip_install( &upgrade, &interpreter, &tags, - &markers, + Some(&markers), &client, &flat_index, &index, diff --git a/crates/uv/src/commands/pip/operations.rs b/crates/uv/src/commands/pip/operations.rs index 247d6abd7..cbab850c7 100644 --- a/crates/uv/src/commands/pip/operations.rs +++ b/crates/uv/src/commands/pip/operations.rs @@ -88,7 +88,7 @@ pub(crate) async fn resolve( upgrade: &Upgrade, interpreter: &Interpreter, tags: &Tags, - markers: &MarkerEnvironment, + markers: Option<&MarkerEnvironment>, client: &RegistryClient, flat_index: &FlatIndex, index: &InMemoryIndex, @@ -182,7 +182,11 @@ pub(crate) async fn resolve( // Collect constraints and overrides. let constraints = Constraints::from_requirements(constraints); 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. let lookaheads = match options.dependency_mode { @@ -196,7 +200,7 @@ pub(crate) async fn resolve( DistributionDatabase::new(client, build_dispatch, concurrency.downloads, preview), ) .with_reporter(ResolverReporter::from(printer)) - .resolve(Some(markers)) + .resolve(markers) .await? } DependencyMode::Direct => Vec::new(), @@ -230,7 +234,7 @@ pub(crate) async fn resolve( manifest, options, &python_requirement, - Some(markers), + markers, tags, flat_index, index, diff --git a/crates/uv/src/commands/pip/sync.rs b/crates/uv/src/commands/pip/sync.rs index f625967e3..ad117ef42 100644 --- a/crates/uv/src/commands/pip/sync.rs +++ b/crates/uv/src/commands/pip/sync.rs @@ -302,7 +302,7 @@ pub(crate) async fn pip_sync( &upgrade, interpreter, &tags, - &markers, + Some(&markers), &client, &flat_index, &index, diff --git a/crates/uv/src/commands/project/lock.rs b/crates/uv/src/commands/project/lock.rs index c9980280f..1bb383083 100644 --- a/crates/uv/src/commands/project/lock.rs +++ b/crates/uv/src/commands/project/lock.rs @@ -158,7 +158,7 @@ pub(super) async fn do_lock( &upgrade, &interpreter, tags, - markers, + None, &client, &flat_index, &index, diff --git a/crates/uv/src/commands/project/mod.rs b/crates/uv/src/commands/project/mod.rs index 28381d689..301a0e72c 100644 --- a/crates/uv/src/commands/project/mod.rs +++ b/crates/uv/src/commands/project/mod.rs @@ -217,7 +217,7 @@ pub(crate) async fn update_environment( &upgrade, &interpreter, tags, - markers, + Some(markers), &client, &flat_index, &index, diff --git a/crates/uv/tests/common/mod.rs b/crates/uv/tests/common/mod.rs index 06dff0de5..bd84c7518 100644 --- a/crates/uv/tests/common/mod.rs +++ b/crates/uv/tests/common/mod.rs @@ -514,6 +514,12 @@ pub fn python_path_with_versions( 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. /// /// This function is derived from `insta_cmd`s `spawn_with_info`. @@ -521,7 +527,7 @@ pub fn run_and_format>( mut command: impl BorrowMut, filters: impl AsRef<[(T, T)]>, function_name: &str, - windows_filters: bool, + windows_filters: Option, ) -> (String, Output) { let program = command .borrow_mut() @@ -566,29 +572,40 @@ pub fn run_and_format>( // pass whether it's on Windows or Unix. In particular, there are some very // common Windows-only dependencies that, when removed from a resolution, // cause the set of dependencies to be the same across platforms. - if cfg!(windows) && windows_filters { - // The optional leading +/- is for install logs, the optional next line is for lock files - let windows_only_deps = [ - ("( [+-] )?colorama==\\d+(\\.[\\d+])+\n( # via .*\n)?"), - ("( [+-] )?colorama==\\d+(\\.[\\d+])+\\s+(# via .*\n)?"), - ("( [+-] )?tzdata==\\d+(\\.[\\d+])+\n( # via .*\n)?"), - ("( [+-] )?tzdata==\\d+(\\.[\\d+])+\\s+(# via .*\n)?"), - ]; - let mut removed_packages = 0; - for windows_only_dep in windows_only_deps { - // TODO(konstin): Cache regex compilation - let re = Regex::new(windows_only_dep).unwrap(); - if re.is_match(&snapshot) { - snapshot = re.replace(&snapshot, "").to_string(); - removed_packages += 1; + 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 + let windows_only_deps = [ + ("( [+-] )?colorama==\\d+(\\.[\\d+])+\n( # via .*\n)?"), + ("( [+-] )?colorama==\\d+(\\.[\\d+])+\\s+(# via .*\n)?"), + ("( [+-] )?tzdata==\\d+(\\.[\\d+])+\n( # via .*\n)?"), + ("( [+-] )?tzdata==\\d+(\\.[\\d+])+\\s+(# via .*\n)?"), + ]; + let mut removed_packages = 0; + for windows_only_dep in windows_only_deps { + // TODO(konstin): Cache regex compilation + let re = Regex::new(windows_only_dep).unwrap(); + if re.is_match(&snapshot) { + snapshot = re.replace(&snapshot, "").to_string(); + removed_packages += 1; + } } - } - if removed_packages > 0 { - for i in 1..20 { - snapshot = snapshot.replace( - &format!("{} packages", i + removed_packages), - &format!("{} package{}", i, if i > 1 { "s" } else { "" }), - ); + if removed_packages > 0 { + 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( + &format!("{verb} {} packages", i + removed_packages), + &format!("{verb} {} package{}", i, if i > 1 { "s" } else { "" }), + ); + } + } } } } @@ -641,13 +658,19 @@ macro_rules! uv_snapshot { }}; ($filters:expr, $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!(), true); + let (snapshot, output) = $crate::common::run_and_format($spawnable, &$filters, function_name!(), Some($crate::common::WindowsFilters::Platform)); ::insta::assert_snapshot!(snapshot, @$snapshot); output }}; ($filters:expr, windows_filters=false, $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!(), 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); output }}; diff --git a/crates/uv/tests/lock.rs b/crates/uv/tests/lock.rs index fb7833d78..3a6daa0ec 100644 --- a/crates/uv/tests/lock.rs +++ b/crates/uv/tests/lock.rs @@ -30,7 +30,7 @@ fn lock_wheel_registry() -> Result<()> { ----- stderr ----- 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"))?; @@ -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 } 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]] name = "idna" version = "3.6" @@ -59,6 +64,19 @@ fn lock_wheel_registry() -> Result<()> { version = "1.3.1" 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]] name = "idna" version = "3.6" @@ -83,6 +101,14 @@ fn lock_wheel_registry() -> Result<()> { 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 } 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 ----- 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"))?; @@ -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" 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]] name = "idna" version = "3.6" @@ -458,6 +489,19 @@ fn lock_wheel_url() -> Result<()> { version = "1.3.1" 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]] name = "idna" version = "3.6" @@ -482,6 +526,14 @@ fn lock_wheel_url() -> Result<()> { 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 } 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 ----- 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"))?; @@ -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" 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]] name = "idna" version = "3.6" @@ -555,6 +612,19 @@ fn lock_sdist_url() -> Result<()> { version = "1.3.1" 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]] name = "idna" version = "3.6" @@ -579,6 +649,14 @@ fn lock_sdist_url() -> Result<()> { 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 } 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 ----- 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"))?; @@ -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 } 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]] name = "idna" version = "3.6" @@ -656,6 +739,19 @@ fn lock_extra() -> Result<()> { version = "1.3.1" 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]] name = "idna" version = "3.6" @@ -704,6 +800,14 @@ fn lock_extra() -> Result<()> { 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 } 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 }] "### ); }); diff --git a/crates/uv/tests/workspace.rs b/crates/uv/tests/workspace.rs index e9b34b1cd..5d60855e6 100644 --- a/crates/uv/tests/workspace.rs +++ b/crates/uv/tests/workspace.rs @@ -405,7 +405,7 @@ fn test_uv_run_with_package_virtual_workspace() -> Result<()> { Success ----- stderr ----- - Resolved 5 packages in [TIME] + Resolved 7 packages in [TIME] Downloaded 5 packages in [TIME] Installed 5 packages in [TIME] + 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("albatross") .arg("packages/albatross/check_installed_albatross.py") @@ -427,7 +427,7 @@ fn test_uv_run_with_package_virtual_workspace() -> Result<()> { Success ----- stderr ----- - Resolved 7 packages in [TIME] + Resolved 10 packages in [TIME] Downloaded 2 packages in [TIME] Installed 2 packages in [TIME] + 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 ----- stderr ----- - Resolved 5 packages in [TIME] + Resolved 7 packages in [TIME] Downloaded 5 packages in [TIME] Installed 5 packages in [TIME] + 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("albatross") .arg("check_installed_albatross.py") @@ -495,7 +495,7 @@ fn test_uv_run_with_package_root_workspace() -> Result<()> { Success ----- stderr ----- - Resolved 7 packages in [TIME] + Resolved 10 packages in [TIME] Downloaded 2 packages in [TIME] Installed 2 packages in [TIME] + albatross==0.1.0 (from file://[TEMP_DIR]/albatross-root-workspace)