Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions crates/uv-configuration/src/preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ bitflags::bitflags! {
const ADD_BOUNDS = 1 << 4;
const PACKAGE_CONFLICTS = 1 << 5;
const EXTRA_BUILD_DEPENDENCIES = 1 << 6;
const DETECT_MODULE_CONFLICTS = 1 << 7;
}
}

Expand All @@ -32,6 +33,7 @@ impl PreviewFeatures {
Self::ADD_BOUNDS => "add-bounds",
Self::PACKAGE_CONFLICTS => "package-conflicts",
Self::EXTRA_BUILD_DEPENDENCIES => "extra-build-dependencies",
Self::DETECT_MODULE_CONFLICTS => "detect-module-conflicts",
_ => panic!("`flag_as_str` can only be used for exactly one feature flag"),
}
}
Expand Down Expand Up @@ -76,6 +78,7 @@ impl FromStr for PreviewFeatures {
"add-bounds" => Self::ADD_BOUNDS,
"package-conflicts" => Self::PACKAGE_CONFLICTS,
"extra-build-dependencies" => Self::EXTRA_BUILD_DEPENDENCIES,
"detect-module-conflicts" => Self::DETECT_MODULE_CONFLICTS,
_ => {
warn_user_once!("Unknown preview feature: `{part}`");
continue;
Expand Down Expand Up @@ -246,6 +249,10 @@ mod tests {
PreviewFeatures::EXTRA_BUILD_DEPENDENCIES.flag_as_str(),
"extra-build-dependencies"
);
assert_eq!(
PreviewFeatures::DETECT_MODULE_CONFLICTS.flag_as_str(),
"detect-module-conflicts"
);
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-dispatch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ impl BuildContext for BuildDispatch<'_> {
if wheels.len() == 1 { "" } else { "s" },
wheels.iter().map(ToString::to_string).join(", ")
);
wheels = Installer::new(venv)
wheels = Installer::new(venv, self.preview)
.with_link_mode(self.link_mode)
.with_cache(self.cache)
.install(wheels)
Expand Down
1 change: 1 addition & 0 deletions crates/uv-install-wheel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ name = "uv_install_wheel"

[dependencies]
uv-cache-info = { workspace = true }
uv-configuration = { workspace = true }
uv-distribution-filename = { workspace = true }
uv-fs = { workspace = true }
uv-normalize = { workspace = true }
Expand Down
21 changes: 21 additions & 0 deletions crates/uv-install-wheel/src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,33 @@ use std::sync::{Arc, Mutex};
use std::time::SystemTime;
use tempfile::tempdir_in;
use tracing::{debug, instrument, trace};
use uv_configuration::{Preview, PreviewFeatures};
use uv_distribution_filename::WheelFilename;
use uv_fs::Simplified;
use uv_warnings::{warn_user, warn_user_once};
use walkdir::WalkDir;

#[allow(clippy::struct_field_names)]
#[derive(Debug, Default)]
pub struct Locks {
/// The parent directory of a file in a synchronized copy
copy_dir_locks: Mutex<FxHashMap<PathBuf, Arc<Mutex<()>>>>,
/// Top level modules (excluding namespaces) we write to.
modules: Mutex<FxHashMap<OsString, WheelFilename>>,
/// Preview settings for feature flags.
preview: Preview,
}

impl Locks {
/// Create a new Locks instance with the given preview settings.
pub fn new(preview: Preview) -> Self {
Self {
copy_dir_locks: Mutex::new(FxHashMap::default()),
modules: Mutex::new(FxHashMap::default()),
preview,
}
}

/// Warn when a module exists in multiple packages.
fn warn_module_conflict(&self, module: &OsStr, wheel_a: &WheelFilename) {
if let Some(wheel_b) = self
Expand All @@ -32,6 +45,14 @@ impl Locks {
.unwrap()
.insert(module.to_os_string(), wheel_a.clone())
{
// Only warn if the preview feature is enabled
if !self
.preview
.is_enabled(PreviewFeatures::DETECT_MODULE_CONFLICTS)
{
return;
}

// Sort for consistent output, at least with two packages
let (wheel_a, wheel_b) = if wheel_b.name > wheel_a.name {
(&wheel_b, wheel_a)
Expand Down
13 changes: 10 additions & 3 deletions crates/uv-installer/src/installer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use tokio::sync::oneshot;
use tracing::instrument;

use uv_cache::Cache;
use uv_configuration::RAYON_INITIALIZE;
use uv_configuration::{Preview, RAYON_INITIALIZE};
use uv_distribution_types::CachedDist;
use uv_install_wheel::{Layout, LinkMode};
use uv_python::PythonEnvironment;
Expand All @@ -21,18 +21,21 @@ pub struct Installer<'a> {
name: Option<String>,
/// The metadata associated with the [`Installer`].
metadata: bool,
/// Preview settings for the installer.
preview: Preview,
}

impl<'a> Installer<'a> {
/// Initialize a new installer.
pub fn new(venv: &'a PythonEnvironment) -> Self {
pub fn new(venv: &'a PythonEnvironment, preview: Preview) -> Self {
Self {
venv,
link_mode: LinkMode::default(),
cache: None,
reporter: None,
name: Some("uv".to_string()),
metadata: true,
preview,
}
}

Expand Down Expand Up @@ -88,6 +91,7 @@ impl<'a> Installer<'a> {
reporter,
name: installer_name,
metadata: installer_metadata,
preview,
} = self;

if cache.is_some_and(Cache::is_temporary) {
Expand All @@ -113,6 +117,7 @@ impl<'a> Installer<'a> {
reporter.as_ref(),
relocatable,
installer_metadata,
preview,
);

// This may fail if the main task was cancelled.
Expand Down Expand Up @@ -143,6 +148,7 @@ impl<'a> Installer<'a> {
self.reporter.as_ref(),
self.venv.relocatable(),
self.metadata,
self.preview,
)
}
}
Expand All @@ -157,10 +163,11 @@ fn install(
reporter: Option<&Arc<dyn Reporter>>,
relocatable: bool,
installer_metadata: bool,
preview: Preview,
) -> Result<Vec<CachedDist>> {
// Initialize the threadpool with the user settings.
LazyLock::force(&RAYON_INITIALIZE);
let locks = uv_install_wheel::Locks::default();
let locks = uv_install_wheel::Locks::new(preview);
wheels.par_iter().try_for_each(|wheel| {
uv_install_wheel::install_wheel(
layout,
Expand Down
1 change: 1 addition & 0 deletions crates/uv/src/commands/pip/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ pub(crate) async fn pip_install(
installer_metadata,
dry_run,
printer,
preview,
)
.await
{
Expand Down
3 changes: 2 additions & 1 deletion crates/uv/src/commands/pip/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ pub(crate) async fn install(
installer_metadata: bool,
dry_run: DryRun,
printer: Printer,
preview: uv_configuration::Preview,
) -> Result<Changelog, Error> {
let start = std::time::Instant::now();

Expand Down Expand Up @@ -571,7 +572,7 @@ pub(crate) async fn install(
let mut installs = wheels.into_iter().chain(cached).collect::<Vec<_>>();
if !installs.is_empty() {
let start = std::time::Instant::now();
installs = uv_installer::Installer::new(venv)
installs = uv_installer::Installer::new(venv, preview)
.with_link_mode(link_mode)
.with_cache(cache)
.with_installer_metadata(installer_metadata)
Expand Down
1 change: 1 addition & 0 deletions crates/uv/src/commands/pip/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ pub(crate) async fn pip_sync(
installer_metadata,
dry_run,
printer,
preview,
)
.await
{
Expand Down
2 changes: 2 additions & 0 deletions crates/uv/src/commands/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2173,6 +2173,7 @@ pub(crate) async fn sync_environment(
installer_metadata,
dry_run,
printer,
preview,
)
.await?;

Expand Down Expand Up @@ -2434,6 +2435,7 @@ pub(crate) async fn update_environment(
installer_metadata,
dry_run,
printer,
preview,
)
.await?;

Expand Down
1 change: 1 addition & 0 deletions crates/uv/src/commands/project/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,7 @@ pub(super) async fn do_sync(
installer_metadata,
dry_run,
printer,
preview,
)
.await?;

Expand Down
25 changes: 24 additions & 1 deletion crates/uv/tests/it/pip_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12486,7 +12486,7 @@ fn overlapping_packages_warning() -> Result<()> {
.child("__init__.py")
.touch()?;

// Check that overlapping packages show a warning
// Check that overlapping packages don't show a warning by default
uv_snapshot!(context.filters(), context.pip_install()
.arg("--no-deps")
.arg(&built_by_uv)
Expand All @@ -12495,6 +12495,29 @@ fn overlapping_packages_warning() -> Result<()> {
exit_code: 0
----- stdout -----

----- stderr -----
Resolved 2 packages in [TIME]
Prepared 2 packages in [TIME]
Installed 2 packages in [TIME]
+ also-built-by-uv==0.1.0 (from file://[TEMP_DIR]/also-built-by-uv)
+ built-by-uv==0.1.0 (from file://[WORKSPACE]/scripts/packages/built-by-uv)
"
);

// Clean up for the next test
context.venv().arg("--clear").assert().success();

// Check that overlapping packages show a warning when preview feature is enabled
uv_snapshot!(context.filters(), context.pip_install()
.arg("--no-deps")
.arg("--preview-features")
.arg("detect-module-conflicts")
.arg(&built_by_uv)
.arg(also_build_by_uv.path()), @r"
success: true
exit_code: 0
----- stdout -----

----- stderr -----
Resolved 2 packages in [TIME]
Prepared 2 packages in [TIME]
Expand Down
4 changes: 2 additions & 2 deletions crates/uv/tests/it/show_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7720,7 +7720,7 @@ fn preview_features() {
show_settings: true,
preview: Preview {
flags: PreviewFeatures(
PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE | JSON_OUTPUT | PYLOCK | ADD_BOUNDS | PACKAGE_CONFLICTS | EXTRA_BUILD_DEPENDENCIES,
PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE | JSON_OUTPUT | PYLOCK | ADD_BOUNDS | PACKAGE_CONFLICTS | EXTRA_BUILD_DEPENDENCIES | DETECT_MODULE_CONFLICTS,
),
},
python_preference: Managed,
Expand Down Expand Up @@ -7946,7 +7946,7 @@ fn preview_features() {
show_settings: true,
preview: Preview {
flags: PreviewFeatures(
PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE | JSON_OUTPUT | PYLOCK | ADD_BOUNDS | PACKAGE_CONFLICTS | EXTRA_BUILD_DEPENDENCIES,
PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE | JSON_OUTPUT | PYLOCK | ADD_BOUNDS | PACKAGE_CONFLICTS | EXTRA_BUILD_DEPENDENCIES | DETECT_MODULE_CONFLICTS,
),
},
python_preference: Managed,
Expand Down
Loading