Skip to content

Commit 13dc80e

Browse files
committed
Split on version
1 parent fab0035 commit 13dc80e

File tree

10 files changed

+243
-49
lines changed

10 files changed

+243
-49
lines changed

crates/uv-cli/src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4047,6 +4047,20 @@ pub struct ToolUpgradeArgs {
40474047
#[arg(long, hide = true)]
40484048
pub pre: bool,
40494049

4050+
/// The strategy to use when selecting multiple versions of a given package across Python
4051+
/// versions and platforms.
4052+
///
4053+
/// By default, uv will minimize the number of versions selected for each package (`fewest`),
4054+
/// to minimize differences between environments. Under `latest`, uv will select the latest
4055+
/// compatible version for each environment, even if it results in more versions being selected.
4056+
#[arg(
4057+
long,
4058+
value_enum,
4059+
env = EnvVars::UV_MULTI_VERSION,
4060+
help_heading = "Resolver options"
4061+
)]
4062+
pub multi_version: Option<MultiVersionMode>,
4063+
40504064
/// Settings to pass to the PEP 517 build backend, specified as `KEY=VALUE` pairs.
40514065
#[arg(
40524066
long,

crates/uv-python/src/python_version.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ impl schemars::JsonSchema for PythonVersion {
5050
..schemars::schema::StringValidation::default()
5151
})),
5252
metadata: Some(Box::new(schemars::schema::Metadata {
53-
description: Some("A Python version specifier, e.g. `3.7` or `3.8.0`.".to_string()),
53+
description: Some(
54+
"A Python version specifier, e.g. `3.11` or `3.12.4`.".to_string(),
55+
),
5456
..schemars::schema::Metadata::default()
5557
})),
5658
..schemars::schema::SchemaObject::default()

crates/uv-resolver/src/requires_python.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -278,23 +278,6 @@ impl RequiresPython {
278278
}
279279
}
280280

281-
/// Returns the [`RequiresPythonBound`] truncated to the major and minor version.
282-
pub fn bound_major_minor(&self) -> LowerBound {
283-
match self.range.lower().as_ref() {
284-
// Ex) `>=3.10.1` -> `>=3.10`
285-
Bound::Included(version) => LowerBound(Bound::Included(Version::new(
286-
version.release().iter().take(2),
287-
))),
288-
// Ex) `>3.10.1` -> `>=3.10`
289-
// This is unintuitive, but `>3.10.1` does indicate that _some_ version of Python 3.10
290-
// is supported.
291-
Bound::Excluded(version) => LowerBound(Bound::Included(Version::new(
292-
version.release().iter().take(2),
293-
))),
294-
Bound::Unbounded => LowerBound(Bound::Unbounded),
295-
}
296-
}
297-
298281
/// Returns the [`Range`] bounding the `Requires-Python` specifier.
299282
pub fn range(&self) -> &RequiresPythonRange {
300283
&self.range

crates/uv-settings/src/settings.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -493,12 +493,14 @@ pub struct ResolverInstallerOptions {
493493
///
494494
/// By default, uv will minimize the number of versions selected for each package (`fewest`),
495495
/// to minimize differences between environments. Under `latest`, uv will select the latest
496-
/// compatible version for each environment, even if it results in more versions being selected.
496+
/// compatible version for each environment and perform an independent solve for each Python
497+
/// minor version, ensuring that the latest-compatible version is used in each environment,
498+
/// even if it results in more versions being selected across the lockfile.
497499
#[option(
498500
default = "\"fewest\"",
499501
value_type = "str",
500502
example = r#"
501-
resolution = "latest"
503+
multi-version = "latest"
502504
"#,
503505
possible_values = true
504506
)]
@@ -1091,12 +1093,14 @@ pub struct PipOptions {
10911093
///
10921094
/// By default, uv will minimize the number of versions selected for each package (`fewest`),
10931095
/// to minimize differences between environments. Under `latest`, uv will select the latest
1094-
/// compatible version for each environment, even if it results in more versions being selected.
1096+
/// compatible version for each environment and perform an independent solve for each Python
1097+
/// minor version, ensuring that the latest-compatible version is used in each environment,
1098+
/// even if it results in more versions being selected across the lockfile.
10951099
#[option(
10961100
default = "\"fewest\"",
10971101
value_type = "str",
10981102
example = r#"
1099-
resolution = "latest"
1103+
multi-version = "latest"
11001104
"#,
11011105
possible_values = true
11021106
)]

crates/uv/src/commands/project/tree.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ pub(crate) async fn tree(
169169
keyring_provider,
170170
resolution: _,
171171
prerelease: _,
172-
dependency_metadata: _,
172+
multi_version: _, dependency_metadata: _,
173173
config_setting: _,
174174
no_build_isolation: _,
175175
no_build_isolation_package: _,

crates/uv/src/settings.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ impl ToolUpgradeSettings {
576576
resolution,
577577
prerelease,
578578
pre,
579-
config_setting,
579+
multi_version, config_setting,
580580
no_build_isolation,
581581
no_build_isolation_package,
582582
build_isolation,
@@ -609,6 +609,7 @@ impl ToolUpgradeSettings {
609609
resolution,
610610
prerelease,
611611
pre,
612+
multi_version,
612613
config_setting,
613614
no_build_isolation,
614615
no_build_isolation_package,

0 commit comments

Comments
 (0)