Ignore Python patch version for --universal pip compile (#14405)

## Summary

The idea here is that if a user runs `uv pip compile --universal`, we
should ignore the patch version on the current interpreter. I think this
makes sense... `--universal` tries to resolve for all future versions,
so it seems a bit odd that we'd start at the _current_ patch version.

Closes https://github.com/astral-sh/uv/issues/14397.
This commit is contained in:
Charlie Marsh 2025-07-02 11:11:51 -04:00 committed by GitHub
parent 43f67a4a4c
commit a9ea756d14
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 66 additions and 23 deletions

View file

@ -337,13 +337,12 @@ pub(crate) async fn pip_compile(
// Determine the Python requirement, if the user requested a specific version.
let python_requirement = if universal {
let requires_python = RequiresPython::greater_than_equal_version(
if let Some(python_version) = python_version.as_ref() {
&python_version.version
} else {
interpreter.python_version()
},
);
let requires_python = if let Some(python_version) = python_version.as_ref() {
RequiresPython::greater_than_equal_version(&python_version.version)
} else {
let version = interpreter.python_minor_version();
RequiresPython::greater_than_equal_version(&version)
};
PythonRequirement::from_requires_python(&interpreter, requires_python)
} else if let Some(python_version) = python_version.as_ref() {
PythonRequirement::from_python_version(&interpreter, python_version)

View file

@ -16345,7 +16345,7 @@ fn pep_751_compile_registry_wheel() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "iniconfig"
@ -16394,7 +16394,7 @@ fn pep_751_compile_registry_sdist() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "source-distribution"
@ -16478,7 +16478,7 @@ fn pep_751_compile_directory() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "anyio"
@ -16549,7 +16549,7 @@ fn pep_751_compile_git() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "uv-public-pypackage"
@ -16599,7 +16599,7 @@ fn pep_751_compile_url_wheel() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "anyio"
@ -16663,7 +16663,7 @@ fn pep_751_compile_url_sdist() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "anyio"
@ -16732,7 +16732,7 @@ fn pep_751_compile_path_wheel() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "iniconfig"
@ -16770,7 +16770,7 @@ fn pep_751_compile_path_wheel() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o nested/pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "iniconfig"
@ -16811,7 +16811,7 @@ fn pep_751_compile_path_sdist() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "iniconfig"
@ -16850,7 +16850,7 @@ fn pep_751_compile_path_sdist() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o nested/pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "iniconfig"
@ -16887,7 +16887,7 @@ fn pep_751_compile_preferences() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "anyio"
@ -16928,7 +16928,7 @@ fn pep_751_compile_preferences() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "anyio"
@ -16968,7 +16968,7 @@ fn pep_751_compile_preferences() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "anyio"
@ -17007,7 +17007,7 @@ fn pep_751_compile_preferences() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "anyio"
@ -17055,7 +17055,7 @@ fn pep_751_compile_warn() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml --emit-index-url
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "iniconfig"
@ -17268,7 +17268,7 @@ fn pep_751_compile_no_emit_package() -> Result<()> {
# uv pip compile --cache-dir [CACHE_DIR] requirements.txt --universal -o pylock.toml --no-emit-package idna
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12.[X]"
requires-python = ">=3.12"
[[packages]]
name = "anyio"
@ -17562,3 +17562,47 @@ fn git_path_transitive_dependency() -> Result<()> {
Ok(())
}
/// Ensure that `--emit-index-annotation` plays nicely with `--annotation-style=line`.
#[test]
fn omit_python_patch_universal() -> Result<()> {
let context = TestContext::new("3.11");
let requirements_in = context.temp_dir.child("requirements.in");
requirements_in.write_str("redis")?;
uv_snapshot!(context.filters(), context.pip_compile()
.arg("requirements.in"), @r"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] requirements.in
redis==5.0.3
# via -r requirements.in
----- stderr -----
Resolved 1 package in [TIME]
"
);
uv_snapshot!(context.filters(), context.pip_compile()
.arg("requirements.in")
.arg("--universal"), @r"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] requirements.in --universal
async-timeout==4.0.3 ; python_full_version < '3.11.[X]'
# via redis
redis==5.0.3
# via -r requirements.in
----- stderr -----
Resolved 2 packages in [TIME]
"
);
Ok(())
}