Skip to content
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 creating venv with free-threaded python builds #7431

Merged
merged 14 commits into from
Sep 23, 2024

Conversation

bschoenmaeckers
Copy link
Contributor

Summary

closes #4828

First iteration for an implementation. I need to add more tests but wanted your opinion on the implementation first.

Test Plan

Currently tested using the following command but will add tests shortly:

D:\repo\uv> cargo run venv -p 3.13t && .venv\Scripts\python.exe
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.52s
     Running `target\debug\uv.exe venv -p 3.13t`
Using Python 3.13.0rc1 interpreter at: C:\Users\bschoen\AppData\Local\Programs\Python\Python313\python3.13t.exe
Creating virtualenv at: .venv
Activate with: .venv\Scripts\activate
Python 3.13.0rc1 experimental free-threading build (tags/v3.13.0rc1:e4a3e78, Jul 31 2024, 21:06:58) [MSC v.1940 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 

@bschoenmaeckers
Copy link
Contributor Author

Working on the unix implementation now.

@zanieb zanieb self-assigned this Sep 16, 2024
@bschoenmaeckers
Copy link
Contributor Author

Working on the unix implementation now.

Tested it on linux using the quay.io/pypa/manylinux2014_x86_64 docker image and I seems to work correctly already. Going to write some tests next.

@bschoenmaeckers
Copy link
Contributor Author

I find it quiet hard to add a test without a free-threaded build available in the CI. So maybe we should add a full integration test later when the downloadable build is available.

@bschoenmaeckers
Copy link
Contributor Author

bschoenmaeckers commented Sep 17, 2024

Should version requests like >=3.13t, >=3.13t,<3.14t or >=3.12,<3.14t be valid?

@zanieb
Copy link
Member

zanieb commented Sep 17, 2024

Should version requests like >=3.13t, >=3.13t,<3.14t or >=3.12,<3.14t be valid?

Maybeee. It seems safe to add support for that later if people need it.

I find it quiet hard to add a test without a free-threaded build available in the CI. So maybe we should add a full integration test later when the downloadable build is available.

You can probably add test coverage in crates/uv-python/src/lib.rs, we support creating mock interpreters there.

@zanieb
Copy link
Member

zanieb commented Sep 17, 2024

Oh also regarding an integration test, is there a Docker image with a free-threaded build? or a system that has it packaged? You can create a new integration-test CI job that does whatever so we get some real-world coverage.

@bschoenmaeckers bschoenmaeckers force-pushed the venv-free-threaded branch 9 times, most recently from 2883594 to f100648 Compare September 18, 2024 13:56
@bschoenmaeckers
Copy link
Contributor Author

I've added a smoke test in the ci using a pre-compiled python 3.13 package installed using apt-get on a bare ubuntu instance. Furthermore I added a mocked interpreter test.

.github/workflows/ci.yml Outdated Show resolved Hide resolved
Co-authored-by: Zanie Blue <[email protected]>
@@ -137,6 +137,7 @@ pub enum VersionRequest {
MajorMinor(u8, u8),
MajorMinorPatch(u8, u8, u8),
MajorMinorPrerelease(u8, u8, Prerelease),
FreeThreaded(Box<VersionRequest>),
Copy link
Member

Choose a reason for hiding this comment

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

Doing some internal debate about this right now — this is sort of the "easiest" way to add support but it might be better to added a freethreaded: bool to each relevant variant instead? Like FreeThreaded(Any) shouldn't be allowed nor FreeThreaded(FreeThreaded(...)) right? Want to share some more about why you went with this pattern?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was at the time of implementing the easiest option to wrap every variant with a FreeThreaded version because it didn't felt right to clutter every variant with yet another flag. You are right that that FreeThreaded(Any) does not make sense but the FreeThreaded(FreeThreaded(...)) should not be possible for the parser to generate, even though it would not be a very big problem because it would behave like a regular FreeThreaded(...) variant. But I understand the debate and would happily switch to a extra flag on every variant if you want me to.

Copy link
Member

Choose a reason for hiding this comment

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

The parser can't generate it but this is a "public" enum so someone could construct that variant — which is a bit awkward. I think I have a preference for adding a boolean to the variants, it looks like it would make some of the downstream logic simpler. It is a bit sad that we'll need to add it everywhere we construct a VersionRequest manually but I'm not sure what else to do there. As a small note, it may need to be Option<bool> for cases in which the free-threaded build is fine, e.g., and can be used if it's first on the PATH.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fine by me. How would you parse a 3.13 request? Does the user allow a free-threaded build or not?

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure.

cc @henryiii / @carljm who may have helpful opinions on that.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think you want to make sure this can change for a future Python version, but yes, I think currently you want free-threaded to be opt-in. In the future, if it works well, it might be opt-out instead, maybe as soon as 3.15 (which may be called 3.27).

Copy link
Member

Choose a reason for hiding this comment

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

What if you have a python executable at the front of your path and it's free-threaded?

Copy link
Contributor

Choose a reason for hiding this comment

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

If it's called python or python3.13, then yes, but usually it's only called python3.13t?

Copy link
Contributor

Choose a reason for hiding this comment

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

Same as pypy. If there's a python that's actually pointing at pypy, then that should be picked up, otherwise pypy should only be opt-in?

Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately people do weird things and we have to think about these edge-cases

zanieb added a commit that referenced this pull request Sep 19, 2024
As we support more complex Python discovery behaviors such as:

- #7431 
- #7335 
- #7300 

`Any` is no longer accurate, we actually are looking for a reasonable
default Python version to use which may exclude the first one we find.
Separately, we need the idea of `Any` to improve behavior when listing
versions (e.g., #7286) where we do actually want to match _any_ Python
version. As a first step, we'll rename `Any` to `Default`. Then, we'll
introduce a new `Any` that actually behaves as we'd expect.
@zanieb
Copy link
Member

zanieb commented Sep 20, 2024

I think this is failing because it's not searching for the executable name properly. I'm going to tweak the possible_names and default_names code — it' really unwieldy (not from this pull request).

@bschoenmaeckers
Copy link
Contributor Author

I think this is failing because it's not searching for the executable name properly. I'm going to tweak the possible_names and default_names code — it' really unwieldy (not from this pull request).

I was thinking so as well, I did not had time to debug this properly. The only thing I knew was that it is working properly on windows.

@bschoenmaeckers
Copy link
Contributor Author

@zanieb, I fixed the tests. So it is ready for review again.

zanieb added a commit that referenced this pull request Sep 23, 2024
…mentations (#7649)

There are two parts to this. 

The first is a restructuring and refactoring. We had some debt around
expected executable name generation, which we address here by
consolidating into a single function that generates a combination of
names. This includes a bit of extra code around free-threaded variants
because this was written on top of #7431 — I'll rebase that on top of
this.

The second addresses some bugs around alternative implementations.
Notably, `uv python list` does not discovery executables with
alternative implementation names. Now, we properly generate all of the
executable names for `VersionRequest::Any` (originally implemented in
#7508) to properly show all the
implementations we can find:

```
❯ cargo run -q -- python list --no-python-downloads
cpython-3.12.6-macos-aarch64-none     /opt/homebrew/opt/[email protected]/bin/python3.12 -> ../Frameworks/Python.framework/Versions/3.12/bin/python3.12
cpython-3.11.10-macos-aarch64-none    /opt/homebrew/opt/[email protected]/bin/python3.11 -> ../Frameworks/Python.framework/Versions/3.11/bin/python3.11
cpython-3.9.6-macos-aarch64-none      /Library/Developer/CommandLineTools/usr/bin/python3 -> ../../Library/Frameworks/Python3.framework/Versions/3.9/bin/python3
pypy-3.10.14-macos-aarch64-none       /opt/homebrew/bin/pypy3 -> ../Cellar/pypy3.10/7.3.17/bin/pypy3
```

While doing both of these changes, I ended up changing the priority of
interpreter discovery slightly. For example, given that the executables
are in the same directory, do we query `python` or `python3.10` first
when you request `--python 3.10`? Previously, we'd check `python3.10`
but I think that was an incorrect optimization. I think we should always
prefer the bare name (i.e. `python`) first. Similarly, this applies to
`python` and an executable for an alternative implementation like
`pypy`. If it's not compatible with the request, we'll skip it anyway.
We might have to query more interpreters with this approach but it seems
rare.


Closes #7286 superseding
#7508
@zanieb
Copy link
Member

zanieb commented Sep 23, 2024

Thanks! I resolved the conflicts with #7649

@zanieb zanieb merged commit 77c2496 into astral-sh:main Sep 23, 2024
59 checks passed
@basnijholt
Copy link

Awesome! Does this mean that there will be a 3.13t version available at the next release of uv?

@zanieb
Copy link
Member

zanieb commented Sep 23, 2024

Unfortunately not, that's much harder and can be tracked at astral-sh/python-build-standalone#326

With this, we'll just let you ask uv to use a free-threaded build you already have installed.

@henryiii
Copy link
Contributor

FYI, this means you can say "3.13t" and get it; you can already use uv with python3.13t as long as you give it via path. (At least I hope so, for example cibuildwheel does that)

zanieb added a commit that referenced this pull request Oct 2, 2024
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Oct 7, 2024
This MR contains the following updates:

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

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.4.18`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#0418)

[Compare Source](astral-sh/uv@0.4.17...0.4.18)

##### Enhancements

-   Allow multiple source entries for each package in `tool.uv.sources` ([#&#8203;7745](astral-sh/uv#7745))
-   Add `.gitignore` file to `uv build` output directory ([#&#8203;7835](astral-sh/uv#7835))
-   Disable jemalloc on FreeBSD ([#&#8203;7780](astral-sh/uv#7780))
-   Respect `PAGER` env var when paging in `uv help` command ([#&#8203;5511](astral-sh/uv#5511))
-   Support `uv run -m foo` to run a module ([#&#8203;7754](astral-sh/uv#7754))
-   Use a top-level output directory for `uv build` in workspaces ([#&#8203;7813](astral-sh/uv#7813))
-   Update `uv init --package` command to match project name ([#&#8203;7670](astral-sh/uv#7670))
-   Add a custom suggestion for `uv add dotenv` ([#&#8203;7799](astral-sh/uv#7799))
-   Add detailed errors for `tool.uv.sources` deserialization failures ([#&#8203;7823](astral-sh/uv#7823))
-   Improve error message copy for failed builds ([#&#8203;7849](astral-sh/uv#7849))
-   Use `serde-untagged` to improve some untagged enum error messages ([#&#8203;7822](astral-sh/uv#7822))
-   Use build failure hints for `dotenv` errors, rather than in `uv add` ([#&#8203;7825](astral-sh/uv#7825))

##### Configuration

-   Add `UV_NO_SYNC` environment variable ([#&#8203;7752](astral-sh/uv#7752))

##### Bug fixes

-   Accept `git+` prefix in `tool.uv.sources` ([#&#8203;7847](astral-sh/uv#7847))
-   Allow spaces in path requirements ([#&#8203;7767](astral-sh/uv#7767))
-   Avoid reusing cached downloaded binaries with `--no-binary` ([#&#8203;7772](astral-sh/uv#7772))
-   Correctly trims values during wheel WHEEL file parsing ([#&#8203;7770](astral-sh/uv#7770))
-   Fix `uv tree --invert` for platform dependencies ([#&#8203;7808](astral-sh/uv#7808))
-   Fix encoding mismatch between python child process and uv ([#&#8203;7757](astral-sh/uv#7757))
-   Reject self-dependencies in `uv add` ([#&#8203;7766](astral-sh/uv#7766))
-   Respect `tool.uv.environments` for legacy virtual workspace roots ([#&#8203;7824](astral-sh/uv#7824))
-   Retain empty extras on workspace members ([#&#8203;7762](astral-sh/uv#7762))
-   Use file stem when parsing cached wheel names ([#&#8203;7773](astral-sh/uv#7773))

##### Rust API

-   Make `FlatDistributions` public ([#&#8203;7833](astral-sh/uv#7833))

##### Documentation

-   Fix table of contents sizing ([#&#8203;7751](astral-sh/uv#7751))
-   GitLab Integration documentation ([#&#8203;6857](astral-sh/uv#6857))
-   Update documentation to setup-uv@v3 ([#&#8203;7807](astral-sh/uv#7807))
-   Use `uv publish` instead of twine in docs ([#&#8203;7837](astral-sh/uv#7837))
-   Fix typo in `projects.md` ([#&#8203;7784](astral-sh/uv#7784))

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

[Compare Source](astral-sh/uv@0.4.16...0.4.17)

##### Enhancements

-   Add `uv build --all` to build all packages in a workspace ([#&#8203;7724](astral-sh/uv#7724))
-   Add support for `uv init --script` ([#&#8203;7565](astral-sh/uv#7565))
-   Add support for upgrading build environment for installed tools (`uv tool upgrade --python`) ([#&#8203;7605](astral-sh/uv#7605))
-   Initialize a Git repository in `uv init` ([#&#8203;5476](astral-sh/uv#5476))
-   Respect `--quiet` flag in `uv build` ([#&#8203;7674](astral-sh/uv#7674))
-   Add context message before listing available tools in `uvx` ([#&#8203;7641](astral-sh/uv#7641))

##### Bug fixes

-   Don't create Python bytecode files during interpreter discovery ([#&#8203;7707](astral-sh/uv#7707))
-   Escape glob patterns in workspace member discovery ([#&#8203;7709](astral-sh/uv#7709))
-   Avoid prefetching source distributions with unbounded lower-bound ranges ([#&#8203;7683](astral-sh/uv#7683))

##### Documentation

-   Add `uv build` and `uv publish` to features overview ([#&#8203;7716](astral-sh/uv#7716))
-   Add documentation on cache versioning ([#&#8203;7693](astral-sh/uv#7693))
-   Spell out the names of the Docker images for easier copy-paste ([#&#8203;7706](astral-sh/uv#7706))
-   Document uv-with-Jupyter workflows ([#&#8203;7625](astral-sh/uv#7625))
-   Note that `uv lock --upgrade-package` retains locked versions ([#&#8203;7694](astral-sh/uv#7694))

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

[Compare Source](astral-sh/uv@0.4.15...0.4.16)

##### Enhancements

-   Add `uv publish` ([#&#8203;7475](astral-sh/uv#7475))
-   Add a `--project` argument to run a command from a project directory ([#&#8203;7603](astral-sh/uv#7603))
-   Display Python implementation when creating environments ([#&#8203;7652](astral-sh/uv#7652))
-   Implement trusted publishing for `uv publish` ([#&#8203;7548](astral-sh/uv#7548))
-   Respect lockfile preferences for `--with` requirements ([#&#8203;7627](astral-sh/uv#7627))
-   Unhide the `--directory` option ([#&#8203;7653](astral-sh/uv#7653))
-   Allow requesting free-threaded Python interpreters ([#&#8203;7431](astral-sh/uv#7431))
-   Show a dedicated PubGrub hint for `--unsafe-best-match` ([#&#8203;7645](astral-sh/uv#7645))
-   Add resolver error checking for conflicting distributions ([#&#8203;7595](astral-sh/uv#7595))

##### Bug fixes

-   Avoid adding double-newlines for CRLF ([#&#8203;7640](astral-sh/uv#7640))
-   Avoid retaining forks when `requires-python` range changes ([#&#8203;7624](astral-sh/uv#7624))
-   Determine if pre-release Python downloads should be allowed using the version specifiers ([#&#8203;7638](astral-sh/uv#7638))
-   Fix `link-mode=clone` for directories on Linux ([#&#8203;7620](astral-sh/uv#7620))
-   Improve Python executable name discovery when using alternative implementations ([#&#8203;7649](astral-sh/uv#7649))
-   Require opt-in to use alternative Python implementations ([#&#8203;7650](astral-sh/uv#7650))
-   Use the first pre-release discovered when only pre-release Python versions are available ([#&#8203;7666](astral-sh/uv#7666))

##### Documentation

-   Document environment variable that disables printing of virtual environment name in prompt ([#&#8203;7648](astral-sh/uv#7648))
-   Remove double whitespaces from the code ([#&#8203;7623](astral-sh/uv#7623))
-   Use anchorlinks rather than permalinks ([#&#8203;7626](astral-sh/uv#7626))

##### Preview features

-   Add build backend scaffolding ([#&#8203;7662](astral-sh/uv#7662))

</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:eyJjcmVhdGVkSW5WZXIiOiIzNy40NDAuNyIsInVwZGF0ZWRJblZlciI6IjM3LjQ0MC43IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
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.

FR: (uv venv) add support for '-p 3.13t' as a shorthand for '-p 3.13*t' ?
4 participants