mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-22 20:45:25 +00:00
Fix handling of changes to requires-python (#14076)
When using `uv lock --upgrade-package=python` after changing `requires-python`, it was possible to get into a state where the fork markers produced corresponded to the empty set. This in turn resulted in an empty lock file. There was already some infrastructure in place that I think was perhaps intended to handle this. In particular, `Lock::check_marker_coverage` checks whether the fork markers have some overlap with the supported environments (including the `requires-python`). But there were two problems with this. First is that in lock validation, this marker coverage check came _after_ a path that returned `Preferable` (meaning that the fork markers should be kept) when `--upgrade-package` was used. Second is that the marker coverage check used the `requires-python` in the lock file and _not_ the `requires-python` in the now updated `pyproject.toml`. We attempt to solve this conundrum by slightly re-arranging lock file validation and by explicitly checking whether the *new* `requires-python` is disjoint from the fork markers in the lock file. If it is, then we return `Versions` from lock file validation (indicating that the fork markers should be dropped). Fixes #13951
This commit is contained in:
parent
d653fbb133
commit
3d4f0c934e
4 changed files with 250 additions and 23 deletions
|
|
@ -768,6 +768,36 @@ impl Lock {
|
|||
}
|
||||
}
|
||||
|
||||
/// Checks whether the new requires-python specification is disjoint with
|
||||
/// the fork markers in this lock file.
|
||||
///
|
||||
/// If they are disjoint, then the union of the fork markers along with the
|
||||
/// given requires-python specification (converted to a marker tree) are
|
||||
/// returned.
|
||||
///
|
||||
/// When disjoint, the fork markers in the lock file should be dropped and
|
||||
/// not used.
|
||||
pub fn requires_python_coverage(
|
||||
&self,
|
||||
new_requires_python: &RequiresPython,
|
||||
) -> Result<(), (MarkerTree, MarkerTree)> {
|
||||
let fork_markers_union = if self.fork_markers().is_empty() {
|
||||
self.requires_python.to_marker_tree()
|
||||
} else {
|
||||
let mut fork_markers_union = MarkerTree::FALSE;
|
||||
for fork_marker in self.fork_markers() {
|
||||
fork_markers_union.or(fork_marker.pep508());
|
||||
}
|
||||
fork_markers_union
|
||||
};
|
||||
let new_requires_python = new_requires_python.to_marker_tree();
|
||||
if fork_markers_union.is_disjoint(new_requires_python) {
|
||||
Err((fork_markers_union, new_requires_python))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the TOML representation of this lockfile.
|
||||
pub fn to_toml(&self) -> Result<String, toml_edit::ser::Error> {
|
||||
// Catch a lockfile where the union of fork markers doesn't cover the supported
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue