Treat `--upgrade-package` on the command-line as overriding `upgrade = false` in configuration (#15395)

## Summary

Right now, if you put `upgrade = false` in a `uv.toml`, then pass
`--upgrade-package numpy` on the CLI, we won't upgrade NumPy. This PR
fixes that interaction by ensuring that when we "combine", we look at
those arguments holistically (i.e., we bundle `upgrade` and
`upgrade-package` into a single struct, which then goes through the
`.combine` logic), rather than combining `upgrade` and `upgrade-package`
independently.

If approved, I then need to add the same thing for `no-build-isolation`,
`reinstall`, `no-build`, and `no-binary`.
This commit is contained in:
Charlie Marsh 2025-08-21 16:20:55 +01:00 committed by GitHub
parent b950453891
commit 0397595e53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 357 additions and 145 deletions

View File

@ -1,7 +1,8 @@
use anstream::eprintln;
use uv_cache::Refresh;
use uv_distribution_types::{ConfigSettings, PackageConfigSettings};
use uv_configuration::UpgradeSelection;
use uv_distribution_types::{ConfigSettings, PackageConfigSettings, Requirement};
use uv_resolver::{ExcludeNewer, ExcludeNewerPackage, PrereleaseMode};
use uv_settings::{Combine, PipOptions, ResolverInstallerOptions, ResolverOptions};
use uv_warnings::owo_colors::OwoColorize;
@ -333,8 +334,10 @@ pub fn resolver_options(
.filter_map(Maybe::into_option)
.collect()
}),
upgrade: flag(upgrade, no_upgrade, "no-upgrade"),
upgrade_package: Some(upgrade_package),
upgrade: UpgradeSelection::from_args(
flag(upgrade, no_upgrade, "no-upgrade"),
upgrade_package.into_iter().map(Requirement::from).collect(),
),
index_strategy,
keyring_provider,
resolution,
@ -442,12 +445,10 @@ pub fn resolver_installer_options(
.filter_map(Maybe::into_option)
.collect()
}),
upgrade: flag(upgrade, no_upgrade, "upgrade"),
upgrade_package: if upgrade_package.is_empty() {
None
} else {
Some(upgrade_package)
},
upgrade: UpgradeSelection::from_args(
flag(upgrade, no_upgrade, "upgrade"),
upgrade_package.into_iter().map(Requirement::from).collect(),
),
reinstall: flag(reinstall, no_reinstall, "reinstall"),
reinstall_package: if reinstall_package.is_empty() {
None

View File

@ -134,9 +134,57 @@ impl From<Reinstall> for Refresh {
}
}
/// An upgrade selection as specified by a user on the command line or in a configuration file.
#[derive(Debug, Default, Clone)]
pub enum UpgradeSelection {
/// Prefer pinned versions from the existing lockfile, if possible.
#[default]
None,
/// Allow package upgrades for all packages, ignoring the existing lockfile.
All,
/// Allow package upgrades, but only for the specified packages.
Packages(Vec<Requirement>),
}
impl UpgradeSelection {
/// Determine the upgrade selection strategy from the command-line arguments.
pub fn from_args(upgrade: Option<bool>, upgrade_package: Vec<Requirement>) -> Option<Self> {
match upgrade {
Some(true) => Some(Self::All),
// TODO(charlie): `--no-upgrade` with `--upgrade-package` should allow the specified
// packages to be upgraded. Right now, `--upgrade-package` is silently ignored.
Some(false) => Some(Self::None),
None if upgrade_package.is_empty() => None,
None => Some(Self::Packages(upgrade_package)),
}
}
/// Combine a set of [`UpgradeSelection`] values.
#[must_use]
pub fn combine(self, other: Self) -> Self {
match self {
// Setting `--upgrade` or `--no-upgrade` should clear previous `--upgrade-package` selections.
Self::All | Self::None => self,
Self::Packages(self_packages) => match other {
// If `--upgrade` was enabled previously, `--upgrade-package` is subsumed by upgrading all packages.
Self::All => other,
// If `--no-upgrade` was enabled previously, then `--upgrade-package` enables an explicit upgrade of those packages.
Self::None => Self::Packages(self_packages),
// If `--upgrade-package` was included twice, combine the requirements.
Self::Packages(other_packages) => {
let mut combined = self_packages;
combined.extend(other_packages);
Self::Packages(combined)
}
},
}
}
}
/// Whether to allow package upgrades.
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
#[derive(Debug, Default, Clone)]
pub enum Upgrade {
/// Prefer pinned versions from the existing lockfile, if possible.
#[default]
@ -149,30 +197,28 @@ pub enum Upgrade {
Packages(FxHashMap<PackageName, Vec<Requirement>>),
}
impl Upgrade {
/// Determine the [`Upgrade`] strategy from the command-line arguments.
pub fn from_args(upgrade: Option<bool>, upgrade_package: Vec<Requirement>) -> Self {
match upgrade {
Some(true) => Self::All,
Some(false) => Self::None,
None => {
if upgrade_package.is_empty() {
Self::None
} else {
Self::Packages(upgrade_package.into_iter().fold(
FxHashMap::default(),
|mut map, requirement| {
map.entry(requirement.name.clone())
.or_default()
.push(requirement);
map
},
))
}
}
/// Determine the [`Upgrade`] strategy from the command-line arguments.
impl From<Option<UpgradeSelection>> for Upgrade {
fn from(value: Option<UpgradeSelection>) -> Self {
match value {
None => Self::None,
Some(UpgradeSelection::None) => Self::None,
Some(UpgradeSelection::All) => Self::All,
Some(UpgradeSelection::Packages(requirements)) => Self::Packages(
requirements
.into_iter()
.fold(FxHashMap::default(), |mut map, requirement| {
map.entry(requirement.name.clone())
.or_default()
.push(requirement);
map
}),
),
}
}
}
impl Upgrade {
/// Create an [`Upgrade`] strategy to upgrade a single package.
pub fn package(package_name: PackageName) -> Self {
Self::Packages({

View File

@ -14,7 +14,7 @@ use uv_pep440::VersionSpecifiers;
use uv_pep508::PackageName;
use uv_pypi_types::VerbatimParsedUrl;
use uv_redacted::DisplaySafeUrl;
use uv_settings::{GlobalOptions, ResolverInstallerOptions};
use uv_settings::{GlobalOptions, ResolverInstallerSchema};
use uv_warnings::warn_user;
use uv_workspace::pyproject::{ExtraBuildDependency, Sources};
@ -424,7 +424,7 @@ pub struct ToolUv {
#[serde(flatten)]
pub globals: GlobalOptions,
#[serde(flatten)]
pub top_level: ResolverInstallerOptions,
pub top_level: ResolverInstallerSchema,
pub override_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
pub constraint_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
pub build_constraint_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,

View File

@ -5,7 +5,7 @@ use url::Url;
use uv_configuration::{
ExportFormat, IndexStrategy, KeyringProviderType, RequiredVersion, TargetTriple,
TrustedPublishing,
TrustedPublishing, UpgradeSelection,
};
use uv_distribution_types::{
ConfigSettings, ExtraBuildVariables, Index, IndexUrl, PackageConfigSettings, PipExtraIndex,
@ -181,6 +181,15 @@ impl Combine for Option<PackageConfigSettings> {
}
}
impl Combine for Option<UpgradeSelection> {
fn combine(self, other: Self) -> Self {
match (self, other) {
(Some(a), Some(b)) => Some(a.combine(b)),
(a, b) => a.or(b),
}
}
}
impl Combine for serde::de::IgnoredAny {
fn combine(self, _other: Self) -> Self {
self

View File

@ -301,7 +301,7 @@ fn warn_uv_toml_masked_fields(options: &Options) {
allow_insecure_host,
},
top_level:
ResolverInstallerOptions {
ResolverInstallerSchema {
index,
index_url,
extra_index_url,

View File

@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use uv_cache_info::CacheKey;
use uv_configuration::{
IndexStrategy, KeyringProviderType, PackageNameSpecifier, RequiredVersion, TargetTriple,
TrustedHost, TrustedPublishing,
TrustedHost, TrustedPublishing, UpgradeSelection,
};
use uv_distribution_types::{
ConfigSettings, ExtraBuildVariables, Index, IndexUrl, IndexUrlError, PackageConfigSettings,
@ -52,7 +52,7 @@ pub struct Options {
pub globals: GlobalOptions,
#[serde(flatten)]
pub top_level: ResolverInstallerOptions,
pub top_level: ResolverInstallerSchema,
#[serde(flatten)]
pub install_mirrors: PythonInstallMirrors,
@ -161,7 +161,7 @@ pub struct Options {
impl Options {
/// Construct an [`Options`] with the given global and top-level settings.
pub fn simple(globals: GlobalOptions, top_level: ResolverInstallerOptions) -> Self {
pub fn simple(globals: GlobalOptions, top_level: ResolverInstallerSchema) -> Self {
Self {
globals,
top_level,
@ -369,8 +369,7 @@ pub struct ResolverOptions {
pub config_settings_package: Option<PackageConfigSettings>,
pub exclude_newer: ExcludeNewer,
pub link_mode: Option<LinkMode>,
pub upgrade: Option<bool>,
pub upgrade_package: Option<Vec<Requirement<VerbatimParsedUrl>>>,
pub upgrade: Option<UpgradeSelection>,
pub no_build: Option<bool>,
pub no_build_package: Option<Vec<PackageName>>,
pub no_binary: Option<bool>,
@ -384,10 +383,159 @@ pub struct ResolverOptions {
/// Shared settings, relevant to all operations that must resolve and install dependencies. The
/// union of [`InstallerOptions`] and [`ResolverOptions`].
#[derive(Debug, Clone, Default, CombineOptions)]
pub struct ResolverInstallerOptions {
pub index: Option<Vec<Index>>,
pub index_url: Option<PipIndex>,
pub extra_index_url: Option<Vec<PipExtraIndex>>,
pub no_index: Option<bool>,
pub find_links: Option<Vec<PipFindLinks>>,
pub index_strategy: Option<IndexStrategy>,
pub keyring_provider: Option<KeyringProviderType>,
pub resolution: Option<ResolutionMode>,
pub prerelease: Option<PrereleaseMode>,
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 extra_build_dependencies: Option<ExtraBuildDependencies>,
pub extra_build_variables: Option<ExtraBuildVariables>,
pub exclude_newer: Option<ExcludeNewerTimestamp>,
pub exclude_newer_package: Option<ExcludeNewerPackage>,
pub link_mode: Option<LinkMode>,
pub compile_bytecode: Option<bool>,
pub no_sources: Option<bool>,
pub upgrade: Option<UpgradeSelection>,
pub reinstall: Option<bool>,
pub reinstall_package: Option<Vec<PackageName>>,
pub no_build: Option<bool>,
pub no_build_package: Option<Vec<PackageName>>,
pub no_binary: Option<bool>,
pub no_binary_package: Option<Vec<PackageName>>,
}
impl From<ResolverInstallerSchema> for ResolverInstallerOptions {
fn from(value: ResolverInstallerSchema) -> Self {
let ResolverInstallerSchema {
index,
index_url,
extra_index_url,
no_index,
find_links,
index_strategy,
keyring_provider,
resolution,
prerelease,
fork_strategy,
dependency_metadata,
config_settings,
config_settings_package,
no_build_isolation,
no_build_isolation_package,
extra_build_dependencies,
extra_build_variables,
exclude_newer,
exclude_newer_package,
link_mode,
compile_bytecode,
no_sources,
upgrade,
upgrade_package,
reinstall,
reinstall_package,
no_build,
no_build_package,
no_binary,
no_binary_package,
} = value;
Self {
index,
index_url,
extra_index_url,
no_index,
find_links,
index_strategy,
keyring_provider,
resolution,
prerelease,
fork_strategy,
dependency_metadata,
config_settings,
config_settings_package,
no_build_isolation,
no_build_isolation_package,
extra_build_dependencies,
extra_build_variables,
exclude_newer,
exclude_newer_package,
link_mode,
compile_bytecode,
no_sources,
upgrade: UpgradeSelection::from_args(
upgrade,
upgrade_package
.into_iter()
.flatten()
.map(Into::into)
.collect(),
),
reinstall,
reinstall_package,
no_build,
no_build_package,
no_binary,
no_binary_package,
}
}
}
impl ResolverInstallerSchema {
/// Resolve the [`ResolverInstallerSchema`] relative to the given root directory.
pub fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
Ok(Self {
index: self
.index
.map(|index| {
index
.into_iter()
.map(|index| index.relative_to(root_dir))
.collect::<Result<Vec<_>, _>>()
})
.transpose()?,
index_url: self
.index_url
.map(|index_url| index_url.relative_to(root_dir))
.transpose()?,
extra_index_url: self
.extra_index_url
.map(|extra_index_url| {
extra_index_url
.into_iter()
.map(|extra_index_url| extra_index_url.relative_to(root_dir))
.collect::<Result<Vec<_>, _>>()
})
.transpose()?,
find_links: self
.find_links
.map(|find_links| {
find_links
.into_iter()
.map(|find_link| find_link.relative_to(root_dir))
.collect::<Result<Vec<_>, _>>()
})
.transpose()?,
..self
})
}
}
/// The JSON schema for the `[tool.uv]` section of a `pyproject.toml` file.
#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
#[serde(rename_all = "kebab-case")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct ResolverInstallerOptions {
pub struct ResolverInstallerSchema {
/// The package indexes to use when resolving dependencies.
///
/// Accepts either a repository compliant with [PEP 503](https://peps.python.org/pep-0503/)
@ -814,46 +962,6 @@ pub struct ResolverInstallerOptions {
pub no_binary_package: Option<Vec<PackageName>>,
}
impl ResolverInstallerOptions {
/// Resolve the [`ResolverInstallerOptions`] relative to the given root directory.
pub fn relative_to(self, root_dir: &Path) -> Result<Self, IndexUrlError> {
Ok(Self {
index: self
.index
.map(|index| {
index
.into_iter()
.map(|index| index.relative_to(root_dir))
.collect::<Result<Vec<_>, _>>()
})
.transpose()?,
index_url: self
.index_url
.map(|index_url| index_url.relative_to(root_dir))
.transpose()?,
extra_index_url: self
.extra_index_url
.map(|extra_index_url| {
extra_index_url
.into_iter()
.map(|extra_index_url| extra_index_url.relative_to(root_dir))
.collect::<Result<Vec<_>, _>>()
})
.transpose()?,
find_links: self
.find_links
.map(|find_links| {
find_links
.into_iter()
.map(|find_link| find_link.relative_to(root_dir))
.collect::<Result<Vec<_>, _>>()
})
.transpose()?,
..self
})
}
}
/// Shared settings, relevant to all operations that might create managed python installations.
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, CombineOptions, OptionsMetadata)]
#[serde(rename_all = "kebab-case")]
@ -1752,8 +1860,8 @@ impl PipOptions {
}
}
impl From<ResolverInstallerOptions> for ResolverOptions {
fn from(value: ResolverInstallerOptions) -> Self {
impl From<ResolverInstallerSchema> for ResolverOptions {
fn from(value: ResolverInstallerSchema) -> Self {
Self {
index: value.index,
index_url: value.index_url,
@ -1778,8 +1886,15 @@ impl From<ResolverInstallerOptions> for ResolverOptions {
.collect(),
),
link_mode: value.link_mode,
upgrade: value.upgrade,
upgrade_package: value.upgrade_package,
upgrade: UpgradeSelection::from_args(
value.upgrade,
value
.upgrade_package
.into_iter()
.flatten()
.map(Into::into)
.collect(),
),
no_build: value.no_build,
no_build_package: value.no_build_package,
no_binary: value.no_binary,
@ -1793,8 +1908,8 @@ impl From<ResolverInstallerOptions> for ResolverOptions {
}
}
impl From<ResolverInstallerOptions> for InstallerOptions {
fn from(value: ResolverInstallerOptions) -> Self {
impl From<ResolverInstallerSchema> for InstallerOptions {
fn from(value: ResolverInstallerSchema) -> Self {
Self {
index: value.index,
index_url: value.index_url,
@ -1830,7 +1945,7 @@ impl From<ResolverInstallerOptions> for InstallerOptions {
/// The options persisted alongside an installed tool.
///
/// A mirror of [`ResolverInstallerOptions`], without upgrades and reinstalls, which shouldn't be
/// A mirror of [`ResolverInstallerSchema`], without upgrades and reinstalls, which shouldn't be
/// persisted in a tool receipt.
#[derive(
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, CombineOptions, OptionsMetadata,
@ -1925,7 +2040,6 @@ impl From<ToolOptions> for ResolverInstallerOptions {
compile_bytecode: value.compile_bytecode,
no_sources: value.no_sources,
upgrade: None,
upgrade_package: None,
reinstall: None,
reinstall_package: None,
no_build: value.no_build,
@ -2120,7 +2234,7 @@ impl From<OptionsWire> for Options {
// Used twice for backwards compatibility
allow_insecure_host: allow_insecure_host.clone(),
},
top_level: ResolverInstallerOptions {
top_level: ResolverInstallerSchema {
index,
index_url,
extra_index_url,

View File

@ -24,7 +24,7 @@ use uv_configuration::{
BuildOptions, Concurrency, DependencyGroups, DryRun, EditableMode, ExportFormat,
ExtrasSpecification, HashCheckingMode, IndexStrategy, InstallOptions, KeyringProviderType,
NoBinary, NoBuild, Preview, ProjectBuildBackend, Reinstall, RequiredVersion, SourceStrategy,
TargetTriple, TrustedHost, TrustedPublishing, Upgrade, VersionControlSystem,
TargetTriple, TrustedHost, TrustedPublishing, Upgrade, UpgradeSelection, VersionControlSystem,
};
use uv_distribution_types::{
ConfigSettings, DependencyMetadata, ExtraBuildVariables, Index, IndexLocations, IndexUrl,
@ -42,7 +42,7 @@ use uv_resolver::{
};
use uv_settings::{
Combine, EnvironmentOptions, FilesystemOptions, Options, PipOptions, PublishOptions,
PythonInstallMirrors, ResolverInstallerOptions, ResolverOptions,
PythonInstallMirrors, ResolverInstallerOptions, ResolverInstallerSchema, ResolverOptions,
};
use uv_static::EnvVars;
use uv_torch::TorchMode;
@ -538,13 +538,14 @@ impl ToolRunSettings {
}
}
let options = resolver_installer_options(installer, build).combine(
filesystem
.clone()
.map(FilesystemOptions::into_options)
.map(|options| options.top_level)
.unwrap_or_default(),
);
let options =
resolver_installer_options(installer, build).combine(ResolverInstallerOptions::from(
filesystem
.clone()
.map(FilesystemOptions::into_options)
.map(|options| options.top_level)
.unwrap_or_default(),
));
let install_mirrors = filesystem
.map(FilesystemOptions::into_options)
@ -636,13 +637,14 @@ impl ToolInstallSettings {
python,
} = args;
let options = resolver_installer_options(installer, build).combine(
filesystem
.clone()
.map(FilesystemOptions::into_options)
.map(|options| options.top_level)
.unwrap_or_default(),
);
let options =
resolver_installer_options(installer, build).combine(ResolverInstallerOptions::from(
filesystem
.clone()
.map(FilesystemOptions::into_options)
.map(|options| options.top_level)
.unwrap_or_default(),
));
let install_mirrors = filesystem
.map(FilesystemOptions::into_options)
@ -777,9 +779,11 @@ impl ToolUpgradeSettings {
.clone()
.map(|options| options.install_mirrors)
.unwrap_or_default();
let top_level = filesystem
.map(|options| options.top_level)
.unwrap_or_default();
let top_level = ResolverInstallerOptions::from(
filesystem
.map(|options| options.top_level)
.unwrap_or_default(),
);
Self {
names: if all { vec![] } else { name },
@ -2798,6 +2802,8 @@ pub(crate) struct ResolverSettings {
impl ResolverSettings {
/// Resolve the [`ResolverSettings`] from the CLI and filesystem configuration.
pub(crate) fn combine(args: ResolverOptions, filesystem: Option<FilesystemOptions>) -> Self {
// The problem is that for `upgrade`... we want to combine the two `Upgrade` structs,
// not the individual fields.
let options = args.combine(ResolverOptions::from(
filesystem
.map(FilesystemOptions::into_options)
@ -2846,15 +2852,7 @@ impl From<ResolverOptions> for ResolverSettings {
exclude_newer: value.exclude_newer,
link_mode: value.link_mode.unwrap_or_default(),
sources: SourceStrategy::from_args(value.no_sources.unwrap_or_default()),
upgrade: Upgrade::from_args(
value.upgrade,
value
.upgrade_package
.into_iter()
.flatten()
.map(Requirement::from)
.collect(),
),
upgrade: Upgrade::from(value.upgrade),
build_options: BuildOptions::new(
NoBinary::from_args(value.no_binary, value.no_binary_package.unwrap_or_default()),
NoBuild::from_args(value.no_build, value.no_build_package.unwrap_or_default()),
@ -2881,12 +2879,12 @@ impl ResolverInstallerSettings {
args: ResolverInstallerOptions,
filesystem: Option<FilesystemOptions>,
) -> Self {
let options = args.combine(
let options = args.combine(ResolverInstallerOptions::from(
filesystem
.map(FilesystemOptions::into_options)
.map(|options| options.top_level)
.unwrap_or_default(),
);
));
Self::from(options)
}
@ -2945,15 +2943,7 @@ impl From<ResolverInstallerOptions> for ResolverInstallerSettings {
prerelease: value.prerelease.unwrap_or_default(),
resolution: value.resolution.unwrap_or_default(),
sources: SourceStrategy::from_args(value.no_sources.unwrap_or_default()),
upgrade: Upgrade::from_args(
value.upgrade,
value
.upgrade_package
.into_iter()
.flatten()
.map(Requirement::from)
.collect(),
),
upgrade: Upgrade::from(value.upgrade),
},
compile_bytecode: value.compile_bytecode.unwrap_or_default(),
reinstall: Reinstall::from_args(
@ -3098,7 +3088,7 @@ impl PipSettings {
exclude_newer_package,
} = pip.unwrap_or_default();
let ResolverInstallerOptions {
let ResolverInstallerSchema {
index: top_level_index,
index_url: top_level_index_url,
extra_index_url: top_level_extra_index_url,
@ -3327,14 +3317,23 @@ impl PipSettings {
args.no_sources.combine(no_sources).unwrap_or_default(),
),
strict: args.strict.combine(strict).unwrap_or_default(),
upgrade: Upgrade::from_args(
args.upgrade.combine(upgrade),
args.upgrade_package
.combine(upgrade_package)
.into_iter()
.flatten()
.map(Requirement::from)
.collect(),
upgrade: Upgrade::from(
UpgradeSelection::from_args(
args.upgrade,
args.upgrade_package
.into_iter()
.flatten()
.map(Requirement::from)
.collect(),
)
.combine(UpgradeSelection::from_args(
upgrade,
upgrade_package
.into_iter()
.flatten()
.map(Requirement::from)
.collect(),
)),
),
reinstall: Reinstall::from_args(
args.reinstall.combine(reinstall),
@ -3418,7 +3417,7 @@ impl PublishSettings {
trusted_publishing,
check_url,
} = publish;
let ResolverInstallerOptions {
let ResolverInstallerSchema {
keyring_provider,
index,
extra_index_url,

View File

@ -3514,7 +3514,6 @@ fn resolve_tool() -> anyhow::Result<()> {
compile_bytecode: None,
no_sources: None,
upgrade: None,
upgrade_package: None,
reinstall: None,
reinstall_package: None,
no_build: None,
@ -8569,7 +8568,6 @@ fn upgrade_pip_cli_config_interaction() -> anyhow::Result<()> {
"})?;
// Despite `upgrade = false` in the configuration file, we should mark `idna` for upgrade.
// TODO(charlie): This doesn't mark `idna` for upgrade; it just disables upgrades.
uv_snapshot!(context.filters(), add_shared_args(context.pip_compile(), context.temp_dir.path())
.arg("--upgrade-package")
.arg("idna")
@ -8727,7 +8725,30 @@ fn upgrade_pip_cli_config_interaction() -> anyhow::Result<()> {
hash_checking: Some(
Verify,
),
upgrade: None,
upgrade: Packages(
{
PackageName(
"idna",
): [
Requirement {
name: PackageName(
"idna",
),
extras: [],
groups: [],
marker: true,
source: Registry {
specifier: VersionSpecifiers(
[],
),
index: None,
conflict: None,
},
origin: None,
},
],
},
),
reinstall: None,
},
}
@ -9600,7 +9621,6 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> {
"#})?;
// Despite `upgrade = false` in the configuration file, we should mark `idna` for upgrade.
// TODO(charlie): This doesn't mark `idna` for upgrade; it just disables upgrades.
uv_snapshot!(context.filters(), add_shared_args(context.lock(), context.temp_dir.path())
.arg("--upgrade-package")
.arg("idna")
@ -9699,7 +9719,30 @@ fn upgrade_project_cli_config_interaction() -> anyhow::Result<()> {
prerelease: IfNecessaryOrExplicit,
resolution: Highest,
sources: Enabled,
upgrade: None,
upgrade: Packages(
{
PackageName(
"idna",
): [
Requirement {
name: PackageName(
"idna",
),
extras: [],
groups: [],
marker: true,
source: Registry {
specifier: VersionSpecifiers(
[],
),
index: None,
conflict: None,
},
origin: None,
},
],
},
),
},
}