Skip to content

Conversation

@CrendKing
Copy link
Contributor

Summary

Related to #6801.

Currently on Windows, uv itself will always creates a console window, even though the window could be empty if uv run --gui-script is used. This is due to it using the default console window subsystem.

This PR introduces a wrapper uvw that, similar to the existing uvx, invokes uv with the CREATE_NO_WINDOW process creation flag on Windows, which creates child process without console window.

Note that this PR does not alter any behaviors regarding run --script and run --gui-script.

Test Plan

Built and tested locally by doing something like uvw run test.py.

@CrendKing
Copy link
Contributor Author

I personally don't like the amount of duplicate code between uvx and uvw. Should I extract the common logic to a separate file?

@zanieb
Copy link
Member

zanieb commented Feb 26, 2025

Thanks for posting the pull request — I haven't looked at the implementation yet but note you'll want to look back at when we added uvx because we messed that up and broke the release process. I think there are various places you need to put the binary in an archive.

@samypr100
Copy link
Collaborator

samypr100 commented Feb 26, 2025

Thanks for posting the pull request — I haven't looked at the implementation yet but note you'll want to look back at when we added uvx because we messed that up and broke the release process. I think there are various places you need to put the binary in an archive.

Is the goal to distribute uvw only on windows or all platforms? For example, I don't think pythonw is available on other platforms besides windows. That will determine the distribution changes needed.

e.g. In the case of windows only, I don't expect bundling this binary in the docker images

@zanieb
Copy link
Member

zanieb commented Feb 26, 2025

Yeah I think we should not publish this on other platforms.

@CrendKing
Copy link
Contributor Author

Thanks for posting the pull request — I haven't looked at the implementation yet but note you'll want to look back at when we added uvx because we messed that up and broke the release process. I think there are various places you need to put the binary in an archive.

Can you link the issue(s) and where do I put this in?

Is the goal to distribute uvw only on windows or all platforms? For example, I don't think pythonw is available on other platforms besides windows. That will determine the distribution changes needed.

e.g. In the case of windows only, I don't expect bundling this binary in the docker images

True. Technically this binary wouldn't need the existence of pythonw. But it also wouldn't do anything special under non-Windows OSes. So it makes sense not to distribute there.

@CrendKing
Copy link
Contributor Author

CrendKing commented Feb 26, 2025

I added the relevant lines to the Action config. However, I think currently the binary is generated under all platforms regardless. I don't know how to generate uvw only under Windows. https://users.rust-lang.org/t/compile-a-binary-for-a-specific-platform/56528 says there isn't built-in way.

@zanieb
Copy link
Member

zanieb commented Feb 26, 2025

That's sort of a blocker.

@Gankra may know some dark arts.

@CrendKing
Copy link
Contributor Author

Any update? I personally don't think having a harmless executable in the build directory, which is not included in the final release archive, is that big of a deal. On the other hand, if you guys have to introduce dark magic to get rid of it, that could become maintenance burden in the future. Would documenting the behavior somewhere in the docs suffice?

@Gankra
Copy link
Contributor

Gankra commented Mar 4, 2025

Ah sorry I missed this!

Yes cargo doesn't let you have platform-conditional-binaries. It does however let you have feature-flag-conditional binaries. So you could, in theory, introduce a windows-gui-bin feature or something and add required-features = ["windows-gui-bin"] to the [[bin]] entry for uvw.

https://doc.rust-lang.org/cargo/reference/cargo-targets.html#binaries

Then in our maturin release build tooling, we could add --features windows-gui-bin to the build invocation:

args: --release --locked --out dist --features self-update

and add uvw to the files we archive:

ARCHIVE_FILE=uv-${{ matrix.platform.target }}.zip
7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/uv.exe
7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/uvx.exe
sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256

Probably the biggest issue with this is I don't think cargo-dist('s installers) would understand? I was actually remarkably pedantic about this possibility in a lot of cargo-dist's code/metadata, so actually it might be a relatively small change to support. But I believe there's no UI to tell cargo-dist "ok I'm actually doing this!" (unless it was added in the last 4 months).

@CrendKing
Copy link
Contributor Author

Thank you Gankra. I updated the PR. Could you check if I'm doing it correctly?

@Gankra
Copy link
Contributor

Gankra commented Mar 6, 2025

Sorry I should have been more clear -- I believe we can't ship this without upstream work in
https://github.com/axodotdev/cargo-dist/

