mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-17 05:47:45 +00:00
Allow --config-settings-package
to apply configuration settings at the package level (#14573)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux aarch64 (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / build binary | msrv (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / smoke test | linux aarch64 (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | aarch64 windows implicit (push) Blocked by required conditions
CI / integration test | aarch64 windows explicit (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux aarch64 (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / build binary | msrv (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / smoke test | linux aarch64 (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | aarch64 windows implicit (push) Blocked by required conditions
CI / integration test | aarch64 windows explicit (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
## Summary Closes https://github.com/astral-sh/uv/issues/14564. Closes https://github.com/astral-sh/uv/issues/10940.
This commit is contained in:
parent
a6a5e65e0c
commit
e724ddc63f
30 changed files with 927 additions and 58 deletions
|
@ -86,8 +86,8 @@ mod resolver {
|
|||
use uv_cache::Cache;
|
||||
use uv_client::RegistryClient;
|
||||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, Constraints, IndexStrategy, PreviewMode,
|
||||
SourceStrategy,
|
||||
BuildOptions, Concurrency, ConfigSettings, Constraints, IndexStrategy,
|
||||
PackageConfigSettings, PreviewMode, SourceStrategy,
|
||||
};
|
||||
use uv_dispatch::{BuildDispatch, SharedState};
|
||||
use uv_distribution::DistributionDatabase;
|
||||
|
@ -144,6 +144,7 @@ mod resolver {
|
|||
let build_options = BuildOptions::default();
|
||||
let concurrency = Concurrency::default();
|
||||
let config_settings = ConfigSettings::default();
|
||||
let config_settings_package = PackageConfigSettings::default();
|
||||
let exclude_newer = Some(
|
||||
jiff::civil::date(2024, 9, 1)
|
||||
.to_zoned(jiff::tz::TimeZone::UTC)
|
||||
|
@ -184,6 +185,7 @@ mod resolver {
|
|||
state,
|
||||
IndexStrategy::default(),
|
||||
&config_settings,
|
||||
&config_settings_package,
|
||||
build_isolation,
|
||||
LinkMode::default(),
|
||||
&build_options,
|
||||
|
|
|
@ -10,8 +10,9 @@ use clap::{Args, Parser, Subcommand};
|
|||
|
||||
use uv_cache::CacheArgs;
|
||||
use uv_configuration::{
|
||||
ConfigSettingEntry, ExportFormat, IndexStrategy, KeyringProviderType, PackageNameSpecifier,
|
||||
ProjectBuildBackend, TargetTriple, TrustedHost, TrustedPublishing, VersionControlSystem,
|
||||
ConfigSettingEntry, ConfigSettingPackageEntry, ExportFormat, IndexStrategy,
|
||||
KeyringProviderType, PackageNameSpecifier, ProjectBuildBackend, TargetTriple, TrustedHost,
|
||||
TrustedPublishing, VersionControlSystem,
|
||||
};
|
||||
use uv_distribution_types::{Index, IndexUrl, Origin, PipExtraIndex, PipFindLinks, PipIndex};
|
||||
use uv_normalize::{ExtraName, GroupName, PackageName, PipGroupName};
|
||||
|
@ -4693,6 +4694,14 @@ pub struct ToolUpgradeArgs {
|
|||
)]
|
||||
pub config_setting: Option<Vec<ConfigSettingEntry>>,
|
||||
|
||||
/// Settings to pass to the PEP 517 build backend for a specific package, specified as `PACKAGE:KEY=VALUE` pairs.
|
||||
#[arg(
|
||||
long,
|
||||
alias = "config-settings-package",
|
||||
help_heading = "Build options"
|
||||
)]
|
||||
pub config_setting_package: Option<Vec<ConfigSettingPackageEntry>>,
|
||||
|
||||
/// Disable isolation when building source distributions.
|
||||
///
|
||||
/// Assumes that build dependencies specified by PEP 518 are already installed.
|
||||
|
@ -5484,6 +5493,14 @@ pub struct InstallerArgs {
|
|||
)]
|
||||
pub config_setting: Option<Vec<ConfigSettingEntry>>,
|
||||
|
||||
/// Settings to pass to the PEP 517 build backend for a specific package, specified as `PACKAGE:KEY=VALUE` pairs.
|
||||
#[arg(
|
||||
long,
|
||||
alias = "config-settings-package",
|
||||
help_heading = "Build options"
|
||||
)]
|
||||
pub config_settings_package: Option<Vec<ConfigSettingPackageEntry>>,
|
||||
|
||||
/// Disable isolation when building source distributions.
|
||||
///
|
||||
/// Assumes that build dependencies specified by PEP 518 are already installed.
|
||||
|
@ -5671,6 +5688,14 @@ pub struct ResolverArgs {
|
|||
)]
|
||||
pub config_setting: Option<Vec<ConfigSettingEntry>>,
|
||||
|
||||
/// Settings to pass to the PEP 517 build backend for a specific package, specified as `PACKAGE:KEY=VALUE` pairs.
|
||||
#[arg(
|
||||
long,
|
||||
alias = "config-settings-package",
|
||||
help_heading = "Build options"
|
||||
)]
|
||||
pub config_settings_package: Option<Vec<ConfigSettingPackageEntry>>,
|
||||
|
||||
/// Disable isolation when building source distributions.
|
||||
///
|
||||
/// Assumes that build dependencies specified by PEP 518 are already installed.
|
||||
|
@ -5860,6 +5885,14 @@ pub struct ResolverInstallerArgs {
|
|||
)]
|
||||
pub config_setting: Option<Vec<ConfigSettingEntry>>,
|
||||
|
||||
/// Settings to pass to the PEP 517 build backend for a specific package, specified as `PACKAGE:KEY=VALUE` pairs.
|
||||
#[arg(
|
||||
long,
|
||||
alias = "config-settings-package",
|
||||
help_heading = "Build options"
|
||||
)]
|
||||
pub config_settings_package: Option<Vec<ConfigSettingPackageEntry>>,
|
||||
|
||||
/// Disable isolation when building source distributions.
|
||||
///
|
||||
/// Assumes that build dependencies specified by PEP 518 are already installed.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use anstream::eprintln;
|
||||
|
||||
use uv_cache::Refresh;
|
||||
use uv_configuration::ConfigSettings;
|
||||
use uv_configuration::{ConfigSettings, PackageConfigSettings};
|
||||
use uv_resolver::PrereleaseMode;
|
||||
use uv_settings::{Combine, PipOptions, ResolverInstallerOptions, ResolverOptions};
|
||||
use uv_warnings::owo_colors::OwoColorize;
|
||||
|
@ -62,6 +62,7 @@ impl From<ResolverArgs> for PipOptions {
|
|||
pre,
|
||||
fork_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
build_isolation,
|
||||
|
@ -84,6 +85,11 @@ impl From<ResolverArgs> for PipOptions {
|
|||
},
|
||||
config_settings: config_setting
|
||||
.map(|config_settings| config_settings.into_iter().collect::<ConfigSettings>()),
|
||||
config_settings_package: config_settings_package.map(|config_settings| {
|
||||
config_settings
|
||||
.into_iter()
|
||||
.collect::<PackageConfigSettings>()
|
||||
}),
|
||||
no_build_isolation: flag(no_build_isolation, build_isolation, "build-isolation"),
|
||||
no_build_isolation_package: Some(no_build_isolation_package),
|
||||
exclude_newer,
|
||||
|
@ -104,6 +110,7 @@ impl From<InstallerArgs> for PipOptions {
|
|||
index_strategy,
|
||||
keyring_provider,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
build_isolation,
|
||||
exclude_newer,
|
||||
|
@ -120,6 +127,11 @@ impl From<InstallerArgs> for PipOptions {
|
|||
keyring_provider,
|
||||
config_settings: config_setting
|
||||
.map(|config_settings| config_settings.into_iter().collect::<ConfigSettings>()),
|
||||
config_settings_package: config_settings_package.map(|config_settings| {
|
||||
config_settings
|
||||
.into_iter()
|
||||
.collect::<PackageConfigSettings>()
|
||||
}),
|
||||
no_build_isolation: flag(no_build_isolation, build_isolation, "build-isolation"),
|
||||
exclude_newer,
|
||||
link_mode,
|
||||
|
@ -147,6 +159,7 @@ impl From<ResolverInstallerArgs> for PipOptions {
|
|||
pre,
|
||||
fork_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
build_isolation,
|
||||
|
@ -173,6 +186,11 @@ impl From<ResolverInstallerArgs> for PipOptions {
|
|||
fork_strategy,
|
||||
config_settings: config_setting
|
||||
.map(|config_settings| config_settings.into_iter().collect::<ConfigSettings>()),
|
||||
config_settings_package: config_settings_package.map(|config_settings| {
|
||||
config_settings
|
||||
.into_iter()
|
||||
.collect::<PackageConfigSettings>()
|
||||
}),
|
||||
no_build_isolation: flag(no_build_isolation, build_isolation, "build-isolation"),
|
||||
no_build_isolation_package: Some(no_build_isolation_package),
|
||||
exclude_newer,
|
||||
|
@ -260,6 +278,7 @@ pub fn resolver_options(
|
|||
pre,
|
||||
fork_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
build_isolation,
|
||||
|
@ -321,6 +340,11 @@ pub fn resolver_options(
|
|||
dependency_metadata: None,
|
||||
config_settings: config_setting
|
||||
.map(|config_settings| config_settings.into_iter().collect::<ConfigSettings>()),
|
||||
config_settings_package: config_settings_package.map(|config_settings| {
|
||||
config_settings
|
||||
.into_iter()
|
||||
.collect::<PackageConfigSettings>()
|
||||
}),
|
||||
no_build_isolation: flag(no_build_isolation, build_isolation, "build-isolation"),
|
||||
no_build_isolation_package: Some(no_build_isolation_package),
|
||||
exclude_newer,
|
||||
|
@ -353,6 +377,7 @@ pub fn resolver_installer_options(
|
|||
pre,
|
||||
fork_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
build_isolation,
|
||||
|
@ -428,6 +453,11 @@ pub fn resolver_installer_options(
|
|||
dependency_metadata: None,
|
||||
config_settings: config_setting
|
||||
.map(|config_settings| config_settings.into_iter().collect::<ConfigSettings>()),
|
||||
config_settings_package: config_settings_package.map(|config_settings| {
|
||||
config_settings
|
||||
.into_iter()
|
||||
.collect::<PackageConfigSettings>()
|
||||
}),
|
||||
no_build_isolation: flag(no_build_isolation, build_isolation, "build-isolation"),
|
||||
no_build_isolation_package: if no_build_isolation_package.is_empty() {
|
||||
None
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::{
|
|||
str::FromStr,
|
||||
};
|
||||
use uv_cache_key::CacheKeyHasher;
|
||||
use uv_normalize::PackageName;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConfigSettingEntry {
|
||||
|
@ -28,6 +29,32 @@ impl FromStr for ConfigSettingEntry {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConfigSettingPackageEntry {
|
||||
/// The package name to apply the setting to.
|
||||
package: PackageName,
|
||||
/// The config setting entry.
|
||||
setting: ConfigSettingEntry,
|
||||
}
|
||||
|
||||
impl FromStr for ConfigSettingPackageEntry {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let Some((package_str, config_str)) = s.split_once(':') else {
|
||||
return Err(format!(
|
||||
"Invalid config setting: {s} (expected `PACKAGE:KEY=VALUE`)"
|
||||
));
|
||||
};
|
||||
|
||||
let package = PackageName::from_str(package_str.trim())
|
||||
.map_err(|e| format!("Invalid package name: {e}"))?;
|
||||
let setting = ConfigSettingEntry::from_str(config_str)?;
|
||||
|
||||
Ok(Self { package, setting })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema), schemars(untagged))]
|
||||
enum ConfigSettingValue {
|
||||
|
@ -212,6 +239,111 @@ impl<'de> serde::Deserialize<'de> for ConfigSettings {
|
|||
}
|
||||
}
|
||||
|
||||
/// Settings to pass to PEP 517 build backends on a per-package basis.
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct PackageConfigSettings(BTreeMap<PackageName, ConfigSettings>);
|
||||
|
||||
impl FromIterator<ConfigSettingPackageEntry> for PackageConfigSettings {
|
||||
fn from_iter<T: IntoIterator<Item = ConfigSettingPackageEntry>>(iter: T) -> Self {
|
||||
let mut package_configs: BTreeMap<PackageName, Vec<ConfigSettingEntry>> = BTreeMap::new();
|
||||
|
||||
for entry in iter {
|
||||
package_configs
|
||||
.entry(entry.package)
|
||||
.or_default()
|
||||
.push(entry.setting);
|
||||
}
|
||||
|
||||
let configs = package_configs
|
||||
.into_iter()
|
||||
.map(|(package, entries)| (package, entries.into_iter().collect()))
|
||||
.collect();
|
||||
|
||||
Self(configs)
|
||||
}
|
||||
}
|
||||
|
||||
impl PackageConfigSettings {
|
||||
/// Returns the config settings for a specific package, if any.
|
||||
pub fn get(&self, package: &PackageName) -> Option<&ConfigSettings> {
|
||||
self.0.get(package)
|
||||
}
|
||||
|
||||
/// Returns `true` if there are no package-specific settings.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
/// Merge two sets of package config settings, with the values in `self` taking precedence.
|
||||
#[must_use]
|
||||
pub fn merge(mut self, other: PackageConfigSettings) -> PackageConfigSettings {
|
||||
for (package, settings) in other.0 {
|
||||
match self.0.entry(package) {
|
||||
Entry::Vacant(vacant) => {
|
||||
vacant.insert(settings);
|
||||
}
|
||||
Entry::Occupied(mut occupied) => {
|
||||
let merged = occupied.get().clone().merge(settings);
|
||||
occupied.insert(merged);
|
||||
}
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl uv_cache_key::CacheKey for PackageConfigSettings {
|
||||
fn cache_key(&self, state: &mut CacheKeyHasher) {
|
||||
for (package, settings) in &self.0 {
|
||||
package.to_string().cache_key(state);
|
||||
settings.cache_key(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::Serialize for PackageConfigSettings {
|
||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
use serde::ser::SerializeMap;
|
||||
|
||||
let mut map = serializer.serialize_map(Some(self.0.len()))?;
|
||||
for (key, value) in &self.0 {
|
||||
map.serialize_entry(&key.to_string(), value)?;
|
||||
}
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for PackageConfigSettings {
|
||||
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
struct Visitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for Visitor {
|
||||
type Value = PackageConfigSettings;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a map from package name to config settings")
|
||||
}
|
||||
|
||||
fn visit_map<A: serde::de::MapAccess<'de>>(
|
||||
self,
|
||||
mut map: A,
|
||||
) -> Result<Self::Value, A::Error> {
|
||||
let mut config = BTreeMap::default();
|
||||
while let Some((key, value)) = map.next_entry::<String, ConfigSettings>()? {
|
||||
let package = PackageName::from_str(&key).map_err(|e| {
|
||||
serde::de::Error::custom(format!("Invalid package name: {e}"))
|
||||
})?;
|
||||
config.insert(package, value);
|
||||
}
|
||||
Ok(PackageConfigSettings(config))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_map(Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -291,4 +423,56 @@ mod tests {
|
|||
);
|
||||
assert_eq!(settings.escape_for_python(), r#"{"key":"val\\1 {}value"}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_config_setting_package_entry() {
|
||||
// Test valid parsing
|
||||
let entry = ConfigSettingPackageEntry::from_str("numpy:editable_mode=compat").unwrap();
|
||||
assert_eq!(entry.package.as_ref(), "numpy");
|
||||
assert_eq!(entry.setting.key, "editable_mode");
|
||||
assert_eq!(entry.setting.value, "compat");
|
||||
|
||||
// Test with package name containing hyphens
|
||||
let entry = ConfigSettingPackageEntry::from_str("my-package:some_key=value").unwrap();
|
||||
assert_eq!(entry.package.as_ref(), "my-package");
|
||||
assert_eq!(entry.setting.key, "some_key");
|
||||
assert_eq!(entry.setting.value, "value");
|
||||
|
||||
// Test with spaces around values
|
||||
let entry = ConfigSettingPackageEntry::from_str(" numpy : key = value ").unwrap();
|
||||
assert_eq!(entry.package.as_ref(), "numpy");
|
||||
assert_eq!(entry.setting.key, "key");
|
||||
assert_eq!(entry.setting.value, "value");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collect_config_settings_package() {
|
||||
let settings: PackageConfigSettings = vec![
|
||||
ConfigSettingPackageEntry::from_str("numpy:editable_mode=compat").unwrap(),
|
||||
ConfigSettingPackageEntry::from_str("numpy:another_key=value").unwrap(),
|
||||
ConfigSettingPackageEntry::from_str("scipy:build_option=fast").unwrap(),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
let numpy_settings = settings
|
||||
.get(&PackageName::from_str("numpy").unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
numpy_settings.0.get("editable_mode"),
|
||||
Some(&ConfigSettingValue::String("compat".to_string()))
|
||||
);
|
||||
assert_eq!(
|
||||
numpy_settings.0.get("another_key"),
|
||||
Some(&ConfigSettingValue::String("value".to_string()))
|
||||
);
|
||||
|
||||
let scipy_settings = settings
|
||||
.get(&PackageName::from_str("scipy").unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
scipy_settings.0.get("build_option"),
|
||||
Some(&ConfigSettingValue::String("fast".to_string()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@ use uv_build_frontend::{SourceBuild, SourceBuildContext};
|
|||
use uv_cache::Cache;
|
||||
use uv_client::RegistryClient;
|
||||
use uv_configuration::{
|
||||
BuildKind, BuildOptions, ConfigSettings, Constraints, IndexStrategy, PreviewMode, Reinstall,
|
||||
SourceStrategy,
|
||||
BuildKind, BuildOptions, ConfigSettings, Constraints, IndexStrategy, PackageConfigSettings,
|
||||
PreviewMode, Reinstall, SourceStrategy,
|
||||
};
|
||||
use uv_configuration::{BuildOutput, Concurrency};
|
||||
use uv_distribution::DistributionDatabase;
|
||||
|
@ -91,6 +91,7 @@ pub struct BuildDispatch<'a> {
|
|||
link_mode: uv_install_wheel::LinkMode,
|
||||
build_options: &'a BuildOptions,
|
||||
config_settings: &'a ConfigSettings,
|
||||
config_settings_package: &'a PackageConfigSettings,
|
||||
hasher: &'a HashStrategy,
|
||||
exclude_newer: Option<ExcludeNewer>,
|
||||
source_build_context: SourceBuildContext,
|
||||
|
@ -113,6 +114,7 @@ impl<'a> BuildDispatch<'a> {
|
|||
shared_state: SharedState,
|
||||
index_strategy: IndexStrategy,
|
||||
config_settings: &'a ConfigSettings,
|
||||
config_settings_package: &'a PackageConfigSettings,
|
||||
build_isolation: BuildIsolation<'a>,
|
||||
link_mode: uv_install_wheel::LinkMode,
|
||||
build_options: &'a BuildOptions,
|
||||
|
@ -134,6 +136,7 @@ impl<'a> BuildDispatch<'a> {
|
|||
dependency_metadata,
|
||||
index_strategy,
|
||||
config_settings,
|
||||
config_settings_package,
|
||||
build_isolation,
|
||||
link_mode,
|
||||
build_options,
|
||||
|
@ -200,6 +203,10 @@ impl BuildContext for BuildDispatch<'_> {
|
|||
self.config_settings
|
||||
}
|
||||
|
||||
fn config_settings_package(&self) -> &PackageConfigSettings {
|
||||
self.config_settings_package
|
||||
}
|
||||
|
||||
fn sources(&self) -> SourceStrategy {
|
||||
self.sources
|
||||
}
|
||||
|
@ -295,6 +302,7 @@ impl BuildContext for BuildDispatch<'_> {
|
|||
self.hasher,
|
||||
self.index_locations,
|
||||
self.config_settings,
|
||||
self.config_settings_package,
|
||||
self.cache(),
|
||||
venv,
|
||||
tags,
|
||||
|
@ -418,6 +426,17 @@ impl BuildContext for BuildDispatch<'_> {
|
|||
build_stack.insert(dist.distribution_id());
|
||||
}
|
||||
|
||||
// Get package-specific config settings if available; otherwise, use global settings.
|
||||
let config_settings = if let Some(name) = dist_name {
|
||||
if let Some(package_settings) = self.config_settings_package.get(name) {
|
||||
package_settings.clone().merge(self.config_settings.clone())
|
||||
} else {
|
||||
self.config_settings.clone()
|
||||
}
|
||||
} else {
|
||||
self.config_settings.clone()
|
||||
};
|
||||
|
||||
let builder = SourceBuild::setup(
|
||||
source,
|
||||
subdirectory,
|
||||
|
@ -431,7 +450,7 @@ impl BuildContext for BuildDispatch<'_> {
|
|||
self.index_locations,
|
||||
sources,
|
||||
self.workspace_cache(),
|
||||
self.config_settings.clone(),
|
||||
config_settings,
|
||||
self.build_isolation,
|
||||
&build_stack,
|
||||
build_kind,
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use std::borrow::Cow;
|
||||
use uv_cache::{Cache, CacheBucket, CacheShard, WheelCache};
|
||||
use uv_cache_info::CacheInfo;
|
||||
use uv_cache_key::cache_digest;
|
||||
use uv_configuration::ConfigSettings;
|
||||
use uv_configuration::{ConfigSettings, PackageConfigSettings};
|
||||
use uv_distribution_types::{
|
||||
DirectUrlSourceDist, DirectorySourceDist, GitSourceDist, Hashed, PathSourceDist,
|
||||
};
|
||||
use uv_normalize::PackageName;
|
||||
use uv_platform_tags::Tags;
|
||||
use uv_types::HashStrategy;
|
||||
|
||||
|
@ -18,7 +20,8 @@ pub struct BuiltWheelIndex<'a> {
|
|||
cache: &'a Cache,
|
||||
tags: &'a Tags,
|
||||
hasher: &'a HashStrategy,
|
||||
build_configuration: &'a ConfigSettings,
|
||||
config_settings: &'a ConfigSettings,
|
||||
config_settings_package: &'a PackageConfigSettings,
|
||||
}
|
||||
|
||||
impl<'a> BuiltWheelIndex<'a> {
|
||||
|
@ -27,13 +30,15 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
cache: &'a Cache,
|
||||
tags: &'a Tags,
|
||||
hasher: &'a HashStrategy,
|
||||
build_configuration: &'a ConfigSettings,
|
||||
config_settings: &'a ConfigSettings,
|
||||
config_settings_package: &'a PackageConfigSettings,
|
||||
) -> Self {
|
||||
Self {
|
||||
cache,
|
||||
tags,
|
||||
hasher,
|
||||
build_configuration,
|
||||
config_settings,
|
||||
config_settings_package,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,10 +68,11 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
let cache_shard = cache_shard.shard(revision.id());
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let cache_shard = if self.build_configuration.is_empty() {
|
||||
let config_settings = self.config_settings_for(&source_dist.name);
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(self.build_configuration))
|
||||
cache_shard.shard(cache_digest(&config_settings))
|
||||
};
|
||||
|
||||
Ok(self.find(&cache_shard))
|
||||
|
@ -100,10 +106,11 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
let cache_shard = cache_shard.shard(revision.id());
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let cache_shard = if self.build_configuration.is_empty() {
|
||||
let config_settings = self.config_settings_for(&source_dist.name);
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(self.build_configuration))
|
||||
cache_shard.shard(cache_digest(&config_settings))
|
||||
};
|
||||
|
||||
Ok(self
|
||||
|
@ -148,10 +155,11 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
let cache_shard = cache_shard.shard(revision.id());
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let cache_shard = if self.build_configuration.is_empty() {
|
||||
let config_settings = self.config_settings_for(&source_dist.name);
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(self.build_configuration))
|
||||
cache_shard.shard(cache_digest(&config_settings))
|
||||
};
|
||||
|
||||
Ok(self
|
||||
|
@ -174,10 +182,11 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
);
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let cache_shard = if self.build_configuration.is_empty() {
|
||||
let config_settings = self.config_settings_for(&source_dist.name);
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(self.build_configuration))
|
||||
cache_shard.shard(cache_digest(&config_settings))
|
||||
};
|
||||
|
||||
self.find(&cache_shard)
|
||||
|
@ -239,4 +248,13 @@ impl<'a> BuiltWheelIndex<'a> {
|
|||
|
||||
candidate
|
||||
}
|
||||
|
||||
/// Determine the [`ConfigSettings`] for the given package name.
|
||||
fn config_settings_for(&self, name: &PackageName) -> Cow<'_, ConfigSettings> {
|
||||
if let Some(package_settings) = self.config_settings_package.get(name) {
|
||||
Cow::Owned(package_settings.clone().merge(self.config_settings.clone()))
|
||||
} else {
|
||||
Cow::Borrowed(self.config_settings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ use uv_cache_key::cache_digest;
|
|||
use uv_client::{
|
||||
CacheControl, CachedClientError, Connectivity, DataWithCachePolicy, RegistryClient,
|
||||
};
|
||||
use uv_configuration::{BuildKind, BuildOutput, SourceStrategy};
|
||||
use uv_configuration::{BuildKind, BuildOutput, ConfigSettings, SourceStrategy};
|
||||
use uv_distribution_filename::{SourceDistExtension, WheelFilename};
|
||||
use uv_distribution_types::{
|
||||
BuildableSource, DirectorySourceUrl, GitSourceUrl, HashPolicy, Hashed, PathSourceUrl,
|
||||
|
@ -373,6 +373,23 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
Ok(metadata)
|
||||
}
|
||||
|
||||
/// Determine the [`ConfigSettings`] for the given package name.
|
||||
fn config_settings_for(&self, name: Option<&PackageName>) -> Cow<'_, ConfigSettings> {
|
||||
if let Some(name) = name {
|
||||
if let Some(package_settings) = self.build_context.config_settings_package().get(name) {
|
||||
Cow::Owned(
|
||||
package_settings
|
||||
.clone()
|
||||
.merge(self.build_context.config_settings().clone()),
|
||||
)
|
||||
} else {
|
||||
Cow::Borrowed(self.build_context.config_settings())
|
||||
}
|
||||
} else {
|
||||
Cow::Borrowed(self.build_context.config_settings())
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a source distribution from a remote URL.
|
||||
async fn url<'data>(
|
||||
&self,
|
||||
|
@ -407,11 +424,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
let source_dist_entry = cache_shard.entry(SOURCE);
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let config_settings = self.build_context.config_settings();
|
||||
let config_settings = self.config_settings_for(source.name());
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(config_settings))
|
||||
cache_shard.shard(cache_digest(&&config_settings))
|
||||
};
|
||||
|
||||
// If the cache contains a compatible wheel, return it.
|
||||
|
@ -580,11 +597,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
}
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let config_settings = self.build_context.config_settings();
|
||||
let config_settings = self.config_settings_for(source.name());
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(config_settings))
|
||||
cache_shard.shard(cache_digest(&config_settings))
|
||||
};
|
||||
|
||||
// Otherwise, we either need to build the metadata.
|
||||
|
@ -779,11 +796,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
let source_entry = cache_shard.entry(SOURCE);
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let config_settings = self.build_context.config_settings();
|
||||
let config_settings = self.config_settings_for(source.name());
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(config_settings))
|
||||
cache_shard.shard(cache_digest(&config_settings))
|
||||
};
|
||||
|
||||
// If the cache contains a compatible wheel, return it.
|
||||
|
@ -941,11 +958,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
}
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let config_settings = self.build_context.config_settings();
|
||||
let config_settings = self.config_settings_for(source.name());
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(config_settings))
|
||||
cache_shard.shard(cache_digest(&config_settings))
|
||||
};
|
||||
|
||||
// Otherwise, we need to build a wheel.
|
||||
|
@ -1083,11 +1100,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
let cache_shard = cache_shard.shard(revision.id());
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let config_settings = self.build_context.config_settings();
|
||||
let config_settings = self.config_settings_for(source.name());
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(config_settings))
|
||||
cache_shard.shard(cache_digest(&config_settings))
|
||||
};
|
||||
|
||||
// If the cache contains a compatible wheel, return it.
|
||||
|
@ -1271,11 +1288,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
}
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let config_settings = self.build_context.config_settings();
|
||||
let config_settings = self.config_settings_for(source.name());
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(config_settings))
|
||||
cache_shard.shard(cache_digest(&config_settings))
|
||||
};
|
||||
|
||||
// Otherwise, we need to build a wheel.
|
||||
|
@ -1476,11 +1493,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
let _lock = cache_shard.lock().await.map_err(Error::CacheWrite)?;
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let config_settings = self.build_context.config_settings();
|
||||
let config_settings = self.config_settings_for(source.name());
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(config_settings))
|
||||
cache_shard.shard(cache_digest(&config_settings))
|
||||
};
|
||||
|
||||
// If the cache contains a compatible wheel, return it.
|
||||
|
@ -1779,11 +1796,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
}
|
||||
|
||||
// If there are build settings, we need to scope to a cache shard.
|
||||
let config_settings = self.build_context.config_settings();
|
||||
let config_settings = self.config_settings_for(source.name());
|
||||
let cache_shard = if config_settings.is_empty() {
|
||||
cache_shard
|
||||
} else {
|
||||
cache_shard.shard(cache_digest(config_settings))
|
||||
cache_shard.shard(cache_digest(&config_settings))
|
||||
};
|
||||
|
||||
// Otherwise, we need to build a wheel.
|
||||
|
|
|
@ -4,7 +4,7 @@ use tracing::{debug, warn};
|
|||
|
||||
use uv_cache::{Cache, CacheBucket, WheelCache};
|
||||
use uv_cache_info::Timestamp;
|
||||
use uv_configuration::{BuildOptions, ConfigSettings, Reinstall};
|
||||
use uv_configuration::{BuildOptions, ConfigSettings, PackageConfigSettings, Reinstall};
|
||||
use uv_distribution::{
|
||||
BuiltWheelIndex, HttpArchivePointer, LocalArchivePointer, RegistryWheelIndex,
|
||||
};
|
||||
|
@ -52,6 +52,7 @@ impl<'a> Planner<'a> {
|
|||
hasher: &HashStrategy,
|
||||
index_locations: &IndexLocations,
|
||||
config_settings: &ConfigSettings,
|
||||
config_settings_package: &PackageConfigSettings,
|
||||
cache: &Cache,
|
||||
venv: &PythonEnvironment,
|
||||
tags: &Tags,
|
||||
|
@ -59,7 +60,13 @@ impl<'a> Planner<'a> {
|
|||
// Index all the already-downloaded wheels in the cache.
|
||||
let mut registry_index =
|
||||
RegistryWheelIndex::new(cache, tags, index_locations, hasher, config_settings);
|
||||
let built_index = BuiltWheelIndex::new(cache, tags, hasher, config_settings);
|
||||
let built_index = BuiltWheelIndex::new(
|
||||
cache,
|
||||
tags,
|
||||
hasher,
|
||||
config_settings,
|
||||
config_settings_package,
|
||||
);
|
||||
|
||||
let mut cached = vec![];
|
||||
let mut remote = vec![];
|
||||
|
|
|
@ -4,8 +4,8 @@ use std::path::PathBuf;
|
|||
use url::Url;
|
||||
|
||||
use uv_configuration::{
|
||||
ConfigSettings, ExportFormat, IndexStrategy, KeyringProviderType, RequiredVersion,
|
||||
TargetTriple, TrustedPublishing,
|
||||
ConfigSettings, ExportFormat, IndexStrategy, KeyringProviderType, PackageConfigSettings,
|
||||
RequiredVersion, TargetTriple, TrustedPublishing,
|
||||
};
|
||||
use uv_distribution_types::{Index, IndexUrl, PipExtraIndex, PipFindLinks, PipIndex};
|
||||
use uv_install_wheel::LinkMode;
|
||||
|
@ -131,6 +131,17 @@ impl Combine for Option<ConfigSettings> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Combine for Option<PackageConfigSettings> {
|
||||
/// Combine two maps by merging the map in `self` with the map in `other`, if they're both
|
||||
/// `Some`.
|
||||
fn combine(self, other: Option<PackageConfigSettings>) -> Option<PackageConfigSettings> {
|
||||
match (self, other) {
|
||||
(Some(a), Some(b)) => Some(a.merge(b)),
|
||||
(a, b) => a.or(b),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Combine for serde::de::IgnoredAny {
|
||||
fn combine(self, _other: Self) -> Self {
|
||||
self
|
||||
|
|
|
@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use uv_cache_info::CacheKey;
|
||||
use uv_configuration::{
|
||||
ConfigSettings, IndexStrategy, KeyringProviderType, PackageNameSpecifier, RequiredVersion,
|
||||
TargetTriple, TrustedHost, TrustedPublishing,
|
||||
ConfigSettings, IndexStrategy, KeyringProviderType, PackageConfigSettings,
|
||||
PackageNameSpecifier, RequiredVersion, TargetTriple, TrustedHost, TrustedPublishing,
|
||||
};
|
||||
use uv_distribution_types::{
|
||||
Index, IndexUrl, IndexUrlError, PipExtraIndex, PipFindLinks, PipIndex, StaticMetadata,
|
||||
|
@ -361,6 +361,7 @@ pub struct ResolverOptions {
|
|||
pub fork_strategy: Option<ForkStrategy>,
|
||||
pub dependency_metadata: Option<Vec<StaticMetadata>>,
|
||||
pub config_settings: Option<ConfigSettings>,
|
||||
pub config_settings_package: Option<PackageConfigSettings>,
|
||||
pub exclude_newer: Option<ExcludeNewer>,
|
||||
pub link_mode: Option<LinkMode>,
|
||||
pub upgrade: Option<bool>,
|
||||
|
@ -587,6 +588,18 @@ pub struct ResolverInstallerOptions {
|
|||
"#
|
||||
)]
|
||||
pub config_settings: Option<ConfigSettings>,
|
||||
/// Settings to pass to the [PEP 517](https://peps.python.org/pep-0517/) build backend for specific packages,
|
||||
/// specified as `KEY=VALUE` pairs.
|
||||
///
|
||||
/// Accepts a map from package names to string key-value pairs.
|
||||
#[option(
|
||||
default = "{}",
|
||||
value_type = "dict",
|
||||
example = r#"
|
||||
config-settings-package = { numpy = { editable_mode = "compat" } }
|
||||
"#
|
||||
)]
|
||||
pub config_settings_package: Option<PackageConfigSettings>,
|
||||
/// Disable isolation when building source distributions.
|
||||
///
|
||||
/// Assumes that build dependencies specified by [PEP 518](https://peps.python.org/pep-0518/)
|
||||
|
@ -1333,6 +1346,16 @@ pub struct PipOptions {
|
|||
"#
|
||||
)]
|
||||
pub config_settings: Option<ConfigSettings>,
|
||||
/// Settings to pass to the [PEP 517](https://peps.python.org/pep-0517/) build backend for specific packages,
|
||||
/// specified as `KEY=VALUE` pairs.
|
||||
#[option(
|
||||
default = "{}",
|
||||
value_type = "dict",
|
||||
example = r#"
|
||||
config-settings-package = { numpy = { editable_mode = "compat" } }
|
||||
"#
|
||||
)]
|
||||
pub config_settings_package: Option<PackageConfigSettings>,
|
||||
/// The minimum Python version that should be supported by the resolved requirements (e.g.,
|
||||
/// `3.8` or `3.8.17`).
|
||||
///
|
||||
|
@ -1651,6 +1674,7 @@ impl From<ResolverInstallerOptions> for ResolverOptions {
|
|||
fork_strategy: value.fork_strategy,
|
||||
dependency_metadata: value.dependency_metadata,
|
||||
config_settings: value.config_settings,
|
||||
config_settings_package: value.config_settings_package,
|
||||
exclude_newer: value.exclude_newer,
|
||||
link_mode: value.link_mode,
|
||||
upgrade: value.upgrade,
|
||||
|
@ -1714,6 +1738,7 @@ pub struct ToolOptions {
|
|||
pub fork_strategy: Option<ForkStrategy>,
|
||||
pub dependency_metadata: Option<Vec<StaticMetadata>>,
|
||||
pub config_settings: Option<ConfigSettings>,
|
||||
pub config_settings_package: Option<PackageConfigSettings>,
|
||||
pub no_build_isolation: Option<bool>,
|
||||
pub no_build_isolation_package: Option<Vec<PackageName>>,
|
||||
pub exclude_newer: Option<ExcludeNewer>,
|
||||
|
@ -1741,6 +1766,7 @@ impl From<ResolverInstallerOptions> for ToolOptions {
|
|||
fork_strategy: value.fork_strategy,
|
||||
dependency_metadata: value.dependency_metadata,
|
||||
config_settings: value.config_settings,
|
||||
config_settings_package: value.config_settings_package,
|
||||
no_build_isolation: value.no_build_isolation,
|
||||
no_build_isolation_package: value.no_build_isolation_package,
|
||||
exclude_newer: value.exclude_newer,
|
||||
|
@ -1770,6 +1796,7 @@ impl From<ToolOptions> for ResolverInstallerOptions {
|
|||
fork_strategy: value.fork_strategy,
|
||||
dependency_metadata: value.dependency_metadata,
|
||||
config_settings: value.config_settings,
|
||||
config_settings_package: value.config_settings_package,
|
||||
no_build_isolation: value.no_build_isolation,
|
||||
no_build_isolation_package: value.no_build_isolation_package,
|
||||
exclude_newer: value.exclude_newer,
|
||||
|
@ -1822,6 +1849,7 @@ pub struct OptionsWire {
|
|||
fork_strategy: Option<ForkStrategy>,
|
||||
dependency_metadata: Option<Vec<StaticMetadata>>,
|
||||
config_settings: Option<ConfigSettings>,
|
||||
config_settings_package: Option<PackageConfigSettings>,
|
||||
no_build_isolation: Option<bool>,
|
||||
no_build_isolation_package: Option<Vec<PackageName>>,
|
||||
exclude_newer: Option<ExcludeNewer>,
|
||||
|
@ -1911,6 +1939,7 @@ impl From<OptionsWire> for Options {
|
|||
fork_strategy,
|
||||
dependency_metadata,
|
||||
config_settings,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
exclude_newer,
|
||||
|
@ -1977,6 +2006,7 @@ impl From<OptionsWire> for Options {
|
|||
fork_strategy,
|
||||
dependency_metadata,
|
||||
config_settings,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
exclude_newer,
|
||||
|
|
|
@ -7,7 +7,9 @@ use anyhow::Result;
|
|||
use rustc_hash::FxHashSet;
|
||||
|
||||
use uv_cache::Cache;
|
||||
use uv_configuration::{BuildKind, BuildOptions, BuildOutput, ConfigSettings, SourceStrategy};
|
||||
use uv_configuration::{
|
||||
BuildKind, BuildOptions, BuildOutput, ConfigSettings, PackageConfigSettings, SourceStrategy,
|
||||
};
|
||||
use uv_distribution_filename::DistFilename;
|
||||
use uv_distribution_types::{
|
||||
CachedDist, DependencyMetadata, DistributionId, IndexCapabilities, IndexLocations,
|
||||
|
@ -87,6 +89,9 @@ pub trait BuildContext {
|
|||
/// The [`ConfigSettings`] used to build distributions.
|
||||
fn config_settings(&self) -> &ConfigSettings;
|
||||
|
||||
/// The [`ConfigSettings`] used to build a specific package.
|
||||
fn config_settings_package(&self) -> &PackageConfigSettings;
|
||||
|
||||
/// Whether to incorporate `tool.uv.sources` when resolving requirements.
|
||||
fn sources(&self) -> SourceStrategy;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder};
|
|||
use uv_configuration::{
|
||||
BuildKind, BuildOptions, BuildOutput, Concurrency, ConfigSettings, Constraints,
|
||||
DependencyGroupsWithDefaults, HashCheckingMode, IndexStrategy, KeyringProviderType,
|
||||
PreviewMode, SourceStrategy,
|
||||
PackageConfigSettings, PreviewMode, SourceStrategy,
|
||||
};
|
||||
use uv_dispatch::{BuildDispatch, SharedState};
|
||||
use uv_distribution_filename::{
|
||||
|
@ -197,6 +197,7 @@ async fn build_impl(
|
|||
fork_strategy: _,
|
||||
dependency_metadata,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
exclude_newer,
|
||||
|
@ -357,6 +358,7 @@ async fn build_impl(
|
|||
dependency_metadata,
|
||||
*link_mode,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
preview,
|
||||
);
|
||||
async {
|
||||
|
@ -434,6 +436,7 @@ async fn build_package(
|
|||
dependency_metadata: &DependencyMetadata,
|
||||
link_mode: LinkMode,
|
||||
config_setting: &ConfigSettings,
|
||||
config_settings_package: &PackageConfigSettings,
|
||||
preview: PreviewMode,
|
||||
) -> Result<Vec<BuildMessage>, Error> {
|
||||
let output_dir = if let Some(output_dir) = output_dir {
|
||||
|
@ -568,6 +571,7 @@ async fn build_package(
|
|||
state.clone(),
|
||||
index_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
build_isolation,
|
||||
link_mode,
|
||||
build_options,
|
||||
|
|
|
@ -14,7 +14,8 @@ use uv_cache::Cache;
|
|||
use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder};
|
||||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, Constraints, ExportFormat, ExtrasSpecification,
|
||||
IndexStrategy, NoBinary, NoBuild, PreviewMode, Reinstall, SourceStrategy, Upgrade,
|
||||
IndexStrategy, NoBinary, NoBuild, PackageConfigSettings, PreviewMode, Reinstall,
|
||||
SourceStrategy, Upgrade,
|
||||
};
|
||||
use uv_configuration::{KeyringProviderType, TargetTriple};
|
||||
use uv_dispatch::{BuildDispatch, SharedState};
|
||||
|
@ -90,6 +91,7 @@ pub(crate) async fn pip_compile(
|
|||
keyring_provider: KeyringProviderType,
|
||||
network_settings: &NetworkSettings,
|
||||
config_settings: ConfigSettings,
|
||||
config_settings_package: PackageConfigSettings,
|
||||
no_build_isolation: bool,
|
||||
no_build_isolation_package: Vec<PackageName>,
|
||||
build_options: BuildOptions,
|
||||
|
@ -477,6 +479,7 @@ pub(crate) async fn pip_compile(
|
|||
state,
|
||||
index_strategy,
|
||||
&config_settings,
|
||||
&config_settings_package,
|
||||
build_isolation,
|
||||
link_mode,
|
||||
&build_options,
|
||||
|
|
|
@ -11,7 +11,8 @@ use uv_cache::Cache;
|
|||
use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder};
|
||||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, Constraints, DryRun, ExtrasSpecification,
|
||||
HashCheckingMode, IndexStrategy, PreviewMode, Reinstall, SourceStrategy, Upgrade,
|
||||
HashCheckingMode, IndexStrategy, PackageConfigSettings, PreviewMode, Reinstall, SourceStrategy,
|
||||
Upgrade,
|
||||
};
|
||||
use uv_configuration::{KeyringProviderType, TargetTriple};
|
||||
use uv_dispatch::{BuildDispatch, SharedState};
|
||||
|
@ -75,6 +76,7 @@ pub(crate) async fn pip_install(
|
|||
hash_checking: Option<HashCheckingMode>,
|
||||
installer_metadata: bool,
|
||||
config_settings: &ConfigSettings,
|
||||
config_settings_package: &PackageConfigSettings,
|
||||
no_build_isolation: bool,
|
||||
no_build_isolation_package: Vec<PackageName>,
|
||||
build_options: BuildOptions,
|
||||
|
@ -422,6 +424,7 @@ pub(crate) async fn pip_install(
|
|||
state.clone(),
|
||||
index_strategy,
|
||||
config_settings,
|
||||
config_settings_package,
|
||||
build_isolation,
|
||||
link_mode,
|
||||
&build_options,
|
||||
|
@ -513,6 +516,7 @@ pub(crate) async fn pip_install(
|
|||
compile,
|
||||
&index_locations,
|
||||
config_settings,
|
||||
config_settings_package,
|
||||
&hasher,
|
||||
&tags,
|
||||
&client,
|
||||
|
|
|
@ -13,7 +13,7 @@ use uv_cache::Cache;
|
|||
use uv_client::{BaseClientBuilder, RegistryClient};
|
||||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, Constraints, DependencyGroups, DryRun,
|
||||
ExtrasSpecification, Overrides, Reinstall, Upgrade,
|
||||
ExtrasSpecification, Overrides, PackageConfigSettings, Reinstall, Upgrade,
|
||||
};
|
||||
use uv_dispatch::BuildDispatch;
|
||||
use uv_distribution::{DistributionDatabase, SourcedDependencyGroups};
|
||||
|
@ -445,6 +445,7 @@ pub(crate) async fn install(
|
|||
compile: bool,
|
||||
index_urls: &IndexLocations,
|
||||
config_settings: &ConfigSettings,
|
||||
config_settings_package: &PackageConfigSettings,
|
||||
hasher: &HashStrategy,
|
||||
tags: &Tags,
|
||||
client: &RegistryClient,
|
||||
|
@ -470,6 +471,7 @@ pub(crate) async fn install(
|
|||
hasher,
|
||||
index_urls,
|
||||
config_settings,
|
||||
config_settings_package,
|
||||
cache,
|
||||
venv,
|
||||
tags,
|
||||
|
|
|
@ -9,7 +9,8 @@ use uv_cache::Cache;
|
|||
use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder};
|
||||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, Constraints, DryRun, ExtrasSpecification,
|
||||
HashCheckingMode, IndexStrategy, PreviewMode, Reinstall, SourceStrategy, Upgrade,
|
||||
HashCheckingMode, IndexStrategy, PackageConfigSettings, PreviewMode, Reinstall, SourceStrategy,
|
||||
Upgrade,
|
||||
};
|
||||
use uv_configuration::{KeyringProviderType, TargetTriple};
|
||||
use uv_dispatch::{BuildDispatch, SharedState};
|
||||
|
@ -60,6 +61,7 @@ pub(crate) async fn pip_sync(
|
|||
allow_empty_requirements: bool,
|
||||
installer_metadata: bool,
|
||||
config_settings: &ConfigSettings,
|
||||
config_settings_package: &PackageConfigSettings,
|
||||
no_build_isolation: bool,
|
||||
no_build_isolation_package: Vec<PackageName>,
|
||||
build_options: BuildOptions,
|
||||
|
@ -355,6 +357,7 @@ pub(crate) async fn pip_sync(
|
|||
state.clone(),
|
||||
index_strategy,
|
||||
config_settings,
|
||||
config_settings_package,
|
||||
build_isolation,
|
||||
link_mode,
|
||||
&build_options,
|
||||
|
@ -448,6 +451,7 @@ pub(crate) async fn pip_sync(
|
|||
compile,
|
||||
&index_locations,
|
||||
config_settings,
|
||||
config_settings_package,
|
||||
&hasher,
|
||||
&tags,
|
||||
&client,
|
||||
|
|
|
@ -436,6 +436,7 @@ pub(crate) async fn add(
|
|||
state.clone().into_inner(),
|
||||
settings.resolver.index_strategy,
|
||||
&settings.resolver.config_setting,
|
||||
&settings.resolver.config_settings_package,
|
||||
build_isolation,
|
||||
settings.resolver.link_mode,
|
||||
&settings.resolver.build_options,
|
||||
|
|
|
@ -432,6 +432,7 @@ async fn do_lock(
|
|||
fork_strategy,
|
||||
dependency_metadata,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
exclude_newer,
|
||||
|
@ -674,6 +675,7 @@ async fn do_lock(
|
|||
state.fork().into_inner(),
|
||||
*index_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
build_isolation,
|
||||
*link_mode,
|
||||
build_options,
|
||||
|
|
|
@ -1674,6 +1674,7 @@ pub(crate) async fn resolve_names(
|
|||
ResolverSettings {
|
||||
build_options,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
dependency_metadata,
|
||||
exclude_newer,
|
||||
fork_strategy: _,
|
||||
|
@ -1742,6 +1743,7 @@ pub(crate) async fn resolve_names(
|
|||
state.clone(),
|
||||
*index_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
build_isolation,
|
||||
*link_mode,
|
||||
build_options,
|
||||
|
@ -1832,6 +1834,7 @@ pub(crate) async fn resolve_environment(
|
|||
fork_strategy,
|
||||
dependency_metadata,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
exclude_newer,
|
||||
|
@ -1948,6 +1951,7 @@ pub(crate) async fn resolve_environment(
|
|||
state.clone().into_inner(),
|
||||
*index_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
build_isolation,
|
||||
*link_mode,
|
||||
build_options,
|
||||
|
@ -2013,6 +2017,7 @@ pub(crate) async fn sync_environment(
|
|||
keyring_provider,
|
||||
dependency_metadata,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
exclude_newer,
|
||||
|
@ -2084,6 +2089,7 @@ pub(crate) async fn sync_environment(
|
|||
state.clone().into_inner(),
|
||||
index_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
build_isolation,
|
||||
link_mode,
|
||||
build_options,
|
||||
|
@ -2106,6 +2112,7 @@ pub(crate) async fn sync_environment(
|
|||
compile_bytecode,
|
||||
index_locations,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
&hasher,
|
||||
tags,
|
||||
&client,
|
||||
|
@ -2169,6 +2176,7 @@ pub(crate) async fn update_environment(
|
|||
ResolverSettings {
|
||||
build_options,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
dependency_metadata,
|
||||
exclude_newer,
|
||||
fork_strategy,
|
||||
|
@ -2305,6 +2313,7 @@ pub(crate) async fn update_environment(
|
|||
state.clone(),
|
||||
*index_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
build_isolation,
|
||||
*link_mode,
|
||||
build_options,
|
||||
|
@ -2362,6 +2371,7 @@ pub(crate) async fn update_environment(
|
|||
*compile_bytecode,
|
||||
index_locations,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
&hasher,
|
||||
tags,
|
||||
&client,
|
||||
|
|
|
@ -573,6 +573,7 @@ pub(super) async fn do_sync(
|
|||
keyring_provider,
|
||||
dependency_metadata,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
exclude_newer,
|
||||
|
@ -709,6 +710,7 @@ pub(super) async fn do_sync(
|
|||
state.clone().into_inner(),
|
||||
index_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
build_isolation,
|
||||
link_mode,
|
||||
build_options,
|
||||
|
@ -733,6 +735,7 @@ pub(super) async fn do_sync(
|
|||
compile_bytecode,
|
||||
index_locations,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
&hasher,
|
||||
&tags,
|
||||
&client,
|
||||
|
|
|
@ -200,6 +200,7 @@ pub(crate) async fn tree(
|
|||
fork_strategy: _,
|
||||
dependency_metadata: _,
|
||||
config_setting: _,
|
||||
config_settings_package: _,
|
||||
no_build_isolation: _,
|
||||
no_build_isolation_package: _,
|
||||
exclude_newer: _,
|
||||
|
|
|
@ -12,7 +12,7 @@ use uv_cache::Cache;
|
|||
use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder};
|
||||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, Constraints, DependencyGroups, IndexStrategy,
|
||||
KeyringProviderType, NoBinary, NoBuild, PreviewMode, SourceStrategy,
|
||||
KeyringProviderType, NoBinary, NoBuild, PackageConfigSettings, PreviewMode, SourceStrategy,
|
||||
};
|
||||
use uv_dispatch::{BuildDispatch, SharedState};
|
||||
use uv_distribution_types::Requirement;
|
||||
|
@ -269,6 +269,7 @@ pub(crate) async fn venv(
|
|||
let build_constraints = Constraints::default();
|
||||
let build_hasher = HashStrategy::default();
|
||||
let config_settings = ConfigSettings::default();
|
||||
let config_settings_package = PackageConfigSettings::default();
|
||||
let sources = SourceStrategy::Disabled;
|
||||
|
||||
// Do not allow builds
|
||||
|
@ -286,6 +287,7 @@ pub(crate) async fn venv(
|
|||
state.clone(),
|
||||
index_strategy,
|
||||
&config_settings,
|
||||
&config_settings_package,
|
||||
BuildIsolation::Isolated,
|
||||
link_mode,
|
||||
&build_options,
|
||||
|
|
|
@ -524,6 +524,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
|||
args.settings.keyring_provider,
|
||||
&globals.network_settings,
|
||||
args.settings.config_setting,
|
||||
args.settings.config_settings_package,
|
||||
args.settings.no_build_isolation,
|
||||
args.settings.no_build_isolation_package,
|
||||
args.settings.build_options,
|
||||
|
@ -594,6 +595,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
|||
args.settings.allow_empty_requirements,
|
||||
globals.installer_metadata,
|
||||
&args.settings.config_setting,
|
||||
&args.settings.config_settings_package,
|
||||
args.settings.no_build_isolation,
|
||||
args.settings.no_build_isolation_package,
|
||||
args.settings.build_options,
|
||||
|
@ -745,6 +747,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
|||
args.settings.hash_checking,
|
||||
globals.installer_metadata,
|
||||
&args.settings.config_setting,
|
||||
&args.settings.config_settings_package,
|
||||
args.settings.no_build_isolation,
|
||||
args.settings.no_build_isolation_package,
|
||||
args.settings.build_options,
|
||||
|
|
|
@ -23,9 +23,9 @@ use uv_client::Connectivity;
|
|||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, DependencyGroups, DryRun, EditableMode,
|
||||
ExportFormat, ExtrasSpecification, HashCheckingMode, IndexStrategy, InstallOptions,
|
||||
KeyringProviderType, NoBinary, NoBuild, PreviewMode, ProjectBuildBackend, Reinstall,
|
||||
RequiredVersion, SourceStrategy, TargetTriple, TrustedHost, TrustedPublishing, Upgrade,
|
||||
VersionControlSystem,
|
||||
KeyringProviderType, NoBinary, NoBuild, PackageConfigSettings, PreviewMode,
|
||||
ProjectBuildBackend, Reinstall, RequiredVersion, SourceStrategy, TargetTriple, TrustedHost,
|
||||
TrustedPublishing, Upgrade, VersionControlSystem,
|
||||
};
|
||||
use uv_distribution_types::{DependencyMetadata, Index, IndexLocations, IndexUrl, Requirement};
|
||||
use uv_install_wheel::LinkMode;
|
||||
|
@ -712,6 +712,7 @@ impl ToolUpgradeSettings {
|
|||
pre,
|
||||
fork_strategy,
|
||||
config_setting,
|
||||
config_setting_package: config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
build_isolation,
|
||||
|
@ -746,6 +747,7 @@ impl ToolUpgradeSettings {
|
|||
pre,
|
||||
fork_strategy,
|
||||
config_setting,
|
||||
config_settings_package,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
build_isolation,
|
||||
|
@ -2694,6 +2696,7 @@ pub(crate) struct InstallerSettingsRef<'a> {
|
|||
pub(crate) keyring_provider: KeyringProviderType,
|
||||
pub(crate) dependency_metadata: &'a DependencyMetadata,
|
||||
pub(crate) config_setting: &'a ConfigSettings,
|
||||
pub(crate) config_settings_package: &'a PackageConfigSettings,
|
||||
pub(crate) no_build_isolation: bool,
|
||||
pub(crate) no_build_isolation_package: &'a [PackageName],
|
||||
pub(crate) exclude_newer: Option<ExcludeNewer>,
|
||||
|
@ -2712,6 +2715,7 @@ pub(crate) struct InstallerSettingsRef<'a> {
|
|||
pub(crate) struct ResolverSettings {
|
||||
pub(crate) build_options: BuildOptions,
|
||||
pub(crate) config_setting: ConfigSettings,
|
||||
pub(crate) config_settings_package: PackageConfigSettings,
|
||||
pub(crate) dependency_metadata: DependencyMetadata,
|
||||
pub(crate) exclude_newer: Option<ExcludeNewer>,
|
||||
pub(crate) fork_strategy: ForkStrategy,
|
||||
|
@ -2770,6 +2774,7 @@ impl From<ResolverOptions> for ResolverSettings {
|
|||
index_strategy: value.index_strategy.unwrap_or_default(),
|
||||
keyring_provider: value.keyring_provider.unwrap_or_default(),
|
||||
config_setting: value.config_settings.unwrap_or_default(),
|
||||
config_settings_package: value.config_settings_package.unwrap_or_default(),
|
||||
no_build_isolation: value.no_build_isolation.unwrap_or_default(),
|
||||
no_build_isolation_package: value.no_build_isolation_package.unwrap_or_default(),
|
||||
exclude_newer: value.exclude_newer,
|
||||
|
@ -2849,6 +2854,7 @@ impl From<ResolverInstallerOptions> for ResolverInstallerSettings {
|
|||
NoBuild::from_args(value.no_build, value.no_build_package.unwrap_or_default()),
|
||||
),
|
||||
config_setting: value.config_settings.unwrap_or_default(),
|
||||
config_settings_package: value.config_settings_package.unwrap_or_default(),
|
||||
dependency_metadata: DependencyMetadata::from_entries(
|
||||
value.dependency_metadata.into_iter().flatten(),
|
||||
),
|
||||
|
@ -2918,6 +2924,7 @@ pub(crate) struct PipSettings {
|
|||
pub(crate) custom_compile_command: Option<String>,
|
||||
pub(crate) generate_hashes: bool,
|
||||
pub(crate) config_setting: ConfigSettings,
|
||||
pub(crate) config_settings_package: PackageConfigSettings,
|
||||
pub(crate) python_version: Option<PythonVersion>,
|
||||
pub(crate) python_platform: Option<TargetTriple>,
|
||||
pub(crate) universal: bool,
|
||||
|
@ -2987,6 +2994,7 @@ impl PipSettings {
|
|||
custom_compile_command,
|
||||
generate_hashes,
|
||||
config_settings,
|
||||
config_settings_package,
|
||||
python_version,
|
||||
python_platform,
|
||||
universal,
|
||||
|
@ -3022,6 +3030,7 @@ impl PipSettings {
|
|||
fork_strategy: top_level_fork_strategy,
|
||||
dependency_metadata: top_level_dependency_metadata,
|
||||
config_settings: top_level_config_settings,
|
||||
config_settings_package: top_level_config_settings_package,
|
||||
no_build_isolation: top_level_no_build_isolation,
|
||||
no_build_isolation_package: top_level_no_build_isolation_package,
|
||||
exclude_newer: top_level_exclude_newer,
|
||||
|
@ -3054,6 +3063,8 @@ impl PipSettings {
|
|||
let fork_strategy = fork_strategy.combine(top_level_fork_strategy);
|
||||
let dependency_metadata = dependency_metadata.combine(top_level_dependency_metadata);
|
||||
let config_settings = config_settings.combine(top_level_config_settings);
|
||||
let config_settings_package =
|
||||
config_settings_package.combine(top_level_config_settings_package);
|
||||
let no_build_isolation = no_build_isolation.combine(top_level_no_build_isolation);
|
||||
let no_build_isolation_package =
|
||||
no_build_isolation_package.combine(top_level_no_build_isolation_package);
|
||||
|
@ -3156,6 +3167,10 @@ impl PipSettings {
|
|||
.config_settings
|
||||
.combine(config_settings)
|
||||
.unwrap_or_default(),
|
||||
config_settings_package: args
|
||||
.config_settings_package
|
||||
.combine(config_settings_package)
|
||||
.unwrap_or_default(),
|
||||
torch_backend: args.torch_backend.combine(torch_backend),
|
||||
python_version: args.python_version.combine(python_version),
|
||||
python_platform: args.python_platform.combine(python_platform),
|
||||
|
@ -3249,6 +3264,7 @@ impl<'a> From<&'a ResolverInstallerSettings> for InstallerSettingsRef<'a> {
|
|||
keyring_provider: settings.resolver.keyring_provider,
|
||||
dependency_metadata: &settings.resolver.dependency_metadata,
|
||||
config_setting: &settings.resolver.config_setting,
|
||||
config_settings_package: &settings.resolver.config_settings_package,
|
||||
no_build_isolation: settings.resolver.no_build_isolation,
|
||||
no_build_isolation_package: &settings.resolver.no_build_isolation_package,
|
||||
exclude_newer: settings.resolver.exclude_newer,
|
||||
|
|
|
@ -4054,13 +4054,13 @@ fn config_settings_path() -> Result<()> {
|
|||
"###
|
||||
);
|
||||
|
||||
// When installed without `--editable_mode=compat`, the `finder.py` file should be present.
|
||||
// When installed without `editable_mode=compat`, the `finder.py` file should be present.
|
||||
let finder = context
|
||||
.site_packages()
|
||||
.join("__editable___setuptools_editable_0_1_0_finder.py");
|
||||
assert!(finder.exists());
|
||||
|
||||
// Reinstalling with `--editable_mode=compat` should be a no-op; changes in build configuration
|
||||
// Reinstalling with `editable_mode=compat` should be a no-op; changes in build configuration
|
||||
// don't invalidate the environment.
|
||||
uv_snapshot!(context.filters(), context.pip_install()
|
||||
.arg("-r")
|
||||
|
@ -4089,7 +4089,7 @@ fn config_settings_path() -> Result<()> {
|
|||
- setuptools-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/setuptools_editable)
|
||||
"###);
|
||||
|
||||
// Install the editable package with `--editable_mode=compat`. We should ignore the cached
|
||||
// Install the editable package with `editable_mode=compat`. We should ignore the cached
|
||||
// build configuration and rebuild.
|
||||
uv_snapshot!(context.filters(), context.pip_install()
|
||||
.arg("-r")
|
||||
|
@ -4109,7 +4109,7 @@ fn config_settings_path() -> Result<()> {
|
|||
"###
|
||||
);
|
||||
|
||||
// When installed without `--editable_mode=compat`, the `finder.py` file should _not_ be present.
|
||||
// When installed without `editable_mode=compat`, the `finder.py` file should _not_ be present.
|
||||
let finder = context
|
||||
.site_packages()
|
||||
.join("__editable___setuptools_editable_0_1_0_finder.py");
|
||||
|
@ -11739,3 +11739,114 @@ fn install_python_preference() {
|
|||
Audited 1 package in [TIME]
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_settings_package() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let requirements_txt = context.temp_dir.child("requirements.txt");
|
||||
requirements_txt.write_str(&format!(
|
||||
"-e {}",
|
||||
context
|
||||
.workspace_root
|
||||
.join("scripts/packages/setuptools_editable")
|
||||
.display()
|
||||
))?;
|
||||
|
||||
// Install the editable package.
|
||||
uv_snapshot!(context.filters(), context.pip_install()
|
||||
.arg("-r")
|
||||
.arg("requirements.txt"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 2 packages in [TIME]
|
||||
Prepared 2 packages in [TIME]
|
||||
Installed 2 packages in [TIME]
|
||||
+ iniconfig==2.0.0
|
||||
+ setuptools-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/setuptools_editable)
|
||||
"###
|
||||
);
|
||||
|
||||
// When installed without `editable_mode=compat`, the `finder.py` file should be present.
|
||||
let finder = context
|
||||
.site_packages()
|
||||
.join("__editable___setuptools_editable_0_1_0_finder.py");
|
||||
assert!(finder.exists());
|
||||
|
||||
// Uninstall the package.
|
||||
uv_snapshot!(context.filters(), context.pip_uninstall()
|
||||
.arg("setuptools-editable"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Uninstalled 1 package in [TIME]
|
||||
- setuptools-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/setuptools_editable)
|
||||
"###);
|
||||
|
||||
// Install the editable package with `editable_mode=compat`, scoped to the package.
|
||||
uv_snapshot!(context.filters(), context.pip_install()
|
||||
.arg("-r")
|
||||
.arg("requirements.txt")
|
||||
.arg("--config-settings-package")
|
||||
.arg("setuptools-editable:editable_mode=compat"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 2 packages in [TIME]
|
||||
Prepared 1 package in [TIME]
|
||||
Installed 1 package in [TIME]
|
||||
+ setuptools-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/setuptools_editable)
|
||||
"
|
||||
);
|
||||
|
||||
// When installed with `editable_mode=compat`, the `finder.py` file should _not_ be present.
|
||||
let finder = context
|
||||
.site_packages()
|
||||
.join("__editable___setuptools_editable_0_1_0_finder.py");
|
||||
assert!(!finder.exists());
|
||||
|
||||
// Uninstall the package.
|
||||
uv_snapshot!(context.filters(), context.pip_uninstall()
|
||||
.arg("setuptools-editable"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Uninstalled 1 package in [TIME]
|
||||
- setuptools-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/setuptools_editable)
|
||||
"###);
|
||||
|
||||
// Install the editable package with `editable_mode=compat`, by scoped to a different package.
|
||||
uv_snapshot!(context.filters(), context.pip_install()
|
||||
.arg("-r")
|
||||
.arg("requirements.txt")
|
||||
.arg("--config-settings-package")
|
||||
.arg("setuptools:editable_mode=compat")
|
||||
, @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 2 packages in [TIME]
|
||||
Installed 1 package in [TIME]
|
||||
+ setuptools-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/setuptools_editable)
|
||||
"
|
||||
);
|
||||
|
||||
// When installed without `editable_mode=compat`, the `finder.py` file should be present.
|
||||
let finder = context
|
||||
.site_packages()
|
||||
.join("__editable___setuptools_editable_0_1_0_finder.py");
|
||||
assert!(finder.exists());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -203,6 +203,9 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -385,6 +388,9 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -568,6 +574,9 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -783,6 +792,9 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -933,6 +945,9 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -1127,6 +1142,9 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: Some(
|
||||
X8664UnknownLinuxGnu,
|
||||
|
@ -1369,6 +1387,9 @@ fn resolve_index_url() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -1621,6 +1642,9 @@ fn resolve_index_url() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -1828,6 +1852,9 @@ fn resolve_find_links() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -2000,6 +2027,9 @@ fn resolve_top_level() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -2232,6 +2262,9 @@ fn resolve_top_level() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -2447,6 +2480,9 @@ fn resolve_top_level() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -2618,6 +2654,9 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -2773,6 +2812,9 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -2928,6 +2970,9 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -3085,6 +3130,9 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -3208,6 +3256,7 @@ fn resolve_tool() -> anyhow::Result<()> {
|
|||
fork_strategy: None,
|
||||
dependency_metadata: None,
|
||||
config_settings: None,
|
||||
config_settings_package: None,
|
||||
no_build_isolation: None,
|
||||
no_build_isolation_package: None,
|
||||
exclude_newer: None,
|
||||
|
@ -3234,6 +3283,9 @@ fn resolve_tool() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
dependency_metadata: DependencyMetadata(
|
||||
{},
|
||||
),
|
||||
|
@ -3426,6 +3478,9 @@ fn resolve_poetry_toml() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -3643,6 +3698,9 @@ fn resolve_both() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -3950,6 +4008,9 @@ fn resolve_config_file() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -4004,7 +4065,7 @@ fn resolve_config_file() -> anyhow::Result<()> {
|
|||
|
|
||||
1 | [project]
|
||||
| ^^^^^^^
|
||||
unknown field `project`, expected one of `required-version`, `native-tls`, `offline`, `no-cache`, `cache-dir`, `preview`, `python-preference`, `python-downloads`, `concurrent-downloads`, `concurrent-builds`, `concurrent-installs`, `index`, `index-url`, `extra-index-url`, `no-index`, `find-links`, `index-strategy`, `keyring-provider`, `allow-insecure-host`, `resolution`, `prerelease`, `fork-strategy`, `dependency-metadata`, `config-settings`, `no-build-isolation`, `no-build-isolation-package`, `exclude-newer`, `link-mode`, `compile-bytecode`, `no-sources`, `upgrade`, `upgrade-package`, `reinstall`, `reinstall-package`, `no-build`, `no-build-package`, `no-binary`, `no-binary-package`, `python-install-mirror`, `pypy-install-mirror`, `python-downloads-json-url`, `publish-url`, `trusted-publishing`, `check-url`, `add-bounds`, `pip`, `cache-keys`, `override-dependencies`, `constraint-dependencies`, `build-constraint-dependencies`, `environments`, `required-environments`, `conflicts`, `workspace`, `sources`, `managed`, `package`, `default-groups`, `dependency-groups`, `dev-dependencies`, `build-backend`
|
||||
unknown field `project`, expected one of `required-version`, `native-tls`, `offline`, `no-cache`, `cache-dir`, `preview`, `python-preference`, `python-downloads`, `concurrent-downloads`, `concurrent-builds`, `concurrent-installs`, `index`, `index-url`, `extra-index-url`, `no-index`, `find-links`, `index-strategy`, `keyring-provider`, `allow-insecure-host`, `resolution`, `prerelease`, `fork-strategy`, `dependency-metadata`, `config-settings`, `config-settings-package`, `no-build-isolation`, `no-build-isolation-package`, `exclude-newer`, `link-mode`, `compile-bytecode`, `no-sources`, `upgrade`, `upgrade-package`, `reinstall`, `reinstall-package`, `no-build`, `no-build-package`, `no-binary`, `no-binary-package`, `python-install-mirror`, `pypy-install-mirror`, `python-downloads-json-url`, `publish-url`, `trusted-publishing`, `check-url`, `add-bounds`, `pip`, `cache-keys`, `override-dependencies`, `constraint-dependencies`, `build-constraint-dependencies`, `environments`, `required-environments`, `conflicts`, `workspace`, `sources`, `managed`, `package`, `default-groups`, `dependency-groups`, `dev-dependencies`, `build-backend`
|
||||
"
|
||||
);
|
||||
|
||||
|
@ -4199,6 +4260,9 @@ fn resolve_skip_empty() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -4357,6 +4421,9 @@ fn resolve_skip_empty() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -4534,6 +4601,9 @@ fn allow_insecure_host() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -4772,6 +4842,9 @@ fn index_priority() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -4989,6 +5062,9 @@ fn index_priority() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -5212,6 +5288,9 @@ fn index_priority() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -5430,6 +5509,9 @@ fn index_priority() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -5655,6 +5737,9 @@ fn index_priority() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -5873,6 +5958,9 @@ fn index_priority() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -6035,6 +6123,9 @@ fn verify_hashes() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -6183,6 +6274,9 @@ fn verify_hashes() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -6329,6 +6423,9 @@ fn verify_hashes() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -6477,6 +6574,9 @@ fn verify_hashes() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -6623,6 +6723,9 @@ fn verify_hashes() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
@ -6770,6 +6873,9 @@ fn verify_hashes() -> anyhow::Result<()> {
|
|||
config_setting: ConfigSettings(
|
||||
{},
|
||||
),
|
||||
config_settings_package: PackageConfigSettings(
|
||||
{},
|
||||
),
|
||||
python_version: None,
|
||||
python_platform: None,
|
||||
universal: false,
|
||||
|
|
|
@ -11126,3 +11126,146 @@ fn sync_python_preference() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_config_settings_package() -> Result<()> {
|
||||
let context = TestContext::new("3.12").with_exclude_newer("2025-07-25T00:00:00Z");
|
||||
|
||||
// Create a child project that uses `setuptools`.
|
||||
let dependency = context.temp_dir.child("dependency");
|
||||
dependency.child("pyproject.toml").write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "dependency"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = []
|
||||
[build-system]
|
||||
requires = ["setuptools>=42"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
"#,
|
||||
)?;
|
||||
dependency
|
||||
.child("dependency")
|
||||
.child("__init__.py")
|
||||
.touch()?;
|
||||
|
||||
// Install the `dependency` without `editable_mode=compat`.
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = ["dependency"]
|
||||
|
||||
[tool.uv.sources]
|
||||
dependency = { path = "dependency", editable = true }
|
||||
"#,
|
||||
)?;
|
||||
|
||||
// Lock the project
|
||||
context.lock().assert().success();
|
||||
|
||||
uv_snapshot!(context.filters(), context.sync(), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 2 packages in [TIME]
|
||||
Prepared 1 package in [TIME]
|
||||
Installed 1 package in [TIME]
|
||||
+ dependency==0.1.0 (from file://[TEMP_DIR]/dependency)
|
||||
");
|
||||
|
||||
// When installed without `editable_mode=compat`, the `finder.py` file should be present.
|
||||
let finder = context
|
||||
.site_packages()
|
||||
.join("__editable___dependency_0_1_0_finder.py");
|
||||
assert!(finder.exists());
|
||||
|
||||
// Remove the virtual environment.
|
||||
fs_err::remove_dir_all(&context.venv)?;
|
||||
|
||||
// Install the `dependency` with `editable_mode=compat` scoped to the package.
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = ["dependency"]
|
||||
|
||||
[tool.uv.sources]
|
||||
dependency = { path = "dependency", editable = true }
|
||||
|
||||
[tool.uv.config-settings-package]
|
||||
dependency = { editable_mode = "compat" }
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.sync(), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
|
||||
Creating virtual environment at: .venv
|
||||
Resolved 2 packages in [TIME]
|
||||
Prepared 1 package in [TIME]
|
||||
Installed 1 package in [TIME]
|
||||
+ dependency==0.1.0 (from file://[TEMP_DIR]/dependency)
|
||||
");
|
||||
|
||||
// When installed with `editable_mode=compat`, the `finder.py` file should _not_ be present.
|
||||
let finder = context
|
||||
.site_packages()
|
||||
.join("__editable___dependency_0_1_0_finder.py");
|
||||
assert!(!finder.exists());
|
||||
|
||||
// Remove the virtual environment.
|
||||
fs_err::remove_dir_all(&context.venv)?;
|
||||
|
||||
// Install the `dependency` with `editable_mode=compat` scoped to another package.
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = ["dependency"]
|
||||
|
||||
[tool.uv.sources]
|
||||
dependency = { path = "dependency", editable = true }
|
||||
|
||||
[tool.uv.config-settings-package]
|
||||
setuptools = { editable_mode = "compat" }
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.sync(), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
|
||||
Creating virtual environment at: .venv
|
||||
Resolved 2 packages in [TIME]
|
||||
Installed 1 package in [TIME]
|
||||
+ dependency==0.1.0 (from file://[TEMP_DIR]/dependency)
|
||||
");
|
||||
|
||||
// When installed without `editable_mode=compat`, the `finder.py` file should be present.
|
||||
let finder = context
|
||||
.site_packages()
|
||||
.join("__editable___dependency_0_1_0_finder.py");
|
||||
assert!(finder.exists());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue