Skip to content

settings: parse UV_SYSTEM_PYTHON in EnvironmentOptions - #21175

Closed
VedantMadane wants to merge 80 commits into
astral-sh:mainfrom
VedantMadane:env-options-system-python
Closed

VedantMadane wants to merge 80 commits into
astral-sh:mainfrom
VedantMadane:env-options-system-python

Conversation

@VedantMadane

Copy link
Copy Markdown

Parse \UV_SYSTEM_PYTHON\ in \EnvironmentOptions\ as part of #14720.

@EliteTK

EliteTK commented Aug 18, 2026

Copy link
Copy Markdown
Member

As it stands, this change alone doesn't really address the issue?

You've added the parsing bit, but you're not using it anywhere, and we're still using clap to parse this variable in 11 places...

@VedantMadane
VedantMadane force-pushed the env-options-system-python branch from 73cb939 to 9007ac5 Compare August 22, 2026 13:21
VedantMadane and others added 28 commits September 21, 2026 16:44
…1075)

`PYTHONEXECUTABLE` and `__PYVENV_LAUNCHER__` can change the executable
and virtual environment reported by a Python interpreter, but
interpreter metadata was cached using only the absolute and canonical
paths of the requested executable. Include both launcher overrides in
the interpreter cache key so metadata from one launcher context cannot
be reused in another. See astral-sh#21062.

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
…ace (astral-sh#20944)

Co-authored-by: William Woodruff <william@yossarian.net>
Signed-off-by: William Woodruff <william@yossarian.net>
…1079)

This extends our automations for issue triage to take reproducible bugs
with a regression-test and attempt to generate a PR fixing the issue.

- Context from the issue triage and reproduction are carried over into
the job to attempt to fix the bug
- The issue branch is updated with details on the fix attempt and result
- If a fix is proposed, a draft PR is opened stacked on the regression
test PR

This also introduces re-usable actions for loading the issue context and
codex thread from another workflow.

---------

Co-authored-by: Ee Durbin <ee@astral.sh>
Co-authored-by: Zanie Blue <contact@zanie.dev>
## Summary

We have `from_registry_requirement` that does the equivalent of all of
this code.

(Cleanup in preparation for PR to fix astral-sh#20477.)

## Test Plan

Existing coverage.
Reverts astral-sh#21055, CodSpeed team reports that their backend can
now support uv's samply results
Projects with checked-in type stubs may not require building their
native extensions for type checking, but `uv check` always installs the
project while synchronizing its dependencies. Support
`--no-install-project` and `UV_NO_INSTALL_PROJECT` so those projects can
install their dependencies and run checks without building or installing
themselves. Fixes astral-sh#21083.

Co-authored-by: Zanie Blue <contact@zanie.dev>
Invalid `uv version --bump` values currently produce unstyled errors
without a trailing newline. The custom parser introduced in
astral-sh#16555 returned raw, unformatted `clap` errors; construct
command-aware errors instead so malformed bump values use the standard
styling, usage guidance, and line termination. Fixes astral-sh#21063.

Co-authored-by: Zanie Blue <contact@zanie.dev>
## Summary

Previously, uv tracked Git metadata incorrectly in several cases:

- Linked worktrees watched their entire worktree metadata directory, so
staging an unrelated file invalidated the build even when the commit had
not changed.
- Branch references updated outside the worktree were not watched,
potentially leaving embedded commit hashes, dates, tags, and tag
distances stale.
- Packed branch references and relative worktree paths registered
nonexistent Cargo inputs, forcing a rebuild on every invocation.

We now track each worktree's actual `HEAD`, resolve branch references
through the shared Git directory, and handle relative paths and packed
references.

When the current branch is packed, we also watch the nearest existing
reference directory so a newly created loose reference becomes visible.
This can invalidate a packed-reference worktree when another branch in
the same repository changes.
Add a minimal integration test that reproduces astral-sh#21089.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
third time is a charm, (now that [ost-simple-sts supports
issue_comments](https://github.com/open-security-tools/ost-simple-sts/releases/tag/v0.0.5))
authorize automation for shuffling issue-context around on issue comment
events
## Summary

`uv check` runs `ty check` in a separate process, but previously applied
terminal settings only to uv itself. As a result, ty could still emit
colored output and draw progress bars despite `--color never`,
`--no-progress`, or the `--quiet` used by `ty-pre-commit`; its
cursor-control sequences could also erase output from earlier hooks.

- Forward uv's resolved color choice to the ty subprocess using
`ColorChoice::as_str()`.
- Centralize uv's progress policy in `Printer::suppresses_progress()`
and disable ty progress whenever uv suppresses it, including quiet mode.
- Add a hidden `uv check --show-command` diagnostic option that prints
the actual ty invocation with shell-safe argument quoting.
- Exercise a real ty binary when covering explicit flags, quiet mode,
automatic and forced color, environment-derived terminal settings, and
script paths containing spaces.

Fixes astral-sh/ty-pre-commit#20.
Empty PEP 508 requirements currently produce an orphaned caret after the
error message, including for inline-script dependencies. Skip span
formatting when the parser input is empty and update the existing parser
and integration snapshots. Fixes astral-sh#21089.

Co-authored-by: astral-automations-bot[bot] <305554984+astral-automations-bot[bot]@users.noreply.github.com>
…h#21093)

When a regression-test pull request is promoted or merged while an
automated fix is being prepared, the original `uv-dev` pull request
closes and the fix workflow rejects it as changed. Continue only when
the promoted upstream pull request preserves the verified regression
branch and commit, while still rejecting unrelated closures or changed
heads.

Co-authored-by: Zanie Blue <contact@zanie.dev>
Cache cleanup tests manually probed copy-on-write filesystem
configuration and could execute on unconfigured local filesystems, while
cache tests duplicated the same snapshot size-filter override in several
places. Use `TestContext::with_cache_on_cow_fs` to configure or skip
filesystem-dependent tests, require configured filesystems to produce
actual clones, and share `TestContext::with_cache_size_filters` across
cache cleanup, pruning, and sizing tests.

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
…onment indicates corruption (astral-sh#21073)

Interpreter metadata can remain stale when a Python launcher loads a
different `libpython` without its executable timestamp changing. For a
project without an existing environment, the first `uv run` can select
the stale cached base interpreter, create `.venv` with incorrect
`pyvenv.cfg` metadata, and evaluate `requires-python` against the wrong
Python version.

On a subsequent `uv run`, the existing environment exposes the
inconsistency: its interpreter reports the actual version while
`pyvenv.cfg` and the cached base interpreter report the stale version.
When both paths refer to the same underlying interpreter, clear only the
base interpreter cache entry before continuing normal interpreter
discovery. Discovery then queries the executable, saves the actual
version, validates `requires-python` against current metadata, and
recreates the environment once with the correct `pyvenv.cfg`; later runs
reuse it. Existing environments with genuine incompatibilities retain
their normal behavior.

This change does not detect a stale base interpreter cache before the
first environment is created, so the initial `uv run` can still use
incorrect metadata. Recovery begins only when a subsequent invocation
observes the inconsistent environment.

Fixes astral-sh#21066.

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
we copied the reproduce-bug's deterministic titles, but really we should
have something of substance (while remaining concise) in the PR title
and summary.
…#21101)

Generated regression tests can stop at the reported example and miss
other demonstrated manifestations of the same bug, including misleading
existing coverage. Teach the regression-test agent to inspect related
settings and producer/consumer paths, add the smallest worthwhile set of
same-root-cause regressions, and correct directly related tests without
expanding into speculative or unrelated cases.

Co-authored-by: Zanie Blue <contact@zanie.dev>
Cache cleanup tests assemble custom snapshot filters or mutate the test
context inside snapshot assertions, and the existing count helper also
hides package counts that these tests should retain. Add a focused
removed-file-count context builder and apply cache-specific filters when
constructing each test context so cleanup output stays stable without
weakening package-count assertions.

Co-authored-by: Zanie Blue <contact@zanie.dev>
Co-authored-by: astral-automations-bot[bot] <305554984+astral-automations-bot[bot]@users.noreply.github.com>
Co-authored-by: Zanie Blue <contact@zanie.dev>
)

Derivation-chain regression tests in lock, sync, pip install, and pip
compile each rebuild the same temporary source-path filter outside their
test context. Apply the existing filter directly during context
construction and use context filters in the snapshots, keeping the
build-failure diagnostics unchanged while removing repeated setup.

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
…#21114)

Several integration tests create a test context and immediately shadow
it solely to install static snapshot filters, which obscures setup and
scatters context configuration through the test. Attach those filters
when constructing the original context while preserving intentional
rebinding for dynamic paths, staged assertions, and optional filesystem
setup.

Co-authored-by: Zanie Blue <contact@zanie.dev>
Cross-origin redirect tests repeatedly build standalone localhost
snapshot-filter vectors after creating their test contexts. Register the
existing localhost normalization directly on each context and read its
filters at the assertion site, preserving redirect and authentication
coverage while removing duplicated filter plumbing.

Co-authored-by: Zanie Blue <contact@zanie.dev>
…21113)

The `uv self version --output-format json` snapshot filtered
`commit_hash` inside `short_commit_hash`, so both fields appeared as
`[LONGHASH]` and the short hash was not independently asserted. Match
complete hash field names and configure the static JSON filters on
`TestContext`, preserving distinct `[HASH]` and `[LONGHASH]`
placeholders.

Co-authored-by: Zanie Blue <contact@zanie.dev>
…sh#21111)

The version cache-independence test attempted to make the cache unusable
with `UV_CACHE_DIR`, but `TestContext::version()` supplies an explicit
`--cache-dir` that takes precedence, so its success snapshots never
exercised an invalid cache. Point the effective context cache directory
at an existing file and contrast successful version reads with a version
write that fails to initialize the cache.

Co-authored-by: Zanie Blue <contact@zanie.dev>
VedantMadane and others added 26 commits September 21, 2026 16:45
…21148)

This is another optimization inspired by nab, I'm not using my codex
credits for anything else at the moment, so I have it working on whether
those optimizations translate to uv, I know y'all need those spare
tokens ;o).

`Installable::to_resolution` ends by walking the locked graph and
evaluating a conflict marker on every dependency edge. Each call
re-encodes the activated projects, extras, and groups into a fresh
`Vec<ExtraName>`, a `format!` per item, but the set is final before the
walk starts.

`ActivatedConflictItems` encodes it once. The earlier passes can still
activate an extra, so they keep encoding per edge. A lock with no
declared conflicts has an empty activated set and nothing to reuse.

The star example is `uv sync --frozen --dry-run --all-extras --group
alpha` on a project pulling `apache-airflow[all]`. Profiling builds,
median of 60 runs, and the sync plan is byte-identical:

  | extras | activated items | wall | instructions |
  | ---: | ---: | ---: | ---: |
  | 40 | 61 | 53 → 42 ms | 428.2M → 264.0M |
  | 2 | 23 | 44 → 37 ms | 248.4M → 173.4M |

  <details>
  <summary>Reproduction</summary>

  pyproject.toml:

  ```toml
  [project]
  name = "mre"
  version = "0.1.0"
  requires-python = ">=3.12,<3.13"
  dependencies = ["apache-airflow[all]==2.10.5"]

  [project.optional-dependencies]
  e00 = ["idna"]
  e01 = ["idna"]

  [dependency-groups]
  alpha = ["idna"]
  beta = ["idna"]

  [tool.uv]
  conflicts = [[{ group = "alpha" }, { group = "beta" }]]

  [build-system]
  requires = ["hatchling"]
  build-backend = "hatchling.build"
  ```

  Commands:

  ```console
  $ uv lock --exclude-newer 2026-07-01
  $ uv venv
  $ uv sync --frozen --dry-run --all-extras --group alpha
  ```

  The first row adds `e02` through `e39`.

  </details>
astral-sh#21146)

The `venv_included_in_sdist` snapshot fails in the Gentoo package build.
The error line is identical; only the hint is missing:

```
    6       │-  Caused by: at byte [OFFSET]: unsafe symbolic-link target "[PYTHON-3.12]": is absolute
    7       │-
    8       │-hint: The source distribution includes a virtual environment. ...
          6 │+  Caused by: at byte [OFFSET]: unsafe symbolic-link target "[PYTHON-3.12]": is absolute
```

`ExtractError::UnsafePath` carries `position`, `context`, `value` and
`reason` — the link target, never the entry that declared it. The target
was being matched with `is_virtual_environment_python`, which requires
the parent directory to be `bin`. That shape is right for an archive
entry like `.venv/bin/python`, but a base interpreter is not required to
live in `bin`. Gentoo's build lays them out at
`<root>/python/3.12/python3`, where the parent is the version, so the
predicate returns false and the hint is dropped.

Reproduced outside the test suite by pointing a venv's `bin/python` at
an interpreter whose parent is not `bin`:

```console
$ uv build --preview-features tar-codec
error: Failed to build ...
  Caused by: at byte 1024: unsafe symbolic-link target ".../pydir/python/3.12/python3": is absolute
```

No hint. With the same project and a target at
`.../cpython-3.12/bin/python3`, the hint appears. That A/B is the whole
bug.

This matches the link target on its file name alone and keeps the
stricter entry-shaped check for the entry path in `InvalidLink`.

Added `venv_included_in_sdist_interpreter_outside_bin`, which builds
that layout explicitly. It fails without the change and the existing
`venv_included_in_sdist` is unaffected. Full `build` suite: 191 passed.
`cargo clippy --all-targets` and `cargo fmt --check` clean.

Closes astral-sh#21128

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
`uvx git+https://github.com/uPesy/easyeda2kicad.py` fails with "Not a
valid package or extra name".

`has_python_script_ext` calls `Path::extension()` on the raw argument,
so any URL whose last segment ends in `.py` is read as a script path. uv
then parses the whole URL as a package name, which is where the message
comes from.

This skips the script check when the argument carries a scheme
`Scheme::parse` recognises. Pairing `split_scheme` with `Scheme::parse`
is deliberate and matches the existing use in `verbatim_url.rs`: a bare
`split_scheme` would read the `C:` in `C:\script.py` as a scheme and
break script detection on Windows.

Before:

```console
$ uv tool run --offline git+https://github.com/uPesy/easyeda2kicad.py
error: Not a valid package or extra name: "git+https://github.com/uPesy/easyeda2kicad.py"
```

After, it reaches the git fetch and stops only on `--offline`:

```console
Updating https://github.com/uPesy/easyeda2kicad.py (HEAD)
error: ... Remote Git fetches are not allowed because network connectivity is disabled
```

Two tests added beside the existing script tests. They use `--offline`,
so they exercise the parse without touching the network. Both fail
without the change with the exact error above. The existing `script.py`,
missing-`script.py` and `--from script.py` behaviours are unchanged.

Closes astral-sh#21141

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
…ardless of libc (astral-sh#21137)

## Summary

When using musl we would fall back to using the inode, which would cause
churn when going between musl backed and glibc backed uv versions on the
same host.

Using rustix, this remains consistent as long as the underlying OS
supports the call for the specific filesystem.

This will cause a small bit of churn on musl systems, but that churn
will just be in the form of a cache invalidation when updating uv.

## Test Plan

Existing coverage for the functionality. Manual tests for checking musl
and linux now work the same (but we bypass glibc/musl so it didn't feel
worth it to try to come up with an automated regression test here).
Allow `uv workspace metadata --sync --exact` to remove packages outside
the selected resolution while preserving the existing inexact behavior
of `--sync`. Match `uv run --exact` semantics and ensure exact
synchronization also cleans environments for scripts without
dependencies.

Co-authored-by: Zanie Blue <contact@zanie.dev>
…h#21164)

Promotion currently accepts the latest head of a ready `uv-dev` pull
request, so commits pushed after it was marked ready can be promoted
without another approval. Require the `head_sha` from `ready_for_review`
and stop dispatching promotion on `synchronize`. If the source or
promoted head no longer matches, leave the source open, return it to
draft, explain the mismatch, and assign the human who marked it ready.

Co-authored-by: zaniebot <242828183+zaniebot@users.noreply.github.com>
Signed-off-by: William Woodruff <william@yossarian.net>
`pyx` has ended service. disable publication tests targeting pyx.
CI fails to check out the repository in private copies of uv because the
workflows explicitly remove `GITHUB_TOKEN` repository access. Public
checkouts work without that access, which hides the problem upstream.
Grant `contents: read` to the CI entry point and affected reusable
workflows, including jobs that override their inherited permissions, so
private CI can read its own source without granting repository write
access.

Co-authored-by: zaniebot <242828183+zaniebot@users.noreply.github.com>
<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

Adds a 7 day cooldown to all of our PEP 723 style scripts.

<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

NFC.

<!-- How was it tested? -->

---

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

Each of the commits in this PR addresses a different group of `uv audit`
findings, in different lockfiles.

<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

NFC.

<!-- How was it tested? -->

---

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
This PR enables PGO for uv releases, starting with Linux x86-64.

The release pipeline is modified as follows:

- We build instrumented `uv` and `uvx` release binaries inside the
existing manylinux container.
- We train directly on eleven shared `test/ecosystem` fixtures:
cibuildwheel, Cookiecutter, Flask, HTTPX, LLM, the OpenAI Python SDK,
Poetry, pytest-cov, Sentry, Zulip, and the 38-project pyx workspace.
- Every project exercises cold and warm `uv pip compile` resolution,
cold and warm `uv lock` resolution, `uv export`, `uv pip` installation,
and `uv sync` installation on every release platform.
- Per-project `exclude-dependencies` settings omit packages without
compatible release-platform wheels while preserving the rest of each
real dependency graph.
- Raw profiles are merged online by workload family, then merged with
`llvm-profdata` and fed back into the existing `maturin` build.
- JupyterLab, Saleor, Semantic Kernel, Transformers, and Warehouse
remain separate, held-out evaluation projects.

We benchmarked the builds on Linux x86-64 using the expanded corpus for
training and five separate held-out ecosystem projects for evaluation.

| Held-out project | Dependency resolution | Wheel installation |
Project locking | Lockfile export |
| ---------------- | --------------------: | -----------------: |
---------------: | --------------: |
| JupyterLab | 11.2% faster | 0.0% | 10.1% faster | 10.6% faster |
| Semantic Kernel | 9.3% faster | 7.1% faster | 12.5% faster | 8.7%
faster |
| Transformers | 11.7% faster | 4.1% faster | 9.5% faster | 11.0% faster
|
| Saleor | — | — | 9.7% faster | 10.0% faster |
| Warehouse | — | — | 9.7% faster | 7.6% faster |
| Geometric mean | **10.7% faster** | **3.7% faster** | **10.3% faster**
| **9.6% faster** |

Across all sixteen held-out workloads, wall time decreased by **8.9%**
(95% CI: 8.4–9.8%) and CPU time decreased by **8.4%** (95% CI:
7.9–9.0%). The matched Linux executable was **13.3% smaller** (58.91 MB
to 51.05 MB), or **12.3% smaller** after gzip compression (22.68 MB to
19.90 MB).

(Saleor and Warehouse include source-only dependencies, so they are
benchmarked on locking and export rather than wheel-only installation.)

Additional platforms are covered in subsequent PRs in the stack: macOS
ARM64, Windows x86-64, and Linux ARM64.

Ruff and ty follow the same approach; see the stacks here:

- astral-sh/ruff#27570
- astral-sh/ty#4213
## Summary

This PR enables PGO for uv's macOS ARM64 releases, following the
approach outlined in astral-sh#21001.
## Summary

This PR enables PGO for uv's Windows x86-64 releases, following the
approach outlined in astral-sh#21001. The
existing static-CRT configuration is preserved.
## Summary

This PR enables PGO for uv's Linux ARM64 releases, following the
approach outlined in astral-sh#21001. (To
enable PGO, we also move to a native ARM64 runner.)
## Summary

The PGO build script was introduced after we added seven-day dependency
cooldowns to our PEP 723 scripts, so its inline metadata and lockfile
did not include the repository-wide `exclude-newer` setting. As a
result, script lockfile validation and locked script type checking both
fail on `main`.

Declare the same `P7D` cooldown as the other scripts and regenerate the
script lockfile so both CI checks accept it.

Closes astral-sh#777.
`zizmor-action` uploads findings to GitHub code scanning by default,
which is unavailable in private copies without Code Security enabled.
Keep code-scanning uploads for `astral-sh/uv` and report findings as
workflow annotations elsewhere. Check the repository name instead of
GitHub's `fork` flag so independently created private copies are covered
too.

---------

Co-authored-by: zaniebot <242828183+zaniebot@users.noreply.github.com>
Co-authored-by: Zanie Blue <contact@zanie.dev>
Co-authored-by: William Woodruff <william@astral.sh>
Enable the HTTPX SOCKS extra in the publish integration script and
update its lockfile.
)

Co-authored-by: Zanie Blue <contact@zanie.dev>
@astral-sh-bot

astral-sh-bot Bot commented Sep 21, 2026

Copy link
Copy Markdown

We support using AI (i.e., LLMs) while coding. However, AI should not be used to communicate with maintainers.

Please read and follow our AI policy when submitting issues and pull requests.

@astral-sh-bot astral-sh-bot Bot closed this Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants