Skip to content

Commit

Permalink
Split on version
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Oct 30, 2024
1 parent 0cf498a commit 86665de
Show file tree
Hide file tree
Showing 5 changed files with 249 additions and 48 deletions.
47 changes: 30 additions & 17 deletions crates/uv-resolver/src/requires_python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,23 +278,6 @@ impl RequiresPython {
}
}

/// Returns the [`RequiresPythonBound`] truncated to the major and minor version.
pub fn bound_major_minor(&self) -> LowerBound {
match self.range.lower().as_ref() {
// Ex) `>=3.10.1` -> `>=3.10`
Bound::Included(version) => LowerBound(Bound::Included(Version::new(
version.release().iter().take(2),
))),
// Ex) `>3.10.1` -> `>=3.10`
// This is unintuitive, but `>3.10.1` does indicate that _some_ version of Python 3.10
// is supported.
Bound::Excluded(version) => LowerBound(Bound::Included(Version::new(
version.release().iter().take(2),
))),
Bound::Unbounded => LowerBound(Bound::Unbounded),
}
}

/// Returns the [`Range`] bounding the `Requires-Python` specifier.
pub fn range(&self) -> &RequiresPythonRange {
&self.range
Expand Down Expand Up @@ -472,6 +455,36 @@ impl RequiresPython {
}
})
}

/// Return a set of fork preferences to cover the range of supported Python minor versions.
pub fn forks(&self) -> Vec<MarkerTree> {
let mut forks = vec![];

let python_marker = self.to_marker_tree();

// Add, e.g., `python_full_version == '3.8.*'` for all supported Python versions.
for minor in 7..13 {
let python_version = Version::new([3, minor]);
let marker = MarkerTree::expression(MarkerExpression::Version {
key: MarkerValueVersion::PythonFullVersion,
specifier: VersionSpecifier::equals_star_version(python_version),
});
if !marker.is_disjoint(&python_marker) {
forks.push(marker);
}
}

// Add, e.g., `python_full_version >= '3.13'` for the latest supported Python version.
let marker = MarkerTree::expression(MarkerExpression::Version {
key: MarkerValueVersion::PythonFullVersion,
specifier: VersionSpecifier::greater_than_equal_version(Version::new([3, 13])),
});
if !marker.is_disjoint(&python_marker) {
forks.push(marker);
}

forks
}
}

impl std::fmt::Display for RequiresPython {
Expand Down
32 changes: 23 additions & 9 deletions crates/uv-resolver/src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,21 +308,35 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
self.markers.clone(),
self.python_requirement.clone(),
);

let mut preferences = self.preferences.clone();
let mut forked_states =
if let ResolverMarkers::Universal { fork_preferences } = &self.markers {
if fork_preferences.is_empty() {
vec![state]
} else {
fork_preferences
let mut forked_states = if let ResolverMarkers::Universal { fork_preferences } =
&self.markers
{
if fork_preferences.is_empty() {
match self.options.multi_version_mode {
MultiVersionMode::Fewest => {
vec![state]
}
MultiVersionMode::Latest => self
.python_requirement
.target()
.forks()
.iter()
.rev()
.map(|fork_preference| state.clone().with_markers(fork_preference.clone()))
.collect()
.collect(),
}
} else {
vec![state]
};
fork_preferences
.iter()
.rev()
.map(|fork_preference| state.clone().with_markers(fork_preference.clone()))
.collect()
}
} else {
vec![state]
};
let mut resolutions = vec![];

'FORK: while let Some(mut state) = forked_states.pop() {
Expand Down
4 changes: 2 additions & 2 deletions crates/uv-settings/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ pub struct ResolverInstallerOptions {
default = "\"fewest\"",
value_type = "str",
example = r#"
resolution = "latest"
multi-version = "latest"
"#,
possible_values = true
)]
Expand Down Expand Up @@ -1018,7 +1018,7 @@ pub struct PipOptions {
default = "\"fewest\"",
value_type = "str",
example = r#"
resolution = "latest"
multi-version = "latest"
"#,
possible_values = true
)]
Expand Down
Loading

0 comments on commit 86665de

Please sign in to comment.