Skip to content

Correctly split dependencies into production and optional markers - #20671

Merged
konstin merged 4 commits into
mainfrom
konsti/metadata-free-lock-selections
Jul 27, 2026
Merged

Correctly split dependencies into production and optional markers#20671
konstin merged 4 commits into
mainfrom
konsti/metadata-free-lock-selections

Conversation

@konstin

@konstin konstin commented Jul 24, 2026

Copy link
Copy Markdown
Member

Using a marker in a non-conventional way (not and extra == "name" at the top-level), such as sys_platform == 'win32' or extra == 'feature', surfaces a resolver bug where this dependency appears to be an unconditional production dependency, and can also move a production dependency into an optional source edge.

To handle this more correctly, if we see e.g.
foo; sys_platform == 'win32' or extra == 'feature'
we split it into
foo; sys_platform == 'win32' (production dependency)
and
foo; extra == 'feature' (extra)
which are tracked in production and optional dependencies respectively.

Fixing this bug simplifies package.metadata-free lockfile validation.

@konstin
konstin force-pushed the konsti/metadata-free-lock-selections branch from 8bcd3ad to ca92575 Compare July 24, 2026 11:46
@astral-sh-bot

This comment has been minimized.

@konstin
konstin force-pushed the konsti/metadata-free-lock-selections branch from ca92575 to 2c63ab7 Compare July 24, 2026 12:39
@konstin
konstin force-pushed the konsti/metadata-free-lock-selections branch from 2c63ab7 to 0038355 Compare July 24, 2026 12:53
@konstin
konstin force-pushed the konsti/metadata-free-lock-selections branch from 64e9a5e to 614255d Compare July 25, 2026 14:16
@codspeed-hq

codspeed-hq Bot commented Jul 25, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 10.59%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 3 regressed benchmarks
✅ 18 untouched benchmarks
⏩ 6 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
WallTime resolve_warm_airflow 210.4 ms 250.2 ms -15.9%
Simulation resolve_warm_airflow 301.8 ms 339.9 ms -11.2%
WallTime resolve_warm_jupyter_universal 87.4 ms 91.3 ms -4.29%

Tip

Investigate this regression with the CodSpeed MCP and your agent.


Comparing konsti/metadata-free-lock-selections (0bb779f) with main (116ca06)

Open in CodSpeed

Footnotes

  1. 6 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@konstin konstin changed the title Support frozen installs from metadata-free lockfiles Extract reusable locked dependency edge builder Jul 25, 2026
@konstin
konstin changed the base branch from main to konsti/locked-dependency-builder July 25, 2026 15:54
@konstin
konstin force-pushed the konsti/locked-dependency-builder branch from 2c244aa to cf1e02b Compare July 25, 2026 15:54
@konstin
konstin force-pushed the konsti/metadata-free-lock-selections branch from 614255d to 2c244aa Compare July 25, 2026 15:54
@konstin
konstin force-pushed the konsti/metadata-free-lock-selections branch from 2c244aa to d908043 Compare July 25, 2026 16:43
@konstin
konstin force-pushed the konsti/locked-dependency-builder branch from cf1e02b to 5a00d9f Compare July 25, 2026 16:43
@konstin konstin changed the title Extract reusable locked dependency edge builder Fix extra marker specialization in dependency resolution Jul 25, 2026
@konstin
konstin force-pushed the konsti/metadata-free-lock-selections branch from d908043 to 95b9be8 Compare July 25, 2026 17:33
@konstin konstin added bug Something isn't working preview Experimental behavior labels Jul 25, 2026
@konstin
konstin requested a review from charliermarsh July 25, 2026 18:53
Comment thread crates/uv-resolver/src/resolver/mod.rs Outdated
Comment on lines +2351 to +2361
let mut marker = requirement
.marker
.simplify_extras(slice::from_ref(extra))
.simplify_not_extras_with(|candidate| candidate != extra);
marker.and(
requirement
.marker
.simplify_not_extras_with(|_| true)
.negate(),
);
marker

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think that's what we should have been doing here in the first place, it looks more correct.

