Skip to content

Commit f80003a

Browse files
authored
Add uv python list test cases (#12374)
Needed for - #12367 - #12375
1 parent bbf4f83 commit f80003a

File tree

3 files changed

+172
-0
lines changed

3 files changed

+172
-0
lines changed

crates/uv/tests/it/common/mod.rs

+33
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,27 @@ impl TestContext {
224224
self
225225
}
226226

227+
/// Add extra filtering for ` -> <PATH>` symlink display for Python versions in the test
228+
/// context, e.g., for use in `uv python list`.
229+
#[must_use]
230+
pub fn with_filtered_python_symlinks(mut self) -> Self {
231+
for (version, executable) in &self.python_versions {
232+
if fs_err::symlink_metadata(executable).unwrap().is_symlink() {
233+
self.filters.extend(
234+
Self::path_patterns(executable.read_link().unwrap())
235+
.into_iter()
236+
.map(|pattern| (format! {" -> {pattern}"}, String::new())),
237+
);
238+
}
239+
// Drop links that are byproducts of the test context too
240+
self.filters.push((
241+
regex::escape(&format!(" -> [PYTHON-{version}]")),
242+
String::new(),
243+
));
244+
}
245+
self
246+
}
247+
227248
/// Add extra standard filtering for a given path.
228249
#[must_use]
229250
pub fn with_filtered_path(mut self, path: &Path, name: &str) -> Self {
@@ -803,6 +824,18 @@ impl TestContext {
803824
command
804825
}
805826

827+
/// Create a `uv python list` command with options shared across scenarios.
828+
pub fn python_list(&self) -> Command {
829+
let mut command = self.new_command();
830+
command
831+
.arg("python")
832+
.arg("list")
833+
.env(EnvVars::UV_PYTHON_INSTALL_DIR, "")
834+
.current_dir(&self.temp_dir);
835+
self.add_shared_options(&mut command, false);
836+
command
837+
}
838+
806839
/// Create a `uv python install` command with options shared across scenarios.
807840
pub fn python_install(&self) -> Command {
808841
let mut command = self.new_command();

crates/uv/tests/it/main.rs

+3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ mod python_dir;
7272
#[cfg(feature = "python")]
7373
mod python_find;
7474

75+
#[cfg(feature = "python")]
76+
mod python_list;
77+
7578
#[cfg(feature = "python-managed")]
7679
mod python_install;
7780

crates/uv/tests/it/python_list.rs

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
use uv_static::EnvVars;
2+
3+
use crate::common::{uv_snapshot, TestContext};
4+
5+
#[test]
6+
fn python_list() {
7+
let mut context: TestContext = TestContext::new_with_versions(&["3.11", "3.12"])
8+
.with_filtered_python_symlinks()
9+
.with_filtered_python_keys();
10+
11+
uv_snapshot!(context.filters(), context.python_list().env(EnvVars::UV_TEST_PYTHON_PATH, ""), @r"
12+
success: true
13+
exit_code: 0
14+
----- stdout -----
15+
16+
----- stderr -----
17+
");
18+
19+
// We show all interpreters
20+
uv_snapshot!(context.filters(), context.python_list(), @r"
21+
success: true
22+
exit_code: 0
23+
----- stdout -----
24+
cpython-3.12.[X]-[PLATFORM] [PYTHON-3.12]
25+
cpython-3.11.[X]-[PLATFORM] [PYTHON-3.11]
26+
27+
----- stderr -----
28+
");
29+
30+
// Swap the order of the Python versions
31+
context.python_versions.reverse();
32+
33+
uv_snapshot!(context.filters(), context.python_list(), @r"
34+
success: true
35+
exit_code: 0
36+
----- stdout -----
37+
cpython-3.12.[X]-[PLATFORM] [PYTHON-3.12]
38+
cpython-3.11.[X]-[PLATFORM] [PYTHON-3.11]
39+
40+
----- stderr -----
41+
");
42+
43+
// Request Python 3.11
44+
uv_snapshot!(context.filters(), context.python_list().arg("3.11"), @r"
45+
success: false
46+
exit_code: 2
47+
----- stdout -----
48+
49+
----- stderr -----
50+
error: unexpected argument '3.11' found
51+
52+
Usage: uv python list [OPTIONS]
53+
54+
For more information, try '--help'.
55+
");
56+
}
57+
58+
#[test]
59+
fn python_list_pin() {
60+
let context: TestContext = TestContext::new_with_versions(&["3.11", "3.12"])
61+
.with_filtered_python_symlinks()
62+
.with_filtered_python_keys();
63+
64+
// Pin to a version
65+
uv_snapshot!(context.filters(), context.python_pin().arg("3.12"), @r###"
66+
success: true
67+
exit_code: 0
68+
----- stdout -----
69+
Pinned `.python-version` to `3.12`
70+
71+
----- stderr -----
72+
"###);
73+
74+
// The pin should not affect the listing
75+
uv_snapshot!(context.filters(), context.python_list(), @r"
76+
success: true
77+
exit_code: 0
78+
----- stdout -----
79+
cpython-3.12.[X]-[PLATFORM] [PYTHON-3.12]
80+
cpython-3.11.[X]-[PLATFORM] [PYTHON-3.11]
81+
82+
----- stderr -----
83+
");
84+
85+
// So `--no-config` has no effect
86+
uv_snapshot!(context.filters(), context.python_list().arg("--no-config"), @r"
87+
success: true
88+
exit_code: 0
89+
----- stdout -----
90+
cpython-3.12.[X]-[PLATFORM] [PYTHON-3.12]
91+
cpython-3.11.[X]-[PLATFORM] [PYTHON-3.11]
92+
93+
----- stderr -----
94+
");
95+
}
96+
97+
#[test]
98+
fn python_list_venv() {
99+
let context: TestContext = TestContext::new_with_versions(&["3.11", "3.12"])
100+
.with_filtered_python_symlinks()
101+
.with_filtered_python_keys()
102+
.with_filtered_exe_suffix()
103+
.with_filtered_python_names()
104+
.with_filtered_virtualenv_bin();
105+
106+
// Create a virtual environment
107+
uv_snapshot!(context.filters(), context.venv().arg("--python").arg("3.12").arg("-q"), @r###"
108+
success: true
109+
exit_code: 0
110+
----- stdout -----
111+
112+
----- stderr -----
113+
"###);
114+
115+
// We should not display the virtual environment
116+
uv_snapshot!(context.filters(), context.python_list(), @r"
117+
success: true
118+
exit_code: 0
119+
----- stdout -----
120+
cpython-3.12.[X]-[PLATFORM] [PYTHON-3.12]
121+
cpython-3.11.[X]-[PLATFORM] [PYTHON-3.11]
122+
123+
----- stderr -----
124+
");
125+
126+
// Same if the `VIRTUAL_ENV` is not set (the test context includes it by default)
127+
uv_snapshot!(context.filters(), context.python_list().env_remove(EnvVars::VIRTUAL_ENV), @r"
128+
success: true
129+
exit_code: 0
130+
----- stdout -----
131+
cpython-3.12.[X]-[PLATFORM] [PYTHON-3.12]
132+
cpython-3.11.[X]-[PLATFORM] [PYTHON-3.11]
133+
134+
----- stderr -----
135+
");
136+
}

0 commit comments

Comments
 (0)