If I checkout your branch (which is indeed written Correctly as I described) we see that dist doesn't understand and will expect every platform to provide uvw. This will likely lead to installers erroring out as they try to validate the presence of missing files:

$ dist plan
...
announcing v0.6.3
  uv 0.6.3
    source.tar.gz
      [checksum] source.tar.gz.sha256
    uv-installer.sh
    uv-installer.ps1
    sha256.sum
    uv-aarch64-apple-darwin.tar.gz
      [bin] uv
      [bin] uvw
      [bin] uvx
      [checksum] uv-aarch64-apple-darwin.tar.gz.sha256
    uv-aarch64-pc-windows-msvc.zip
      [bin] uv.exe
      [bin] uvw.exe
      [bin] uvx.exe
      [checksum] uv-aarch64-pc-windows-msvc.zip.sha256
      ...

@CrendKing
Copy link
Contributor Author

CrendKing commented Mar 6, 2025

Sorry I didn't understand that cargo-dist is a required component/step for uv.

I think there are three options forward.

  1. Like I mentioned above, we can make it so every platform builds the uvw binary. It is just that uvw does nothing special other than directly wrapping uv on non-Windows platforms, which I consider being useless but also harmless. Maybe this requires some documentation somewhere, if you guys are OK with that.
  2. We wait for cargo-dist to update to support platform-specific binaries.
  3. We abandon this PR. I could move the source code to a new repository that you guys own (like under astral-sh account, e.g. astral-sh/uvw). Setup a release process there.

@zanieb
Copy link
Member

zanieb commented Mar 6, 2025

Regarding (1), I think there's a cost to every additional artifact we add to releases. It's user-facing complexity.

(2) I think we'll need to push for support in cargo-dist directly, or wait until we start to take more ownership over that component of our releases.

(3) A derived third-party artifact is an option, though I'd be a bit sad about it. I understanding pursuing it as a stop-gap, but hopefully we can do better for users.

@Gankra do you have an idea of the scope of work needed upstream?

@CrendKing
Copy link
Contributor Author

Thank you zanieb. I do believe option 2 is the best to go, if we can push the required changes to cargo-dist in timely fashion. Please let me know if you need me to create or follow-up issue ticket in their repo.

@Gankra
Copy link
Contributor

Gankra commented Mar 6, 2025

On paper it's actually not a huge lift. It's ideally mostly just adding config option similar to the min-glibc-version but for package.binaries instead.

Then that config value would need to be queried/applied here:

https://github.com/axodotdev/cargo-dist/blob/c8ba950c63f9c38c77782912ec6cdb6807bd0fbd/cargo-dist/src/tasks/mod.rs#L1340-L1344

So in an ideal world 99% of the work is agreeing on the config and piping it to this location and it Just Works.

However there's a non-zero chance that random things will blow up because although the code tries really hard to make things deal with per-platform-binaries it hasn't ever really been a thing so it's very easy for something to have cut a corner and for it to have been fine up until now. However the only way to know is Try It And See.

@CrendKing
Copy link
Contributor Author

I see that currently the package.binaries is internally a Vec of string, while min-glibc-version is a SortedMap<String, LibcVersion>. Pushing through this backward incompatible change doesn't seem to be a trivial task at all, not to mention the cargo-dist owners might not like the idea of platform-specific artifacts to begin with. Maybe I'm a bit pessimistic here.

Do you guys want me to start an issue ticket on cargo-dist and reference to this PR?

@zanieb
Copy link
Member

zanieb commented Mar 8, 2025

@Gankra is a former cargo-dist maintainer and has a fair amount of perspective there. Anyway, please do open an issue there and we can try to coordinate with them.

@CrendKing
Copy link
Contributor Author

axodotdev/cargo-dist#1791

@Gankra
Copy link
Contributor

Gankra commented Apr 9, 2025

platform-specific bins support in cargo-dist astral-sh/cargo-dist#17

@Gankra Gankra mentioned this pull request Apr 9, 2025
@CrendKing
Copy link
Contributor Author

Great news! I'll wait for the release there.

Below is for documentation.

I've been using the uvw locally myself, and the only thing bothering me is that even though there is no visible console window now, since uvw actually invokes uv, which is built with console option, it still spawns a useless conhost.exe process.

