Skip to content

Commit dbc97d7

Browse files
committed
Add support for Python version requests in uv python list
1 parent 5cafd11 commit dbc97d7

File tree

5 files changed

+58
-102
lines changed

5 files changed

+58
-102
lines changed

crates/uv-cli/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4557,6 +4557,11 @@ pub enum PythonCommand {
45574557
#[derive(Args)]
45584558
#[allow(clippy::struct_excessive_bools)]
45594559
pub struct PythonListArgs {
4560+
/// A Python request to filter by.
4561+
///
4562+
/// See `uv help python` to view supported request formats.
4563+
pub request: Option<String>,
4564+
45604565
/// List all Python versions, including old patch versions.
45614566
///
45624567
/// By default, only the latest patch version is shown for each minor version.

crates/uv/src/commands/python/list.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct PrintData {
5252
/// List available Python installations.
5353
#[allow(clippy::too_many_arguments, clippy::fn_params_excessive_bools)]
5454
pub(crate) async fn list(
55+
request: Option<String>,
5556
kinds: PythonListKinds,
5657
all_versions: bool,
5758
all_platforms: bool,
@@ -63,23 +64,31 @@ pub(crate) async fn list(
6364
cache: &Cache,
6465
printer: Printer,
6566
) -> Result<ExitStatus> {
67+
let request = request.as_deref().map(PythonRequest::parse);
68+
let base_download_request = if python_preference == PythonPreference::OnlySystem {
69+
None
70+
} else {
71+
// If the user request cannot be mapped to a download request, we won't show any downloads
72+
PythonDownloadRequest::from_request(request.as_ref().unwrap_or(&PythonRequest::Any))
73+
};
74+
6675
let mut output = BTreeSet::new();
67-
if python_preference != PythonPreference::OnlySystem {
76+
if let Some(base_download_request) = base_download_request {
6877
let download_request = match kinds {
6978
PythonListKinds::Installed => None,
7079
PythonListKinds::Downloads => Some(if all_platforms {
71-
PythonDownloadRequest::default()
80+
base_download_request
7281
} else {
73-
PythonDownloadRequest::from_env()?
82+
base_download_request.fill()?
7483
}),
7584
PythonListKinds::Default => {
7685
if python_downloads.is_automatic() {
7786
Some(if all_platforms {
78-
PythonDownloadRequest::default()
87+
base_download_request
7988
} else if all_arches {
80-
PythonDownloadRequest::from_env()?.with_any_arch()
89+
base_download_request.fill()?.with_any_arch()
8190
} else {
82-
PythonDownloadRequest::from_env()?
91+
base_download_request.fill()?
8392
})
8493
} else {
8594
// If fetching is not automatic, then don't show downloads as available by default
@@ -109,7 +118,7 @@ pub(crate) async fn list(
109118
match kinds {
110119
PythonListKinds::Installed | PythonListKinds::Default => {
111120
Some(find_python_installations(
112-
&PythonRequest::Any,
121+
request.as_ref().unwrap_or(&PythonRequest::Any),
113122
EnvironmentPreference::OnlySystem,
114123
python_preference,
115124
cache,

crates/uv/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
12441244
let cache = cache.init()?;
12451245

12461246
commands::python_list(
1247+
args.request,
12471248
args.kinds,
12481249
args.all_versions,
12491250
args.all_platforms,

crates/uv/src/settings.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,7 @@ pub(crate) enum PythonListKinds {
820820
#[allow(clippy::struct_excessive_bools)]
821821
#[derive(Debug, Clone)]
822822
pub(crate) struct PythonListSettings {
823+
pub(crate) request: Option<String>,
823824
pub(crate) kinds: PythonListKinds,
824825
pub(crate) all_platforms: bool,
825826
pub(crate) all_arches: bool,
@@ -833,6 +834,7 @@ impl PythonListSettings {
833834
#[allow(clippy::needless_pass_by_value)]
834835
pub(crate) fn resolve(args: PythonListArgs, _filesystem: Option<FilesystemOptions>) -> Self {
835836
let PythonListArgs {
837+
request,
836838
all_versions,
837839
all_platforms,
838840
all_arches,
@@ -851,6 +853,7 @@ impl PythonListSettings {
851853
};
852854

853855
Self {
856+
request,
854857
kinds,
855858
all_platforms,
856859
all_arches,

crates/uv/tests/it/python_list.rs

Lines changed: 33 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -30,103 +30,75 @@ fn python_list() {
3030

3131
// Request Python 3.12
3232
uv_snapshot!(context.filters(), context.python_list().arg("3.12"), @r"
33-
success: false
34-
exit_code: 2
33+
success: true
34+
exit_code: 0
3535
----- stdout -----
36+
cpython-3.12.[X]-[PLATFORM] [PYTHON-3.12]
3637
3738
----- stderr -----
38-
error: unexpected argument '3.12' found
39-
40-
Usage: uv python list [OPTIONS]
41-
42-
For more information, try '--help'.
4339
");
4440

4541
// Request Python 3.11
4642
uv_snapshot!(context.filters(), context.python_list().arg("3.11"), @r"
47-
success: false
48-
exit_code: 2
43+
success: true
44+
exit_code: 0
4945
----- stdout -----
46+
cpython-3.11.[X]-[PLATFORM] [PYTHON-3.11]
5047
5148
----- stderr -----
52-
error: unexpected argument '3.11' found
53-
54-
Usage: uv python list [OPTIONS]
55-
56-
For more information, try '--help'.
5749
");
5850

5951
// Request CPython
6052
uv_snapshot!(context.filters(), context.python_list().arg("cpython"), @r"
61-
success: false
62-
exit_code: 2
53+
success: true
54+
exit_code: 0
6355
----- stdout -----
56+
cpython-3.12.[X]-[PLATFORM] [PYTHON-3.12]
57+
cpython-3.11.[X]-[PLATFORM] [PYTHON-3.11]
6458
6559
----- stderr -----
66-
error: unexpected argument 'cpython' found
67-
68-
Usage: uv python list [OPTIONS]
69-
70-
For more information, try '--help'.
7160
");
7261

7362
// Request CPython 3.12
7463
uv_snapshot!(context.filters(), context.python_list().arg("[email protected]"), @r"
75-
success: false
76-
exit_code: 2
64+
success: true
65+
exit_code: 0
7766
----- stdout -----
67+
cpython-3.12.[X]-[PLATFORM] [PYTHON-3.12]
7868
7969
----- stderr -----
80-
error: unexpected argument '[email protected]' found
81-
82-
Usage: uv python list [OPTIONS]
83-
84-
For more information, try '--help'.
8570
");
8671

8772
// Request CPython 3.12 via partial key syntax
8873
uv_snapshot!(context.filters(), context.python_list().arg("cpython-3.12"), @r"
89-
success: false
90-
exit_code: 2
74+
success: true
75+
exit_code: 0
9176
----- stdout -----
77+
cpython-3.12.[X]-[PLATFORM] [PYTHON-3.12]
9278
9379
----- stderr -----
94-
error: unexpected argument 'cpython-3.12' found
95-
96-
Usage: uv python list [OPTIONS]
97-
98-
For more information, try '--help'.
9980
");
10081

10182
// Request CPython 3.12 for the current platform
10283
let os = Os::from_env();
10384
let arch = Arch::from_env();
10485

10586
uv_snapshot!(context.filters(), context.python_list().arg(format!("cpython-3.12-{os}-{arch}")), @r"
106-
success: false
107-
exit_code: 2
87+
success: true
88+
exit_code: 0
10889
----- stdout -----
90+
cpython-3.12.[X]-[PLATFORM] [PYTHON-3.12]
10991
11092
----- stderr -----
111-
error: unexpected argument 'cpython-3.12-macos-aarch64' found
112-
113-
Usage: uv python list [OPTIONS]
114-
115-
For more information, try '--help'.
11693
");
11794

11895
// Request PyPy (which should be missing)
11996
uv_snapshot!(context.filters(), context.python_list().arg("pypy"), @r"
120-
success: false
121-
exit_code: 2
97+
success: true
98+
exit_code: 0
12299
----- stdout -----
123100
124101
----- stderr -----
125-
error: unexpected argument 'pypy' found
126-
127-
Usage: uv python list [OPTIONS]
128-
129-
For more information, try '--help'.
130102
");
131103

132104
// Swap the order of the Python versions
@@ -144,16 +116,12 @@ fn python_list() {
144116

145117
// Request Python 3.11
146118
uv_snapshot!(context.filters(), context.python_list().arg("3.11"), @r"
147-
success: false
148-
exit_code: 2
119+
success: true
120+
exit_code: 0
149121
----- stdout -----
122+
cpython-3.11.[X]-[PLATFORM] [PYTHON-3.11]
150123
151124
----- stderr -----
152-
error: unexpected argument '3.11' found
153-
154-
Usage: uv python list [OPTIONS]
155-
156-
For more information, try '--help'.
157125
");
158126
}
159127

@@ -251,11 +219,7 @@ fn python_list_unsupported_version() {
251219
----- stdout -----
252220
253221
----- stderr -----
254-
error: unexpected argument '3.6' found
255-
256-
Usage: uv python list [OPTIONS]
257-
258-
For more information, try '--help'.
222+
error: Invalid version request: Python <3.7 is not supported but 3.6 was requested.
259223
");
260224

261225
// Request a low version with a patch
@@ -265,11 +229,7 @@ fn python_list_unsupported_version() {
265229
----- stdout -----
266230
267231
----- stderr -----
268-
error: unexpected argument '3.6.9' found
269-
270-
Usage: uv python list [OPTIONS]
271-
272-
For more information, try '--help'.
232+
error: Invalid version request: Python <3.7 is not supported but 3.6.9 was requested.
273233
");
274234

275235
// Request a really low version
@@ -279,11 +239,7 @@ fn python_list_unsupported_version() {
279239
----- stdout -----
280240
281241
----- stderr -----
282-
error: unexpected argument '2.6' found
283-
284-
Usage: uv python list [OPTIONS]
285-
286-
For more information, try '--help'.
242+
error: Invalid version request: Python <3.7 is not supported but 2.6 was requested.
287243
");
288244

289245
// Request a really low version with a patch
@@ -293,39 +249,25 @@ fn python_list_unsupported_version() {
293249
----- stdout -----
294250
295251
----- stderr -----
296-
error: unexpected argument '2.6.8' found
297-
298-
Usage: uv python list [OPTIONS]
299-
300-
For more information, try '--help'.
252+
error: Invalid version request: Python <3.7 is not supported but 2.6.8 was requested.
301253
");
302254

303255
// Request a future version
304256
uv_snapshot!(context.filters(), context.python_list().arg("4.2"), @r"
305-
success: false
306-
exit_code: 2
257+
success: true
258+
exit_code: 0
307259
----- stdout -----
308260
309261
----- stderr -----
310-
error: unexpected argument '4.2' found
311-
312-
Usage: uv python list [OPTIONS]
313-
314-
For more information, try '--help'.
315262
");
316263

317264
// Request a low version with a range
318265
uv_snapshot!(context.filters(), context.python_list().arg("<3.0"), @r"
319-
success: false
320-
exit_code: 2
266+
success: true
267+
exit_code: 0
321268
----- stdout -----
322269
323270
----- stderr -----
324-
error: unexpected argument '<3.0' found
325-
326-
Usage: uv python list [OPTIONS]
327-
328-
For more information, try '--help'.
329271
");
330272

331273
// Request free-threaded Python on unsupported version
@@ -335,10 +277,6 @@ fn python_list_unsupported_version() {
335277
----- stdout -----
336278
337279
----- stderr -----
338-
error: unexpected argument '3.12t' found
339-
340-
Usage: uv python list [OPTIONS]
341-
342-
For more information, try '--help'.
280+
error: Invalid version request: Python <3.13 does not support free-threading but 3.12t was requested.
343281
");
344282
}

0 commit comments

Comments
 (0)