I think this would give us better hygiene than a global flag. It makes
it easier for users to opt-in to overlapping features, such as Python
upgrades and Python bin installations and to disable warnings for
preview mode without opting in to a bunch of other features. In general,
I want to reduce the burden for putting something under preview.
The `--preview` and `--no-preview` flags are retained as global
overrides. A new `--preview-features` option is added which accepts
comma separated features or can be passed multiple times, e.g.,
`--preview-features add-bounds,pylock`. There's a `UV_PREVIEW_FEATURES`
environment variable for that option (I'm not sure if we should overload
`UV_PREVIEW`, but could be convinced).
`Candidate` has an optional field `prioritized`, which was mostly
redundant with `CandidateDist`. Specifically, it was only `None`, if
`CandidateDist` was `Installed`. This commit removes this duplication.
## Summary
This is an alternative to #14003 that takes advantage of the fact that
we already validate that the requirements are up-to-date when validating
the lockfile, and the requirements for pinned requirements include the
index itself -- so rather than collecting all the explicit indexes
upfront, we can just add them to the available list as we iterate over
the lockfile's dependency graph.
This gets all the tests passing from that PR, but with ~no performance
impact and a much less invasive change. It also gets the "circular
dependency" test passing, which is marked with a TODO in that PR.
Closes https://github.com/astral-sh/uv/issues/11419.
It seems that non-standard entrypoints are still widely used,
downgrading the error to a tracing warning.
Fixes#14442
---------
Co-authored-by: Ed Morley <501702+edmorley@users.noreply.github.com>
## Summary
This fixes a regression from https://github.com/astral-sh/uv/pull/14447
that we seemingly didn't have test coverage for. Specifically, if you
have a version of a package in your project, and then install a
different version with `--with`, the environment should import the
`--with` version.
Closes#14860.
## Summary
The core problem here is that `allowed_indexes` only includes at most
one "default" index. This is problematic for tool upgrades, since the
index in the receipt will be marked as default, but credentials will be
omitted; if credentials are then defined in a `uv.toml`, we'll never
look at those, since that will _also_ be marked as default, and we only
look at the first default.
Instead, we should consider all defined indexes in priority order.
Closes https://github.com/astral-sh/uv/issues/14806.
## Summary
Right now, we write index URLs to the tool receipt with redacted
credentials (i.e., a username, and `****` in lieu of a password). This
is always wrong and unusable. Instead, this PR drops them entirely.
Part of https://github.com/astral-sh/uv/issues/14806.
<!--
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
We are using UV as a library and need to set `tls_built_in_root_certs`
on the reqwest client.
This PR exposes this property in the `BaseClientBuilder` and in the
`RegistryClientBuilder`. The default is set to `false`, so this does not
change any behaviour unless you explicitly opt into it.
<!-- What's the purpose of the change? What does it do, and why? -->
## Test Plan
<!-- How was it tested? -->
## Summary
A little nuanced, but... When you add multiple `--index` URLs on the CLI
(e.g., in `uv pip install`), we check the first-provided index, then the
second index, etc. However, when we _write_ those URLs to the
`pyproject.toml` in `uv add`, we were adding them in reverse-order. We
now add them in a way that preserves the priority order.
Closes https://github.com/astral-sh/uv/issues/14817.
## Summary
This PR adds derivation chain for another class of resolver failures.
For example, if we encounter a transitive URL dependency, we now tell
the user which package included it, and the full derivation chain:
```
× Failed to resolve dependencies for `foo` (v0.1.0)
╰─▶ Package `flask` was included as a URL dependency. URL dependencies must be
expressed as direct requirements or constraints. Consider adding `flask @
9d4508e893/flask-3.1.1-py3-none-any.whl`
to your dependencies or constraints file.
help: `foo` (v0.1.0) was included because `baz` (v0.1.0) depends on `foo`
```
Closes#14795.
When users run `uv version` in a directory without a `pyproject.toml`
file, they often intend to check uv's own version rather than a
project's version. This change adds a helpful hint to guide users to the
correct command.
**Before:**
```
❯ uv version
error: No `pyproject.toml` found in current directory or any parent directory
```
**After:**
```
❯ uv version
error: No `pyproject.toml` found in current directory or any parent directory
hint: If you meant to view uv's version, use `uv self version` instead
```
## Changes
- Modified `find_target()` function in
`crates/uv/src/commands/project/version.rs` to catch
`WorkspaceError::MissingPyprojectToml` specifically and enhance the
error message with a helpful hint
- Added import for `WorkspaceError` to access the specific error type
- Updated existing tests to expect the new hint message in error output
- Added new test case `version_get_missing_with_hint()` to verify
behavior
The hint appears consistently across all scenarios where `uv version`
fails to find a project:
- `uv version` (normal mode)
- `uv version --project .` (explicit project mode)
- `uv version --preview` (preview mode)
The change maintains all existing functionality - when a
`pyproject.toml` is found, `uv version` continues to work normally
without showing the hint.
Fixes#14730.
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: zanieb <2586601+zanieb@users.noreply.github.com>
## Summary
Closes#12163.
## Test Plan
Created an offending source distribution with this script:
```python
import io
import tarfile
import textwrap
import time
PKG_NAME = "badpkg"
VERSION = "0.1"
DIST_NAME = f"{PKG_NAME}-{VERSION}"
ARCHIVE = f"{DIST_NAME}.tar.gz"
def _bytes(data: str) -> io.BytesIO:
"""Helper: wrap a text blob as a BytesIO for tarfile.addfile()."""
return io.BytesIO(data.encode())
def main(out_path: str = ARCHIVE) -> None:
now = int(time.time())
with tarfile.open(out_path, mode="w:gz") as tar:
def add_file(path: str, data: str, mode: int = 0o644) -> None:
"""Add a regular file whose *content* is supplied as a string."""
buf = _bytes(data)
info = tarfile.TarInfo(path)
info.size = len(buf.getbuffer())
info.mtime = now
info.mode = mode
tar.addfile(info, buf)
# ── top‑level setup.py ───────────────────────────────────────────────
setup_py = textwrap.dedent(f"""\
from setuptools import setup, find_packages
setup(
name="{PKG_NAME}",
version="{VERSION}",
packages=find_packages(),
)
""")
add_file(f"{DIST_NAME}/setup.py", setup_py)
# ── minimal package code ─────────────────────────────────────────────
add_file(f"{DIST_NAME}/{PKG_NAME}/__init__.py", "# placeholder\\n")
# ── the malicious symlink ────────────────────────────────────────────
link = tarfile.TarInfo(f"{DIST_NAME}/{PKG_NAME}/evil_link")
link.type = tarfile.SYMTYPE
link.mtime = now
link.mode = 0o777
link.linkname = "../../../outside.txt"
tar.addfile(link)
print(f"Created {out_path}")
if __name__ == "__main__":
main()
```
Verified that both `pip install` and `uv pip install` rejected it.
I also changed `link.linkname = "../../../outside.txt"` to
`link.linkname = "/etc/outside"`, and verified that the absolute path
was rejected too.
This is an alternative to https://github.com/astral-sh/uv/pull/14788
which has the benefit that it addresses
https://github.com/astral-sh/uv/issues/13327 which would be an issue
even if we reverted #14447.
There are two changes here
1. We copy entry points into the ephemeral environment, and rewrite
their shebangs (or trampoline target) to ensure the ephemeral
environment is not bypassed.
2. We link `etc/jupyter` and `share/jupyter` data directories into the
ephemeral environment, this is in order to ensure the above doesn't
break Jupyter which unfortunately cannot find the `share` directory
otherwise. I'd love not to do this, as it seems brittle and we don't
have a motivating use-case beyond Jupyter. I've opened
https://github.com/jupyterlab/jupyterlab/issues/17716 upstream for
discussion, as there is a viable patch that could be made upstream to
resolve the problem. I've limited the fix to Jupyter directories so we
can remove it without breakage.
Closes https://github.com/astral-sh/uv/issues/14729
Closes https://github.com/astral-sh/uv/issues/13327
Closes https://github.com/astral-sh/uv/issues/14749
---------
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.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
fix some minor issues in comments
<!-- What's the purpose of the change? What does it do, and why? -->
## Test Plan
<!-- How was it tested? -->
Signed-off-by: pingshuijie <pingshuijie@outlook.com>
## Summary
If `HF_TOKEN` is set, we'll automatically wire it up to authenticate
requests when hitting private `huggingface.co` URLs in `uv run`.
## Test Plan
An unauthenticated request:
```
> cargo run -- run https://huggingface.co/datasets/cmarsh/test/resolve/main/main.py
File "/var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/mainYadr5M.py", line 1
Invalid username or password.
^^^^^^^^
SyntaxError: invalid syntax
```
An authenticated request:
```
> HF_TOKEN=hf_... cargo run run https://huggingface.co/datasets/cmarsh/test/resolve/main/main.py
Hello from main.py!
```
We currently have two marker keys that a list, `extras` and
`dependency_groups`, both from PEP 751. With the variants PEP, we will
add three more. This change is broken out of the wheel variants PR to
introduce generic marker list support, plus a change to use
`ContainerOperator` in more places.
## Summary
I found it confusing that the `else` case for `== "graalpy"` is still
necessary for the `== "pypy"` branch (i.e., that `pythonw.exe` is copied
for PyPy despite not being in the `== "pypy"` branch).
Instead, we now use a match for PyP, GraalPy, and then everything else.
The `version_get_fallback_unmanaged_json` test was failing when running
tests outside of a git checkout (e.g., from a release tarball) due to
inconsistent behavior based on git availability.
The test had conditional logic that expected different outcomes
depending on whether `git_version_info_expected()` returned true or
false:
- In git checkouts: Expected failure with "The project is marked as
unmanaged" error
- Outside git checkouts: Expected success with fallback behavior showing
version info
However, the fallback behavior was removed in version 0.8.0, making this
test obsolete. All other similar tests
(`version_get_fallback_unmanaged`,
`version_get_fallback_unmanaged_short`,
`version_get_fallback_unmanaged_strict`) consistently expect failure
when a project is marked as unmanaged, regardless of git availability.
This change removes the problematic test entirely, as suggested by
@zanieb. All remaining version tests (51 total) continue to pass.
Fixes#14785.
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: zanieb <2586601+zanieb@users.noreply.github.com>
## Summary
This should give us some performance and error message improvements.
---------
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
Co-authored-by: Zanie Blue <contact@zanie.dev>
## Summary
We don't yet support writing these, but we can at least read them
(which, e.g., allows you to install PDM-exported `pylock.toml` files
with uv, since PDM _always_ writes a default group).
Closes#14740.