mirror of
https://github.com/astral-sh/uv.git
synced 2025-09-30 14:01:13 +00:00
Add filtering of patch Python versions unless explicitly requested (#2930)
Elides Python patch versions from the test suite unless the test specifically requests a patch version. This reduces some toil when not using our bootstrapped Python versions. Partially addresses https://github.com/astral-sh/uv/issues/2165 though we'll need changes to the scenario tests to really support their case.
This commit is contained in:
parent
d7ff8d93c0
commit
1cdadbdec8
7 changed files with 82 additions and 38 deletions
|
@ -15,10 +15,11 @@ use std::env;
|
|||
use std::ffi::OsString;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Output;
|
||||
use std::str::FromStr;
|
||||
use uv_fs::Simplified;
|
||||
|
||||
use uv_cache::Cache;
|
||||
use uv_interpreter::find_requested_python;
|
||||
use uv_interpreter::{find_requested_python, PythonVersion};
|
||||
|
||||
// Exclude any packages uploaded after this date.
|
||||
pub static EXCLUDE_NEWER: &str = "2024-03-25T00:00:00Z";
|
||||
|
@ -69,6 +70,9 @@ impl TestContext {
|
|||
|
||||
let site_packages = site_packages_path(&venv, format!("python{python_version}"));
|
||||
|
||||
let python_version =
|
||||
PythonVersion::from_str(python_version).expect("Tests must use valid Python versions");
|
||||
|
||||
let mut filters = Vec::new();
|
||||
filters.extend(
|
||||
Self::path_patterns(&cache_dir)
|
||||
|
@ -123,6 +127,18 @@ impl TestContext {
|
|||
// Destroy any remaining UNC prefixes (Windows only)
|
||||
filters.push((r"\\\\\?\\".to_string(), String::new()));
|
||||
|
||||
// Add Python patch version filtering unless explicitly requested to ensure
|
||||
// snapshots are patch version agnostic when it is not a part of the test.
|
||||
if python_version.patch().is_none() {
|
||||
filters.push((
|
||||
format!(
|
||||
r"({})\.\d+",
|
||||
regex::escape(python_version.to_string().as_str())
|
||||
),
|
||||
"$1.[X]".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
Self {
|
||||
temp_dir,
|
||||
cache_dir,
|
||||
|
|
|
@ -5779,14 +5779,14 @@ requires-python = "<=3.8"
|
|||
let requirements_in = context.temp_dir.child("requirements.in");
|
||||
requirements_in.write_str(&format!("-e {}", editable_dir.path().display()))?;
|
||||
|
||||
uv_snapshot!(context.compile()
|
||||
uv_snapshot!(context.filters(), context.compile()
|
||||
.arg("requirements.in"), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: Editable `example` requires Python <=3.8, but resolution targets Python 3.12.1
|
||||
error: Editable `example` requires Python <=3.8, but resolution targets Python 3.12.[X]
|
||||
"###
|
||||
);
|
||||
|
||||
|
@ -6056,7 +6056,7 @@ requires-python = "<=3.8"
|
|||
let requirements_in = context.temp_dir.child("requirements.in");
|
||||
requirements_in.write_str(&format!("example @ {}", editable_dir.path().display()))?;
|
||||
|
||||
uv_snapshot!(context.compile()
|
||||
uv_snapshot!(context.filters(), context.compile()
|
||||
.arg("requirements.in"), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
|
@ -6064,7 +6064,7 @@ requires-python = "<=3.8"
|
|||
|
||||
----- stderr -----
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because the current Python version (3.12.1) does not satisfy Python<=3.8 and example==0.0.0 depends on Python<=3.8, we can conclude that example==0.0.0 cannot be used.
|
||||
╰─▶ Because the current Python version (3.12.[X]) does not satisfy Python<=3.8 and example==0.0.0 depends on Python<=3.8, we can conclude that example==0.0.0 cannot be used.
|
||||
And because only example==0.0.0 is available and you require example, we can conclude that the requirements are unsatisfiable.
|
||||
"###
|
||||
);
|
||||
|
|
|
@ -84,7 +84,7 @@ fn incompatible_python_compatible_override() -> Result<()> {
|
|||
package-a==1.0.0
|
||||
|
||||
----- stderr -----
|
||||
warning: The requested Python version 3.11 is not available; 3.9.18 will be used to build dependencies instead.
|
||||
warning: The requested Python version 3.11 is not available; 3.9.[X] will be used to build dependencies instead.
|
||||
Resolved 1 package in [TIME]
|
||||
"###
|
||||
);
|
||||
|
@ -130,7 +130,7 @@ fn compatible_python_incompatible_override() -> Result<()> {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
warning: The requested Python version 3.9 is not available; 3.11.7 will be used to build dependencies instead.
|
||||
warning: The requested Python version 3.9 is not available; 3.11.[X] will be used to build dependencies instead.
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because the requested Python version (3.9) does not satisfy Python>=3.10 and package-a==1.0.0 depends on Python>=3.10, we can conclude that package-a==1.0.0 cannot be used.
|
||||
And because you require package-a==1.0.0, we can conclude that the requirements are unsatisfiable.
|
||||
|
@ -184,9 +184,9 @@ fn incompatible_python_compatible_override_unavailable_no_wheels() -> Result<()>
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
warning: The requested Python version 3.11 is not available; 3.9.18 will be used to build dependencies instead.
|
||||
warning: The requested Python version 3.11 is not available; 3.9.[X] will be used to build dependencies instead.
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because the current Python version (3.9.18) does not satisfy Python>=3.10 and package-a==1.0.0 depends on Python>=3.10, we can conclude that package-a==1.0.0 cannot be used.
|
||||
╰─▶ Because the current Python version (3.9.[X]) does not satisfy Python>=3.10 and package-a==1.0.0 depends on Python>=3.10, we can conclude that package-a==1.0.0 cannot be used.
|
||||
And because you require package-a==1.0.0, we can conclude that the requirements are unsatisfiable.
|
||||
"###
|
||||
);
|
||||
|
@ -295,9 +295,9 @@ fn incompatible_python_compatible_override_no_compatible_wheels() -> Result<()>
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
warning: The requested Python version 3.11 is not available; 3.9.18 will be used to build dependencies instead.
|
||||
warning: The requested Python version 3.11 is not available; 3.9.[X] will be used to build dependencies instead.
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because the current Python version (3.9.18) does not satisfy Python>=3.10 and package-a==1.0.0 depends on Python>=3.10, we can conclude that package-a==1.0.0 cannot be used.
|
||||
╰─▶ Because the current Python version (3.9.[X]) does not satisfy Python>=3.10 and package-a==1.0.0 depends on Python>=3.10, we can conclude that package-a==1.0.0 cannot be used.
|
||||
And because you require package-a==1.0.0, we can conclude that the requirements are unsatisfiable.
|
||||
"###
|
||||
);
|
||||
|
@ -353,9 +353,9 @@ fn incompatible_python_compatible_override_other_wheel() -> Result<()> {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
warning: The requested Python version 3.11 is not available; 3.9.18 will be used to build dependencies instead.
|
||||
warning: The requested Python version 3.11 is not available; 3.9.[X] will be used to build dependencies instead.
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because the current Python version (3.9.18) does not satisfy Python>=3.10 and package-a==1.0.0 depends on Python>=3.10, we can conclude that package-a==1.0.0 cannot be used.
|
||||
╰─▶ Because the current Python version (3.9.[X]) does not satisfy Python>=3.10 and package-a==1.0.0 depends on Python>=3.10, we can conclude that package-a==1.0.0 cannot be used.
|
||||
And because only the following versions of package-a are available:
|
||||
package-a==1.0.0
|
||||
package-a==2.0.0
|
||||
|
|
|
@ -2415,7 +2415,7 @@ requires-python = "<=3.8"
|
|||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.install()
|
||||
uv_snapshot!(context.filters(), context.install()
|
||||
.arg("--editable")
|
||||
.arg(editable_dir.path()), @r###"
|
||||
success: false
|
||||
|
@ -2423,7 +2423,7 @@ requires-python = "<=3.8"
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: Editable `example` requires Python <=3.8, but 3.12.1 is installed
|
||||
error: Editable `example` requires Python <=3.8, but 3.12.[X] is installed
|
||||
"###
|
||||
);
|
||||
|
||||
|
@ -2864,7 +2864,7 @@ requires-python = "<=3.8"
|
|||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.install()
|
||||
uv_snapshot!(context.filters(), context.install()
|
||||
.arg(format!("example @ {}", editable_dir.path().display())), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
|
@ -2872,7 +2872,7 @@ requires-python = "<=3.8"
|
|||
|
||||
----- stderr -----
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because the current Python version (3.12.1) does not satisfy Python<=3.8 and example==0.0.0 depends on Python<=3.8, we can conclude that example==0.0.0 cannot be used.
|
||||
╰─▶ Because the current Python version (3.12.[X]) does not satisfy Python<=3.8 and example==0.0.0 depends on Python<=3.8, we can conclude that example==0.0.0 cannot be used.
|
||||
And because only example==0.0.0 is available and you require example, we can conclude that the requirements are unsatisfiable.
|
||||
"###
|
||||
);
|
||||
|
|
|
@ -3671,7 +3671,7 @@ fn python_version_does_not_exist() {
|
|||
|
||||
----- stderr -----
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because the current Python version (3.8.18) does not satisfy Python>=3.30 and package-a==1.0.0 depends on Python>=3.30, we can conclude that package-a==1.0.0 cannot be used.
|
||||
╰─▶ Because the current Python version (3.8.[X]) does not satisfy Python>=3.30 and package-a==1.0.0 depends on Python>=3.30, we can conclude that package-a==1.0.0 cannot be used.
|
||||
And because you require package-a==1.0.0, we can conclude that the requirements are unsatisfiable.
|
||||
"###);
|
||||
|
||||
|
@ -3713,7 +3713,7 @@ fn python_less_than_current() {
|
|||
|
||||
----- stderr -----
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because the current Python version (3.9.18) does not satisfy Python<=3.8 and package-a==1.0.0 depends on Python<=3.8, we can conclude that package-a==1.0.0 cannot be used.
|
||||
╰─▶ Because the current Python version (3.9.[X]) does not satisfy Python<=3.8 and package-a==1.0.0 depends on Python<=3.8, we can conclude that package-a==1.0.0 cannot be used.
|
||||
And because you require package-a==1.0.0, we can conclude that the requirements are unsatisfiable.
|
||||
"###);
|
||||
|
||||
|
@ -3755,7 +3755,7 @@ fn python_greater_than_current() {
|
|||
|
||||
----- stderr -----
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because the current Python version (3.9.18) does not satisfy Python>=3.10 and package-a==1.0.0 depends on Python>=3.10, we can conclude that package-a==1.0.0 cannot be used.
|
||||
╰─▶ Because the current Python version (3.9.[X]) does not satisfy Python>=3.10 and package-a==1.0.0 depends on Python>=3.10, we can conclude that package-a==1.0.0 cannot be used.
|
||||
And because you require package-a==1.0.0, we can conclude that the requirements are unsatisfiable.
|
||||
"###);
|
||||
|
||||
|
@ -3961,22 +3961,22 @@ fn python_greater_than_current_excluded() {
|
|||
|
||||
----- stderr -----
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because the current Python version (3.9.18) does not satisfy Python>=3.10,<3.11 and the current Python version (3.9.18) does not satisfy Python>=3.12, we can conclude that any of:
|
||||
╰─▶ Because the current Python version (3.9.[X]) does not satisfy Python>=3.10,<3.11 and the current Python version (3.9.[X]) does not satisfy Python>=3.12, we can conclude that any of:
|
||||
Python>=3.10,<3.11
|
||||
Python>=3.12
|
||||
are incompatible.
|
||||
And because the current Python version (3.9.18) does not satisfy Python>=3.11,<3.12, we can conclude that Python>=3.10 are incompatible.
|
||||
And because the current Python version (3.9.[X]) does not satisfy Python>=3.11,<3.12, we can conclude that Python>=3.10 are incompatible.
|
||||
And because package-a==2.0.0 depends on Python>=3.10 and only the following versions of package-a are available:
|
||||
package-a<=2.0.0
|
||||
package-a==3.0.0
|
||||
package-a==4.0.0
|
||||
we can conclude that package-a>=2.0.0,<3.0.0 cannot be used. (1)
|
||||
|
||||
Because the current Python version (3.9.18) does not satisfy Python>=3.11,<3.12 and the current Python version (3.9.18) does not satisfy Python>=3.12, we can conclude that Python>=3.11 are incompatible.
|
||||
Because the current Python version (3.9.[X]) does not satisfy Python>=3.11,<3.12 and the current Python version (3.9.[X]) does not satisfy Python>=3.12, we can conclude that Python>=3.11 are incompatible.
|
||||
And because package-a==3.0.0 depends on Python>=3.11, we can conclude that package-a==3.0.0 cannot be used.
|
||||
And because we know from (1) that package-a>=2.0.0,<3.0.0 cannot be used, we can conclude that package-a>=2.0.0,<4.0.0 cannot be used. (2)
|
||||
|
||||
Because the current Python version (3.9.18) does not satisfy Python>=3.12 and package-a==4.0.0 depends on Python>=3.12, we can conclude that package-a==4.0.0 cannot be used.
|
||||
Because the current Python version (3.9.[X]) does not satisfy Python>=3.12 and package-a==4.0.0 depends on Python>=3.12, we can conclude that package-a==4.0.0 cannot be used.
|
||||
And because we know from (2) that package-a>=2.0.0,<4.0.0 cannot be used, we can conclude that package-a>=2.0.0 cannot be used.
|
||||
And because you require package-a>=2.0.0, we can conclude that the requirements are unsatisfiable.
|
||||
"###);
|
||||
|
|
|
@ -2995,14 +2995,14 @@ requires-python = "<=3.5"
|
|||
let requirements_in = context.temp_dir.child("requirements.in");
|
||||
requirements_in.write_str(&format!("-e {}", editable_dir.path().display()))?;
|
||||
|
||||
uv_snapshot!(command(&context)
|
||||
uv_snapshot!(context.filters(), command(&context)
|
||||
.arg("requirements.in"), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: Editable `example` requires Python <=3.5, but 3.12.1 is installed
|
||||
error: Editable `example` requires Python <=3.5, but 3.12.[X] is installed
|
||||
"###
|
||||
);
|
||||
|
||||
|
@ -3071,7 +3071,7 @@ requires-python = "<=3.5"
|
|||
|
||||
----- stderr -----
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because the current Python version (3.12.1) does not satisfy Python<=3.5 and example==0.0.0 depends on Python<=3.5, we can conclude that example==0.0.0 cannot be used.
|
||||
╰─▶ Because the current Python version (3.12.[X]) does not satisfy Python<=3.5 and example==0.0.0 depends on Python<=3.5, we can conclude that example==0.0.0 cannot be used.
|
||||
And because only example==0.0.0 is available and you require example, we can conclude that the requirements are unsatisfiable.
|
||||
"###
|
||||
);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![cfg(feature = "python")]
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::process::Command;
|
||||
use std::{ffi::OsString, str::FromStr};
|
||||
|
||||
use anyhow::Result;
|
||||
use assert_cmd::prelude::*;
|
||||
|
@ -9,6 +9,7 @@ use assert_fs::fixture::ChildPath;
|
|||
use assert_fs::prelude::*;
|
||||
use fs_err::PathExt;
|
||||
use uv_fs::Simplified;
|
||||
use uv_interpreter::PythonVersion;
|
||||
|
||||
use crate::common::{
|
||||
create_bin_with_executables, get_bin, uv_snapshot, TestContext, EXCLUDE_NEWER,
|
||||
|
@ -21,6 +22,7 @@ struct VenvTestContext {
|
|||
temp_dir: assert_fs::TempDir,
|
||||
venv: ChildPath,
|
||||
bin: OsString,
|
||||
python_versions: Vec<PythonVersion>,
|
||||
}
|
||||
|
||||
impl VenvTestContext {
|
||||
|
@ -29,11 +31,18 @@ impl VenvTestContext {
|
|||
let bin = create_bin_with_executables(&temp_dir, python_versions)
|
||||
.expect("Failed to create bin dir");
|
||||
let venv = temp_dir.child(".venv");
|
||||
let python_versions = python_versions
|
||||
.iter()
|
||||
.map(|version| {
|
||||
PythonVersion::from_str(version).expect("Tests should use valid Python versions")
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
Self {
|
||||
cache_dir: assert_fs::TempDir::new().unwrap(),
|
||||
temp_dir,
|
||||
venv,
|
||||
bin,
|
||||
python_versions,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,6 +79,25 @@ impl VenvTestContext {
|
|||
r"Activate with: (?:.*)\\Scripts\\activate".to_string(),
|
||||
"Activate with: source .venv/bin/activate".to_string(),
|
||||
));
|
||||
|
||||
// Add Python patch version filtering unless one was explicitly requested to ensure
|
||||
// snapshots are patch version agnostic when it is not a part of the test.
|
||||
if self
|
||||
.python_versions
|
||||
.iter()
|
||||
.all(|version| version.patch().is_none())
|
||||
{
|
||||
for python_version in &self.python_versions {
|
||||
filters.push((
|
||||
format!(
|
||||
r"({})\.\d+",
|
||||
regex::escape(python_version.to_string().as_str())
|
||||
),
|
||||
"$1.[X]".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
filters
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +116,7 @@ fn create_venv() {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.12.1 interpreter at: [PATH]
|
||||
Using Python 3.12.[X] interpreter at: [PATH]
|
||||
Creating virtualenv at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
"###
|
||||
|
@ -107,7 +135,7 @@ fn create_venv() {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.12.1 interpreter at: [PATH]
|
||||
Using Python 3.12.[X] interpreter at: [PATH]
|
||||
Creating virtualenv at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
"###
|
||||
|
@ -128,7 +156,7 @@ fn create_venv_defaults_to_cwd() {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.12.1 interpreter at: [PATH]
|
||||
Using Python 3.12.[X] interpreter at: [PATH]
|
||||
Creating virtualenv at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
"###
|
||||
|
@ -151,7 +179,7 @@ fn seed() {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.12.1 interpreter at: [PATH]
|
||||
Using Python 3.12.[X] interpreter at: [PATH]
|
||||
Creating virtualenv at: .venv
|
||||
+ pip==24.0
|
||||
Activate with: source .venv/bin/activate
|
||||
|
@ -175,7 +203,7 @@ fn seed_older_python_version() {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.10.13 interpreter at: [PATH]
|
||||
Using Python 3.10.[X] interpreter at: [PATH]
|
||||
Creating virtualenv at: .venv
|
||||
+ pip==24.0
|
||||
+ setuptools==69.2.0
|
||||
|
@ -293,7 +321,7 @@ fn file_exists() -> Result<()> {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.12.1 interpreter at: [PATH]
|
||||
Using Python 3.12.[X] interpreter at: [PATH]
|
||||
Creating virtualenv at: .venv
|
||||
uv::venv::creation
|
||||
|
||||
|
@ -321,7 +349,7 @@ fn empty_dir_exists() -> Result<()> {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.12.1 interpreter at: [PATH]
|
||||
Using Python 3.12.[X] interpreter at: [PATH]
|
||||
Creating virtualenv at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
"###
|
||||
|
@ -350,7 +378,7 @@ fn non_empty_dir_exists() -> Result<()> {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using Python 3.12.1 interpreter at: [PATH]
|
||||
Using Python 3.12.[X] interpreter at: [PATH]
|
||||
Creating virtualenv at: .venv
|
||||
uv::venv::creation
|
||||
|
||||
|
@ -395,7 +423,7 @@ fn windows_shims() -> Result<()> {
|
|||
|
||||
----- stderr -----
|
||||
warning: virtualenv's `--clear` has no effect (uv always clears the virtual environment).
|
||||
Using Python 3.8.12 interpreter at: [PATH]
|
||||
Using Python 3.8.[X] interpreter at: [PATH]
|
||||
Creating virtualenv at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
"###
|
||||
|
@ -422,7 +450,7 @@ fn virtualenv_compatibility() {
|
|||
|
||||
----- stderr -----
|
||||
warning: virtualenv's `--clear` has no effect (uv always clears the virtual environment).
|
||||
Using Python 3.12.1 interpreter at: [PATH]
|
||||
Using Python 3.12.[X] interpreter at: [PATH]
|
||||
Creating virtualenv at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
"###
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue