Skip to content

Comments

feature(python list): added --format param to uv python list#10448

Closed
jzlotek wants to merge 4 commits intoastral-sh:mainfrom
jzlotek:jzlotek/python-list-json
Closed

feature(python list): added --format param to uv python list#10448
jzlotek wants to merge 4 commits intoastral-sh:mainfrom
jzlotek:jzlotek/python-list-json

Conversation

@jzlotek
Copy link
Contributor

@jzlotek jzlotek commented Jan 9, 2025

Summary

I use uv for automation on remote hosts and it would be useful to have it be able to tell me the supported versions of python (for the remote machine) in a machine readable manner so I do not need to parse uv python list.

This change adds --format (json|text) to uv python list to make it's output machine readable

Loosely related:

Test Plan

Manually tested via

# quick inspection without pretty print
cargo run -- python list --format json

Short example of output (trimmed down)

Cmd: cargo run -- python list --format json | jq '.[:2]'

[
  {
    "key": "cpython-3.13.1+freethreaded-linux-x86_64-gnu",
    "version": "3.13.1",
    "version_parts": {
      "major": 3,
      "minor": 13,
      "patch": 1
    },
    "path": null,
    "symlink": null,
    "url": "https://github.com/astral-sh/python-build-standalone/releases/download/20241219/cpython-3.13.1%2B20241219-x86_64-unknown-linux-gnu-freethreaded%2Bpgo%2Blto-full.tar.zst",
    "os": "linux",
    "variant": "freethreaded",
    "implementation": "cpython",
    "arch": "x86_64",
    "libc": "gnu"
  },
  {
    "key": "cpython-3.13.1-linux-x86_64-gnu",
    "version": "3.13.1",
    "version_parts": {
      "major": 3,
      "minor": 13,
      "patch": 1
    },
    "path": "/usr/bin/python3.13",
    "symlink": null,
    "url": null,
    "os": "linux",
    "variant": "default",
    "implementation": "cpython",
    "arch": "x86_64",
    "libc": "gnu"
  }
]

@zanieb zanieb requested review from Gankra and zanieb January 9, 2025 22:22
Copy link
Contributor

@Gankra Gankra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks good except one detail. Although not 100% confident on if there's any fields that would be "bad" to expose since machine-readable outputs are ideally making a stronger guarantee of stable output.

Comment on lines 192 to 194
Either::Left(path) => {
let is_symlink = fs_err::symlink_metadata(path).unwrap().is_symlink();
if is_symlink {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

afaict these 3 paths only differ by one field each. I'd like to see this refactored to just compute the 2 special fields and then make one PrintData at the end.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you're right! I'll make that adjustment. Thanks for the pointer.

@jzlotek
Copy link
Contributor Author

jzlotek commented Jan 10, 2025

Everything looks good except one detail. Although not 100% confident on if there's any fields that would be "bad" to expose since machine-readable outputs are ideally making a stronger guarantee of stable output.

I'll think about it. The only thing I can think of adding that is probably worthwhile is to add the version parts. Thoughts? I am not super familiar with the api as this is my first time doing rust/uv work so any suggestions would be appriciated

Copy link
Contributor

@Gankra Gankra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a bunch, I'll do the last little fixes because they need some turbofish surgery

version_parts: NamedVersionParts {
major: *(release.get(0).unwrap_or(&0)),
minor: *(release.get(1).unwrap_or(&0)),
patch: *(release.get(2).unwrap_or(&0)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Sharing Tips) I think either is fine here but letting you know the copied api exists:

patch: release.get(2).copied().unwrap_or(0),

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also in this case also patch: release.get(2).copied().unwrap_or_default(), but i think what you have is clearer in that regard.

Either::Left(path) => {
path_or_none = Some(path.user_display().to_string());

let is_symlink = fs_err::symlink_metadata(path).unwrap().is_symlink();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let is_symlink = fs_err::symlink_metadata(path).unwrap().is_symlink();
let is_symlink = fs_err::symlink_metadata(path)?.is_symlink();

let is_symlink = fs_err::symlink_metadata(path).unwrap().is_symlink();
if is_symlink {
symlink_or_none =
Some(path.read_link().unwrap().user_display().to_string());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Some(path.read_link().unwrap().user_display().to_string());
Some(path.read_link()?.user_display().to_string());

@Gankra
Copy link
Contributor

Gankra commented Jan 14, 2025

Merged in #10596, thanks so much!

@Gankra Gankra closed this Jan 14, 2025
@jzlotek
Copy link
Contributor Author

jzlotek commented Jan 14, 2025

Merged in #10596, thanks so much!

No problem. Thanks for the tips

@jzlotek jzlotek deleted the jzlotek/python-list-json branch January 14, 2025 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants