diff --git a/crates/pixi_core/src/lock_file/update.rs b/crates/pixi_core/src/lock_file/update.rs index fb5e0733cd..22ae050102 100644 --- a/crates/pixi_core/src/lock_file/update.rs +++ b/crates/pixi_core/src/lock_file/update.rs @@ -44,6 +44,7 @@ use pypi_modifiers::pypi_marker_env::determine_marker_environment; use rattler::package_cache::PackageCache; use rattler_conda_types::{Arch, GenericVirtualPackage, PackageName, Platform}; use rattler_lock::{LockFile, LockedPackageRef, ParseCondaLockError}; +use std::collections::hash_map::Entry; use std::{ cmp::PartialEq, collections::{HashMap, HashSet}, @@ -1345,6 +1346,7 @@ impl<'p> UpdateContext<'p> { // Spawn tasks to update the pypi packages. let uv_context = once_cell::sync::OnceCell::new(); + let mut pypi_conda_prefix_updaters = HashMap::new(); for (environment, platform) in self.outdated_envs .pypi @@ -1388,19 +1390,26 @@ impl<'p> UpdateContext<'p> { .get_latest_group_repodata_records(&group, environment.best_platform()) .ok_or_else(|| make_unsupported_pypi_platform_error(environment, false)); - // Creates an object to initiate an update at a later point - let prefix_platform = environment.best_platform(); - let conda_prefix_updater = CondaPrefixUpdater::builder( - group.clone(), - prefix_platform, - environment - .virtual_packages(prefix_platform) - .into_iter() - .map(GenericVirtualPackage::from) - .collect(), - self.command_dispatcher.clone(), - ) - .finish()?; + // Creates an object to initiate an update at a later point. Make sure to only create a single entry if we are solving for multiple platforms. + let conda_prefix_updater = + match pypi_conda_prefix_updaters.entry(environment.name().clone()) { + Entry::Vacant(entry) => { + let prefix_platform = environment.best_platform(); + let conda_prefix_updater = CondaPrefixUpdater::builder( + group.clone(), + prefix_platform, + environment + .virtual_packages(prefix_platform) + .into_iter() + .map(GenericVirtualPackage::from) + .collect(), + self.command_dispatcher.clone(), + ) + .finish()?; + entry.insert(conda_prefix_updater).clone() + } + Entry::Occupied(entry) => entry.get().clone(), + }; let uv_context = uv_context .get_or_try_init(|| UvResolutionContext::from_workspace(project))? diff --git a/crates/pixi_utils/src/reqwest.rs b/crates/pixi_utils/src/reqwest.rs index d154deb823..ede757bd9b 100644 --- a/crates/pixi_utils/src/reqwest.rs +++ b/crates/pixi_utils/src/reqwest.rs @@ -212,13 +212,15 @@ mod tests { Url::parse("https://pypi.org/simple/").unwrap(), vec![Url::parse("https://my-mirror.example.com/simple/").unwrap()], ); - + let middlewares = uv_middlewares(&config); - + // Should have: mirror + OCI + auth middleware - assert!(middlewares.len() >= 3, - "Expected at least 3 middlewares (mirror, OCI, auth) when mirrors configured, got {}", - middlewares.len()); + assert!( + middlewares.len() >= 3, + "Expected at least 3 middlewares (mirror, OCI, auth) when mirrors configured, got {}", + middlewares.len() + ); } #[test] @@ -227,10 +229,13 @@ mod tests { // This ensures existing non-mirror auth scenarios continue to work let config = Config::default(); let middlewares = uv_middlewares(&config); - + // Should have: auth middleware only - assert_eq!(middlewares.len(), 1, - "Expected exactly 1 middleware (auth) when no mirrors configured, got {}", - middlewares.len()); + assert_eq!( + middlewares.len(), + 1, + "Expected exactly 1 middleware (auth) when no mirrors configured, got {}", + middlewares.len() + ); } } diff --git a/tests/integration_rust/pypi_tests.rs b/tests/integration_rust/pypi_tests.rs index 82c910fc35..b5485bc5f7 100644 --- a/tests/integration_rust/pypi_tests.rs +++ b/tests/integration_rust/pypi_tests.rs @@ -460,7 +460,7 @@ async fn test_pinned_help_message() { [dependencies] python = "3.12.*" - pandas = "*" + pandas = "2.3.2" [pypi-dependencies] databricks-sql-connector = ">=4.0.0" @@ -472,6 +472,6 @@ async fn test_pinned_help_message() { // Second, it should contain a help message assert_eq!( format!("{}", err.help().unwrap()), - "The following PyPI packages have been pinned by the conda solve, and this version may be causing a conflict:\npandas==2.3.1" + "The following PyPI packages have been pinned by the conda solve, and this version may be causing a conflict:\npandas==2.3.2" ); }