The only way to make that conhost.exe never spawn is to change our creation flag to DETACHED_PROCESS, and always use --gui-script. Unfortunately, if user doesn't use --gui-script (which is the default), the console window is back.

For maximum ease of use, I think we should keep the current CREATE_NO_WINDOW flag, unless one day uv supports an option to always use --gui-script through config file.

Gankra added a commit that referenced this pull request Apr 10, 2025
Putting this up to confirm that it does what it should:

* undirty the release.yml by including action-commits in the config
* add `persist-credentials=false` hardening
* includes but does not use `[package.metadata.dist.binaries]` overrides
(for #11786)
@dpy013
Copy link

dpy013 commented Apr 20, 2025

Suggested Resolve conflicts

@CrendKing
Copy link
Contributor Author

CrendKing commented Apr 21, 2025

I added a [workspace.metadata.dist.binaries] section in Cargo.toml. I tested with dist plan and see only Windows target has the extra uvw.exe. I'm not sure if there is more concise way to write all Windows targets though (e.g. *-windows-msvc = ...)

I also applied the update to uvx from #12923 about suffix searching. I tested myself. Though now there are even more duplicate logic between uvx and uvw.

@CrendKing
Copy link
Contributor Author

Anyone still interested?

@zanieb
Copy link
Member

zanieb commented May 14, 2025

@Gankra can take a look, but is at a conference right now.

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.

Apologies for all the delays, this seems to just be... done? I don't see any obvious reasons to complain, other than we should probably add some tests.

@Gankra
Copy link
Contributor

Gankra commented May 28, 2025

Ok I've locally confirmed uvw.exe does what it intends, by creating a windows shortcut

C:\Users\gankra\dev\uv\target\release\uvw.exe run C:\Users\gankra\dev\tmp\tkinter-app\main.py

And double-clicking it. (And changing uvw.exe to uv.exe does indeed spawn a shell)

@Gankra
Copy link
Contributor

Gankra commented May 28, 2025

Hmm I guess this is basically as tested as uvx is?

@Gankra Gankra merged commit e5d002b into astral-sh:main May 28, 2025
109 checks passed
@Gankra
Copy link
Contributor

Gankra commented May 28, 2025

Thanks so much for this!

@CrendKing
Copy link
Contributor Author

Hmm I guess this is basically as tested as uvx is?

I'm sorry I am not familiar with the code structure of uv. I did not see uvx itself have dedicated test, so I didn't start one for uvw. I see uvx --help is called in build-binaries.yml, so I added for uvw.

I see there is also a scripts/smoke-test which seems like an integration test. Maybe we can add some uvw calls there?

tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jun 13, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [astral-sh/uv](https://github.com/astral-sh/uv) | patch | `0.7.7` -> `0.7.13` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>astral-sh/uv (astral-sh/uv)</summary>

### [`v0.7.13`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0713)

[Compare Source](astral-sh/uv@0.7.12...0.7.13)

##### Python

-   Add Python 3.14.0b2
-   Add Python 3.13.5
-   Fix stability of `uuid.getnode` on 3.13

See the
[`python-build-standalone` release notes](https://github.com/astral-sh/python-build-standalone/releases/tag/20250612)
for more details.

##### Enhancements

-   Download versions in `uv python pin` if not found ([#&#8203;13946](astral-sh/uv#13946))
-   Use TTY detection to determine if SIGINT forwarding is enabled ([#&#8203;13925](astral-sh/uv#13925))
-   Avoid fetching an exact, cached Git commit, even if it isn't locked ([#&#8203;13748](astral-sh/uv#13748))
-   Add `zstd` and `deflate` to `Accept-Encoding` ([#&#8203;13982](astral-sh/uv#13982))
-   Build binaries for riscv64  ([#&#8203;12688](astral-sh/uv#12688))

##### Bug fixes

-   Check if relative URL is valid directory before treating as index ([#&#8203;13917](astral-sh/uv#13917))
-   Ignore Python discovery errors during `uv python pin` ([#&#8203;13944](astral-sh/uv#13944))
-   Do not allow `uv add --group ... --script` ([#&#8203;13997](astral-sh/uv#13997))

##### Preview changes

-   Build backend: Support namespace packages ([#&#8203;13833](astral-sh/uv#13833))

##### Documentation

-   Add 3.14 to the supported platform reference ([#&#8203;13990](astral-sh/uv#13990))
-   Add an `llms.txt` to uv ([#&#8203;13929](astral-sh/uv#13929))
-   Add supported macOS version to the platform reference ([#&#8203;13993](astral-sh/uv#13993))
-   Update platform support reference to include Python implementation list ([#&#8203;13991](astral-sh/uv#13991))
-   Update pytorch.md ([#&#8203;13899](astral-sh/uv#13899))
-   Update the CLI help and reference to include references to the Python bin directory ([#&#8203;13978](astral-sh/uv#13978))

### [`v0.7.12`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0712)

[Compare Source](astral-sh/uv@0.7.11...0.7.12)

##### Enhancements

-   Add `uv python pin --rm` to remove `.python-version` pins ([#&#8203;13860](astral-sh/uv#13860))
-   Don't hint at versions removed by `excluded-newer` ([#&#8203;13884](astral-sh/uv#13884))
-   Add hint to use `tool.uv.environments` on resolution error ([#&#8203;13455](astral-sh/uv#13455))
-   Add hint to use `tool.uv.required-environments` on resolution error ([#&#8203;13575](astral-sh/uv#13575))
-   Improve `python pin` error messages ([#&#8203;13862](astral-sh/uv#13862))

##### Bug fixes

-   Lock environments during `uv sync`, `uv add` and `uv remove` to prevent race conditions ([#&#8203;13869](astral-sh/uv#13869))
-   Add `--no-editable` to `uv export` for `pylock.toml` ([#&#8203;13852](astral-sh/uv#13852))

##### Documentation

-   List `.gitignore` in project init files ([#&#8203;13855](astral-sh/uv#13855))
-   Move the pip interface documentation into the concepts section ([#&#8203;13841](astral-sh/uv#13841))
-   Remove the configuration section in favor of concepts / reference ([#&#8203;13842](astral-sh/uv#13842))
-   Update Git and GitHub Actions docs to mention `gh auth login` ([#&#8203;13850](astral-sh/uv#13850))

##### Preview

-   Fix directory glob traversal fallback preventing exclusion of all files ([#&#8203;13882](astral-sh/uv#13882))

### [`v0.7.11`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0711)

[Compare Source](astral-sh/uv@0.7.10...0.7.11)

##### Python

-   Add Python 3.14.0b1
-   Add Python 3.13.4
-   Add Python 3.12.11
-   Add Python 3.11.13
-   Add Python 3.10.18
-   Add Python 3.9.23

##### Enhancements

-   Add Pyodide support ([#&#8203;12731](astral-sh/uv#12731))
-   Better error message for version specifier with missing operator ([#&#8203;13803](astral-sh/uv#13803))

##### Bug fixes

-   Downgrade `reqwest` and `hyper-util` to resolve connection reset errors over IPv6 ([#&#8203;13835](astral-sh/uv#13835))
-   Prefer `uv`'s binary's version when checking if it's up to date ([#&#8203;13840](astral-sh/uv#13840))

##### Documentation

-   Use "terminal driver" instead of "shell" in `SIGINT` docs ([#&#8203;13787](astral-sh/uv#13787))

### [`v0.7.10`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0710)

[Compare Source](astral-sh/uv@0.7.9...0.7.10)

##### Enhancements

-   Add `--show-extras` to `uv tool list` ([#&#8203;13783](astral-sh/uv#13783))
-   Add dynamically generated sysconfig replacement mappings ([#&#8203;13441](astral-sh/uv#13441))
-   Add data locations to install wheel logs ([#&#8203;13797](astral-sh/uv#13797))

##### Bug fixes

-   Avoid redaction of placeholder `git` username when using SSH authentication ([#&#8203;13799](astral-sh/uv#13799))
-   Propagate credentials to files on devpi indexes ending in `/+simple` ([#&#8203;13743](astral-sh/uv#13743))
-   Restore retention of credentials for direct URLs in `uv export` ([#&#8203;13809](astral-sh/uv#13809))

### [`v0.7.9`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#079)

[Compare Source](astral-sh/uv@0.7.8...0.7.9)

##### Python

The changes reverted in [0.7.8](#&#8203;078) have been restored.

See the
[`python-build-standalone` release notes](https://github.com/astral-sh/python-build-standalone/releases/tag/20250529)
for more details.

##### Enhancements

-   Improve obfuscation of credentials in URLs ([#&#8203;13560](astral-sh/uv#13560))
-   Allow running non-default Python implementations via `uvx` ([#&#8203;13583](astral-sh/uv#13583))
-   Add `uvw` as alias for `uv` without console window on Windows ([#&#8203;11786](astral-sh/uv#11786))
-   Allow discovery of x86-64 managed Python builds on macOS ([#&#8203;13722](astral-sh/uv#13722))
-   Differentiate between implicit vs explicit architecture requests ([#&#8203;13723](astral-sh/uv#13723))
-   Implement ordering for Python architectures to prefer native installations ([#&#8203;13709](astral-sh/uv#13709))
-   Only show the first match per platform (and architecture) by default in `uv python list`  ([#&#8203;13721](astral-sh/uv#13721))
-   Write the path of the parent environment to an `extends-environment` key in the `pyvenv.cfg` file of an ephemeral environment ([#&#8203;13598](astral-sh/uv#13598))
-   Improve the error message when libc cannot be found, e.g., when using the distroless containers ([#&#8203;13549](astral-sh/uv#13549))

##### Performance

-   Avoid rendering info log level ([#&#8203;13642](astral-sh/uv#13642))
-   Improve performance of `uv-python` crate's manylinux submodule ([#&#8203;11131](astral-sh/uv#11131))
-   Optimize `Version` display ([#&#8203;13643](astral-sh/uv#13643))
-   Reduce number of reference-checks for `uv cache clean` ([#&#8203;13669](astral-sh/uv#13669))

##### Bug fixes

-   Avoid reinstalling dependency group members with `--all-packages` ([#&#8203;13678](astral-sh/uv#13678))
-   Don't fail direct URL hash checking with dependency metadata ([#&#8203;13736](astral-sh/uv#13736))
-   Exit early on `self update` if global `--offline` is set ([#&#8203;13663](astral-sh/uv#13663))
-   Fix cases where the uv lock is incorrectly marked as out of date ([#&#8203;13635](astral-sh/uv#13635))
-   Include pre-release versions in `uv python install --reinstall` ([#&#8203;13645](astral-sh/uv#13645))
-   Set `LC_ALL=C` for git when checking git worktree ([#&#8203;13637](astral-sh/uv#13637))
-   Avoid rejecting Windows paths for remote Python download JSON targets ([#&#8203;13625](astral-sh/uv#13625))

##### Preview

-   Add `uv add --bounds` to configure version constraints ([#&#8203;12946](astral-sh/uv#12946))

##### Documentation

-   Add documentation about Python versions to Tools concept page ([#&#8203;7673](astral-sh/uv#7673))
-   Add example of enabling Dependabot ([#&#8203;13692](astral-sh/uv#13692))
-   Fix `exclude-newer` date format for persistent configuration files ([#&#8203;13706](astral-sh/uv#13706))
-   Quote versions variables in GitLab documentation ([#&#8203;13679](astral-sh/uv#13679))
-   Update Dependabot support status ([#&#8203;13690](astral-sh/uv#13690))
-   Explicitly specify to add a new repo entry to the repos list item in the `.pre-commit-config.yaml` ([#&#8203;10243](astral-sh/uv#10243))
-   Add integration with marimo guide ([#&#8203;13691](astral-sh/uv#13691))
-   Add pronunciation to README ([#&#8203;5336](astral-sh/uv#5336))

### [`v0.7.8`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#078)

[Compare Source](astral-sh/uv@0.7.7...0.7.8)

##### Python

We are reverting most of our Python changes from `uv 0.7.6` and `uv 0.7.7` due to
a miscompilation that makes the Python interpreter behave incorrectly, resulting
in spurious type-errors involving str. This issue seems to be isolated to
x86\_64 Linux, and affected at least Python 3.12, 3.13, and 3.14.

The following changes that were introduced in those versions of uv are temporarily
being reverted while we test and deploy a proper fix for the miscompilation:

-   Add Python 3.14 on musl
-   free-threaded Python on musl
-   Add Python 3.14.0a7
-   Statically link `libpython` into the interpreter on Linux for a significant performance boost

See [the issue for details](astral-sh/uv#13610).

##### Documentation

-   Remove misleading line in pin documentation ([#&#8203;13611](astral-sh/uv#13611))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4yNi4xIiwidXBkYXRlZEluVmVyIjoiNDAuNTEuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90Il19-->
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.

5 participants