-
Notifications
You must be signed in to change notification settings - Fork 760
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow uv
crate to be used as a library
#4642
Conversation
// `std::env::args` is not `Send` so we parse before passing to our runtime | ||
// https://github.com/rust-lang/rust/pull/48005 | ||
let cli = match Cli::try_parse_from(args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This moved without change from run
above because it's not safe to send std::env
values across threads depending on the platform.
Closes #4476 Originally, this used the changes in #4642 to invoke `main()` from a `uvx` binary. This had the benefit of `uvx` being entirely standalone at the cost of doubling our artifact size. We think that's the incorrect trade-off. Instead, we assume `uvx` is always next to `uv` and create a tiny binary (<1MB) that invokes `uv` in a child process. This seems preferable to a `cargo-dist` alias because we have more control over it. This binary should "just work" for all of our cargo-dist distributions and installers, but we'll need to add a new entry point for our PyPI distribution. I'll probably tackle support there separately? ``` ❯ ls -lah target/release/uv target/release/uvx -rwxr-xr-x 1 zb staff 31M Jun 28 23:23 target/release/uv -rwxr-xr-x 1 zb staff 452K Jun 28 23:22 target/release/uvx ``` This includes some small overhead: ``` ❯ hyperfine --shell=none --warmup=100 './target/release/uv tool run --help' './target/release/uvx --help' --min-runs 2000 Benchmark 1: ./target/release/uv tool run --help Time (mean ± σ): 2.2 ms ± 0.1 ms [User: 1.3 ms, System: 0.5 ms] Range (min … max): 2.0 ms … 4.0 ms 2000 runs Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. Benchmark 2: ./target/release/uvx --help Time (mean ± σ): 2.9 ms ± 0.1 ms [User: 1.7 ms, System: 0.9 ms] Range (min … max): 2.8 ms … 4.2 ms 2000 runs Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. Summary ./target/release/uv tool run --help ran 1.35 ± 0.09 times faster than ./target/release/uvx --help ``` I presume there may be some other downsides to a child process? The wrapper is a little awkward. We could consider `execv` but this is complicated across platforms. An example implementation of that over in [monotrail](https://github.com/konstin/poc-monotrail/blob/433af5aed90921e2c3f4b426b3ffffd83f04d3ff/crates/monotrail/src/monotrail.rs#L764-L799).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a little unsure of this personally. Maybe it's fine, but I think it would warrant a docstring somewhere saying that this is not officially supported and to Use At Your Own Risk.
My main specific worry is that this will enable calling the entire uv
application more than once in the same process. I can't think of anything off the top of my head that will definitely break as a result of this, but if we're leaving state around that gets reused, it could be an issue.
My more vague worry is that we didn't really design uv
to be invoked as a library. So there may be other things that can go wrong here.
Hey We wanted to share our use case for We want to embed a toolchain to obtain dependencies and manage Our dispatch style is a bit weird: we are calling We are happy to continue using It is possible, of course, to ship
All in all if you guys strongly feel like Of course thank you for all your hard work on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this because it's helpful for some testing improvements i want to try. There are some differences between using uv through the main function from rust and calling it as a subprocess (we have some global and thread local state), so i'd keep our officially supported and stable interface to calling binary with cli arguments.
I added a warning |
I have a use for this as well. Are you planning on publishing There is an existing 'uv' "universal getter" that has the name currently, but looks abandoned. |
We aren't prioritizing it — we're far from a stable Rust API and we move very quickly which sometimes requires a |
What's your use case? :) |
We have an internal tool that sets up Python environments for developers: The venv, tox, dependencies, etc. I also have need for calling Unfortunately I can't use |
This is pulled out of #4632 — a user noted that it would be useful to use the
uv
crate from Rust. This makes it way easier to invokeuv
from Rust with arbitrary arguments as well as use various functionality in theuv
crate.Note this is no longer needed for #4632 and is not particularly urgent.