Commit Graph

164 Commits

Author SHA1 Message Date
John Mumm c19a294a48
Add `DisplaySafeUrl` newtype to prevent leaking of credentials by default (#13560)
Prior to this PR, there were numerous places where uv would leak
credentials in logs. We had a way to mask credentials by calling methods
or a recently-added `redact_url` function, but this was not secure by
default. There were a number of other types (like `GitUrl`) that would
leak credentials on display.

This PR adds a `DisplaySafeUrl` newtype to prevent leaking credentials
when logging by default. It takes a maximalist approach, replacing the
use of `Url` almost everywhere. This includes when first parsing config
files, when storing URLs in types like `GitUrl`, and also when storing
URLs in types that in practice will never contain credentials (like
`DirectorySourceUrl`). The idea is to make it easy for developers to do
the right thing and for the compiler to support this (and to minimize
ever having to manually convert back and forth). Displaying credentials
now requires an active step. Note that despite this maximalist approach,
the use of the newtype should be zero cost.

One conspicuous place this PR does not use `DisplaySafeUrl` is in the
`uv-auth` crate. That would require new clones since there are calls to
`request.url()` that return a `&Url`. One option would have been to make
`DisplaySafeUrl` wrap a `Cow`, but this would lead to lifetime
annotations all over the codebase. I've created a separate PR based on
this one (#13576) that updates `uv-auth` to use `DisplaySafeUrl` with
one new clone. We can discuss the tradeoffs there.

Most of this PR just replaces `Url` with `DisplaySafeUrl`. The core is
`uv_redacted/lib.rs`, where the newtype is implemented. To make it
easier to review the rest, here are some points of note:

* `DisplaySafeUrl` has a `Display` implementation that masks
credentials. Currently, it will still display the username when there is
both a username and password. If we think is the wrong choice, it can
now be changed in one place.
* `DisplaySafeUrl` has a `remove_credentials()` method and also a
`.to_string_with_credentials()` method. This allows us to use it in a
variety of scenarios.
* `IndexUrl::redacted()` was renamed to
`IndexUrl::removed_credentials()` to make it clearer that we are not
masking.
* We convert from a `DisplaySafeUrl` to a `Url` when calling `reqwest`
methods like `.get()` and `.head()`.
* We convert from a `DisplaySafeUrl` to a `Url` when creating a
`uv_auth::Index`. That is because, as mentioned above, I will be
updating the `uv_auth` crate to use this newtype in a separate PR.
* A number of tests (e.g., in `pip_install.rs`) that formerly used
filters to mask tokens in the test output no longer need those filters
since tokens in URLs are now masked automatically.
* The one place we are still knowingly writing credentials to
`pyproject.toml` is when a URL with credentials is passed to `uv add`
with `--raw`. Since displaying credentials is no longer automatic, I
have added a `to_string_with_credentials()` method to the `Pep508Url`
trait. This is used when `--raw` is passed. Adding it to that trait is a
bit weird, but it's the simplest way to achieve the goal. I'm open to
suggestions on how to improve this, but note that because of the way
we're using generic bounds, it's not as simple as just creating a
separate trait for that method.
2025-05-27 00:05:30 +02:00
Charlie Marsh c5032aee80
Bump MSRV to 1.85 and Edition 2024 (#13516)
## Summary

Builds on https://github.com/astral-sh/uv/pull/11724.

Closes https://github.com/astral-sh/uv/issues/13476.
2025-05-18 19:38:43 -04:00
konsti 5d37c7ecc5
Apply first set of Rustfmt edition 2024 changes (#13478)
Rustfmt introduces a lot of formatting changes in the 2024 edition. To
not break everything all at once, we split out the set of formatting
changes compatible with both the 2021 and 2024 edition by first
formatting with the 2024 style, and then again with the currently used
2021 style.

Notable changes are the formatting of derive macro attributes and lines
with overly long strings and adding trailing semicolons after statements
consistently.
2025-05-16 20:19:02 -04:00
John Mumm c73819371c
Revert fix handling of authentication when encountering redirects (#13215)
These changes to redirect handling appear to have caused #13208. This PR
reverts the redirect changes to give us time to investigate.
2025-04-30 10:53:10 +02:00
John Mumm 4ee4a8861e
Implement RFC 7231 compliant relative URI and fragment handling in redirects (#13050)
This PR restores #13041 and integrates two PRs from @zanieb:
* #13038
* #13040

It also adds tests for relative URI and fragment handling.

Closes #13037.

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2025-04-28 09:07:06 +02:00
Zanie Blue 534953290b
Revert "Properly handle authentication for 302 redirect URLs" (#13041)
This reverts commit 17ed789edb / #12920 

There's a regression reported in
https://github.com/astral-sh/uv/issues/13037 and it looks like we're
missing some important parts per #13040
2025-04-22 03:40:42 +00:00
John Mumm 17ed789edb
Properly handle authentication for 302 redirect URLs (#12920)
uv was failing to authenticate on 302 redirects when credentials were
available. This was because it was relying on `reqwest_middleware`'s
default redirect behavior which bypasses the middleware pipeline when
trying the redirect request (and hence bypasses our authentication
middleware). This PR updates uv to retrigger the middleware pipeline
when handling a 302 redirect, correctly using credentials from the URL,
the keyring, or `.netrc`.

Closes #5595
Closes #11097
2025-04-18 14:56:17 +02:00
Charlie Marsh d99983a630
Avoid querying GitHub on repeated install invocations (#12767)
## Summary

If you run `cargo run pip install "pip-test-package @
git+https://github.com/pypa/pip-test-package@5547fa909e83df8bd743d3978d6667497983a4b7"`
repeatedly, then every time, we'll take the "GitHub fast path" every
time, even if the package is already cached. This PR adds logic to skip
the fast path if the reference looks like a commit that we've already
checked out.

Closes https://github.com/astral-sh/uv/issues/12760.
2025-04-08 22:00:40 -04:00
justin 1ff7265e8a
respect --offline flag for git cli operations (#12619)
## Summary
closes #12234


[fetch_with_cli](e0f81f0d4a/crates/uv-git/src/git.rs (L573))
doesn't respect the registry client's [connectivity
setting](e0f81f0d4a/crates/uv-client/src/registry_client.rs (L1009))
- this pr updates `fetch_with_cli` to set `GIT_ALLOW_PROTOCOL=file` when
the client's connectivity setting is `Connectivity::Offline`

## Test Plan
E2E

```sh
cargo run add "pycurl @ git+https://github.com/pycurl/pycurl.git" --directory ~/src/offline-test/ --offline
```

```sh
   Compiling uv-cli v0.0.1 (/Users/justinchapman/src/uv/crates/uv-cli)
   Compiling uv v0.6.11 (/Users/justinchapman/src/uv/crates/uv)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 4.47s
     Running `target/debug/uv add 'pycurl @ git+https://github.com/pycurl/pycurl.git' --directory /Users/justinchapman/src/offline-test/ --offline`
   Updating https://github.com/pycurl/pycurl.git (HEAD)                                                                                                                                   × Failed to download and build `pycurl @ git+https://github.com/pycurl/pycurl.git`
  ├─▶ Git operation failed
  ├─▶ failed to fetch into: /Users/justinchapman/.cache/uv/git-v0/db/9a596e5213c3162d
  ╰─▶ process didn't exit successfully: `/usr/bin/git fetch --force --update-head-ok 'https://github.com/pycurl/pycurl.git' '+HEAD:refs/remotes/origin/HEAD'` (exit status: 128)
      --- stderr
      fatal: transport 'https' not allowed

  help: If you want to add the package regardless of the failed resolution, provide the `--frozen` flag to skip locking and syncing.
```

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2025-04-04 11:02:54 -05:00
Charlie Marsh 42dcea0ee2
Bump MSRV to 1.84 (#12670)
## Summary

Closes https://github.com/astral-sh/uv/issues/12649.
2025-04-04 11:49:26 -04:00
Aria Desires 992f54ec17
improve archive error messages (#12627) 2025-04-02 15:57:00 +00:00
Charlie Marsh e4c98e976f
Use `Box<Path>` in lieu of `PathBuf` for immutable structs (#12346)
## Summary

I don't know if I actually want to commit this, but I did it on the
plane last time and just polished it off (got it to compile) while
waiting to board.
2025-03-25 21:56:06 +00:00
Charlie Marsh 011a6de6dc
Make deserialization non-fatal when assessing source tree revisions (#12319)
## Summary

Closes https://github.com/astral-sh/uv/issues/12318.
2025-03-19 17:15:12 +00:00
Charlie Marsh 72be5ffb25
Always reinstall local source trees passed to `uv pip install` (#12176)
## Summary

This ended up being more involved than expected. The gist is that we
setup all the packages we want to reinstall upfront (they're passed in
on the command-line); but at that point, we don't have names for all the
packages that the user has specified. (Consider, e.g., `uv pip install
.` -- we don't have a name for `.`, so we can't add it to the list of
`Reinstall` packages.)

Now, `Reinstall` also accepts paths, so we can augment `Reinstall` based
on the user-provided paths.

Closes #12038.
2025-03-17 21:12:21 +00:00
konsti e843433b07
Cache workspace discovery (#12096)
Reduce the overhead of `uv run` in large workspaces. Instead of
re-discovering the entire workspace each time we resolve the metadata of
a member, we can the discovered set of workspace members. Care needs to
be taken to not cache the discovery for `uv init`, `uv add` and `uv
remove`, which change the definitions of workspace members.

Below is apache airflow e3fe06382df4b19f2c0de40ce7c0bdc726754c74 `uv run
python` with a minimal payload. With this change, we avoid a ~350ms
overhead of each `uv run` invocation.

```
$ hyperfine --warmup 2 \
    "uv run --no-dev python -c \"print('hi')\"" \
    "uv-profiling run --no-dev python -c \"print('hi')\""
Benchmark 1: uv run --no-dev python -c "print('hi')"
  Time (mean ± σ):     492.6 ms ±   7.0 ms    [User: 393.2 ms, System: 97.1 ms]
  Range (min … max):   482.3 ms … 501.5 ms    10 runs
 
Benchmark 2: uv-profiling run --no-dev python -c "print('hi')"
  Time (mean ± σ):     129.7 ms ±   2.5 ms    [User: 105.4 ms, System: 23.2 ms]
  Range (min … max):   126.0 ms … 136.1 ms    22 runs
 
Summary
  uv-profiling run --no-dev python -c "print('hi')" ran
    3.80 ± 0.09 times faster than uv run --no-dev python -c "print('hi')"
```

The profile after those change below. We still spend a large chunk in
toml parsing (both `uv.lock` and `pyproject.toml`), but it's not
excessive anymore.


![image](https://github.com/user-attachments/assets/6fe78510-7e25-48ee-8a6d-220ee98ad120)
2025-03-10 22:03:30 +01:00
Charlie Marsh 04f20169db
Avoid silently dropping errors in directory enumeration (#11890)
## Summary

Right now, _all_ errors are dropped here, which seems wrong. We should
only return an empty iterator if the directory doesn't exist.
2025-03-03 02:39:17 +00:00
Charlie Marsh 21f4b0863d
Use boxed slices for hash vector (#11714)
## Summary

We never resize these, and they're stored everywhere (on `File`, etc.).
Seems useful to use a more efficient structure for them.
2025-02-24 11:11:44 -06:00
samypr100 878497a014
Upgrade Rust toolchain to 1.85 (#11720)
## Summary

* Upgrade the rust toolchain to 1.85.0. This does not increase the MSRV.
* Update windows trampoline to 1.86 nightly beta (previously in 1.85
nightly beta).

## Test Plan

Existing tests
2025-02-23 16:52:34 +01:00
Charlie Marsh 3c541e2368
Check subdirectory existence after cache heal (#11719)
## Summary

Closes https://github.com/astral-sh/uv/issues/11703.
2025-02-23 00:13:29 +00:00
konsti 248da23f6d
Split uv-git and uv-git-types (#11448)
We want to build `uv-build` without depending on the network crates. In
preparation for that, we split uv-git into uv-git and uv-git-types,
where only uv-git depends on reqwest, so that uv-build can use
uv-git-types.
2025-02-17 10:37:55 +01:00
Zanie Blue 35564e189d Avoid reading metadata from `.egg-info` files (#11395)
We added this to help with resolving some specific packages, and for
parity with Poetry. But in some cases, this metadata is just wrong, and
at the very least it's unreliable.

Closes https://github.com/astral-sh/uv/issues/8989.

Closes #10945.
2025-02-13 16:17:49 -06:00
Charlie Marsh a4bd73f922
Omit lockfile version when additional fields are dynamic (#11468)
## Summary

Just a logic issue... If we see a dynamic field that isn't `"version"`,
we end up _not_ propagating the fact that `"version"` is also dynamic.

Closes https://github.com/astral-sh/uv/issues/11460.
2025-02-13 01:44:14 +00:00
Charlie Marsh 2aaabb544d
Allow source distributions to produce wheels with +local suffixes (#11429)
## Summary

We currently enforce that if you do `uv pip install
./dist/iniconfig-1.0.0.tar.gz`, the build _must_ produce a wheel like
`iniconfig-1.0.0-py3-none-any.whl` (i.e., the name and version must
match). It turns out some packages produce a wheel that has a local
suffix on it, like `vllm`. This PR makes the check a little more
permissive in that we now accept `1.0.0` or that version with a local
suffix (e.g., `1.0.0+cpu`). I don't love this practice, but we already
relaxed this check when _installing_ a wheel, so this seems reasonable:


5e15881dcc/crates/uv-install-wheel/src/install.rs (L50-L52)

Note that this is _still_ stricter than pip. pip seems to only require
that the package name is the same (i.e., `iniconfig` matches
`iniconfig`; but they'll happily install a wheel like
`iniconfig-2.0.0-py3-none-any.whl` given
`./dist/iniconfig-1.0.0.tar.gz`).

Closes https://github.com/astral-sh/uv/issues/11038.
2025-02-11 17:26:40 -05:00
Charlie Marsh 748582ee6f
Disable SSL in Git commands for `--allow-insecure-host` (#11210)
## Summary

Closes https://github.com/astral-sh/uv/issues/11176.

## Test Plan

- Created a self-signed certificate.
- Ran `openssl s_server -cert cert.pem -key key.pem -WWW -port 8443`.
- Verified that `cargo run pip install
git+https://localhost:8443/repo.git` failed with:

```
error: Git operation failed
  Caused by: failed to fetch into: /Users/crmarsh/.cache/uv/git-v0/db/0773914b3ec4a56e
  Caused by: process didn't exit successfully: `/usr/bin/git fetch --force --update-head-ok 'https://localhost:8443/repo.git' '+HEAD:refs/remotes/origin/HEAD'` (exit status: 128)
--- stderr
fatal: unable to access 'https://localhost:8443/repo.git/': SSL certificate problem: self signed certificate
```

- Verified that `cargo run pip install
git+https://localhost:8443/repo.git --allow-insecure-host
https://localhost:8443` continued further.
2025-02-04 10:57:57 -05:00
Zanie Blue dd7cd2e86a
Remove warnings for missing lower bounds (#11195)
These are noisy relative to the effect they have on the user. It seems
better to prioritize hints on poor resolutions. Notably, it seems hard
to make these "not noisy" ref #11091.

Does not include the "lowest" resolution mode, in which lower bounds are
critical.
2025-02-03 16:03:31 -06:00
Charlie Marsh d106ab1a9a
Make metadata deserialization failures non-fatal in the cache (#11105)
## Summary

If we fail to deserialize cached metadata in the cache, we should just
ignore it, rather than failing.

Ideally, this never happens. If it does, it means we missed a cache
version bump. But if it does happen, it should still be non-fatal.

Closes https://github.com/astral-sh/uv/issues/11043.

Closes https://github.com/astral-sh/uv/issues/11101.

## Test Plan

Prior to this PR, the following would fail:

- `uvx uv@0.5.25 venv --python 3.12 --cache-dir foo`
- `uvx uv@0.5.25 pip install ./scripts/packages/hatchling_dynamic
--no-deps --python 3.12 --cache-dir foo`
- `uvx uv@0.5.18 venv --python 3.12 --cache-dir foo`
- `uvx uv@0.5.18 pip install ./scripts/packages/hatchling_dynamic
--no-deps --python 3.12 --cache-dir foo`

We can't go back and fix 0.5.18, but this will prevent such regressions
in the future.
2025-01-30 12:48:35 -05:00
Charlie Marsh 3878c00dbd
Mark metadata as dynamic when reading from built wheel cache (#11046)
## Summary

The issue here boils down to: when we write metadata that came from
building the wheel itself, we aren't setting the `dynamic` field.

We now _always_ set the dynamic field when reading, even when we read
cached data.

Closes https://github.com/astral-sh/uv/issues/11047.
2025-01-29 01:27:09 +00:00
Charlie Marsh f1840c77b6
Guard against concurrent cache writes on Windows (#11007)
## Summary

On Windows, we have a lot of issues with atomic replacement and such.
There are a bunch of different failure modes, but they generally
involve: trying to persist a fail to a path at which the file already
exists, trying to replace or remove a file while someone else is reading
it, etc.

This PR adds locks to all of the relevant database paths. We already use
these advisory locks when building source distributions; now we use them
when unzipping wheels, storing metadata, etc.

Closes #11002.

## Test Plan

I ran the following script:

```shell
# Define the cache directory path
$cacheDir = "C:\Users\crmar\workspace\uv\cache"

# Clear the cache directory if it exists
if (Test-Path $cacheDir) {
    Remove-Item -Recurse -Force $cacheDir
}

# Create the cache directory again
New-Item -ItemType Directory -Force -Path $cacheDir

# Define the command to run with --cache-dir flag
$command = {
    param ($venvPath)

    # Create a virtual environment in the specified path with --python
    uv venv $venvPath

    # Run the pip install command with --cache-dir flag
    C:\Users\crmar\workspace\uv\target\profiling\uv.exe pip install flask==1.0.4 --no-binary flask --cache-dir C:\Users\crmar\workspace\uv\cache -v --python $venvPath
}

# Define the paths for the different virtual environments
$venv1 = "C:\Users\crmar\workspace\uv\venv1"
$venv2 = "C:\Users\crmar\workspace\uv\venv2"
$venv3 = "C:\Users\crmar\workspace\uv\venv3"
$venv4 = "C:\Users\crmar\workspace\uv\venv4"
$venv5 = "C:\Users\crmar\workspace\uv\venv5"

# Start the command in parallel five times using Start-Job, each with a different venv
$job1 = Start-Job -ScriptBlock $command -ArgumentList $venv1
$job2 = Start-Job -ScriptBlock $command -ArgumentList $venv2
$job3 = Start-Job -ScriptBlock $command -ArgumentList $venv3
$job4 = Start-Job -ScriptBlock $command -ArgumentList $venv4
$job5 = Start-Job -ScriptBlock $command -ArgumentList $venv5

# Wait for all jobs to complete
$jobs = @($job1, $job2, $job3, $job4, $job5)
$jobs | ForEach-Object { Wait-Job $_ }

# Retrieve the results (optional)
$jobs | ForEach-Object { Receive-Job -Job $_ }

# Clean up the jobs
$jobs | ForEach-Object { Remove-Job -Job $_ }
```

And ensured it succeeded in five straight invocations (whereas on
`main`, it consistently fails with a variety of different traces).
2025-01-28 15:33:49 -05:00
Charlie Marsh d454f9c34b
Make GitHub fast path errors non-fatal (#10859)
## Summary

For example: in the linked issue, the user has a symlink at
`pyproject.toml`. The GitHub CDN doesn't give us any way to determine
whether a file is a symlink, so we should just log the error and move on
to the slow path.

Closes https://github.com/astral-sh/uv/issues/10857
2025-01-22 11:54:02 -05:00
Charlie Marsh 47a31fc61c
Treat version mismatch errors as non-fatal in fast paths (#10860)
## Summary

I noticed that we're only handling `Error::WheelMetadataNameMismatch`
here; but `Error::WheelMetadataVersionMismatch` should also be treated
as non-fatal.
2025-01-22 10:13:24 -05:00
Charlie Marsh 5c7fba86e1
Deduplicate `GitSha` and `GitOid` types (#10802)
## Summary

I think this split is leftover from using `libgit2`. I kept `Oid` since
that seems to be the official terminology.
2025-01-21 09:15:11 -05:00
Charlie Marsh 44d2bfeb65
Remove allocation in Git SHA truncation (#10801) 2025-01-21 01:53:12 +00:00
Charlie Marsh 8e13eb5bb6
Validate metadata under GitHub fast path (#10796)
## Summary

This is leading to a failing test (when not rate-limited).
2025-01-20 18:30:23 -05:00
Charlie Marsh 5ee4cf6ff5
Fetch `pyproject.toml` from GitHub API (#10765)
## Summary

When resolving Git metadata, we may be able to fetch the metadata from
GitHub directly in some cases. This is _way_ faster, since we don't need
to perform many Git operations and, in particular, don't need to clone
the repo.

This only works in the following cases:

- The Git repository is public. Otherwise, I believe you need an access
token, which we don't have.
- The `pyproject.toml` has static metadata.
- The `pyproject.toml` has no `tool.uv.sources`. Otherwise, we need to
lower them... And, if there are any paths or workspace sources, that
requires an install path (i.e., we need the content on-disk).
- The project is in the repo root. If it's in a subdirectory, it could
be a workspace member. And if it's a workspace member, there could be
sources defined in the workspace root. But we can't know without
fetching the workspace root -- and we need the workspace in order to
find the root...

Closes #10568.
2025-01-20 17:50:39 +00:00
Charlie Marsh 80bdb3a997
Avoid building dynamic versions when validating lockfile (#10703)
## Summary

Closes #10689.
2025-01-17 04:27:46 +00:00
Charlie Marsh 0617fd5da6
Omit dynamic versions from the lockfile (#10622)
## Summary

This PR modifies the lockfile to omit versions for source trees that use
`dynamic` versioning, thereby enabling projects to use dynamic
versioning with `uv.lock`.

Prior to this change, dynamic versioning was largely incompatible with
locking, especially for popular tools like `setuptools_scm` -- in that
case, every commit bumps the version, so every commit invalidates the
committed lockfile.

Closes https://github.com/astral-sh/uv/issues/7533.
2025-01-15 11:54:32 -05:00
Charlie Marsh 66a603b6c4
Use dynamic dispatch to simplify reporters (#10086)
## Summary

Sort of undecided on this. These are already stored as `dyn Reporter` in
each struct, so we're already using dynamic dispatch in that sense. But
all the methods take `impl Reporter`. This is sometimes nice (the
callsites are simpler?), but it also means that in practice, you often
_can't_ pass `None` to these methods that accept `Option<impl
Reporter>`, because Rust can't infer the generic type.

Anyway, this adds more consistency and simplifies the setup by using
`Arc<dyn Reporter>` everywhere.
2025-01-06 12:04:00 -05:00
Charlie Marsh 7bbec6b2e4
Parse URLs lazily in resolver (#10259)
## Summary

The idea here is to avoid parsing all registry URLs upfront, and instead
parse them when we need them.

Closes #6133.
2025-01-01 12:35:30 -05:00
Charlie Marsh 9e0b35ad82
Detect cyclic dependencies during builds (#10258)
## Summary

Closes
https://github.com/astral-sh/uv/issues/10255#issuecomment-2566782671.
2024-12-31 22:22:42 -05:00
Charlie Marsh 33cb3497aa
Strip fragment when storing direct URL (#10093)
## Summary

Closes
https://github.com/astral-sh/uv/issues/10088#issuecomment-2558280467.
2024-12-22 09:07:04 -05:00
konsti ebc6d20d9d
Better build error messages (#9660)
Build failures are one of the most common user facing failures that
aren't "obivous" errors (such as typos) or resolver errors. Currently,
they show more technical details than being focussed on this being an
error in a subprocess that is either on the side of the package or -
more likely - in the build environment, e.g. the user needs to install a
dev package or their python version is incompatible.

The new error message clearly delineates the part that's important (this
is a build backend problem) from the internals (we called this hook) and
is consistent about which part of the dist building stage failed. We
have to calibrate the exact wording of the error message some more. Most
of the implementation is working around the orphan rule, (this)error
rules and trait rules, so it came out more of a refactoring than
intended.

Example:


![image](https://github.com/user-attachments/assets/2bc12992-db79-4362-a444-fd0d94594b77)
2024-12-17 09:44:32 -06:00
Zanie Blue ae25c2f4db
Upgrade minimum Rust version to 1.83 (#9815)
This reverts commit 6cc7a560f7 to reapply
#9511 since we've disabled ppc64le-musl per #9793
2024-12-11 10:06:19 -06:00
Charlie Marsh 341126cf72
Show a dedicated error for missing subdirectories (#9761)
## Summary

On `main`, if you ask for a source but name a missing subdirectory, you
just get:

```
{source} does not appear to be a Python project, as neither `pyproject.toml` nor `setup.py` are present in the directory
```

But, in reality, the directory doesn't exist at all.
2024-12-10 02:48:50 +00:00
Charlie Marsh 8a2e3a8339
Don't read metadata from stale `.egg-info` files (#9760)
## Summary

We were reading an `.egg-info` file from the root directory that didn't
apply to the root member -- it was for another workspace member. I think
this is driven from some idiosyncracies in the `setuptools` setup for
that workspace member, but it's still wrong to fail.

This PR adds a few measures to fix this:

1. We validate the `egg-info` filename against the package metadata.
2. We skip, rather than fail, if we see incorrect metadata in an
`egg-info` file or similar. This is an optimization anyway; worst case,
we try to build the package, then fail there.

Closes https://github.com/astral-sh/uv/issues/9743.
2024-12-10 02:24:43 +00:00
Charlie Marsh da4b885d92
Eagerly error when parsing `pyproject.toml` requirements (#9704)
## Summary

Small thing I noticed while working on another change: if we error when
extracting `requires-dist`, we go through the full metadata build. We
need to distinguish between fatal errors and "the data isn't static".
2024-12-07 14:14:26 +00:00
konsti 6ed6fc108e
Build backend: Add direct builds to the resolver and installer (#9621)
This is like #9556, but at the level of all other builds, including the
resolver and installer. Going through PEP 517 to build a package is
slow, so when building a package with the uv build backend, we can call
into the uv build backend directly instead: No temporary virtual env, no
temp venv sync, no python subprocess calls, no uv subprocess calls.

This fast path is gated through preview. Since the uv wheel is not
available at test time, I've manually confirmed the feature by comparing
`uv venv && cargo run pip install . -v --preview --reinstall .` and `uv
venv && cargo run pip install . -v --reinstall .`. When hacking the
preview so that the python uv build backend works without the setting
the direct build also (wheel built with `maturin build --profile
profiling`), we can see the perfomance difference:

```
$ hyperfine --prepare "uv venv" --warmup 3 \
    "UV_PREVIEW=1 target/profiling/uv pip install --no-deps --reinstall scripts/packages/built-by-uv --preview" \
    "target/profiling/uv pip install --no-deps --reinstall scripts/packages/built-by-uv --find-links target/wheels/"
Benchmark 1: UV_PREVIEW=1 target/profiling/uv pip install --no-deps --reinstall scripts/packages/built-by-uv --preview
  Time (mean ± σ):      33.1 ms ±   2.5 ms    [User: 25.7 ms, System: 13.0 ms]
  Range (min … max):    29.8 ms …  47.3 ms    73 runs
 
Benchmark 2: target/profiling/uv pip install --no-deps --reinstall scripts/packages/built-by-uv --find-links target/wheels/
  Time (mean ± σ):     115.1 ms ±   4.3 ms    [User: 54.0 ms, System: 27.0 ms]
  Range (min … max):   109.2 ms … 123.8 ms    25 runs
 
Summary
  UV_PREVIEW=1 target/profiling/uv pip install --no-deps --reinstall scripts/packages/built-by-uv --preview ran
    3.48 ± 0.29 times faster than target/profiling/uv pip install --no-deps --reinstall scripts/packages/built-by-uv --find-links target/wheels/
```

Do we need a global option to disable the fast path? There is one for
`uv build` because `--force-pep517` moves `uv build` much closer to a
`pip install` from source that a user of a library would experience (See
discussion at #9610), but uv overall doesn't really make guarantees
around the build env of dependencies, so I consider the direct build a
valid option.

Best reviewed commit-by-commit, only the last commit is the actual
implementation, while the preview mode introduction is just a
refactoring touching too many files.
2024-12-04 15:57:18 +00:00
konsti c314c68bff
Ignore dynamic version in source dist (#9549)
When encountering `dynamic = ["version"]` in the pyproject.toml of a
source dist, we can ignore that and treat it as a statically known
metadata distribution, since the filename tells us the version and that
version must not change on build.

This fixed locking PyGObject 3.50.0 from `pygobject-3.50.0.tar.gz`
(minimized):

```toml
[project]
name = "PyGObject"
description = "Python bindings for GObject Introspection"
requires-python = ">=3.9, <4.0"
dependencies = [
    "pycairo>=1.16"
]
dynamic = ["version"]
```

Afterwards, `uv add --no-sync toga` passes on Ubuntu 24.04 without the
pygobject build deps, when previously it needed `{ name = "pygobject",
version = "3.50.0", requires-dist = [], requires-python = ">=3.9" }`.

I've added a check that source distribution versions are respected after
build.

Fixes #9548
2024-12-04 11:40:31 +00:00
Zanie Blue 6cc7a560f7
Revert "Upgrade to Rust 1.83 (#9511)" (#9617)
This reverts commit cf20673197 (#9511) due
to failure on powerpc64le in https://github.com/astral-sh/uv/pull/9612
2024-12-03 19:21:05 +00:00
Eric Mark Martin 16ca0c34a1
Include Git member information when getting metadata from cache (#9388)
## Summary

Include the `git_member` when fetching metadata from cache.

h/t to @PhilipVinc for the suggested fix

Resolves #8887 

## Test Plan

Pending

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-12-03 05:07:21 +00:00
Charlie Marsh cf20673197
Upgrade to Rust 1.83 (#9511)
## Summary

A lot of good new lints, and most importantly, error stabilizations. I
tried to find a few usages of the new stabilizations, but I'm sure there
are more.

IIUC, this _does_ require bumping our MSRV.
2024-11-29 12:04:22 -05:00