This isn't a commitment to supporting non-and extra == "name" extra markers, but currently we're somewhat supporting them, just wrongly.

@charliermarsh charliermarsh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think I would consider not making this a preview feature. Isn't it a bug fix?

@konstin
konstin force-pushed the konsti/metadata-free-lock-selections branch from 1afc48a to e976a52 Compare July 25, 2026 22:11
@konstin
konstin force-pushed the konsti/locked-dependency-builder branch from 184aaed to 920910c Compare July 25, 2026 22:11
Katomoto

This comment was marked as spam.

@konstin
konstin force-pushed the konsti/locked-dependency-builder branch from 920910c to fe2bd84 Compare July 26, 2026 17:33
@konstin
konstin force-pushed the konsti/metadata-free-lock-selections branch from fe6288d to 8c20a69 Compare July 26, 2026 17:33
@konstin
konstin requested review from EliteTK and removed request for EliteTK July 26, 2026 18:19
Base automatically changed from konsti/locked-dependency-builder to main July 27, 2026 14:29
@konstin konstin removed the preview Experimental behavior label Jul 27, 2026
@konstin

konstin commented Jul 27, 2026

Copy link
Copy Markdown
Member Author

I've removed the preview feature.

@konstin
konstin enabled auto-merge (squash) July 27, 2026 19:38
konstin added 4 commits July 27, 2026 21:57
Keep production and selected-extra dependency markers distinct while preserving the reviewed preview feature, generated schema, and lock regression coverage.
@konstin
konstin force-pushed the konsti/metadata-free-lock-selections branch from 56bbf5f to 0bb779f Compare July 27, 2026 20:05
@konstin
konstin merged commit 6b3b62a into main Jul 27, 2026
59 checks passed
@konstin
konstin deleted the konsti/metadata-free-lock-selections branch July 27, 2026 20:17
konstin added a commit that referenced this pull request Jul 28, 2026
## 0.11.33

Released on 2026-07-28.

### Enhancements

- Abort panics in release builds for smaller uv binaries
([#20271](#20271))
- Use `.tar.gz` archives for Pyodide installs
([#20667](#20667))

### Preview features

- Avoid checking any scripts in `uv check` unless `--script` is passed
([#20676](#20676))
- Check locked tools for malware before cache reuse
([#20301](#20301))
- Write and read `package.metadata`-free lockfiles
([#20688](#20688),
[#20691](#20691),
[#20685](#20685),
[#20695](#20695))

### Bug fixes

- Correctly split dependencies into production and optional markers
([#20671](#20671))
- Fix discrepancies in argument parsing of exclude-newer
([#20679](#20679))
- Cleanup managed Python temporary directory on error
([#20752](#20752))
luketainton pushed a commit to luketainton/repos_labmcp that referenced this pull request Jul 28, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [ghcr.io/astral-sh/uv](https://github.com/astral-sh/uv) | final | minor | `0.11.32` → `0.12.0` |

---

### Release Notes

<details>
<summary>astral-sh/uv (ghcr.io/astral-sh/uv)</summary>

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

[Compare Source](astral-sh/uv@0.11.33...0.12.0)

Released on 2026-07-28.

Since we released uv [0.11.0](https://github.com/astral-sh/uv/releases/tag/0.11.0) in March, we've accumulated changes that improve correctness, safety, and compatibility with specifications, but could break some workflows. This release contains those changes; many have been marked as breaking out of an abundance of caution.

**We expect most users to be able to upgrade without making changes.**

There are no breaking changes to the configuration of the [uv build backend](https://docs.astral.sh/uv/concepts/build-backend/). If your `[build-system]` table includes an upper bound on `uv_build`, update it from `<0.12` to `<0.13` to allow `uv_build` 0.12:

```toml
requires = ["uv_build>=0.11.32,<0.13"]
```

##### Breaking changes

- **Define build systems by default with `uv init`** ([#&#8203;19197](astral-sh/uv#19197))

  Projects created with `uv init` now declare a build system and are packaged by default. This was the default project layout all the way back in [v0.3](https://github.com/astral-sh/uv/releases/tag/0.3.0), but we found that the use of the `hatchling` build system was confusing to newcomers and consequently dropped use of a build system by default in [v0.4](https://github.com/astral-sh/uv/releases/tag/0.4.0). Since then, we've created our own build system (`uv_build`) with tight integration with uv and are excited to restore the default to a best-practice project layout.

  Previously, `uv init example` created an unpackaged layout containing `main.py` and a `pyproject.toml` without a build system. The project could declare dependencies but was not itself installed into its virtual environment.

  Now, `uv init example` defines a `[build-system]` using `uv_build`, places application source code in `src/example`, and includes a `[project.scripts]` entry named `example`. Defining a build system allows the project to be imported from tests or other code, installed as a dependency, and run as a command:

  ```console
  $ uv init example
  $ cd example
  $ uv run example
  Hello from example!
  ```

  Existing projects are unaffected. Use [`uv init --no-package example`](https://docs.astral.sh/uv/concepts/projects/init/#creating-a-project-without-a-build-system) to create the previous unpackaged layout without a build system.

  See the [project creation documentation](https://docs.astral.sh/uv/concepts/projects/init/#applications) for more details.

  This stabilizes the `packaged-init` preview feature.

- **Reject unsupported source distribution and wheel archive formats** ([#&#8203;18927](astral-sh/uv#18927))

  [PEP 625](https://peps.python.org/pep-0625/) requires [source distributions](https://docs.astral.sh/uv/concepts/resolution/#source-distribution) to use `.tar.gz` archives. Previously, uv also accepted legacy formats such as `.tar.bz2` and `.tar.xz`. Those formats are now rejected, including when referenced by an existing lockfile. Legacy `.zip` source distributions remain supported for backwards compatibility.

  Wheels and other ZIP archives can no longer contain entries compressed with bzip2, LZMA, or XZ. Entries must use the stored, DEFLATE, or zstd compression methods.

  Removing support for uncommon compression methods reduces uv's compression dependencies and the attack surface exposed when processing untrusted packages.

  You cannot opt out of this behavior. If you depend on a legacy source distribution that uses an unsupported format, we recommend rebuilding it as a `.tar.gz` archive and regenerating any lockfile containing references to the legacy archive.

- **Reject wheel files that could replace the Python interpreter** ([#&#8203;20748](astral-sh/uv#20748), [#&#8203;20749](astral-sh/uv#20749))

  uv already rejected wheel entry points named `python`, but case variants such as `Python` were still accepted. On case-insensitive filesystems, including common macOS and Windows setups, these entry points could overwrite the virtual environment's interpreter.

  Wheels could also place interpreter files in their `.data/scripts` directory or in paths such as `.data/data/bin/python`, bypassing the entry-point check and replacing the interpreter during installation.

  uv now rejects case-insensitive variants of reserved interpreter names and wheel data files that would be installed over an interpreter. This includes names such as `Python`, `python.py`, and `Python.exe`, along with other reserved interpreter names and their versioned variants.

  You cannot opt out of these checks. Rename conflicting entry points or wheel data files and rebuild the affected wheel.

- **Prefer stable releases before falling back to pre-releases** ([#&#8203;19993](astral-sh/uv#19993))

  A dependency can introduce a [pre-release requirement](https://docs.astral.sh/uv/concepts/resolution/#pre-release-handling) after resolution starts. uv previously required each package's pre-release eligibility to be known before resolution began: the default `if-necessary-or-explicit` mode allowed them for direct requirements that explicitly requested a pre-release, or for packages that only published pre-releases.

  This meant that a pre-release requirement discovered in a dependency's metadata, e.g., `example>=2.0.0b1`, would fail to resolve even when a compatible pre-release existed. To resolve it, you had to add that dependency as a direct requirement or allow pre-releases across your entire dependency graph.

  The default mode is now `if-necessary`. uv tries stable candidates first and falls back to pre-releases when no stable candidate satisfies the active constraints. Like pip, uv now supports [pre-release requirements discovered transitively](https://docs.astral.sh/uv/pip/compatibility/#pre-release-compatibility), but can select different versions than previous uv releases when both stable and pre-release candidates are available.

  You can opt out of automatic pre-release selection with `--prerelease disallow`. Alternatively, `--prerelease allow` considers pre-releases without first preferring stable releases, and `--prerelease explicit` only allows them for direct requirements that mention a pre-release.

  The old `if-necessary-or-explicit` mode distinguished between explicitly requested pre-releases and packages with no stable releases. That distinction is unnecessary now that `if-necessary` handles both cases, including transitive requirements. The old name remains available as an alias but is deprecated and will be removed in a future release.

- **Respect `--require-hashes` directives in `requirements.txt`** ([#&#8203;19336](astral-sh/uv#19336))

  Previously, `uv pip install` and `uv pip sync` warned about `--require-hashes` inside a `requirements.txt` file but still installed dependencies without checking their hashes. Now, the directive enables hash-checking mode, just as if `--require-hashes` had been passed on the command line.

  For example, this requirements file is no longer accepted because the requirement is neither pinned nor hashed:

  ```text
  --require-hashes
  anyio
  ```

  You cannot opt out while the directive is present. Pin every requirement with `==` and provide its hash, or remove `--require-hashes` if hash checking is not intended.

- **Reject MD5-only hashes in hash-checking mode** ([#&#8203;20758](astral-sh/uv#20758))

  Previously, `uv pip install --require-hashes` and `uv pip sync --require-hashes` accepted requirements whose only available digest used MD5. MD5 is not collision-resistant, so relying on it undermined installations that require hash verification and differed from pip's behavior.

  Hash-checking mode now requires at least one secure digest for every requirement. For example, the following requirement is rejected unless a secure hash, such as SHA-256, is also supplied:

  ```text
  anyio==4.0.0 --hash=md5:420d85e19168705cdf0223621b18831a
  ```

  A secure hash can be supplied directly on the requirement or in a matching constraints file. Ordinary hash verification without `--require-hashes` continues to support MD5.

  You cannot opt out while hash checking is required. Regenerate affected hashes with SHA-256 or another supported secure hash.

- **Reject invalid `pylock.toml` files and artifacts** ([#&#8203;20402](astral-sh/uv#20402), [#&#8203;20440](astral-sh/uv#20440), [#&#8203;20443](astral-sh/uv#20443))

  uv now validates additional requirements from the [`pylock.toml` specification](https://packaging.python.org/en/latest/specifications/pylock-toml/):

  - The `packages` array must be present. Previously, uv interpreted a missing array as an empty lockfile, so `uv pip sync` could uninstall an environment instead of rejecting malformed input. An explicitly empty `packages = []` array remains valid.
  - Lockfile filenames must be `pylock.toml` or a single-name variant such as `pylock.dev.toml`. Names such as `pylock..toml` and `pylock.foo.bar.toml` are rejected.
  - If a wheel, source distribution, or other artifact declares a `size`, the downloaded or cached artifact must match. Previously, an incorrect size was accepted when the hash was correct. Sizes reported by package indexes remain advisory.

  You cannot opt out of these checks. Regenerate malformed lockfiles, rename invalid filenames, and either correct or remove an incorrect optional `size` value.

- **Honor explicit certificate overrides even when no certificates can be loaded** ([#&#8203;20741](astral-sh/uv#20741), [#&#8203;20767](astral-sh/uv#20767))

  Previously, uv ignored [`SSL_CERT_FILE` or `SSL_CERT_DIR`](https://docs.astral.sh/uv/concepts/authentication/certificates/#custom-certificates) values that pointed to missing or inaccessible paths, empty files or directories, or sources without valid certificates. Instead, it fell back to its default trust roots, potentially allowing HTTPS connections that the configured override was intended to reject.

  Now, any non-empty `SSL_CERT_FILE` or `SSL_CERT_DIR` value replaces uv's default certificate roots, even when no valid certificates can be loaded. In that case, HTTPS requests fail because no certificates are trusted. This applies to package downloads and remote scripts, including GitHub Gists.

  Fix or unset the certificate override. Unsetting it restores the default trust store; empty environment-variable values continue to be ignored.

- **Support pip-compatible `--cert` handling in `uv pip`** ([#&#8203;20418](astral-sh/uv#20418))

  The `uv pip` interface now accepts [`--cert <path>`](https://docs.astral.sh/uv/concepts/authentication/certificates/#custom-certificates), e.g.:

  ```console
  $ uv pip install --cert ./company-ca.pem example
  ```

  As in pip, the provided PEM bundle replaces all other certificate sources for that invocation, including system certificates and `SSL_CERT_FILE` or `SSL_CERT_DIR`. This change has no effect unless you pass `--cert`. Include the necessary certificate authorities in the bundle.

  `--cert` is only supported by `uv pip` commands; other uv commands continue to use their existing certificate configuration.

- **Discover projects relative to the script passed to `uv run`** ([#&#8203;20225](astral-sh/uv#20225))

  Previously, `uv run project/script.py` discovered its project from the current directory, even when the script belonged to another project. uv now starts project and workspace discovery from the script's directory instead.

  For example, running `uv run other-project/script.py` now uses `other-project` and its dependencies. This fixes scripts that previously failed because their own dependencies were not installed, but can select a different environment than before.

  You can opt out of script-relative discovery by selecting a project explicitly, e.g., `uv run --project . other-project/script.py`.

  This stabilizes the `target-workspace-discovery` preview feature.

- **Require `--force` before clearing a directory that is not a virtual environment** ([#&#8203;20225](astral-sh/uv#20225))

  `uv venv --clear` previously removed any existing target directory, even if it was not a virtual environment. uv emitted a warning but still deleted the directory and its contents. Now, uv refuses to clear directories that do not contain a virtual environment.

  You can opt out of this safety check by explicitly passing `--force`, e.g., `uv venv --clear --force ./not-a-virtualenv`.

  This stabilizes the `venv-safe-clear` preview feature.

- **Reject `--project` when initializing a project** ([#&#8203;20225](astral-sh/uv#20225))

  `--project` selects an existing project, so it is not meaningful when initializing a new one. Previously, `uv init --project example` warned and initialized `example` anyway; if a positional path was also provided, `--project` was ignored.

  This usage is now an error. Use `uv init example` to initialize a project at the requested path, or `uv init --directory example` to change the working directory first.

  This stabilizes the `init-project-flag` preview feature.

- **Reject missing or invalid `--project` paths** ([#&#8203;20225](astral-sh/uv#20225))

  uv previously warned when `--project` referred to a missing directory or a file other than `pyproject.toml`, but then attempted to continue. This could produce confusing errors later or run against an unintended project.

  Now, `uv run --project missing python` fails immediately instead of continuing. You cannot opt out of this behavior. Create the directory first or select an existing project. Passing `--project path/to/pyproject.toml` remains supported and selects the file's parent directory.

  This stabilizes the `project-directory-must-exist` preview feature.

- **Skip distributions with non-normalized filenames when publishing** ([#&#8203;20225](astral-sh/uv#20225))

  Distribution filenames must use [normalized package names](https://packaging.python.org/en/latest/specifications/name-normalization/) and versions. For example, a wheel for version `1.01.0` should be named `example-1.1.0-py3-none-any.whl`, not `example-1.01.0-py3-none-any.whl`.

  Previously, `uv publish` warned about non-normalized filenames but still attempted to upload them. It now skips the affected wheels and source distributions instead.

  You cannot opt out of this behavior. Rebuild distributions with normalized filenames before publishing.

  This stabilizes the `publish-require-normalized` preview feature.

- **Classify Conda environments named `base` and `root` by their paths** ([#&#8203;20225](astral-sh/uv#20225))

  Conda environments named `base` or `root` were previously assumed to be the base Conda environment, even when they were ordinary child environments. uv now recognizes child Conda environments named `base` or `root` based on their paths, as it already does for other names.

  You can opt out of automatic interpreter selection by requesting an interpreter explicitly with `--python /path/to/python`.

  This stabilizes the `special-conda-env-names` preview feature.

- **Reject broken `.venv` symlinks during environment discovery** ([#&#8203;20433](astral-sh/uv#20433))

  Previously, uv could ignore a broken `.venv` symlink and continue searching parent directories for another virtual environment. As a result, commands such as `uv pip install` could unexpectedly modify an unrelated ancestor environment.

  uv now stops at a broken `.venv` symlink and reports its exact path. Errors encountered while reading virtual environment metadata, including permission failures, are also reported immediately instead of being ignored.

  You cannot opt out of this behavior. Repair or remove the broken `.venv` symlink and correct any permissions that prevent uv from inspecting the environment.

- **Reinstall matching installed Python patch versions instead of upgrading implicitly** ([#&#8203;20659](astral-sh/uv#20659))

  Before [Python upgrades](https://docs.astral.sh/uv/guides/install-python/#upgrading-python-versions) were supported, `uv python install 3.12 --reinstall` doubled as a way to install the latest Python 3.12 patch release. Now that `--upgrade` is available, `--reinstall` reinstalls the matching patch releases that are already present.

  For example, if Python 3.12.6 and 3.12.7 are installed, `uv python install 3.12 --reinstall` reinstalls both versions instead of installing the latest available 3.12 release.

  You can recover the previous upgrade behavior with `uv python install 3.12 --upgrade`. Combine `--upgrade --reinstall` to reinstall only the latest patch.

- **Require `--upgrade-group` to name an existing dependency group** ([#&#8203;18957](astral-sh/uv#18957))

  Previously, `uv lock --upgrade-group docs` silently succeeded even if no `docs` [dependency group](https://docs.astral.sh/uv/concepts/projects/dependencies/#dependency-groups) existed. uv now validates the requested group against the project, its workspace members, and workspace-level dependency groups.

  You cannot opt out of this behavior. Correct the group name or add it to `[dependency-groups]`. Legacy `tool.uv.dev-dependencies` still satisfies `--upgrade-group dev`.

- **Resolve relative indexes and find-links against `--directory`** ([#&#8203;20740](astral-sh/uv#20740))

  The `--directory` option changes the directory in which uv operates. Previously, relative index and find-links paths supplied on the command line were still resolved against the original working directory.

  uv now resolves `--index`, `--default-index`, `--index-url`, `--extra-index-url`, and `--find-links` relative to the directory selected by `--directory`. For example:

  ```console
  $ uv add --directory project --index ./packages example
  ```

  This now uses `project/packages` instead of `./packages` in the original working directory. Absolute paths and indexes loaded from configuration files are unaffected.

  To preserve the previous target, pass an absolute path or adjust the relative path, e.g., `--index ../packages`.

- **Preserve absolute paths provided to `uv add`** ([#&#8203;18402](astral-sh/uv#18402))

  `uv add` previously converted every local dependency into a project-relative path, even when the original request used an absolute path or a literal `file://` URL. It now preserves the form of the request in `pyproject.toml` and `uv.lock`:

  ```console
  $ uv add ../library             # remains relative
  $ uv add /projects/library      # remains absolute
  ```

  Absolute paths make a project less portable. Use a relative path to avoid recording an absolute path. URLs containing expanded variables retain their existing relative-path behavior.

- **Remove older PyPy distributions that are only available as bzip2 archives** ([#&#8203;20423](astral-sh/uv#20423))

  Older PyPy patch releases that are only distributed as `.tar.bz2` archives are no longer available through `uv python install`. These releases require unsupported bzip2 archives.

  The latest PyPy release for each supported Python minor version is available as a gzip-compressed archive and remains supported. For example, `uv python list 3.10 --all-versions` still includes the latest PyPy 3.10 release, but older bzip2-only patch releases are omitted.

  You cannot opt out of this behavior. Request a newer PyPy patch release instead.

- **Omit excluded-package comments when annotations are disabled** ([#&#8203;20085](astral-sh/uv#20085))

  `uv pip compile --no-annotate` suppresses comments describing the generated requirements file. Previously, a footer listing packages excluded with `--unsafe-package` was still included, even though annotations were disabled. That footer is now omitted.

  You can recover the footer by removing `--no-annotate`.

##### Stabilizations

- **TOML 1.0-compatible source distributions** ([#&#8203;20225](astral-sh/uv#20225))

  `uv_build` now writes a TOML 1.0-compatible `pyproject.toml` when building source distributions, allowing older Python build frontends to consume projects that use newer TOML syntax. The original project file remains available in the archive as `pyproject.toml.orig`.

  This stabilizes the `toml-backwards-compatibility` preview feature.

- **Automatic open-file limit adjustment on Unix** ([#&#8203;20225](astral-sh/uv#20225))

  On Linux and macOS, uv now attempts to raise the soft open-file limit at startup toward the hard limit, capped at 1,048,576 descriptors. The new limit also applies to subprocesses and reduces failures caused by running out of file descriptors. If the limit cannot be raised, uv continues running with the existing limit.

  This stabilizes the `adjust-ulimit` preview feature.

##### Preview features

- Allow `uv upgrade` to target multiple packages, upgrade all production dependencies, and exclude selected dependencies ([#&#8203;20338](astral-sh/uv#20338))

##### Bug fixes

- Include extras activated by dependency groups when evaluating conflicts ([#&#8203;20237](astral-sh/uv#20237))

### [`v0.11.33`](https://github.com/astral-sh/uv/releases/tag/0.11.33)

[Compare Source](astral-sh/uv@0.11.32...0.11.33)

#### Release Notes

Released on 2026-07-28.

##### Enhancements

- Abort panics in release builds for smaller uv binaries ([#&#8203;20271](astral-sh/uv#20271))
- Use `.tar.gz` archives for Pyodide installs ([#&#8203;20667](astral-sh/uv#20667))

##### Preview features

- Avoid checking any scripts in `uv check` unless `--script` is passed ([#&#8203;20676](astral-sh/uv#20676))
- Check locked tools for malware before cache reuse ([#&#8203;20301](astral-sh/uv#20301))
- Write and read `package.metadata`-free lockfiles ([#&#8203;20688](astral-sh/uv#20688), [#&#8203;20691](astral-sh/uv#20691), [#&#8203;20685](astral-sh/uv#20685), [#&#8203;20695](astral-sh/uv#20695))

##### Bug fixes

- Correctly split dependencies into production and optional markers ([#&#8203;20671](astral-sh/uv#20671))
- Fix discrepancies in argument parsing of exclude-newer ([#&#8203;20679](astral-sh/uv#20679))
- Cleanup managed Python temporary directory on error ([#&#8203;20752](astral-sh/uv#20752))

#### Install uv 0.11.33

##### Install prebuilt binaries via shell script

```sh
curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-installer.sh | sh
```

##### Install prebuilt binaries via powershell script

```sh
powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-installer.ps1 | iex"
```

#### Download uv 0.11.33

| File                                                                                                                                                | Platform                     | Checksum                                                                                                                   |
| --------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| [uv-aarch64-apple-darwin.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-aarch64-apple-darwin.tar.gz)                     | Apple Silicon macOS          | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-aarch64-apple-darwin.tar.gz.sha256)           |
| [uv-x86\_64-apple-darwin.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-x86_64-apple-darwin.tar.gz)                      | Intel macOS                  | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-x86_64-apple-darwin.tar.gz.sha256)            |
| [uv-aarch64-pc-windows-msvc.zip](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-aarch64-pc-windows-msvc.zip)                     | ARM64 Windows                | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-aarch64-pc-windows-msvc.zip.sha256)           |
| [uv-i686-pc-windows-msvc.zip](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-i686-pc-windows-msvc.zip)                           | x86 Windows                  | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-i686-pc-windows-msvc.zip.sha256)              |
| [uv-x86\_64-pc-windows-msvc.zip](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-x86_64-pc-windows-msvc.zip)                      | x64 Windows                  | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-x86_64-pc-windows-msvc.zip.sha256)            |
| [uv-aarch64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-aarch64-unknown-linux-gnu.tar.gz)           | ARM64 Linux                  | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-aarch64-unknown-linux-gnu.tar.gz.sha256)      |
| [uv-i686-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-i686-unknown-linux-gnu.tar.gz)                 | x86 Linux                    | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-i686-unknown-linux-gnu.tar.gz.sha256)         |
| [uv-powerpc64le-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-powerpc64le-unknown-linux-gnu.tar.gz)   | PPC64LE Linux                | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-powerpc64le-unknown-linux-gnu.tar.gz.sha256)  |
| [uv-riscv64gc-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-riscv64gc-unknown-linux-gnu.tar.gz)       | RISCV Linux                  | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-riscv64gc-unknown-linux-gnu.tar.gz.sha256)    |
| [uv-s390x-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-s390x-unknown-linux-gnu.tar.gz)               | S390x Linux                  | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-s390x-unknown-linux-gnu.tar.gz.sha256)        |
| [uv-x86\_64-unknown-linux-gnu.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-x86_64-unknown-linux-gnu.tar.gz)            | x64 Linux                    | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-x86_64-unknown-linux-gnu.tar.gz.sha256)       |
| [uv-armv7-unknown-linux-gnueabihf.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-armv7-unknown-linux-gnueabihf.tar.gz)   | ARMv7 Linux                  | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-armv7-unknown-linux-gnueabihf.tar.gz.sha256)  |
| [uv-aarch64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-aarch64-unknown-linux-musl.tar.gz)         | ARM64 MUSL Linux             | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-aarch64-unknown-linux-musl.tar.gz.sha256)     |
| [uv-i686-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-i686-unknown-linux-musl.tar.gz)               | x86 MUSL Linux               | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-i686-unknown-linux-musl.tar.gz.sha256)        |
| [uv-riscv64gc-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-riscv64gc-unknown-linux-musl.tar.gz)     | RISCV MUSL Linux             | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-riscv64gc-unknown-linux-musl.tar.gz.sha256)   |
| [uv-x86\_64-unknown-linux-musl.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-x86_64-unknown-linux-musl.tar.gz)          | x64 MUSL Linux               | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-x86_64-unknown-linux-musl.tar.gz.sha256)      |
| [uv-arm-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-arm-unknown-linux-musleabihf.tar.gz)     | ARMv6 MUSL Linux (Hardfloat) | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-arm-unknown-linux-musleabihf.tar.gz.sha256)   |
| [uv-armv7-unknown-linux-musleabihf.tar.gz](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-armv7-unknown-linux-musleabihf.tar.gz) | ARMv7 MUSL Linux             | [checksum](https://releases.astral.sh/github/uv/releases/download/0.11.33/uv-armv7-unknown-linux-musleabihf.tar.gz.sha256) |

#### Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the [GitHub CLI](https://cli.github.com/manual/gh_attestation_verify):

```sh
gh attestation verify <file-path of downloaded artifact> --repo astral-sh/uv
```

You can also download the attestation from [GitHub](https://github.com/astral-sh/uv/attestations) and verify against that directly:

```sh
gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>
```

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

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

---

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

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODUuMyIsInVwZGF0ZWRJblZlciI6IjQzLjI4NS4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJ0eXBlL2RlcGVuZGVuY2llcyJdfQ==-->Reviewed-on: https://git.tainton.uk/repos/labmcp/pulls/22

Co-authored-by: renovate[bot] <renovate-bot@git.tainton.uk>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants