Commit Graph

1446 Commits

Author SHA1 Message Date
Charlie Marsh e31851fb52
Avoid erroneous version warning for .dist-info (#7444)
## Summary

Since https://github.com/astral-sh/uv/pull/7208, this is now _always_
firing, for every directory, because the version gets normalized (e.g.,
`1.2.3` gets normalized to `1-2-3`, which never matches the parsed
version). pip doesn't warn here, I guess we won't either, because I
can't figure out a robust way to do this... We need to get the
non-normalized remainder after stripping the normalized package name,
but we strip the normalized package name from the normalized string, so
we only have a normalized remainder.
2024-09-16 22:32:56 +00:00
Charlie Marsh 7ab1ea22f6
Run `cargo update` (#7413) 2024-09-15 14:46:29 -04:00
konsti 4aad89cf06
Hint at missing `project.name` (#6803)
We got user reports where users were confused about why they can't use
`[project.urls]` in `pyproject.toml` (i think that's from poetry?). This
PR adds a hint that (according to PEP 621), you need to set
`project.name` when using any `project` fields. (PEP 621 also requires
`project.version` xor `dynamic = ["version"]`, but we check that later.)

The intermediate parsing layer to tell apart syntax errors from schema
errors doesn't incur a performance penalty according to epage
(https://github.com/toml-rs/toml/issues/778#issuecomment-2310369253).

Closes #6419
Closes #6760
2024-09-14 20:03:47 +00:00
Charlie Marsh 6907164841
Bump version to v0.4.10 (#7368) 2024-09-13 13:46:56 -04:00
Frost Ming e1e85ab4c8
feat(cli): add `--token` option to `self update` command (#7279)
<!--
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

It often reaches the GitHub API rate limit and shows error like `error:
HTTP status client error (403 Forbidden) for url
(https://api.github.com/repos/astral-sh/uv/releases)` when running `uv
self update`.

To bypass this rate limit issue, allow user to pass a GitHub token via
`--token` or `UV_GITHUB_TOKEN` env.

## Test Plan

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

---------

Signed-off-by: Frost Ming <me@frostming.com>
2024-09-12 14:27:54 -05:00
Charlie Marsh 65d53a7474
Use `globwalk` for `cache-keys` matching (#7337)
## Summary

This should be more efficient as we can do a single traversal.

Closes https://github.com/astral-sh/uv/issues/7321.
2024-09-12 15:06:05 -04:00
Charlie Marsh 58a157a0ad
Support globs as cache keys in `tool.uv.cache-keys` (#7268)
## Summary

This has been asked for a few times. There are risks that these checks
could be slow, but they're buyer-beware.

Closes https://github.com/astral-sh/uv/issues/7246.
2024-09-11 15:30:59 -04:00
Charlie Marsh 15792a3775
Apply `--no-install` options when constructing resolution (#7277)
## Summary

We need to apply the `--no-install` filters earlier, such that we don't
error if we only have a source distribution for a given package when
`--no-build` is provided but that package is _omitted_.

Closes #7247.
2024-09-11 14:31:24 -04:00
Zanie Blue f5891e3296
Bump version to 0.4.9 (#7274) 2024-09-10 16:44:39 -05:00
Michał Górny 4b7fed84eb
Replace `tokio-tar` with `krata-tokio-tar` fork (#7271)
## Summary

Replace the unmaintained `tokio-tar` crate with the `krata-tokio-tar`
fork. The latter just merged a fix necessary for the crate to work on
PowerPC, and has better chances of future maintenance.

Fixes #3423

## Test Plan

`cargo test`
2024-09-10 17:28:53 -04:00
Ibraheem Ahmed cc3259be5f
Revert `Cargo.lock` changes (#7276)
## Summary

Reverts accidental changes in https://github.com/astral-sh/uv/pull/5927.
2024-09-10 21:20:50 +00:00
Ibraheem Ahmed 4f03d204df
Run benchmarks with `--profile profiling` (#5927)
## Summary

The CodSpeed flamegraphs are currently useless after
https://github.com/astral-sh/uv/pull/5745.
2024-09-10 14:25:53 -04:00
konsti 2b3890f2b4
Extract METADATA reading into a crate (#7231)
This is preparatory work for the upload functionality, which needs to
read the METADATA file and attach its parsed contents to the POST
request: We move finding the `.dist-info` from `install-wheel-rs` and
`uv-client` to a new `uv-metadata` crate, so it can be shared with the
publish crate.

I don't properly know if its the right place since the upload code isn't
ready, but i'm PR-ing it now because it already had merge conflicts.
2024-09-10 13:31:01 +00:00
Charlie Marsh a8bd0211e0
Invalidate cache when `--config-settings` change (#7139)
## Summary

If `--config-settings` are provided, we cache the built wheels under one
more subdirectory.

We _don't_ invalidate the actual source (i.e., trigger a re-download) or
metadata, though -- those can be reused even when `--config-settings`
change.

Closes https://github.com/astral-sh/uv/issues/7028.
2024-09-10 01:49:16 +00:00
Charlie Marsh 956cadd1a6
Bump version to v0.4.8 (#7233) 2024-09-09 17:19:40 -04:00
Charlie Marsh 4f2349119c
Add support for dynamic cache keys (#7136)
## Summary

This PR adds a more flexible cache invalidation abstraction for uv, and
uses that new abstraction to improve support for dynamic metadata.

Specifically, instead of relying solely on a timestamp, we now pass
around a `CacheInfo` struct which (as of now) contains
`Option<Timestamp>` and `Option<Commit>`. The `CacheInfo` is saved in
`dist-info` as `uv_cache.json`, so we can test already-installed
distributions for cache validity (along with testing _cached_
distributions for cache validity).

Beyond the defaults (`pyproject.toml`, `setup.py`, and `setup.cfg`
changes), users can also specify additional cache keys, and it's easy
for us to extend support in the future. Right now, cache keys can either
be instructions to include the current commit (for `setuptools_scm` and
similar) or file paths (for `hatch-requirements-txt` and similar):

```toml
[tool.uv]
cache-keys = [{ file = "requirements.txt" }, { git = true }]
```

This change should be fully backwards compatible.

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

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

Closes https://github.com/astral-sh/uv/issues/6860.
2024-09-09 20:19:15 +00:00
Charlie Marsh 9a7262c360
Avoid batch prefetching for un-optimized registries (#7226)
## Summary

We now track the discovered `IndexCapabilities` for each `IndexUrl`. If
we learn that an index doesn't support range requests, we avoid doing
any batch prefetching.

Closes https://github.com/astral-sh/uv/issues/7221.
2024-09-09 15:46:19 -04:00
Charlie Marsh 970bd1aa0c
Respect exclusion when collecting workspace members (#7175)
## Summary

We were only applying exclusions when discovering the root, apparently.

Our logic now matches the original intent, which is...

- `exclude` always post-filters `members`.
- We don't treat globs any differently than non-globs.

The one confusing setup that falls out of this is that given:

```toml
members = ["foo/bar/baz"]
exclude = ["foo/bar"]
```

`foo/bar/baz` **would** be included. To exclude it, you would need:

```toml
members = ["foo/bar/baz"]
exclude = ["foo/bar/*"]
```

Closes https://github.com/astral-sh/uv/issues/7071.
2024-09-09 12:08:06 -04:00
kranurag7 5e4bd311c2
bump quinn-proto crate to 0.11.7 (#7191) 2024-09-08 12:11:02 -04:00
Charlie Marsh a178051e81
Bump version to v0.4.7 (#7150) 2024-09-07 02:18:15 +00:00
Amos Wenger 5e1b9b1964
chore: Remove dep on derivative (#7133)
(This is part of #5711)

## Summary

@BurntSushi and I spotted that the `derivative` crate is only used for
one enum in the entire codebase — however, it's a proc macro, and we pay
for the cost of (re)compiling it in many different contexts.

This replaces it with a private `Inner` core which uses the regular std
derive macros — inlining and optimizations should make this equivalent
to the other implementation, and not too hard to maintain hopefully
(versus a manual impl of `PartialEq` and `Hash` which have to be kept in
sync.)

## Test Plan

Trust CI?
2024-09-06 17:46:56 -04:00
Charlie Marsh 93fe3e83be
Prune unused source distributions from the cache (#7112)
## Summary

This has bothered me for a while and should be fairly impactful for
users. It requires a weird implementation, since the
distribution-building crate depends on the cache, and so the prune
operation can't live in the cache, since it needs to access internals of
the distribution-building crate.

Closes https://github.com/astral-sh/uv/issues/7096.
2024-09-05 21:40:51 -04:00
Zanie Blue 84f25e8cf8
Bump version to 0.4.6 (#7103) 2024-09-05 17:39:53 -05:00
Zanie Blue 42b6bfbad7
Bump version to 0.4.5 (#7044) 2024-09-04 16:56:10 -04:00
Charlie Marsh 05ed4bc11d
Show build output by default in `uv build` (#6912)
## Summary

This is a big improvement IMO:

![Screenshot 2024-09-01 at 12 52
28 PM](https://github.com/user-attachments/assets/2d8b1370-3385-429a-9a1d-e1d44611a2b4)
2024-09-04 15:39:21 +00:00
Charlie Marsh df84d25a7e
Implement `uv build` (#6895)
## Summary

This PR exposes uv's PEP 517 implementation via a `uv build` frontend,
such that you can use `uv build` to build source and binary
distributions (i.e., wheels and sdists) from a given directory.

There are some TODOs that I'll tackle in separate PRs:

- [x] Support building a wheel from a source distribution (rather than
from source) (#6898)
- [x] Stream the build output (#6912)

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

Closes https://github.com/astral-sh/uv/issues/1663.
2024-09-04 11:23:46 -04:00
Charlie Marsh ae144e05ac
Revert `pyproject.toml` modifications on Ctrl-C (#7024)
## Summary

Not perfect, but an improvement at least for an interactive experience.

Closes #6818.
2024-09-04 11:04:00 -04:00
Charlie Marsh 3d75df6ab2
Bump version to v0.4.4 (#6988) 2024-09-04 00:30:38 +00:00
Zanie Blue 2a425152b9
Add warning when `VIRTUAL_ENV` is set but will not be respected in project commands (#6864)
Following https://github.com/astral-sh/uv/pull/6834
2024-09-03 19:51:43 -04:00
Charlie Marsh 47f4ca24b3
Bump version to v0.4.3 (#6947) 2024-09-02 17:18:57 -04:00
Charlie Marsh 736ccb950a
Bump version to v0.4.2 (#6916) 2024-09-01 13:37:27 -04:00
Charlie Marsh 2ce8b916cc
Run `cargo update` (#6888) 2024-08-30 16:42:04 -04:00
Charlie Marsh 823f23e225
Bump version to v0.4.1 (#6870) 2024-08-30 10:07:06 -04:00
konsti a39eb61ade
Use windows registry to discover python (#6761)
Our current strategy of parsing the output of `py --list-paths` to get
the installed python versions on windows is brittle (#6524, missing
`py`, etc.) and it's slow (10ms last time i measured).

Instead, we should behave spec-compliant and read the python versions
from the registry following PEP 514.

It's not fully clear which errors we should ignore and which ones we
need to raise.

We're using the official rust-for-windows crates for accessing the
registry.

Fixes #1521
Fixes #6524
2024-08-29 22:48:22 +02:00
Zanie Blue e3d5d3d26d
Avoid deadlocks when multiple uv processes lock resources (#6790)
This is achieved by updating the `LockedFile::acquire` API to be async —
as in some cases we were attempting to acquire the lock synchronously,
i.e., without yielding, which blocked the runtime.

Closes https://github.com/astral-sh/uv/issues/6691 — I tested with the
reproduction there and a local release build and no longer reproduce the
deadlock with these changes.

Some additional context in the [internal Discord
thread](https://discord.com/channels/1039017663004942429/1278430431204741270/1278478941262188595)
2024-08-29 11:16:14 -05:00
Chan Kang 4f5356ed55
sort dependencies in `pyproject.toml` (#6388)
## Summary
resolves https://github.com/astral-sh/uv/issues/6203

## Test Plan
added a test fixing the bug described in the issue.

---------

Co-authored-by: konstin <konstin@mailbox.org>
2024-08-29 16:55:03 +02:00
Charlie Marsh d9bd3bc7a5
Bump to v0.4.0 (#6764) 2024-08-28 17:29:16 +00:00
renovate[bot] 1309f24c43
Update Rust crate windows-sys to 0.59.0 (#5785)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [windows-sys](https://togithub.com/microsoft/windows-rs) |
workspace.dependencies | minor | `0.52.0` -> `0.59.0` |

---

### Release Notes

<details>
<summary>microsoft/windows-rs (windows-sys)</summary>

###
[`v0.59.0`](https://togithub.com/microsoft/windows-rs/releases/tag/0.59.0)

[Compare
Source](https://togithub.com/microsoft/windows-rs/compare/0.52.0...0.59.0)

This release includes an update to the
[windows-sys](https://crates.io/crates/windows-sys) crate only. The
`windows-sys` crate is updated very infrequently and only when there is
an explicit need to do so. The 0.59.0 release includes a rollup of API
fixes, updates, and additions since the
[0.52.0](https://togithub.com/microsoft/windows-rs/releases/tag/0.52.0)
release nine months ago. Notably:

- This update introduces support for Arm64EC
([#&#8203;2957](https://togithub.com/microsoft/windows-rs/issues/2957))
- Updated bindings for the latest APIs
https://github.com/microsoft/windows-rs/tree/0.59.0/crates/libs/bindgen/default
- Derive standard traits
([#&#8203;3041](https://togithub.com/microsoft/windows-rs/issues/3041))
-   Updates to code generation to handle newer Rust warnings and lints
- Overall smaller crate and more efficient code gen to reduce build time
- Support for feature search
https://microsoft.github.io/windows-rs/features/#/0.59.0
-   MSRV is updated to 1.60

**Full Changelog**:
https://github.com/microsoft/windows-rs/compare/0.52.0...0.59.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, 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 was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/astral-sh/uv).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40NDAuNyIsInVwZGF0ZWRJblZlciI6IjM4LjU2LjAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbImludGVybmFsIl19-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-28 08:43:59 -05:00
Charlie Marsh 53ef633c6d
Do not require workspace members to sync with `--frozen` (#6737)
## Summary

Closes https://github.com/astral-sh/uv/issues/6685.
2024-08-28 07:58:50 -04:00
Amos Wenger 2c5cc62106
ci: Make Windows tests ~27% faster by putting temp folder in dev drive (#6680)
## Summary

This PR makes `cargo test | windows` faster in CI.

### Before

![Windows tests take
5m44s](https://github.com/user-attachments/assets/8dd9c619-9b7b-4ebd-a027-56e7967b6d34)

### After

![Windows tests take
5m12s](https://github.com/user-attachments/assets/7702fdba-3034-4db8-b211-85207a1feffa)

## Also

This PR disables the `brotli` feature of `async-compression` since it's
not strictly needed, but this has little to do with the improvements
(it's still less code to build).

This PR introduces additional code in uv tool uninstall to ignore errors
(that only seem to happen on ReFS, ie. on Dev Drives) akin to "the thing
we're trying to delete cannot be deleted because it's already being
deleted".

If `raw_os_error` was stable we could do u32 matching instead of that
`.to_string().contains()` abomination.
2024-08-27 15:25:05 -05:00
Charlie Marsh 6c62d9fbf1
Bump version to v0.3.5 (#6696) 2024-08-27 16:30:12 +00:00
Charlie Marsh d86075fc1e
Add support for `--trusted-host` (#6591)
## Summary

This PR revives https://github.com/astral-sh/uv/pull/4944, which I think
was a good start towards adding `--trusted-host`. Last night, I tried to
add `--trusted-host` with a custom verifier, but we had to vendor a lot
of `reqwest` code and I eventually hit some private APIs. I'm not
confident that I can implement it correctly with that mechanism, and
since this is security, correctness is the priority.

So, instead, we now use two clients and multiplex between them.

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

## Test Plan

Created self-signed certificate, and ran `python3 -m http.server --bind
127.0.0.1 4443 --directory . --certfile cert.pem --keyfile key.pem` from
the packse index directory.

Verified that `cargo run pip install
transitive-yanked-and-unyanked-dependency-a-0abad3b6 --index-url
https://127.0.0.1:8443/simple-html` failed with:

```
error: Request failed after 3 retries
  Caused by: error sending request for url (https://127.0.0.1:8443/simple-html/transitive-yanked-and-unyanked-dependency-a-0abad3b6/)
  Caused by: client error (Connect)
  Caused by: invalid peer certificate: Other(OtherError(CaUsedAsEndEntity))
```

Verified that `cargo run pip install
transitive-yanked-and-unyanked-dependency-a-0abad3b6 --index-url
'https://127.0.0.1:8443/simple-html' --trusted-host '127.0.0.1:8443'`
failed with the expected error (invalid resolution) and made valid
requests.

Verified that `cargo run pip install
transitive-yanked-and-unyanked-dependency-a-0abad3b6 --index-url
'https://127.0.0.1:8443/simple-html' --trusted-host '127.0.0.2' -n` also
failed.
2024-08-27 09:36:50 -04:00
Mathieu Kniewallner 6a988aca55
refactor: use a struct for install options (#6561)
## Summary

Closes #6545.

## Test Plan

Relying on existing tests.
2024-08-27 05:38:16 -05:00
konsti ae57d85dfb
Detect musl and error for musl pbs builds (#6643)
As described in #4242, we're currently incorrectly downloading glibc
python-build-standalone on musl target, but we also can't fix this by
using musl python-build-standalone on musl targets since the musl builds
are effectively broken.

We reintroduce the libc detection previously removed in #2381, using it
to detect which libc is the current one before we have a python
interpreter. I changed the strategy a big to support an empty `PATH`
which we use in the tests.

For simplicity, i've decided to just filter out the musl
python-build-standalone archives from the list of available archive,
given this is temporary. This means we show the same error message as if
we don't have a build for the platform. We could also add a dedicated
error message for musl.

Fixes #4242

## Test Plan

Tested manually.

On my ubuntu host, python downloads continue to pass:
```
target/x86_64-unknown-linux-musl/debug/uv python install
```

On alpine, we fail:
```
$ docker run -it --rm -v .:/io alpine /io/target/x86_64-unknown-linux-musl/debug/uv python install
  Searching for Python installations
  error: No download found for request: cpython-any-linux-x86_64-musl
```
2024-08-27 00:06:53 +00:00
Charlie Marsh 39f3cd2a94
Bump version to v0.3.4 (#6656) 2024-08-26 16:51:01 -04:00
renovate[bot] a25f800aae
Update Rust crate syn to v2.0.76 (#6630) 2024-08-26 00:23:27 +00:00
renovate[bot] f8b8aa72ce
Update Rust crate serde_json to v1.0.127 (#6629) 2024-08-26 00:21:22 +00:00
renovate[bot] 8de12fd42e
Update Rust crate serde to v1.0.209 (#6628) 2024-08-26 00:21:07 +00:00
renovate[bot] d98d28a8ca
Update Rust crate rkyv to v0.7.45 (#6627) 2024-08-26 00:20:17 +00:00
renovate[bot] 413cf00a0c
Update Rust crate reqwest to v0.12.7 (#6626) 2024-08-26 00:15:15 +00:00
renovate[bot] 768840da49
Update Rust crate quote to v1.0.37 (#6625) 2024-08-26 00:14:55 +00:00
renovate[bot] faf534f997
Update Rust crate jiff to v0.1.10 (#6624) 2024-08-26 00:12:26 +00:00
renovate[bot] e4e1f384ce
Update Rust crate flate2 to v1.0.33 (#6623) 2024-08-25 20:12:14 -04:00
Charlie Marsh a72a09e9af
Use `tl` fork to support unquoted hrefs (#6622)
## Summary

Closes https://github.com/astral-sh/uv/issues/6082.
2024-08-26 00:02:26 +00:00
Jp 2bfc450418
Parses wheels WHEEL and METADATA files content as email messages (#6616)
## Summary

Fixes: #6615 
Currently, some packages are not installable with `uv`, like `ziglang`
on Linux.
Everything is described in the issue! 😄 

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

## Test Plan

<!-- How was it tested? -->
I added a unit test for the problematic use case.
I also checked that previous unit test are still running in order to
ensure the backward compatibility.
2024-08-25 18:31:07 -04:00
Charlie Marsh 0dc74f619c
Remove `path-absolutize` dependency (#6589)
## Summary

This is now in the standard library.
2024-08-25 12:01:07 +00:00
Charlie Marsh f7835243c5
Only use relative paths in lockfile (#6490)
For users who were using absolute paths in the `pyproject.toml`
previously, this is a behavior change: We now convert all absolute paths
in `path` entries to relative paths. Since i assume that no-one relies
on absolute path in their lockfiles - they are intended to be portable -
I'm tagging this as a bugfix.

Closes https://github.com/astral-sh/uv/pull/6438
Fixes https://github.com/astral-sh/uv/issues/6371
2024-08-23 22:19:10 -04:00
Charlie Marsh 44e36a7e69
Store test temporary directories outside of `/tmp` (#6559)
## Summary

There's a long comment inline describing the motivation here.
2024-08-24 01:51:32 +00:00
Zanie Blue deea6025a1
Bump version to 0.3.3 (#6558) 2024-08-23 18:35:55 -05:00
konsti bbcd10d3cc
Remove rustc-hash 1.1.0 (#6507)
Update tracing-durations-export so we only have rustc-hash 2.0.0
remaining.
2024-08-23 11:50:08 +00:00
konsti 33f15ac456
Update pubgrub to 388685a8711092971930986644cfed152d1a1f6c (#6495)
Regular maintenance.
2024-08-23 12:43:55 +02:00
Charlie Marsh c5440001ce
Bump version to v0.3.2 (#6483) 2024-08-23 03:11:23 +00:00
Charlie Marsh be17d132ad
Bump version to v0.3.1 (#6385) 2024-08-21 19:07:50 -04:00
Zanie Blue dd1934c9c3
Bump version to 0.3.0 (#6260)
[Rendered](https://github.com/astral-sh/uv/blob/zb/030/CHANGELOG.md#030)

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-08-20 12:29:58 -05:00
konsti e740322549
Impl `Ord` for ADD `MarkerTree` (#6253)
The ADD `MarkerTree` was including the non-deterministic, unstable
`NodeId` in its `Ord` implementation since switching algebraic decision
diagrams. By replacing this with a correct `Ord` implementation, we fix
#6249.

Requires https://github.com/astral-sh/pubgrub/pull/31
2024-08-20 19:11:57 +02:00
Charlie Marsh e11bbb539a Migrate to XDG and Linux strategy for macOS directories (#5806)
This PR moves us to the Linux strategy for our global directories on
macOS. We both feel on the team _and_ have received feedback (in Issues
and Polls) that the `Application Support` directories are more intended
for GUIs, and CLI tools are correct to respect the XDG variables and use
the same directory paths on Linux and macOS.

Namely, we now use:

- `/Users/crmarsh/.local/share/uv/tools` (for tools)
- `/Users/crmarsh/.local/share/uv/python` (for Pythons)
- `/Users/crmarsh/.cache/uv` (for the cache)

The strategy is such that if the `/Users/crmarsh/Library/Application
Support/uv` already exists, we keep using it -- same goes for
`/Users/crmarsh/Library/Caches/uv`, so **it's entirely backwards
compatible**.

If you want to force a migration to the new schema, you can run:

- `uv cache clean`
- `uv tool uninstall --all`
- `uv python uninstall --all`

Which will clean up the macOS-specific directories, paving the way for
the above paths. In other words, once you run those commands, subsequent
`uv` operations will automatically use the `~/.cache` and `~/.local`
variants.

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

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2024-08-20 11:31:46 -05:00
Zanie Blue 04e3e7ce65 Remove preview labeling for uv 0.3.0 (#6166)
- Removes "experimental" labels from command documentation
- Removes preview warnings
- Removes `PreviewMode` from most structs and methods — we could keep it
around but I figure we can propagate it again easily where needed in the
future
- Enables preview behavior by default everywhere, e.g., `uv venv` will
download Python versions
2024-08-20 11:31:46 -05:00
Andrew Gallant 33480d61eb switch to jiff from chrono (#6205)
This PR migrates uv's use of `chrono` to `jiff`.

I did most of this work a while back as one of my tests to ensure Jiff
could actually be used in a real world project. I decided to revive
this because I noticed that `reqwest-retry` dropped its Chrono
dependency,
which is I believe the only other thing requiring Chrono in uv.
(Although, we use a fork of `reqwest-middleware` at present, and that
hasn't been updated to latest upstream yet. I wasn't quite sure of the
process we have for that.)

In course of doing this, I actually made two changes to uv:

First is that the lock file now writes an RFC 3339 timestamp for
`exclude-newer`. Previously, we were using Chrono's `Display`
implementation for this which is a non-standard but "human readable"
format. I think the right thing to do here is an RFC 3339 timestamp.

Second is that, in addition to an RFC 3339 timestamp, `--exclude-newer`
used to accept a "UTC date." But this PR changes it to a "local date."
That is, a date in the user's system configured time zone. I think
this makes more sense than a UTC date, but one alternative is to drop
support for a date and just rely on an RFC 3339 timestamp. The main
motivation here is that automatically assuming UTC is often somewhat
confusing, since just writing an unqualified date like `2024-08-19` is
often assumed to be interpreted relative to the writer's "local" time.
2024-08-20 11:31:46 -05:00
konsti 310412a2ff
Update reqwest-middleware (#6206)
Update reqwest-middleware to the latest upstream
(https://github.com/TrueLayer/reqwest-middleware,
603ef97144b6b328c4e9ef7b13297d40bf461779) for #6205.
2024-08-19 10:25:40 -04:00
Andrew Gallant c7218e19ac cargo: add 'similar' dev dependency
We were already using this via 'insta'. We bring it in so that
we can explicitly snapshot diffs.
2024-08-19 05:33:30 -07:00
Andrew Gallant 74066ec29b cargo: remove unused 'derivative' dependency
This seems to be failing the `cargo shear` check on `main`. It looks
like this was caused by #6200.
2024-08-19 05:19:23 -07:00
renovate[bot] e008b38df2
Update Rust crate indexmap to v2.4.0 (#6194) 2024-08-19 02:31:24 +00:00
renovate[bot] 8a48f755d1
Update Rust crate which to v6.0.3 (#6193) 2024-08-19 02:31:05 +00:00
renovate[bot] 457ef73209
Update Rust crate tokio to v1.39.3 (#6192) 2024-08-19 02:29:13 +00:00
renovate[bot] 20ef94b15d
Update Rust crate syn to v2.0.75 (#6191) 2024-08-19 02:25:42 +00:00
renovate[bot] be095570f5
Update Rust crate serde_json to v1.0.125 (#6190) 2024-08-19 02:25:25 +00:00
renovate[bot] f1d2e3fe96
Update Rust crate serde to v1.0.208 (#6189) 2024-08-19 02:24:01 +00:00
renovate[bot] 75d57f50aa
Update Rust crate ctrlc to v3.4.5 (#6188) 2024-08-19 02:23:08 +00:00
renovate[bot] c40f3e4cc1
Update Rust crate clap to v4.5.16 (#6187) 2024-08-19 02:20:44 +00:00
Charlie Marsh 91fba4e1e6
Use `FxHash` in `uv-auth` (#6149) 2024-08-16 13:14:51 -04:00
Charlie Marsh 15dfb660ab
Bump version to v0.2.37 (#6134) 2024-08-15 22:13:03 -04:00
Charlie Marsh 8fac63d4ce
Redact Git credentials from `pyproject.toml` (#6074)
## Summary

We retain them if you use `--raw-sources`, but otherwise they're
removed. We still respect them in the subsequent `uv.lock` via an
in-process store.

Closes #6056.
2024-08-14 01:30:02 +00:00
Zanie Blue 8d66718077
Bump version to 0.2.36 (#6060) 2024-08-13 12:05:11 -05:00
Charlie Marsh 73e32f4eb9
Add test coverage for direct URLs with sources (#6046)
## Summary

Ensures that we don't respect `tool.uv.sources` for (eg.) direct URL
requirements, as intended.

Related to https://github.com/astral-sh/uv/issues/3943.

Closes https://github.com/astral-sh/uv/issues/6048.
2024-08-12 23:14:08 +00:00
renovate[bot] 2eb692ace1
Update Rust crate syn to v2.0.74 (#6022) 2024-08-12 01:33:16 +00:00
renovate[bot] 2421012bfe
Update Rust crate serde_json to v1.0.124 (#6021) 2024-08-12 01:29:12 +00:00
renovate[bot] 0c7e67f7d1
Update Rust crate serde to v1.0.206 (#6020) 2024-08-12 01:27:18 +00:00
renovate[bot] a295551d93
Update Rust crate clap to v4.5.15 (#6018) 2024-08-12 01:26:06 +00:00
Alexander Gherm 798cc7bf3c
Make more informative warning message when failed to parse pyproject.toml (#6009)
## Summary

Added the actual error message to the warning when uv fails to parse
`pyproject.toml`.

Resolves https://github.com/astral-sh/uv/issues/5934

## Test Plan

Took the case from the issue:
- have `pyproject.toml` which contains
```
[tool.uv]
foobar = false
```
- 
```
$ uv venv --preview -v
```
- Expect the message that contains the actual problem in the
`pyproject.toml` like:
```
warning: Failed to parse `pyproject.toml` during settings discovery: unknown field `foobar`; skipping...
```
2024-08-11 21:13:14 +00:00
Charlie Marsh f10c28225c
Support `tool.uv` in PEP 723 scripts (#5990)
## Summary

This includes both _settings_ and _sources.

Closes https://github.com/astral-sh/uv/issues/5855.
2024-08-09 23:11:10 -04:00
Zanie Blue e097f948c9
Bump version to 0.2.35 (#5984) 2024-08-09 19:21:06 -05:00
Charlie Marsh f89403f4f6
Retain and respect settings in tool upgrades (#5937)
## Summary

We now persist the `ResolverInstallerOptions` when writing out a tool
receipt. When upgrading, we grab the saved options, and merge with the
command-line arguments and user-level filesystem settings (CLI > receipt
> filesystem).
2024-08-09 18:21:49 +00:00
Ibraheem Ahmed ffd18cc75d
Implement marker trees using algebraic decision diagrams (#5898)
## Summary

This PR rewrites the `MarkerTree` type to use algebraic decision
diagrams (ADD). This has many benefits:
- The diagram is canonical for a given marker function. It is impossible
to create two functionally equivalent marker trees that don't refer to
the same underlying ADD. This also means that any trivially true or
unsatisfiable markers are represented by the same constants.
- The diagram can handle complex operations (conjunction/disjunction) in
polynomial time, as well as constant-time negation.
- The diagram can be converted to a simplified DNF form for user-facing
output.

The new representation gives us a lot more confidence in our marker
operations and simplification, which is proving to be very important
(see https://github.com/astral-sh/uv/pull/5733 and
https://github.com/astral-sh/uv/pull/5163).

Unfortunately, it is not easy to split this PR into multiple commits
because it is a large rewrite of the `marker` module. I'd suggest
reading through the `marker/algebra.rs`, `marker/simplify.rs`, and
`marker/tree.rs` files for the new implementation, as well as the
updated snapshots to verify how the new simplification rules work in
practice. However, a few other things were changed:
- [We now use release-only comparisons for `python_full_version`, where
we previously only did for
`python_version`](https://github.com/astral-sh/uv/blob/ibraheem/canonical-markers/crates/pep508-rs/src/marker/algebra.rs#L522).
I'm unsure how marker operations should work in the presence of
pre-release versions if we decide that this is incorrect.
- [Meaningless marker expressions are now
ignored](https://github.com/astral-sh/uv/blob/ibraheem/canonical-markers/crates/pep508-rs/src/marker/parse.rs#L502).
This means that a marker such as `'x' == 'x'` will always evaluate to
`true` (as if the expression did not exist), whereas we previously
treated this as always `false`. It's negation however, remains `false`.
- [Unsatisfiable markers are written as `python_version <
'0'`](https://github.com/astral-sh/uv/blob/ibraheem/canonical-markers/crates/pep508-rs/src/marker/tree.rs#L1329).
- The `PubGrubSpecifier` type has been moved to the new `uv-pubgrub`
crate, shared by `pep508-rs` and `uv-resolver`. `pep508-rs` also depends
on the `pubgrub` crate for the `Range` type, we probably want to move
`pubgrub::Range` into a separate crate to break this, but I don't think
that should block this PR (cc @konstin).

There is still some remaining work here that I decided to leave for now
for the sake of unblocking some of the related work on the resolver.
- We still use `Option<MarkerTree>` throughout uv, which is unnecessary
now that `MarkerTree::TRUE` is canonical.
- The `MarkerTree` type is now interned globally and can potentially
implement `Copy`. However, it's unclear if we want to add more
information to marker trees that would make it `!Copy`. For example, we
may wish to attach extra and requires-python environment information to
avoid simplifying after construction.
- We don't currently combine `python_full_version` and `python_version`
markers.
- I also have not spent too much time investigating performance and
there is probably some low-hanging fruit. Many of the test cases I did
run actually saw large performance improvements due to the markers being
simplified internally, reducing the stress on the old `normalize`
routine, especially for the extremely large markers seen in
`transformers` and other projects.

Resolves https://github.com/astral-sh/uv/issues/5660,
https://github.com/astral-sh/uv/issues/5179.
2024-08-09 13:40:02 -04:00
Charlie Marsh cdd7341b6d
Run `cargo update` (#5960) 2024-08-09 13:36:11 -04:00
Ibraheem Ahmed ddb82a01c8
Add basic universal benchmarks to CI (#5938)
## Summary

Resolves https://github.com/astral-sh/uv/issues/4921.
2024-08-09 12:52:28 -04:00
Charlie Marsh 21408c1f35
Enforce extension validity at parse time (#5888)
## Summary

This PR adds a `DistExtension` field to some of our distribution types,
which requires that we validate that the file type is known and
supported when parsing (rather than when attempting to unzip). It
removes a bunch of extension parsing from the code too, in favor of
doing it once upfront.

Closes https://github.com/astral-sh/uv/issues/5858.
2024-08-08 21:39:47 -04:00
Charlie Marsh c681c5a33c
Bump version to v0.2.34 (#5889) 2024-08-07 16:33:53 -04:00
renovate[bot] 02eba290f6
Update Rust crate tempfile to v3.11.0 (#5784) 2024-08-05 01:46:44 +00:00
renovate[bot] b4cb3f2266
Update Rust crate indexmap to v2.3.0 (#5783) 2024-08-05 01:43:29 +00:00
renovate[bot] c14d84609d
Update Rust crate winsafe to 0.0.22 (#5780) 2024-08-05 01:13:37 +00:00
renovate[bot] 77141464fe
Update Rust crate which to v6.0.2 (#5779) 2024-08-05 01:08:55 +00:00
renovate[bot] 03b033f828
Update Rust crate toml to v0.8.19 (#5777) 2024-08-05 01:01:56 +00:00
renovate[bot] 0c3ac4eafe
Update Rust crate target-lexicon to v0.12.16 (#5776) 2024-08-05 00:57:41 +00:00
renovate[bot] e16ba6ed51
Update Rust crate serde_json to v1.0.122 (#5775) 2024-08-05 00:53:28 +00:00
renovate[bot] 28aa720e29
Update Rust crate regex to v1.10.6 (#5774) 2024-08-05 00:52:47 +00:00
renovate[bot] 96b52510e1
Update Rust crate flate2 to v1.0.31 (#5773) 2024-08-05 00:49:10 +00:00
renovate[bot] f38fd25e95
Update Rust crate dunce to v1.0.5 (#5772) 2024-08-05 00:46:43 +00:00
renovate[bot] 09b227ce86
Update Rust crate clap to v4.5.13 (#5771) 2024-08-05 00:45:52 +00:00
Zanie Blue b14945a7b1
Bump version to 0.2.33 (#5712) 2024-08-01 21:39:17 +00:00
Zanie Blue f107406727
Generate CLI reference for documentation (#5685)
Loosely based on [Cargo's
format](https://github.com/rust-lang/cargo/blob/master/src/doc/src/commands/cargo-build.md)

<img width="896" alt="Screenshot 2024-08-01 at 9 44 03 AM"
src="https://github.com/user-attachments/assets/7c016bb3-2b54-46af-8ea8-ce82e07a0e30">

Future work includes:

- Grouping options
- Enforcing some sort of specific command ordering
- Showing possible values for enums
- Adding "long_about" to commands for more context
2024-08-01 16:04:16 +00:00
Charlie Marsh f266fb711c
Use full requirement when serializing receipt (#5494)
## Summary

The current receipt doesn't capture quite enough information. For
example, it doesn't differentiate between editable and non-editable
requirements. This PR instead uses the full `Requirement` type. I think
we should use a custom representation like we do in the lockfile, but
I'm just using the default representation to demonstrate the idea.
2024-07-31 16:16:39 +00:00
Charlie Marsh dfec262586
Capture portable path serialization in a struct (#5652)
## Summary

I need to reuse this in #5494, so want to abstract it out and make it
reusable.
2024-07-31 16:00:37 +00:00
konsti 981661c4af
Update pubgrub (#5649)
We improved the API structure in pubgrub, and also update to generally
keep up with upstream.
2024-07-31 12:54:11 +00:00
Charlie Marsh 38c232e466
Bump version to v0.2.32 (#5641) 2024-07-30 18:56:39 -04:00
Maksim Bondarenkov 228a803fde
uv-python: use windows-sys instead of winapi (#5591)
<!--
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

use windows-sys bindings maintained by microsoft devs. winapi didn't has
any updates for more than 3 years

## Test Plan

cargo test. it failed locally because I don't have Python 3.12 installed
2024-07-30 11:43:04 +02:00
Charlie Marsh ecb85c9894
Statically link liblzma (#5577)
## Summary

Found via https://github.com/indygreg/PyOxidizer/issues/585.

Closes https://github.com/astral-sh/uv/issues/5572.
2024-07-29 21:46:43 +00:00
Charlie Marsh 48162de974
Bump version to v0.2.31 (#5568) 2024-07-29 14:06:20 -04:00
Charlie Marsh a346d257cb
Update `rs-async-zip` fork commit (#5560)
## Summary

Closes https://github.com/astral-sh/uv/issues/5556.
2024-07-29 14:42:53 +00:00
renovate[bot] 77696c4ab4
Update Rust crate axoupdater to 0.7.0 (#5547) 2024-07-29 09:44:25 -04:00
renovate[bot] 600ef6f18c
Update Rust crate assert_cmd to v2.0.15 (#5534) 2024-07-28 20:32:02 -04:00
renovate[bot] c9099b1ed3
Update Rust crate toml to v0.8.16 (#5541) 2024-07-28 20:31:46 -04:00
renovate[bot] 335fe82cfe
Update Rust crate tokio to v1.39.2 (#5540) 2024-07-28 20:31:39 -04:00
renovate[bot] 834a1ed515
Update Rust crate serde_json to v1.0.121 (#5539) 2024-07-28 20:31:36 -04:00
renovate[bot] 96c65628b7
Update Rust crate predicates to v3.1.2 (#5538) 2024-07-28 20:31:29 -04:00
renovate[bot] f2860df91f
Update Rust crate clap to v4.5.11 (#5537) 2024-07-28 20:30:53 -04:00
renovate[bot] 3b488d8635
Update Rust crate cargo-util to v0.2.13 (#5536) 2024-07-28 20:30:28 -04:00
renovate[bot] f8f82b354d
Update Rust crate assert_fs to v1.1.2 (#5535) 2024-07-28 20:30:21 -04:00
renovate[bot] 9164d5cf97
Update Rust crate anstream to v0.6.15 (#5533) 2024-07-28 20:30:14 -04:00
Krishnan Chandra 4b4128446d
Support xz compressed packages (#5513)
## Summary

Closes #2187.

The [xz
backdoor](https://gist.github.com/thesamesam/223949d5a074ebc3dce9ee78baad9e27)
is still fairly recent, but luckily the [Rust `xz2` crate bundles
version 5.2.5 of the C `xz`
package](https://github.com/alexcrichton/xz2-rs/tree/main/lzma-sys),
which is before the backdoor was introduced.

It's worth noting that a security risk still exists if you have a
compromised version of `xz` installed on your system, but that risk is
not introduced by `uv` or the Rust packages in general.

## Test Plan

Tried installing the package mentioned in the linked issue: `python-apt
@
https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/python-apt/2.7.6/python-apt_2.7.6.tar.xz`

(Note that this will only work on Ubuntu - I tried on a Mac and while
the archive was extracted properly, the package did not install because
of some missing files)

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-07-28 18:37:48 +00:00
Charlie Marsh 1734c7ed50
Use existing METADATA parser in wheel installer (#5508) 2024-07-27 14:38:16 -04:00
Charlie Marsh 24859bd3ee
Upgrade to Rust 1.80.0 (#5472) 2024-07-27 01:49:47 +00:00
Charlie Marsh 6901a14aa0
Bump version to v0.2.30 (#5486) 2024-07-26 13:36:05 -04:00
Charlie Marsh d0919329fd
Make `--reinstall` imply `--refresh` (#5425)
## Summary

It's hard for me to imagine a scenario in which a user passed
`--reinstall`, but wanted us to keep respecting cached data for a
package. For example, to actually "rebuild and reinstall" an editable
today, you have to pass both `--reinstall` and `--refresh`.

This PR makes `--reinstall` imply `--refresh`, so we always validate
that the cached data is fresh.

Closes https://github.com/astral-sh/uv/issues/5424.
2024-07-25 09:45:58 -04:00
Zanie Blue 35b6726df5
Bump version to 0.2.29 (#5431) 2024-07-24 22:23:34 +00:00
Charlie Marsh 3d36b71ab1
Show additions and removals in `uv lock` updates (#5410)
## Summary

Closes https://github.com/astral-sh/uv/issues/5401.
2024-07-24 15:33:09 +00:00
Zanie Blue 3a85353707
Bump version to 0.2.28 (#5363) 2024-07-23 14:04:55 -05:00
renovate[bot] f76a08a3ac
Update Rust crate toml to v0.8.15 (#5273) 2024-07-22 00:24:43 +00:00
renovate[bot] 3d719922ee
Update Rust crate tokio to v1.38.1 (#5272) 2024-07-22 00:21:56 +00:00
renovate[bot] fcdebfc420
Update Rust crate thiserror to v1.0.63 (#5271) 2024-07-22 00:21:24 +00:00
renovate[bot] 8fb2f9eb1e
Update Rust crate axoupdater to v0.6.9 (#5269)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [axoupdater](https://togithub.com/axodotdev/axoupdater) |
workspace.dependencies | patch | `0.6.8` -> `0.6.9` |

---

### Release Notes

<details>
<summary>axodotdev/axoupdater (axoupdater)</summary>

###
[`v0.6.9`](https://togithub.com/axodotdev/axoupdater/blob/HEAD/CHANGELOG.md#Version-069-2024-07-18)

[Compare
Source](https://togithub.com/axodotdev/axoupdater/compare/v0.6.8...v0.6.9)

This release fixes a bug in which axoupdater could pick the wrong
installer when handling releases containing more than one app.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, 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://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/astral-sh/uv).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40MzguMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-21 20:21:08 -04:00
renovate[bot] 5d1d35cd47
Update Rust crate syn to v2.0.72 (#5270) 2024-07-22 00:18:00 +00:00
renovate[bot] e765bd55b2
Update Rust crate async-compression to v0.4.12 (#5268) 2024-07-22 00:14:35 +00:00
Charlie Marsh d798bb3973
Avoid always rebuilding dynamic metadata (#5206)
## Summary

I don't think that "always reinstall" is tenable for `uv run`. My
perspective on this is that if you want "always reinstall", you can now
set it persistently in your `pyproject.toml` or `uv.toml`.

As a smaller change, we could instead disable this _only_ for the
Project API.

Closes https://github.com/astral-sh/uv/issues/4946.
2024-07-22 00:04:03 +00:00
Charlie Marsh 841edc3718
Move workspace abstractions to `uv-workspace` crate (#5236)
## Summary

These are really different from the rest of the existing crate as
evidenced by the bifurcation in the requirements.
2024-07-20 02:15:32 +00:00
Zanie Blue 833097b93f
Bump version to 0.2.27 (#5230) 2024-07-19 22:06:49 +00:00
Charlie Marsh 92e11022e7
Downgrade to winsafe v0.0.19 (#5233) 2024-07-19 17:14:57 -04:00
Ibraheem Ahmed 12dd450a8e
Implement `uv init` (#4791)
## Summary

Implements the `uv init` command, which initializes a project
(`pyproject.toml`, `README.md`, `src/__init__.py`) in the current
directory, or in the given path. `uv init` also does workspace
discovery.

Resolves https://github.com/astral-sh/uv/issues/1360.

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2024-07-19 15:11:48 +00:00
Charlie Marsh 4a875afc07
Skip invalid tools in `uv tool list` (#5156)
## Summary

Makes the `tools()` return value include per-tool errors. This makes it
easy to skip (rather than failing) in `uv tool list`, _and_ improves `uv
tool uninstall` to remove those invalid tools, rather than leaving them
around. (We already had that behavior for `uv tool uninstall ruff` with
an invalid `ruff`, but `uv tool uninstall --all` just left them.)

Closes https://github.com/astral-sh/uv/issues/5151.
2024-07-18 17:56:40 +00:00
konsti 7beae77283
Search for all `python3.x` in PATH (#5148)
Search for all `python3.x` minor versions in PATH, skipping those we
already know we can use.

For example, let's say `python` and `python3` are Python 3.10. When a
user requests `>= 3.11`, we still need to find a `python3.12` in PATH.
We do so with a regex matcher.

Fixes #4709
2024-07-18 17:00:01 +02:00
Charlie Marsh 564f4b2958
Use display representation for download error (#5173)
## Summary

Turns out we already have display for this.

Closes https://github.com/astral-sh/uv/issues/4914.
2024-07-18 02:05:17 +00:00
Charlie Marsh fe403576c5
Bump version to v0.2.26 (#5149) 2024-07-17 12:51:11 -04:00
Charlie Marsh a191f84929
Autogenerate possible values for enums in reference documentation (#5137)
## Summary

For example:

![Screenshot 2024-07-16 at 7 44
10 PM](https://github.com/user-attachments/assets/73ce16ba-eb0e-43c4-a741-65a54637452f)

Closes https://github.com/astral-sh/uv/issues/5129.
2024-07-17 12:37:33 -04:00
messense 38504dcaee
Download wheel to disk when streaming unzip failed with HTTP streaming error (#5094)
## Summary

Workaround the `stream_wheel` not retry issue
[found](https://github.com/astral-sh/uv/issues/3514#issuecomment-2229820667)
in #3514, it's not a perfect solution but I think it's acceptable
because the error should not occur frequently.

## Test Plan

Manually using `iptables -A OUTPUT -p tcp -dport 3128 -j REJECT
--reject-with tcp-reset` to inject connection reset error to the HTTP
proxy that proxies PyPI requests.

```
error: Failed to prepare distributions
  Caused by: Failed to fetch wheel: piqp==0.4.1
  Caused by: Request failed after 3 retries
  Caused by: error sending request for url (09ade94dfdd3c368ac505b6ca09831/piqp-0.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl)
  Caused by: client error (Connect)
  Caused by: tcp connect error: Connection refused (os error 111)
  Caused by: Connection refused (os error 111)
```
2024-07-16 09:00:46 -04:00
Charlie Marsh d1010228b3
Bump version to v0.2.25 (#5083) 2024-07-15 22:38:59 +00:00
Charlie Marsh 6275b54d51
Generate API reference for options documentation (#5072)
## Summary

Generates Markdown from the `OptionsMetadata`, following the same
strategy as in Ruff.

## Test Plan

`cargo dev generate-options-reference`
2024-07-15 19:48:40 +00:00
Charlie Marsh 8c0ad5b75e
Add `OptionsMetadata` macro to uv (#5063)
## Summary

The bulk of the change is copied directly from Ruff:

-
dc8db1afb0/crates/ruff_workspace/src/options_base.rs
-
dc8db1afb0/crates/ruff_macros/src/config.rs
2024-07-15 19:24:08 +00:00
konsti e34ab96e80
Remove special casing from no solution error (#5067)
The only pubgrub error that can occur is a `NoSolutionError`, and the
only place it can occur is `unit_propagation`, all other variants if
`PubGrubError` are unreachable. By changing the return type on pubgrub's
side (https://github.com/astral-sh/pubgrub/pull/28), we can remove the
pattern matching and the `unreachable!()` asserts on `PubGrubError`.

Our pubgrub error wrapper used to have a two phased initialization,
first mostly stubs in `solve[_tracked]()` and then adding the actual
context in `resolve()`. When constructing the error in `solve` we
already have all this context, so we can unify this to a regular
constructor and remove the special casing in `resolve()` and `hints()`.
2024-07-15 17:43:35 +02:00
renovate[bot] cc0983a8db
Update Rust crate toml_edit to v0.22.15 (#5055) 2024-07-14 20:40:23 -04:00
renovate[bot] 865ba6db10
Update Rust crate tracing-tree to 0.4.0 (#5059) 2024-07-14 20:39:56 -04:00
renovate[bot] 97d2a7c567
Update Rust crate tikv-jemallocator to 0.6.0 (#5058) 2024-07-14 20:39:50 -04:00
renovate[bot] 4d14a1a371
Update Rust crate clap_complete_command to 0.6.0 (#5057) 2024-07-14 20:39:43 -04:00
renovate[bot] d230323241
Update Rust crate thiserror to v1.0.62 (#5054) 2024-07-14 20:39:26 -04:00
renovate[bot] 27247029c9
Update Rust crate target-lexicon to v0.12.15 (#5053) 2024-07-14 20:39:21 -04:00
renovate[bot] 517487e2d0
Update Rust crate syn to v2.0.71 (#5052) 2024-07-14 20:39:15 -04:00
Charlie Marsh 4eb19c76bd
Add Windows path updates for `uv tool` (#5029)
## Summary

Largely based on rustup's implementation (linked in the source).

Closes #5027.

## Test Plan

- Changed the executable directory to `uv/foo`.
- Ran script; verified that I could access executables in `foo`.
2024-07-13 01:55:05 +00:00
Charlie Marsh a61464e802
Move shell manipulation into its own crate (#5028)
## Summary

This is going to get a little more complex as we support Windows, so
carving it out.
2024-07-12 21:12:58 -04:00
Charlie Marsh a4cb21e081
Add a command to append uv's binary directory to PATH (#4975)
## Summary

I'll open follow-up tickets for Windows support.

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

## Test Plan

```
❯ cargo run tool install flask
Resolved 7 packages in 353ms
Prepared 7 packages in 392ms
Installed 7 packages in 17ms
 + blinker==1.8.2
 + click==8.1.7
 + flask==3.0.3
 + itsdangerous==2.2.0
 + jinja2==3.1.4
 + markupsafe==2.1.5
 + werkzeug==3.0.3
Installed 1 executable: flask
warning: /Users/crmarsh/.local/bin is not on your PATH. To use installed tools, run:
  export PATH="/Users/crmarsh/.local/bin:$PATH"
```

Then:

```
❯ which flask
flask not found
```

Then:

```
❯ cargo run tool ensurepath
warning: `uv tool ensurepath` is experimental and may change without warning.
Updated configuration file: /Users/crmarsh/workspace/puffin/bar
Restart your shell for the changes to take effect.
```

Then:
```
❯ which flask
/Users/crmarsh/.local/bin/flask
```
2024-07-12 22:09:34 +00:00
Zanie Blue 527b711bc7
Bump version to 0.2.24 (#4974) 2024-07-10 13:50:12 -05:00
Charlie Marsh 1fcc3c4797
Warn if tool binary directory is not on path (#4951)
## Summary

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

## Test Plan

```
❯ XDG_BIN_HOME="/Users/crmarsh/workspace/uv/foo bar" cargo run tool install black --force
Installed 2 executables: black, blackd
warning: `/Users/crmarsh/workspace/uv/foo bar` is not on your PATH. To use installed tools, run:
  export PATH="/Users/crmarsh/workspace/uv/foo bar:$PATH"
```
2024-07-10 15:24:16 +00:00
Charlie Marsh 23eb42deed
Allow constraints to be provided in `--upgrade-package` (#4952)
## Summary

Allows, e.g., `--upgrade-package flask<3.0.0`.

Closes https://github.com/astral-sh/uv/issues/1964.
2024-07-09 20:09:13 -07:00
Charlie Marsh 540ff24302
Perform lock in `uv sync` by default (#4839)
## Summary

- `uv sync` will now lock by default.
- `uv sync --locked` will lock, and error if the generated lock does not
match `uv.lock` on-disk.
- `uv sync --frozen` will skip locking and just use `uv.lock`.

Closes https://github.com/astral-sh/uv/issues/4812.
Closes https://github.com/astral-sh/uv/issues/4803.
2024-07-09 15:18:30 -07:00
Zanie Blue bd7a25f604
Use paging for `uv help` display when available (#4909)
Extends https://github.com/astral-sh/uv/pull/4906

Adds paged display of "long' help to `uv help` invocations when `less`
or `more` is available.
2024-07-09 18:06:27 +00:00
renovate[bot] ef120dcc54
Update Rust crate hyper to v1.4.1 (#4877) 2024-07-09 09:08:10 -07:00
Zanie Blue babb1e3ec2
Upgrade `clap` (#4927)
For https://github.com/clap-rs/clap/pull/5574 for #4772
2024-07-09 16:06:53 +00:00
Ibraheem Ahmed dc7ad3abdb
Implement `uv tree` (#4708)
## Summary

Implements the `uv tree`, which displays dependencies from the lockfile
as a tree. Resolves https://github.com/astral-sh/uv/issues/4699.
2024-07-08 18:07:48 +00:00
Zanie Blue 4bc36c0cb8
Bump version to 0.2.23 (#4903) 2024-07-08 12:29:37 -05:00
Charlie Marsh 4f340580c7
Show user-facing warning when falling back to copy installs (#4880)
## Summary

This has come up a few times including in a recent email to me.
2024-07-08 13:35:58 +00:00
renovate[bot] 889f4efd21
Update Rust crate syn to v2.0.69 (#4875) 2024-07-08 00:26:58 +00:00
renovate[bot] 7a914b900c
Update Rust crate serde_json to v1.0.120 (#4874) 2024-07-07 20:25:18 -04:00
renovate[bot] 621e0e9df8
Update Rust crate serde to v1.0.204 (#4873) 2024-07-07 20:25:13 -04:00
renovate[bot] f07f1006d9
Update Rust crate reflink-copy to v0.1.19 (#4872) 2024-07-07 20:25:08 -04:00
renovate[bot] 08c544ddd5
Update Rust crate hyper-util to v0.1.6 (#4871) 2024-07-07 20:25:00 -04:00
renovate[bot] 28e71eba99
Update Rust crate axoupdater to v0.6.8 (#4870) 2024-07-07 20:24:52 -04:00
renovate[bot] 12a922261f
Update Rust crate async-trait to v0.1.81 (#4869) 2024-07-07 20:24:46 -04:00
Jo f4c4b69cc7
Add progress bar when downloading python (#4840)
## Summary

Resolves #4825 

## Test Plan

```sh
$ cargo run -- python install --force --preview
$ cargo run -- venv -p 3.12 --python-preference only-managed
$ cargo run -- tool install --preview -p 3.12 --python-preference only-managed --force black
````

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-07-07 20:01:35 +00:00
Charlie Marsh f5e84bbbab
Bump version to v0.2.22 (#4862) 2024-07-07 19:23:38 +00:00
Charlie Marsh de40f798b9
Cache tool environments in `uv tool run` (#4784)
## Summary

The basic strategy:

- When the user does `uv tool run`, we resolve the `from` and `with`
requirements (always).
- After resolving, we generate a hash of the requirements. For now, I'm
just converting to a lockfile and hashing _that_, but that's an
implementation detail.
- Once we have a hash, we _also_ hash the interpreter.
- We then store environments in
`${CACHE_DIR}/${INTERPRETER_HASH}/${RESOLUTION_HASH}`.

Some consequences:

- We cache based on the interpreter, so if you request a different
Python, we'll create a new environment (even if they're compatible).
This has the nice side-effect of ensuring that we don't use environments
for interpreters that were later deleted.
- We cache the `from` and `with` together. In practice, we may want to
cache them separately, then layer them? But this is also an
implementation detail that we could change later.
- Because we use the lockfile as the cache key, we will invalidate the
cache when the format changes. That seems ok, but we could improve it in
the future by generating a stable hash from a lockfile that's
independent of the schema.

Closes https://github.com/astral-sh/uv/issues/4752.
2024-07-03 19:25:39 -04:00
Caíque Porfirio c17761904e
feat: add tool version to list command (#4674)
<!--
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?
-->
Closes #4653

## Summary
Adds the tool version to the list command right beside the tool name

```
$ uv tool list
black v24.2.0
```

Following the proposed format discussed in #4653


## Test Plan
`cargo test tool_list`

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

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2024-07-03 18:24:37 +00:00
Charlie Marsh f980e3f4fc
Use already-installed tools in `uv tool run` (#4750)
## Summary

This doesn't cache the tool environment; rather, it just uses the `tool
install` environment if it satisfies the request.

Closes https://github.com/astral-sh/uv/issues/4742.
2024-07-03 16:35:11 +00:00
Zanie Blue dd7da6af5f
Change "toolchain" to "python" (#4735)
Whew this is a lot.

The user-facing changes are:

- `uv toolchain` to `uv python` e.g. `uv python find`, `uv python
install`, ...
- `UV_TOOLCHAIN_DIR` to` UV_PYTHON_INSTALL_DIR`
- `<UV_STATE_DIR>/toolchains` to `<UV_STATE_DIR>/python` (with
[automatic
migration](https://github.com/astral-sh/uv/pull/4735/files#r1663029330))
- User-facing messages no longer refer to toolchains, instead using
"Python", "Python versions" or "Python installations"

The internal changes are:

- `uv-toolchain` crate to `uv-python`
- `Toolchain` no longer referenced in type names
- Dropped unused `SystemPython` type (previously replaced)
- Clarified the type names for "managed Python installations"
- (more little things)
2024-07-03 07:44:29 -05:00
Zanie Blue ebfe6d8fcc
Bump version to 0.2.21 (#4757) 2024-07-03 04:27:00 +00:00
Zanie Blue e88e1373e6
Bump version to 0.2.20 (#4745) 2024-07-02 22:30:43 +00:00
Zanie Blue c5bf64abeb
Bump version to 0.2.19 (#4738) 2024-07-02 21:15:58 +00:00
Charlie Marsh 32dc9bef59
Respect tool upgrades in `uv tool install` (#4736)
## Summary

For now the semantics are such that if the requested requirements from
the command line don't match the receipt (or if any `--reinstall` or
`--upgrade` is requested), we proceed with an install, passing the
`--reinstall` and `--upgrade` to the underlying Python environment.

This may lead to some unintuitive behaviors, but it's simplest for now.
For example:

- `uv tool install black<24` followed by `uv tool install black
--upgrade` will install the latest version of `black`, removing the
`<24` constraint.
- `uv tool install black --with black-plugin` followed by `uv tool
install black` will remove `black-plugin`.

Closes https://github.com/astral-sh/uv/issues/4659.
2024-07-02 16:46:31 -04:00
konsti 4b19319485
Show when we retried requests (#4725)
In #3514 and #2755, users had intermittent network errors, but it was
not always clear whether we had already retried these requests or not.
Building upon https://github.com/TrueLayer/reqwest-middleware/pull/159,
this PR adds the number of retries to the error message, so we can see
at first glance where we're missing retries and where we might need to
change retry settings.

Example error trace:

```
Could not connect, are you offline?
  Caused by: Request failed after 3 retries
  Caused by: error sending request for url (https://pypi.org/simple/uv/)
  Caused by: client error (Connect)
  Caused by: dns error: failed to lookup address information: Name or service not known
  Caused by: failed to lookup address information: Name or service not known
```

This code is ugly since i'm missing a better pattern for attaching
context to reqwest middleware errors in
https://github.com/TrueLayer/reqwest-middleware/pull/159.
2024-07-02 19:04:11 +02:00
Charlie Marsh 8e935e2c17
Support unnamed requirements in `uv tool install` (#4716)
## Summary

This PR adds support for (e.g.) `uv tool install
git+https://github.com/psf/black`.

Closes https://github.com/astral-sh/uv/issues/4664.
2024-07-01 21:37:14 -04:00
Charlie Marsh 324e9fe5cf
Respect data scripts in `uv tool install` (#4693)
## Summary

Packages that provide scripts that _aren't_ Python entrypoints need to
respected in `uv tool install`. For example, Ruff ships a script in
`ruff-0.5.0.data/scripts`.

Unfortunately, the `.data` directory doesn't exist in the virtual
environment at all (it's removed, per the spec, after install). So this
PR changes the entry point detection to look at the `RECORD` file, which
is the only evidence that the scripts were installed.

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

## Test Plan

`cargo run uv tool install ruff` (snapshot tests to-come)
2024-07-01 12:22:37 -04:00
Charlie Marsh bfadadefaf
Add PEP 723 support to uv run (#4656)
Closes #3096 

## Summary

Enables `uv run foo.py` to execute PEP 723-compatible scripts.

For example, given:

```python
# /// script
# requires-python = ">=3.11"
# dependencies = [
#   "requests<3",
#   "rich",
# ]
# ///

import requests
from rich.pretty import pprint

resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])
```

![Screenshot 2024-06-29 at 7 23
52 PM](https://github.com/astral-sh/uv/assets/1309177/c60f2415-4874-4b15-b9f5-dd8c8c35382e)
2024-07-01 08:20:24 -04:00
renovate[bot] 8f881d4796
Update Rust crate dashmap to v6 (#4682) 2024-07-01 01:49:15 +00:00
renovate[bot] 36625465c1
Update Rust crate reqwest-retry to 0.6.0 (#4680) 2024-06-30 21:45:35 -04:00
renovate[bot] 56ecc4617a
Update Rust crate either to v1.13.0 (#4678) 2024-06-30 21:45:19 -04:00
renovate[bot] 8b5d979010
Update Rust crate serde_json to v1.0.119 (#4677) 2024-06-30 21:45:03 -04:00
renovate[bot] 87b7ccb37c
Update Rust crate reqwest-middleware to v0.3.2 (#4676) 2024-06-30 21:44:57 -04:00
renovate[bot] 4c8aaed532
Update Rust crate clap to v4.5.8 (#4675) 2024-06-30 21:40:23 -04:00
Charlie Marsh 13b0beb56f
Bump version to v0.2.18 (#4650) 2024-06-29 14:30:01 -04:00
Charlie Marsh 0bb99952f6
Sync all packages in a virtual workspace (#4636)
## Summary

This PR dodges some of the bigger issues raised by
https://github.com/astral-sh/uv/pull/4554 and
https://github.com/astral-sh/uv/pull/4555 by _not_ changing any of the
bigger semantics around syncing and instead merely changing virtual
workspace roots to sync all packages in the workspace (rather than
erroring due to being unable to find a project).

Closes #4541.
2024-06-29 12:43:59 -04:00
Zanie Blue 3a627f3799
Track tool entry points in receipts (#4634)
We need this to power uninstallations! 

The latter two commits were reviewed in:

- #4637 
- #4638 

Note this is a breaking change for existing tool installations, but it's
in preview and very new. In the future, we'll need a clear upgrade path
for tool receipt changes.
2024-06-28 22:45:40 -05:00
Zanie Blue a444e59668
Add `uv tool list` (#4630)
What it says on the tin.

We skip tools with malformed receipts now and warn instead of failing
all tool operations.
2024-06-28 22:00:18 +00:00
Zanie Blue 2eb1e6693c
Bump version to 0.2.17 (#4573) 2024-06-26 23:16:44 +00:00
Charlie Marsh 95b4aacc25
Bump version to v0.2.16 (#4561) 2024-06-26 17:00:09 -04:00
Zanie Blue fc681ec738
Move from a shared `tools.toml` to separated tool receipts (#4560)
Refactors the installed tool metadata per commentary in #4492 

We now store a `uv-receipt.toml` per tool install instead of a single
`tools.toml`
2024-06-26 16:48:18 -04:00
Zanie Blue b44c47fdab
Add support for `--reinstall` and `--reinstall-package` in `uv tool install` (#4504)
Adds support for `--reinstall` and `--reinstall-package` to `uv tool
install`. These are already available via the installer settings, we
just respect them now.

`--reinstall` implies a recreation of the environment and reinstallation
of the entry points.
`--reinstall-package` will only update a subset of the environment. If
the target package is the one with the entry points, we'll reinstall the
entry points. Otherwise, the entry points are not changed.
2024-06-26 20:23:34 +00:00
Zanie Blue c9657b0015
Add `uv tool install` (#4492)
This is the minimal "working" implementation. In summary, we:

- Resolve the requested requirements
- Create an environment at `$UV_STATE_DIR/tools/$name`
- Inspect the `dist-info` for the main requirement to determine its
entry points scripts
- Link the entry points from a user-executable directory
(`$XDG_BIN_HOME`) to the environment bin
- Create an entry at `$UV_STATE_DIR/tools/tools.toml` tracking the
user's request

The idea with `tools.toml` is that it allows us to perform upgrades and
syncs, retaining the original user request (similar to declarations in a
`pyproject.toml`). I imagine using a similar schema in the
`pyproject.toml` in the future if/when we add project-levle tools. I'm
also considering exposing `tools.toml` in the standard uv configuration
directory instead of the state directory, but it seems nice to tuck it
away for now while we iterate on it. Installing a tool won't perform a
sync of other tool environments, we'll probably have an explicit `uv
tool sync` command for that?

I've split out todos into follow-up pull requests:

- #4509 (failing on Windows)
- #4501 
- #4504 

Closes #4485
2024-06-26 10:24:29 -05:00
Charlie Marsh a81742c06b
Read persistent configuration from non-workspace `pyproject.toml` (#4526)
## Summary

If the user puts their configuration in a `pyproject.toml` that _isn't_
a valid workspace root (e.g., it's a Poetry file), we won't discover it,
because we only look in `uv.toml` files in that case. I think this is
somewhat debatable... We could choose to _require_ `uv.toml` there, but
as a user I'd probably expect it to work?

Closes https://github.com/astral-sh/uv/issues/4521.
2024-06-25 18:53:14 +00:00
Charlie Marsh 9905521957
Use shared client in Git fetch implementation (#4487)
## Summary

It turns out that the Git fetch implementation is initializing its own
client, which can be really expensive on macOS (due to loading native
certificates) _and_ bypasses any of our middleware. This PR modifies the
Git implementation to accept a shared client.
2024-06-24 17:09:29 -04:00
Zanie Blue bfc342da94
Bump version to 0.2.15 (#4475)
Releasing 0.2.15 with a few additions over 0.2.14. Motivated by the
incorrect tagging of 0.2.14 (#4474).

Generated the changelog with a small patch to Rooster allowing me to
force the previous commit to be correct.

```diff
diff --git a/src/rooster/_cli.py b/src/rooster/_cli.py
index 2a4f61b..4ec1299 100644
--- a/src/rooster/_cli.py
+++ b/src/rooster/_cli.py
@@ -38,6 +38,7 @@ def release(
     without_sections: list[str] = typer.Option(
         [], help="Sections to exclude from the changelog"
     ),
+    previous_commit: str = None,
 ):
     """
     Create a new release.
@@ -58,7 +59,11 @@ def release(
         typer.echo("It looks like there are no version tags for this project.")
 
     # Get the commits since the last release
-    changes = list(get_commits_between(config, repo, last_version))
+    changes = list(
+        get_commits_between(
+            config, repo, last_version, force_first_commit=previous_commit
+        )
+    )
     since = "since last release" if last_version else "in the project"
     typer.echo(f"Found {len(changes)} commits {since}.")
 
diff --git a/src/rooster/_git.py b/src/rooster/_git.py
index 597bb88..66bc54e 100644
--- a/src/rooster/_git.py
+++ b/src/rooster/_git.py
@@ -29,12 +29,13 @@ def get_commits_between(
     target: Path,
     first_version: Version | None = None,
     second_version: Version | None = None,
+    force_first_commit: str | None = None,
 ) -> Generator[git.Commit, None, None]:
     """
     Yield all commits between two tags
     """
     repo = git.repository.Repository(target.absolute())
-    first_commit = (
+    first_commit = force_first_commit or (
         repo.lookup_reference(
             TAG_PREFIX + config.version_tag_prefix + str(first_version)
         )
```
2024-06-24 10:04:09 -05:00
Zanie Blue 64e07b68a8
Reapply "Bump version to 0.2.14" (#4472)
Restores #4431

This reverts commit 9ff6a5ed74 (#4436)
2024-06-24 09:14:16 -05:00
Charlie Marsh 1eee427c94
Add standalone CLI crate (#4456)
## Summary

This PR moves all the CLI code into its own crate, separate from the
`uv` crate. The `uv` crate is iterated on frequently, and the CLI code
comprises a significant portion of it but rarely changes. Removing the
CLI code reduces the `uv` crate size from 1.4MiB to 1.0MiB.
2024-06-24 06:16:22 -04:00
renovate[bot] 3251690327
Update Rust crate rustc-hash to v2 (#4461) 2024-06-24 01:13:05 +00:00
renovate[bot] cdba918453
Update Rust crate syn to v2.0.68 (#4459) 2024-06-24 00:10:32 +00:00
renovate[bot] 5c7576abc2
Update Rust crate cargo-util to v0.2.12 (#4457) 2024-06-24 00:08:14 +00:00
renovate[bot] 628e5112e8
Update Rust crate mimalloc to v0.1.43 (#4458) 2024-06-24 00:07:52 +00:00
samypr100 2288ff7bf4
feat: pythonw support on gui scripts (#4409)
## Summary

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

This changes the bootstrap launcher script to use `pythonw.exe` instead
of `python.exe` on `gui_scripts` via a helper fn both in the shebang and
the python exe path encoded before `UVUV` magic, that way
uv-trampoline's `find_python_exe` can use the right pythonw executable.

## Test Plan

New unit tests for the helper was added.
Tested on example from #2956 on Windows to make sure it works as
expected.

## Questions

I noticed the docs in `fn windows_script_launcher` says ```The launcher
will look for `python[w].exe` adjacent to it in the same directory to
start the embedded script.``` but I didn't find such functionality when
I looked in uv-trampoline.
I only saw `clear_app_starting_state` getting called when `is_gui` is
set.

Was the intention to do this in uv-trampoline at some point instead?

---------

Co-authored-by: konstin <konstin@mailbox.org>
2024-06-23 09:48:47 +00:00
renovate[bot] 895f202b77
Update Rust crate url to v2.5.2 (#4351) 2024-06-22 09:28:58 -05:00
Zanie Blue 9ff6a5ed74
Revert "Bump version to 0.2.14 (#4431)" (#4436)
This reverts commit e0ad649c74.

We shouldn't be linking to this version in the readme.

See https://github.com/astral-sh/uv/issues/4432
2024-06-21 16:24:32 +00:00
Zanie Blue e0ad649c74
Bump version to 0.2.14 (#4431) 2024-06-20 13:58:10 -05:00
Zanie Blue 93c6e0df56
Expose `toolchain-preference` as a CLI and configuration file option (#4424)
Exposes the option added in #4416. Adds `--toolchain-preference` and
`tool.uv.toolchain-preference` to configure if system or managed
toolchains are preferred. Users can opt-out of managed toolchains or
system toolchains entirely as well.
2024-06-20 13:42:09 -05:00
Ibraheem Ahmed e797d3eb5c
Pin benchmark requirements (#4429)
## Summary

This should make benchmarks more consistent.
2024-06-20 14:13:38 -04:00
konsti 3c5b13695e
Move adding dependencies for versions into dedicated method (#4410)
To support diverging urls, we have to check urls when adding
dependencies (after forking). To prepare for this, i've moved adding
dependencies for the current version to
`SolveState::add_package_version_dependencies` and removed the
duplication when checking for self-dependencies.

This changed is joined with a change in pubgrub
(https://github.com/astral-sh/pubgrub/pull/27) that simplifies the same
code path.
2024-06-19 20:19:12 +02:00
Zanie Blue fa6ed34105
Bump version to 0.2.13 (#4388) 2024-06-18 11:46:32 -05:00
Zanie Blue b8c0391667
Bump version to 0.2.12 (#4371) 2024-06-17 16:46:28 -05:00
Zanie Blue 631994c485
Remove `cargo dev fetch-python` (#4337)
This has been fully replaced by `uv toolchain install`
2024-06-17 18:49:06 +00:00
Zanie Blue fdcdc2cbe6
Allow multiple toolchains to be requested in `uv toolchain install` (#4334)
Allows installation of multiple toolchains in a single invocation
because I don't want to be limited to one! Most of the implementation
for concurrent downloads ported from `cargo dev fetch-python`.
2024-06-17 18:24:11 +00:00
renovate[bot] 4db6b902eb
Update Rust crate reqwest to v0.12.5 (#4363) 2024-06-17 13:18:46 -05:00
renovate[bot] 147aec4d37
Update Rust crate configparser to v3.1.0 (#4353) 2024-06-17 05:40:51 -05:00
renovate[bot] e0b5b0b84a
Update Rust crate reflink-copy to v0.1.18 (#4350) 2024-06-17 00:03:12 -05:00
renovate[bot] df04fdf33d
Update Rust crate http-body-util to v0.1.2 (#4349) 2024-06-17 00:02:07 -05:00
renovate[bot] b044606126
Update Rust crate clap to v4.5.7 (#4348) 2024-06-17 00:01:40 -05:00
renovate[bot] aaeb8b9856
Update Rust crate axoupdater to v0.6.6 (#4347) 2024-06-17 00:01:29 -05:00
Charlie Marsh b7fb0b445f
Use portable slash paths in lockfile (#4324)
## Summary

This would be a lightweight solution to
https://github.com/astral-sh/uv/issues/4307 that doesn't fully engage
with all the possibilities in the design space (but would unblock
cross-platform for now).
2024-06-14 09:05:14 -04:00
Charlie Marsh 74c05683bb
Add a derive macro for `Combine` (#4325)
## Summary

Saves us some boilerplate when adding settings in the future.
2024-06-14 04:53:27 +00:00
Charlie Marsh cacd1a2b5a
Load configuration options from workspace root (#4295)
## Summary

In a workspace, we now read configuration from the workspace root.
Previously, we read configuration from the first `pyproject.toml` or
`uv.toml` file in path -- but in a workspace, that would often be the
_project_ rather than the workspace configuration.

We need to read configuration from the workspace root, rather than its
members, because we lock the workspace globally, so all configuration
applies to the workspace globally.

As part of this change, the `uv-workspace` crate has been renamed to
`uv-settings` and its purpose has been narrowed significantly (it no
longer discovers a workspace; instead, it just reads the settings from a
directory).

If a user has a `uv.toml` in their directory or in a parent directory
but is _not_ in a workspace, we will still respect that use-case as
before.

Closes #4249.
2024-06-14 01:26:20 +00:00
Zanie Blue f7f55ede2f
Refactor `uv-toolchain::platform` to use `target-lexicon` (#4236)
Closes https://github.com/astral-sh/uv/issues/3857

Instead of using custom `Arch`, `Os`, and `Libc` types I just use
`target-lexicon`'s which enumerate way more variants and implement
display and parsing. We use a wrapper type to represent a couple special
cases to support the "x86" alias for "i686" and "macos" for "darwin".
Alternatively we could try to use our `platform-tags` types but those
capture more information (like operating system versions) that we don't
have for downloads.

As discussed in https://github.com/astral-sh/uv/pull/4160, this is not
sufficient for proper libc detection but that work is larger and will be
handled separately.
2024-06-12 09:11:56 -05:00
Charlie Marsh 44041bccd2
Bump version to v0.2.11 (#4258) 2024-06-11 20:47:25 -04:00
Charlie Marsh 6dae1920af
Make missing `METADATA` file a recoverable error (#4247)
## Summary

I don't have a great way to test it, but this makes the error described
in https://github.com/astral-sh/uv/issues/4246 an incompatibility rather
than a fatal error.

Closes https://github.com/astral-sh/uv/issues/4246.
2024-06-11 19:49:38 +00:00
Ibraheem Ahmed eefa9e62fc
Initial implementation of `uv add` and `uv remove` (#4193)
## Summary

Basic implementation of `uv add` and `uv remove` that supports writing
PEP508 requirements to `project.dependencies`.

First step for https://github.com/astral-sh/uv/issues/3959 and
https://github.com/astral-sh/uv/issues/3960.
2024-06-11 09:21:28 -04:00
Charlie Marsh 10e0abc9b1
Create temporary environments in dedicated cache bucket (#4223)
## Summary

We may choose to persist these eventually, but for now, it's useful to
have them colocated with the cache, and in their own dedicated bucket
(so, at the very least, we can keep track of the use-cases).

Closes https://github.com/astral-sh/uv/issues/4219.
2024-06-10 23:17:35 +00:00
Zanie Blue 907727cb1b
Bump version to 0.2.10 (#4201) 2024-06-10 11:40:19 -05:00
Zanie Blue 45df889fe4
Implement `Toolchain::find_or_fetch` and use in `uv venv --preview` (#4138)
Extends https://github.com/astral-sh/uv/pull/4121
Part of #2607 

Adds support for managed toolchain fetching to `uv venv`, e.g.

```
❯ cargo run -q -- venv --python 3.9.18 --preview -v
DEBUG Searching for Python 3.9.18 in search path or managed toolchains
DEBUG Searching for managed toolchains at `/Users/zb/Library/Application Support/uv/toolchains`
DEBUG Found CPython 3.12.3 at `/opt/homebrew/bin/python3` (search path)
DEBUG Found CPython 3.9.6 at `/usr/bin/python3` (search path)
DEBUG Found CPython 3.12.3 at `/opt/homebrew/bin/python3` (search path)
DEBUG Requested Python not found, checking for available download...
DEBUG Using registry request timeout of 30s
INFO Fetching requested toolchain...
DEBUG Downloading https://github.com/indygreg/python-build-standalone/releases/download/20240224/cpython-3.9.18%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst to temporary location /Users/zb/Library/Application Support/uv/toolchains/.tmpgohKwp
DEBUG Extracting cpython-3.9.18%2B20240224-aarch64-apple-darwin-pgo%2Blto-full.tar.zst
DEBUG Moving /Users/zb/Library/Application Support/uv/toolchains/.tmpgohKwp/python to /Users/zb/Library/Application Support/uv/toolchains/cpython-3.9.18-macos-aarch64-none
Using Python 3.9.18 interpreter at: /Users/zb/Library/Application Support/uv/toolchains/cpython-3.9.18-macos-aarch64-none/install/bin/python3
Creating virtualenv at: .venv
INFO Removing existing directory
Activate with: source .venv/bin/activate
```

The preview flag is required. The fetch is performed if we can't find an
interpreter that satisfies the request. Once fetched, the toolchain will
be available for later invocations that include the `--preview` flag.
There will be follow-ups to improve toolchain management in general,
there is still outstanding work from the initial implementation.
2024-06-10 14:10:45 +00:00
renovate[bot] 5e620e4cb5
Update Rust crate unicode-width to v0.1.13 (#4179) 2024-06-09 20:33:16 -04:00
renovate[bot] c41de1954a
Update Rust crate regex to v1.10.5 (#4178) 2024-06-09 20:33:01 -04:00
renovate[bot] e6efb0d96b
Update Rust crate clap to v4.5.6 (#4177) 2024-06-09 20:32:52 -04:00
Charlie Marsh 72859d8f9b
Move PEP 440 and PEP 508 parsing out of TOML deserialization (#4176)
## Summary

If we want more granular control over how these errors are handled, then
we need to move them out of the TOML deserialization.

No actual behavior changes here.

Part of https://github.com/astral-sh/uv/issues/4142.
2024-06-10 00:09:39 +00:00
Zanie Blue 325982c418
Rename `uv-interpreter` crate to `uv-toolchain` (#4120)
In preparation for managed toolchains #2607, just renames the crate to
something broader.

See #4121 and https://github.com/astral-sh/uv/pull/4138 to see the final
intent.
2024-06-07 13:59:14 -05:00
Charlie Marsh cc7c780523
Remove PubGrub dependency from `uv` (#4116)
## Summary

Encapsulates more of the details are `Requires-Python` and PubGrub.

Closes https://github.com/astral-sh/uv/issues/4110.
2024-06-06 23:45:58 +00:00
konsti e4e2590076
Use union of `requires-python` in workspace (#4041)
Follow-up to #4016.

This exposes `Range` and `PubGrubSpecifier` from outside the resolver to
use pubgrub's union creating a dependency edge we don't really want.
2024-06-06 19:21:02 +00:00
konsti a6f53e2aa4
Lock all packages in workspace (#4016)
When creating a lockfile, lock the combined dependencies for all
packages in a workspace. This make the lockfile independent of where you
are in the workspace.

Fixes #3983
2024-06-06 19:09:44 +00:00
Charlie Marsh e9fc99e622
Bump version to v0.2.9 (#4107) 2024-06-06 14:21:33 -04:00
Charlie Marsh 120148f0a1
Remove integration tests from `uv-resolver` (#4083)
## Summary

I don't think it's worth maintaining this separate test harness for ~18
tests, when they can all be tested in the `uv` package itself. Let's
drop the maintenance burden.
2024-06-06 01:48:42 +00:00
Charlie Marsh 0acae9bd9c
Add support for development dependencies (#4036)
## Summary

Externally, development dependencies are currently structured as a flat
list of PEP 580-compatible requirements:

```toml
[tool.uv]
dev-dependencies = ["werkzeug"]
```

When locking, we lock all development dependencies; when syncing, users
can provide `--dev`.

Internally, though, we model them as dependency groups, similar to
Poetry, PDM, and [PEP 735](https://peps.python.org/pep-0735). This
enables us to change out the user-facing frontend without changing the
internal implementation, once we've decided how these should be exposed
to users.

A few important decisions encoded in the implementation (which we can
change later):

1. Groups are enabled globally, for all dependencies. This differs from
extras, which are enabled on a per-requirement basis. Note, however,
that we'll only discover groups for uv-enabled packages anyway.
2. Installing a group requires installing the base package. We rely on
this in PubGrub to ensure that we resolve to the same version (even
though we only expect groups to come from workspace dependencies anyway,
which are unique). But anyway, that's encoded in the resolver right now,
just as it is for extras.
2024-06-06 01:40:17 +00:00
Zanie Blue e48b9cd94b
Bump version to 0.2.8 (#4076) 2024-06-05 21:09:05 +00:00
konsti 8596525d97
Update pubgrub to new `add_incompatibility_from_dependencies` (#4062)
We had previously changed the signature of
`DependencyProvider::get_dependencies` to return an iterator instead of
a hashmap to avoid the conversion cost from our dependencies `Vec` to
the pubgrub's hashmap. These changes are difficult to make in pubgrub
since they complicate the public api. But we don't actually use
`DependencyProvider::get_dependencies`, so we rolled those
customizations back in https://github.com/pubgrub-rs/pubgrub/pull/226
and instead opted to change only the internal
`add_incompatibility_from_dependencies` method that we exposed in our
fork. This aligns us closer with upstream, removes the design questions
about `DependencyProvider` from our concerns and reduces our diff (not
counting the github action) to +36 -12.
2024-06-05 20:46:00 +02:00
Charlie Marsh a241f148de
Bump version to v0.2.7 (#4060) 2024-06-05 14:25:25 -04:00
Charlie Marsh 6afb659c9a
Respect `Requires-Python` in universal resolution (#3998)
## Summary

Closes #3982.
2024-06-04 13:56:08 +00:00
konsti 63c84ed4a6
Log transient network request failures (#3933)
We retry several kinds of network request failures, but it's often
unclear whether a request was retried or not
(https://github.com/astral-sh/uv/issues/3514#issuecomment-2105485773).
This PR adds a small intermediary layer that logs all transient request
failures, adding the `DEBUG Transient request failure` lines:

```
DEBUG Searching for Python interpreter in virtual environments
DEBUG Found CPython 3.12.3 at `/home/konsti/projects/uv/.venv/bin/python3` (active virtual environment)
DEBUG Using Python 3.12.3 environment at .venv/bin/python3
DEBUG Acquired lock for `.venv`
DEBUG At least one requirement is not satisfied: tqdm
DEBUG Using registry request timeout of 30s
DEBUG Solving with target Python version 3.12.3
DEBUG Adding direct dependency: tqdm*
DEBUG No cache entry for: https://pypi.org/simple/tqdm/
DEBUG Transient request failure for https://pypi.org/simple/tqdm/, retrying: Request error: error sending request for url (https://pypi.org/simple/tqdm/)
  Caused by: error sending request for url (https://pypi.org/simple/tqdm/)
  Caused by: client error (Connect)
  Caused by: dns error: failed to lookup address information: Name or service not known
  Caused by: failed to lookup address information: Name or service not known
DEBUG Transient request failure for https://pypi.org/simple/tqdm/, retrying: Request error: error sending request for url (https://pypi.org/simple/tqdm/)
  Caused by: error sending request for url (https://pypi.org/simple/tqdm/)
  Caused by: client error (Connect)
  Caused by: dns error: failed to lookup address information: Name or service not known
  Caused by: failed to lookup address information: Name or service not known
DEBUG Transient request failure for https://pypi.org/simple/tqdm/, retrying: Request error: error sending request for url (https://pypi.org/simple/tqdm/)
  Caused by: error sending request for url (https://pypi.org/simple/tqdm/)
  Caused by: client error (Connect)
  Caused by: dns error: failed to lookup address information: Name or service not known
  Caused by: failed to lookup address information: Name or service not known
DEBUG Transient request failure for https://pypi.org/simple/tqdm/, retrying: Request error: error sending request for url (https://pypi.org/simple/tqdm/)
  Caused by: error sending request for url (https://pypi.org/simple/tqdm/)
  Caused by: client error (Connect)
  Caused by: dns error: failed to lookup address information: Name or service not known
  Caused by: failed to lookup address information: Name or service not known
error: Could not connect, are you offline?
  Caused by: error sending request for url (https://pypi.org/simple/tqdm/)
  Caused by: client error (Connect)
  Caused by: dns error: failed to lookup address information: Name or service not known
  Caused by: failed to lookup address information: Name or service not known
```

I decided for multi-line logging to show the complete error trace since
only `Transient request failure for https://pypi.org/simple/tqdm/,
retrying: Request error: error sending request for url
(https://pypi.org/simple/tqdm/)` doesn't tell you the actual problem (a
dns error).

Note that running with `-v` will not show messages about retry backoff
timing, but running with `RUST_LOG=debug` now shows a complete picture:

```
DEBUG starting new connection: https://pypi.org/
DEBUG resolving host="pypi.org"
DEBUG Transient request failure for https://pypi.org/simple/tqdm/, retrying: Request error: error sending request for url (https://pypi.org/simple/tqdm/)
  Caused by: error sending request for url (https://pypi.org/simple/tqdm/)
  Caused by: client error (Connect)
  Caused by: dns error: failed to lookup address information: Name or service not known
  Caused by: failed to lookup address information: Name or service not known
WARN Retry attempt #2. Sleeping 528.728192ms before the next attempt
```

Fixes #3572
2024-06-04 15:39:16 +02:00
konsti da7d5549a3
Don't copy gitignored files in workspace tests (#4012)
The workspace test directories can be used both in tests and directly
for developing/debugging. In the latter, we shouldn't copy the venv and
the lockfile when running tests. Using the ignore crate over manual
recursion we exclude those files.
2024-06-04 12:58:07 +00:00
Charlie Marsh 40e0dddd00
Run `cargo update` (#4005) 2024-06-04 01:05:45 +00:00
Charlie Marsh a589ad5066
Bump version to v0.2.6 (#3991) 2024-06-03 17:40:28 +00:00
konsti 8c3a8bf026
Update pubgrub to d4795a31be17669aba11eb741b4a9086acc3eb11 (#3988)
I trimmed down the diff of our pubgrub fork with upstream and
[d4795a31be17669aba11eb741b4a9086acc3eb11](d4795a31be)
(diff:
https://github.com/pubgrub-rs/pubgrub/compare/dev...astral-sh:pubgrub:perma-35)
is the result.
2024-06-03 15:33:34 +00:00
Di-Is 5c776939d2
Add override namespace to pyproject.toml/uv.toml (#3839)
<!--
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

See #3834 .

This PR adds a new namespace, `override-dependencies`, to
pyproject.toml/uv.toml.
This namespace assumes that the dependencies you want to override are
written in the form of `requirements.txt`.


a example of pyproject.toml
```toml
[project]
name = "example"
version = "0.0.0"
dependencies = [
  "flask==3.0.0"
]

[tool.uv]
override-dependencies = [
  "werkzeug==2.3.0"
]
```

This will improve usability by allowing you to override dependencies
without having to specify the --override option when running `uv pip
compile/install`.

## Test Plan

added test to `crates/uv/tests/pip_compile.rs`.

---------

Co-authored-by: konstin <konstin@mailbox.org>
2024-06-03 12:15:51 +02:00
renovate[bot] 314cdbb15b
Update Rust crate axoupdater to v0.6.5 (#3972) 2024-06-02 21:52:35 -04:00
renovate[bot] 95d9bb5ee7
Update Rust crate tokio to v1.38.0 (#3976) 2024-06-03 01:51:39 +00:00
renovate[bot] e4a9366586
Update Rust crate async-compression to v0.4.11 (#3971) 2024-06-02 21:45:41 -04:00
renovate[bot] 0addc10fca
Update Rust crate hyper-util to v0.1.5 (#3973) 2024-06-03 01:45:29 +00:00
konsti 01d1a39c21
Add `uv run --package` (#3864)
Add a `--package` option that allows switching the current project in
the workspace. Wherever you are in a workspace, you should be able to
run with any other project as root. This is the uv equivalent of `cargo
run -p`.

I don't love the `--package` name, esp. since `-p` is already taken and
in general to many things start with p already.

Part of this change is moving the workspace discovery of
`ProjectWorkspace` to `Workspace` itself.

## Usage

In albatross-virtual-workspace:

```console
$ uv venv
$ uv run --preview --package bird-feeder python -c "import albatross"
   Built file:///home/konsti/projects/uv/scripts/workspaces/albatross-virtual-workspace/packages/bird-feeder
   Built file:///home/konsti/projects/uv/scripts/workspaces/albatross-virtual-workspace/packages/seeds
Built 2 editables in 167ms
Resolved 5 packages in 4ms
Installed 5 packages in 1ms
 + anyio==4.4.0
 + bird-feeder==1.0.0 (from file:///home/konsti/projects/uv/scripts/workspaces/albatross-virtual-workspace/packages/bird-feeder)
 + idna==3.6
 + seeds==1.0.0 (from file:///home/konsti/projects/uv/scripts/workspaces/albatross-virtual-workspace/packages/seeds)
 + sniffio==1.3.1
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'albatross'
$ uv venv
$ uv run --preview --package albatross python -c "import albatross"
   Built file:///home/konsti/projects/uv/scripts/workspaces/albatross-virtual-workspace/packages/albatross
   Built file:///home/konsti/projects/uv/scripts/workspaces/albatross-virtual-workspace/packages/bird-feeder
   Built file:///home/konsti/projects/uv/scripts/workspaces/albatross-virtual-workspace/packages/seeds
Built 3 editables in 173ms
Resolved 7 packages in 6ms
Installed 7 packages in 1ms
 + albatross==0.1.0 (from file:///home/konsti/projects/uv/scripts/workspaces/albatross-virtual-workspace/packages/albatross)
 + anyio==4.4.0
 + bird-feeder==1.0.0 (from file:///home/konsti/projects/uv/scripts/workspaces/albatross-virtual-workspace/packages/bird-feeder)
 + idna==3.6
 + seeds==1.0.0 (from file:///home/konsti/projects/uv/scripts/workspaces/albatross-virtual-workspace/packages/seeds)
 + sniffio==1.3.1
 + tqdm==4.66.4
```

In albatross-root-workspace:

```console
$ uv venv
$ uv run --preview --package bird-feeder python -c "import albatross"
  Using Python 3.12.3 interpreter at: /home/konsti/.local/bin/python3
  Creating virtualenv at: .venv
  Activate with: source .venv/bin/activate
      Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.10s
       Running `/home/konsti/projects/uv/target/debug/uv run --preview --package bird-feeder python -c 'import albatross'`
     Built file:///home/konsti/projects/uv/scripts/workspaces/albatross-root-workspace/packages/bird-feeder
     Built file:///home/konsti/projects/uv/scripts/workspaces/albatross-root-workspace/packages/seeds                                              Built 2 editables in 161ms
  Resolved 5 packages in 4ms
  Installed 5 packages in 1ms
   + anyio==4.4.0
   + bird-feeder==1.0.0 (from file:///home/konsti/projects/uv/scripts/workspaces/albatross-root-workspace/packages/bird-feeder)
   + idna==3.6
   + seeds==1.0.0 (from file:///home/konsti/projects/uv/scripts/workspaces/albatross-root-workspace/packages/seeds)
   + sniffio==1.3.1
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
  ModuleNotFoundError: No module named 'albatross'
$ uv venv
$ cargo run run --preview --package albatross python -c "import albatross"
Using Python 3.12.3 interpreter at: /home/konsti/.local/bin/python3
Creating virtualenv at: .venv
Activate with: source .venv/bin/activate
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.13s
     Running `/home/konsti/projects/uv/target/debug/uv run --preview --package albatross python -c 'import albatross'`
   Built file:///home/konsti/projects/uv/scripts/workspaces/albatross-root-workspace
   Built file:///home/konsti/projects/uv/scripts/workspaces/albatross-root-workspace/packages/bird-feeder
   Built file:///home/konsti/projects/uv/scripts/workspaces/albatross-root-workspace/packages/seeds
Built 3 editables in 168ms
Resolved 7 packages in 5ms
Installed 7 packages in 1ms
 + albatross==0.1.0 (from file:///home/konsti/projects/uv/scripts/workspaces/albatross-root-workspace)
 + anyio==4.4.0
 + bird-feeder==1.0.0 (from file:///home/konsti/projects/uv/scripts/workspaces/albatross-root-workspace/packages/bird-feeder)
 + idna==3.6
 + seeds==1.0.0 (from file:///home/konsti/projects/uv/scripts/workspaces/albatross-root-workspace/packages/seeds)
 + sniffio==1.3.1
 + tqdm==4.66.4
```
2024-06-02 21:42:14 +00:00
Charlie Marsh b7d77c04cc
Add Git resolver in lieu of static hash map (#3954)
## Summary

This PR removes the static resolver map:

```rust
static RESOLVED_GIT_REFS: Lazy<Mutex<FxHashMap<RepositoryReference, GitSha>>> =
    Lazy::new(Mutex::default);
```

With a `GitResolver` struct that we now pass around on the
`BuildContext`. There should be no behavior changes here; it's purely an
internal refactor with an eye towards making it cleaner for us to
"pre-populate" the list of resolved SHAs.
2024-05-31 22:44:42 -04:00
Charlie Marsh 7b7da803bb
Unify editable and unnamed URL parsing (#3946)
## Summary

This will help prevent bugs like #3934 by unifying the implementations
for editables and non-editable unnamed requirements. Specifically, both
of these now go through the same parsing paths and use the same struct
representations (with the exception that the editable flag is flipped in
the first case):

```
-e ./foo/bar
./foo/bar
```

We also now support PEP 508 in editable URLs. It turns out this is just
a limitation in pip, so it's correct to support it. For example, this
now works:

```
-e black[d] @ file://${PROJECT_ROOT}/scripts/packages/black_editable
```

Closes #3941.

Closes #3942.
2024-05-31 21:08:00 +00:00
konsti 3c074142f5
Re-add lowering unit tests (#3935)
Re-add the lowering unit tests removed in #3904. This also adds a
`stop_discovery_at` feature to avoid running actual workspace discovery.
2024-05-31 12:17:49 +00:00
konsti 081f20c53e
Add support for `tool.uv` into distribution building (#3904)
With the change, we remove the special casing of workspace dependencies
and resolve `tool.uv` for all git and directory distributions. This
gives us support for non-editable workspace dependencies and path
dependencies in other workspaces. It removes a lot of special casing
around workspaces. These changes are the groundwork for supporting
`tool.uv` with dynamic metadata.

The basis for this change is moving `Requirement` from
`distribution-types` to `pypi-types` and the lowering logic from
`uv-requirements` to `uv-distribution`. This changes should be split out
in separate PRs.

I've included an example workspace `albatross-root-workspace2` where
`bird-feeder` depends on `a` from another workspace `ab`. There's a
bunch of failing tests and regressed error messages that still need
fixing. It does fix the audited package count for the workspace tests.
2024-05-31 02:42:03 +00:00
Charlie Marsh a14fe2f6c7
Avoid filtering preferences by `--reinstall` (#3929)
## Summary

In general, it's not quite right to filter preferences by `--reinstall`
-- we still want to respect existing versions, we just don't want to
respect _installed_ versions. But now that the installed versions and
preferences are decoupled, we can remove this (`--reinstall` is enforced
on the installed versions via the `Exclusions` struct that we pass to
the resolver).

While I was here, I also cleaned up the lockfile preference code to
better match the structure for `requirements.txt`.
2024-05-30 20:19:08 +00:00
Ibraheem Ahmed 261aa2c70a
Port all git functionality to use git CLI (#3833)
## Summary

We currently rely on libgit2 for most git-related functionality.
However, libgit2 has long-standing performance issues, as well as lags
significantly behind git in terms of new features. For these reasons we
now use the git CLI by default for fetching repositories
(https://github.com/astral-sh/uv/pull/1781). This PR completely drops
libgit2 in favor of the git CLI for all git-related functionality, which
should allow us to use features such as partial clones and sparse
checkouts in the future for performance.

There is also a lot of technical debt in the current git code as it's
mostly taken from Cargo. Switching to the git CLI *vastly* simplifies
the `uv-git` codebase.

Eventually we might want to look into switching to
[`gitoxide`](https://github.com/Byron/gitoxide), but it's currently too
immature for our use case.
2024-05-30 15:28:48 -04:00
Ibraheem Ahmed 85183c1c36
Custom lock-file serialization (#3909)
## Summary

This PR changes the lock-file format to use inline tables for wheels and
source distributions, which currently use separate tables that make the
file harder to follow.

```diff
[[distribution]]
name = "typing-extensions"
version = "4.10.0"
source = "registry+https://pypi.org/simple"

- [distribution.sdist]
- url = "0d26ce356c7c323176620b7b483e44/typing_extensions-4.10.0.tar.gz"
- hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"
- size = 77558
-
- [[distribution.wheel]]
- url = "dc04a3ea60b9bc8074b5d6b7ab90bb/typing_extensions-4.10.0-py3-none-any.whl"
- hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"
- size = 33926

+ sdist = { url = "0d26ce356c7c323176620b7b483e44/typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb", size = 77558 }
+ wheel = [{ url = "dc04a3ea60b9bc8074b5d6b7ab90bb/typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475", size = 33926 }]
```

The downside is that the inline-tables end up quite long and TOML
doesn't support line breaks in inline tables, yet.

Part of https://github.com/astral-sh/uv/issues/3611.
2024-05-30 19:08:29 +00:00
Charlie Marsh 47db418ba2
Bump version to v0.2.5 (#3885) 2024-05-28 18:05:32 +00:00
Charlie Marsh 1fc6a59707
Remove special-casing for editable requirements (#3869)
## Summary

There are a few behavior changes in here:

- We now enforce `--require-hashes` for editables, like pip. So if you
use `--require-hashes` with an editable requirement, we'll reject it. I
could change this if it seems off.
- We now treat source tree requirements, editable or not (e.g., both `-e
./black` and `./black`) as if `--refresh` is always enabled. This
doesn't mean that we _always_ rebuild them; but if you pass
`--reinstall`, then yes, we always rebuild them. I think this is an
improvement and is close to how editables work today.

Closes #3844.

Closes #2695.
2024-05-28 15:49:34 +00:00
konsti a89e146107
Initial workspace support (#3705)
Add workspace support when using `-r <path>/pyproject.toml` or `-e
<path>` in the pip interface. It is limited to all-editable
static-metadata workspaces, and tests only include a single main
workspace, ignoring path dependencies in another workspace. This can be
considered the MVP for workspace support: You can create a workspace,
you can install from it, but some options and conveniences are still
missing. I'll file follow-up tickets (support in lockfiles, support path
deps in other workspace, #3625)

There is also support in `uv run`, but we need
https://github.com/astral-sh/uv/issues/3700 first to properly support
using different current projects in the bluejay interface, currently the
resolution and therefore the lockfile depends on the current project.
I'd do this change first (it's big enough already), then #3700, and then
add workspace support properly to bluejay.

Fixes #3404
2024-05-28 07:41:53 +00:00
Tim de Jager 65b17f6e81
feat: bump pep580 and pep440 types (#3860)
This bumps the versions of pep580 and pep440 to coincide with the
crates.io versions. While not strictly the same, the new types in uv us
an `Inner` struct. Practically I've found I'm still able to use the
patched versions, as can seen from the open PR here:
https://github.com/prefix-dev/pixi/pull/1436.

Would be great if this bump can be done so we can keep combining the
types :)
2024-05-27 09:38:39 +02:00
Zanie Blue 31b0ff6373
Gate discovery of managed toolchains with preview (#3835)
Prepares for merge of https://github.com/astral-sh/uv/pull/3797, gating
managed toolchain discovery with the preview flag to lower risk of
releasing.

e.g.

```
❯ cargo dev -q fetch-python         
❯ cargo run -q -- venv --python 3.11
Using Python 3.11.9 interpreter at: /opt/homebrew/opt/python@3.11/bin/python3.11
Creating virtualenv at: .venv
Activate with: source .venv/bin/activate
❯ cargo run -q -- venv --preview --python 3.11
Using Python 3.11.7 interpreter at: /Users/zb/Library/Application Support/uv/toolchains/cpython-3.11.7-macos-aarch64-none/install/bin/python3
Creating virtualenv at: .venv
Activate with: source .venv/bin/activate
```

We'll add automatic fetching of managed interpreters later.
2024-05-27 04:05:19 +00:00
Zanie Blue 30e780e1dd
Add persistent storage of installed toolchains (#3797)
Extends #3726 

Moves toolchain storage out of `UV_BOOTSTRAP_DIR` (`./bin`) into the
proper user data directory as defined by #3726.

Replaces `UV_BOOTSTRAP_DIR` with `UV_TOOLCHAIN_DIR` for customization.
Installed toolchains will be discovered without opt-in, but the idea is
still that these are not yet user-facing.
2024-05-27 03:54:49 +00:00
renovate[bot] 89daa58458
Update Rust crate hyper-util to v0.1.4 (#3847) 2024-05-27 01:25:23 +00:00
renovate[bot] e2971a7a4b
Update Rust crate tracing-tree to v0.3.1 (#3851) 2024-05-27 00:58:06 +00:00
renovate[bot] 3416f4247f
Update Rust crate serde to v1.0.203 (#3850) 2024-05-27 00:57:45 +00:00
renovate[bot] 2aba5867e7
Update Rust crate schemars to v0.8.21 (#3849) 2024-05-27 00:56:04 +00:00
renovate[bot] 57bb7a9507
Update Rust crate mimalloc to v0.1.42 (#3848) 2024-05-27 00:54:38 +00:00
Zanie Blue 98652e3954
Bump version to 0.2.4 (#3840) 2024-05-26 12:11:15 -05:00
Charlie Marsh 6682765630
Require pinned version in `Preference` type (#3828)
## Summary

This PR makes a variety of invalid states unrepresentable by changing
`Preference` to require a `PackageName` and `Version`, rather than
accepting a generic `Requirement`. There should be no meaningful
behavior changes.
2024-05-24 18:48:36 +00:00
Zanie Blue ce4d862b06
Bump version to 0.2.3 (#3827) 2024-05-24 13:19:28 -05:00
Charlie Marsh 8d566e553d
Use a cross-platform representation for relative paths in `pip compile` (#3804)
## Summary

I haven't tested on Windows yet, but the idea here is that we should use
a portable representation when printing paths.

I decided to limit the scope here to paths that we write to output
files.

Closes https://github.com/astral-sh/uv/issues/3800.
2024-05-24 03:02:42 +00:00
Charlie Marsh ce38fccdc9
Remove `tracing-indicatif` dependency (#3816)
## Summary

It's only used in `uv-dev`; can restore later if important.
2024-05-24 02:59:26 +00:00
konsti 4db468e27f
Use `VerbatimParsedUrl` in `pep508_rs` (#3758)
When parsing requirements from any source, directly parse the url parts
(and reject unsupported urls) instead of parsing url parts at a later
stage. This removes a bunch of error branches and concludes the work
parsing url parts once and passing them around everywhere.

Many usages of the assembled `VerbatimUrl` remain, but these can be
removed incrementally.

Please review commit-by-commit.
2024-05-23 19:52:47 +00:00
Ibraheem Ahmed 0d2f3fc4e4
Add airflow benchmark (#3643)
## Summary

This seems to be one of the most consistent benchmark cases we have in
terms of standard deviation:
```
➜  hyperfine "target/profiling/main pip compile scripts/requirements/airflow.in" --runs 200
Benchmark 1: target/profiling/main pip compile scripts/requirements/airflow.in
  Time (mean ± σ):     292.6 ms ±   6.6 ms    [User: 414.1 ms, System: 194.2 ms]
  Range (min … max):   282.7 ms … 320.1 ms    200 runs
```

For smaller benchmarks, scispacy and dtlssocket seem to be a bit more
consistent than our current jupyter benchmark, but it hasn't given us
any problems so I'll leave it for now.
2024-05-23 13:25:54 -04:00
Zanie Blue e52ae0e2bc
Bump version to 0.2.2 (#3774) 2024-05-22 21:45:00 +00:00
Charlie Marsh 74c494d7dd
Report yanks for cached and resolved packages (#3772)
## Summary

We now show yanks as part of the resolution diagnostics, so they now
appear for `sync`, `install`, `compile`, and any other operations.
Further, they'll also appear for cached packages (but not packages that
are _already_ installed).

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

Closes #3766.
2024-05-22 21:21:37 +00:00
Charlie Marsh 1fc71ea736
Bump version to v0.2.1 (#3763) 2024-05-22 20:05:17 +00:00
Charlie Marsh fe28b2c278
Remove unused methods from `Resolution` (#3754) 2024-05-22 18:48:44 +00:00
Zanie Blue 1dd6b89be8
Bump version to 0.2.0 (#3745) 2024-05-22 13:39:34 -05:00
Zanie Blue d540d0f28b
Rewrite Python interpreter discovery (#3266)
Updates our Python interpreter discovery to conform to the rules
described in #2386, please see that issue for a full description of the
behavior. Briefly, we now will search for interpreters that satisfy a
requested version without stopping at the first Python executable.
Additionally, if retrieving information about an interpreter fails we
will continue to search for a working interpreter. We also add the
plumbing necessary to request Python implementations other than CPython,
though we do not add support for other implementations at this time.

A major internal goal of this work is to prepare for user-facing managed
toolchains i.e. fetching a requested version during `uv run`. These APIs
are not introduced, but there is some managed toolchain handling as
required for our test suite.

Some noteworthy implementation changes:

- The `uv_interpreter::find_python` module has been removed in favor of
a `uv_interpreter::discovery` module.
- There are new types to help structure interpreter requests and track
sources
- Executable discovery is implemented as a big lazy iterator and is a
central authority for source precedence
- `uv_interpreter::Error` variants were split into scoped types in each
module
- There's much more unit test coverage, but not for Windows yet

Remaining work:

- [x] Write new test cases
- [x] Determine correct behavior around executables in the current
directory
- _Future_: Combine `PythonVersion` and `VersionRequest`
- _Future_: Consider splitting `ManagedToolchain` into local and remote
variants
- _Future_: Add Windows unit test coverage
- _Future_: Explore behavior around implementation precedence (i.e.
CPython over PyPy)

Refactors split into:

- #3329 
- #3330 
- #3331
- #3332

Closes #2386
2024-05-21 14:37:23 -05:00
konsti 2ffd453003
Discover workspaces without using them in resolution (#3585)
Add minimal support for workspace discovery, only used for determining
paths in the bluejay commands.

We can now discover the workspace structure, namely that the
`pyproject.toml` of a package belongs to a workspace `pyproject.toml`
with members and exclusion. The globbing logic is inspired by cargo. We
don't resolve `workspace = true` metadata declarations yet.
2024-05-21 17:17:26 +00:00
Charlie Marsh a33a05e2d9
Bump version to v0.1.45 (#3674) 2024-05-20 16:34:05 -04:00
renovate[bot] e3ae876801
Update Rust crate itertools to 0.13.0 (#3664) 2024-05-20 00:49:42 +00:00
renovate[bot] 00f8e8cd1b
Update Rust crate thiserror to v1.0.61 (#3663) 2024-05-20 00:40:03 +00:00
renovate[bot] 65238499e1
Update Rust crate schemars to v0.8.20 (#3662) 2024-05-20 00:35:53 +00:00
renovate[bot] fcb27cfd6b
Update Rust crate anyhow to v1.0.86 (#3661) 2024-05-20 00:33:42 +00:00
Ben Beasley 53c2551fac
Pin the zip crate to 0.6 (#3645)
## Summary

Restore API-compatibility with pre-1.1.0 versions of the `zip` crate,
and pin the dependency to the 0.6 series, due to concerns discussed in
https://github.com/astral-sh/uv/issues/3642.

## Test Plan

```
cargo run -p uv-dev -- fetch-python
cargo test
```
2024-05-18 17:31:53 +00:00
Ibraheem Ahmed 53633392c3
Add `UV_CONCURRENT_INSTALLS` variable in favor of `RAYON_NUM_THREADS` (#3646)
## Summary

Continuation of https://github.com/astral-sh/uv/pull/3493. This gives us
more flexibility in case we decide to move away from `rayon` in the
future.
2024-05-17 23:12:37 -04:00
Ibraheem Ahmed 39af09f09b
Parallelize resolver (#3627)
## Summary

This PR introduces parallelism to the resolver. Specifically, we can
perform PubGrub resolution on a separate thread, while keeping all I/O
on the tokio thread. We already have the infrastructure set up for this
with the channel and `OnceMap`, which makes this change relatively
simple. The big change needed to make this possible is removing the
lifetimes on some of the types that need to be shared between the
resolver and pubgrub thread.

A related PR, https://github.com/astral-sh/uv/pull/1163, found that
adding `yield_now` calls improved throughput. With optimal scheduling we
might be able to get away with everything on the same thread here.
However, in the ideal pipeline with perfect prefetching, the resolution
and prefetching can run completely in parallel without depending on one
another. While this would be very difficult to achieve, even with our
current prefetching pattern we see a consistent performance improvement
from parallelism.

This does also require reverting a few of the changes from
https://github.com/astral-sh/uv/pull/3413, but not all of them. The
sharing is isolated to the resolver task.

## Test Plan

On smaller tasks performance is mixed with ~2% improvements/regressions
on both sides. However, on medium-large resolution tasks we see the
benefits of parallelism, with improvements anywhere from 10-50%.

```
./scripts/requirements/jupyter.in
Benchmark 1: ./target/profiling/baseline (resolve-warm)
  Time (mean ± σ):      29.2 ms ±   1.8 ms    [User: 20.3 ms, System: 29.8 ms]
  Range (min … max):    26.4 ms …  36.0 ms    91 runs
 
Benchmark 2: ./target/profiling/parallel (resolve-warm)
  Time (mean ± σ):      25.5 ms ±   1.0 ms    [User: 19.5 ms, System: 25.5 ms]
  Range (min … max):    23.6 ms …  27.8 ms    99 runs
 
Summary
  ./target/profiling/parallel (resolve-warm) ran
    1.15 ± 0.08 times faster than ./target/profiling/baseline (resolve-warm)
```
```
./scripts/requirements/boto3.in   
Benchmark 1: ./target/profiling/baseline (resolve-warm)
  Time (mean ± σ):     487.1 ms ±   6.2 ms    [User: 464.6 ms, System: 61.6 ms]
  Range (min … max):   480.0 ms … 497.3 ms    10 runs
 
Benchmark 2: ./target/profiling/parallel (resolve-warm)
  Time (mean ± σ):     430.8 ms ±   9.3 ms    [User: 529.0 ms, System: 77.2 ms]
  Range (min … max):   417.1 ms … 442.5 ms    10 runs
 
Summary
  ./target/profiling/parallel (resolve-warm) ran
    1.13 ± 0.03 times faster than ./target/profiling/baseline (resolve-warm)
```
```
./scripts/requirements/airflow.in 
Benchmark 1: ./target/profiling/baseline (resolve-warm)
  Time (mean ± σ):     478.1 ms ±  18.8 ms    [User: 482.6 ms, System: 205.0 ms]
  Range (min … max):   454.7 ms … 508.9 ms    10 runs
 
Benchmark 2: ./target/profiling/parallel (resolve-warm)
  Time (mean ± σ):     308.7 ms ±  11.7 ms    [User: 428.5 ms, System: 209.5 ms]
  Range (min … max):   287.8 ms … 323.1 ms    10 runs
 
Summary
  ./target/profiling/parallel (resolve-warm) ran
    1.55 ± 0.08 times faster than ./target/profiling/baseline (resolve-warm)
```
2024-05-17 11:47:30 -04:00
Charlie Marsh 70a1782745
Run cargo update to pull in h2 (#3638) 2024-05-17 11:09:54 -04:00
Charlie Marsh d76b023cd6
Remove `resolve_cli.rs` and `resolve_many.rs` (#3606)
## Summary

These depend on some APIs that I want to be internal-only for the
resolver crate, and we're no longer using them.
2024-05-15 16:04:47 +00:00
Charlie Marsh 913fc91afe
Remove binary from `uv-virtualenv` crate (#3605)
## Summary

I'm doing some refactoring and it requires updating this binary, but I
doubt we really use it?
2024-05-15 16:02:44 +00:00
Zanie Blue d417daad7e
Bump version to v0.1.44 (#3577) 2024-05-14 09:05:31 -05:00
konsti c22c7cad4c
Add parsed URL fields to `Dist` variants (#3429)
Avoid reparsing urls by storing the parsed parts across resolution on
`Dist`.

Part 2 of https://github.com/astral-sh/uv/issues/3408 and part of #3409

Closes #3408
2024-05-14 01:23:27 +00:00
konsti 0010954ca7
Add parsed URL to `PubGrubPackage` (#3426)
Avoid reparsing urls by storing the parsed parts across resolution on
`PubGrubPackage`.

Part 1 of #3408
2024-05-14 00:55:21 +00:00
Charlie Marsh 5132c6a6e2
Bump version to v0.1.43 (#3564) 2024-05-14 00:38:11 +00:00
Charlie Marsh e0da977fc9
Get `cargo shear` passing (#3533)
## Summary

Remove a few unused deps, and ignore `flate2` (which we include for
feature control).
2024-05-13 01:43:45 +00:00
renovate[bot] 84602c467b
Update Rust crate async-channel to v2.3.0 (#3532) 2024-05-13 01:30:55 +00:00
renovate[bot] a81752a0cf
Update Rust crate zip to v1.2.3 (#3530) 2024-05-12 20:17:34 -04:00
renovate[bot] 3422bea1a7
Update Rust crate axoupdater to v0.6.2 (#3529) 2024-05-12 20:17:18 -04:00
Charlie Marsh c2452957f9
Remove unused dependencies (#3527)
Surfaced with `cargo shear`.
2024-05-11 13:33:49 -04:00
Ibraheem Ahmed 783df8f657
Consolidate concurrency limits (#3493)
## Summary

This PR consolidates the concurrency limits used throughout `uv` and
exposes two limits, `UV_CONCURRENT_DOWNLOADS` and
`UV_CONCURRENT_BUILDS`, as environment variables.

Currently, `uv` has a number of concurrent streams that it buffers using
relatively arbitrary limits for backpressure. However, many of these
limits are conflated. We run a relatively small number of tasks overall
and should start most things as soon as possible. What we really want to
limit are three separate operations:
- File I/O. This is managed by tokio's blocking pool and we should not
really have to worry about it.
- Network I/O.
- Python build processes.

Because the current limits span a broad range of tasks, it's possible
that a limit meant for network I/O is occupied by tasks performing
builds, reading from the file system, or even waiting on a `OnceMap`. We
also don't limit build processes that end up being required to perform a
download. While this may not pose a performance problem because our
limits are relatively high, it does mean that the limits do not do what
we want, making it tricky to expose them to users
(https://github.com/astral-sh/uv/issues/1205,
https://github.com/astral-sh/uv/issues/3311).

After this change, the limits on network I/O and build processes are
centralized and managed by semaphores. All other tasks are unbuffered
(note that these tasks are still bounded, so backpressure should not be
a problem).
2024-05-10 12:43:08 -04:00
Andrew Gallant eab2b832a6
uv-resolver: make hashes optional (#3505)
This only makes hashes optional for wheels/sdists that come from
registires or direct URLs. For wheels/sdists that come from other
sources, a hash should not be present.

For path dependencies, a hash should not be present because the state of
the path dependency is not intended to be tracked in the lock file. This
is consistent with how other tools deal with path dependencies, and if
it were otherwise, the hash would I believe need to be updated for every
change to the path dependency.

For git dependencies (source dists only), a hash should not be present
because the lock will contain the specific commit revision hash. This is
functionally equivalent to a hash, and so a hash is redundant.

As part of this change, we validate the presence or absence of a hash
based on the dependency source. We also add our first regression tests.
2024-05-10 10:32:30 -04:00
Charlie Marsh 5e3260933c
Run `cargo update` (#3488) 2024-05-09 15:09:13 -04:00
Charlie Marsh 367958e6b2
Bump version to v0.1.42 (#3472) 2024-05-08 17:47:16 -04:00
Charlie Marsh 7d41e7d260
Respect `MACOSX_DEPLOYMENT_TARGET` in `--python-platform` (#3470)
## Summary

This is universal environment variable used to determine the mac OS
deployment target. We now respect it in `--python-platform` -- so we
default to 12.0, but users can override it as needed.
2024-05-08 20:03:41 +00:00
Charlie Marsh 18d229e2bb
Upgrade `async_http_range_reader` to v0.8.0 (#3460)
## Summary

Closes #2025.
Closes https://github.com/astral-sh/uv/issues/3255.
Closes https://github.com/astral-sh/uv/pull/2843.
2024-05-08 10:54:08 -04:00
konsti 1ad6aa8a23
Use generic pubgrub incompatibility reason (#3335)
Pubgrub got a new feature where all unavailability is a custom, instead
of the reasonless `UnavailableDependencies` and our custom `String` type
previously (https://github.com/pubgrub-rs/pubgrub/pull/208). This PR
introduces a `UnavailableReason` that tracks either an entire version
being unusable, or a specific version. The error messages now also track
this difference properly.

The pubgrub commit is our main rebased onto the merged
https://github.com/pubgrub-rs/pubgrub/pull/208, i'll push
`konsti/main-rebase-generic-reason` to `main` after checking for rebase
problems.
2024-05-08 08:40:15 +00:00
Charlie Marsh b0d7a26431
Bump version to v0.1.41 (#3446) 2024-05-08 01:05:47 +00:00
Charlie Marsh 7fe9f0a3dd
Bump version to v0.1.40 (#3433) 2024-05-07 17:29:29 +00:00
renovate[bot] 1efaf3fd31
Update Rust crate junction to v1.1.0 (#3393) 2024-05-06 02:41:15 +00:00
renovate[bot] aec9573d42
Update Rust crate mailparse to 0.15.0 (#3394) 2024-05-06 02:29:55 +00:00
renovate[bot] c125ce394a
Update Rust crate rmp-serde to v1.3.0 (#3395) 2024-05-06 02:29:24 +00:00
renovate[bot] 5a8d13a05a
Update Rust crate axoupdater to 0.6.0 (#3392) 2024-05-06 02:12:42 +00:00
renovate[bot] 1cf07ebf08
Update Rust crate zip to v1.1.4 (#3390) 2024-05-06 02:12:21 +00:00
renovate[bot] 409f38c7f5
Update Rust crate tokio-util to v0.7.11 (#3389) 2024-05-06 02:09:04 +00:00
renovate[bot] cce8e0dd7d
Update Rust crate test-log to v0.2.16 (#3388) 2024-05-06 02:06:27 +00:00
renovate[bot] c06266874e
Update Rust crate serde to v1.0.200 (#3387) 2024-05-06 02:04:30 +00:00
renovate[bot] e6efe48d52
Update Rust crate cargo-util to v0.2.11 (#3386) 2024-05-06 02:02:11 +00:00
renovate[bot] 0042533dc3
Update Rust crate base64 to v0.22.1 (#3385) 2024-05-06 02:01:09 +00:00
renovate[bot] a9756872e6
Update Rust crate anstream to v0.6.14 (#3384) 2024-05-06 02:00:17 +00:00
Charlie Marsh 37635fda56
Update activation scripts from virtualenv (#3376)
## Summary

Refreshes some of the activation scripts, and fixes some bugs in
`activate_this.py` that were likely the rest of some erroneous
copy-pasting.

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

## Test Plan

```
❯ python
Python 3.12.0 (main, Feb 28 2024, 09:44:16) [Clang 15.0.0 (clang-1500.1.0.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import httpx
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'httpx'
>>> activator = '.venv/bin/activate_this.py'
>>> with open(activator) as f:
...     exec(f.read(), {'__file__': activator})
...
>>> import httpx
```
2024-05-04 23:30:00 +00:00
Charlie Marsh 69e99b3502
Use canonical URLs in satisfaction check (#3373)
## Summary

Closes https://github.com/astral-sh/uv/issues/3367.
2024-05-04 12:44:25 +00:00
Charlie Marsh 100935f4f1
Respect `editable = true` setting in sources map (#3363)
## Summary

We need to partition the editable and non-editable requirements. As-is,
`editable = true` requirements were still being installed as
non-editable.
2024-05-04 02:17:55 +00:00
konsti 4f87edbe66
Add basic `tool.uv.sources` support (#3263)
## Introduction

PEP 621 is limited. Specifically, it lacks
* Relative path support
* Editable support
* Workspace support
* Index pinning or any sort of index specification

The semantics of urls are a custom extension, PEP 440 does not specify
how to use git references or subdirectories, instead pip has a custom
stringly format. We need to somehow support these while still stying
compatible with PEP 621.

## `tool.uv.source`

Drawing inspiration from cargo, poetry and rye, we add `tool.uv.sources`
or (for now stub only) `tool.uv.workspace`:

```toml
[project]
name = "albatross"
version = "0.1.0"
dependencies = [
  "tqdm >=4.66.2,<5",
  "torch ==2.2.2",
  "transformers[torch] >=4.39.3,<5",
  "importlib_metadata >=7.1.0,<8; python_version < '3.10'",
  "mollymawk ==0.1.0"
]

[tool.uv.sources]
tqdm = { git = "https://github.com/tqdm/tqdm", rev = "cc372d09dcd5a5eabdc6ed4cf365bdb0be004d44" }
importlib_metadata = { url = "https://github.com/python/importlib_metadata/archive/refs/tags/v7.1.0.zip" }
torch = { index = "torch-cu118" }
mollymawk = { workspace = true }

[tool.uv.workspace]
include = [
  "packages/mollymawk"
]

[tool.uv.indexes]
torch-cu118 = "https://download.pytorch.org/whl/cu118"
```

See `docs/specifying_dependencies.md` for a detailed explanation of the
format. The basic gist is that `project.dependencies` is what ends up on
pypi, while `tool.uv.sources` are your non-published additions. We do
support the full range or PEP 508, we just hide it in the docs and
prefer the exploded table for easier readability and less confusing with
actual url parts.

This format should eventually be able to subsume requirements.txt's
current use cases. While we will continue to support the legacy `uv pip`
interface, this is a piece of the uv's own top level interface. Together
with `uv run` and a lockfile format, you should only need to write
`pyproject.toml` and do `uv run`, which generates/uses/updates your
lockfile behind the scenes, no more pip-style requirements involved. It
also lays the groundwork for implementing index pinning.

## Changes

This PR implements:
* Reading and lowering `project.dependencies`,
`project.optional-dependencies` and `tool.uv.sources` into a new
requirements format, including:
  * Git dependencies
  * Url dependencies
  * Path dependencies, including relative and editable
* `pip install` integration
* Error reporting for invalid `tool.uv.sources`
* Json schema integration (works in pycharm, see below)
* Draft user-level docs (see `docs/specifying_dependencies.md`)

It does not implement:
* No `pip compile` testing, deprioritizing towards our own lockfile
* Index pinning (stub definitions only)
* Development dependencies
* Workspace support (stub definitions only)
* Overrides in pyproject.toml
* Patching/replacing dependencies

One technically breaking change is that we now require user provided
pyproject.toml to be valid wrt to PEP 621. Included files still fall
back to PEP 517. That means `pip install -r requirements.txt` requires
it to be valid while `pip install -r requirements.txt` with `-e .` as
content falls back to PEP 517 as before.

## Implementation

The `pep508` requirement is replaced by a new `UvRequirement` (name up
for bikeshedding, not particularly attached to the uv prefix). The still
existing `pep508_rs::Requirement` type is a url format copied from pip's
requirements.txt and doesn't appropriately capture all features we
want/need to support. The bulk of the diff is changing the requirement
type throughout the codebase.

We still use `VerbatimUrl` in many places, where we would expect a
parsed/decomposed url type, specifically:
* Reading core metadata except top level pyproject.toml files, we fail a
step later instead if the url isn't supported.
* Allowed `Urls`.
* `PackageId` with a custom `CanonicalUrl` comparison, instead of
canonicalizing urls eagerly.
* `PubGrubPackage`: We eventually convert the `VerbatimUrl` back to a
`Dist` (`Dist::from_url`), instead of remembering the url.
* Source dist types: We use verbatim url even though we know and require
that these are supported urls we can and have parsed.

I tried to make improve the situation be replacing `VerbatimUrl`, but
these changes would require massive invasive changes (see e.g.
https://github.com/astral-sh/uv/pull/3253). A main problem is the ref
`VersionOrUrl` and applying overrides, which assume the same
requirement/url type everywhere. In its current form, this PR increases
this tech debt.

I've tried to split off PRs and commits, but the main refactoring is
still a single monolith commit to make it compile and the tests pass.

## Demo

Adding
d1ae3b85d5/pyproject.json
as json schema (v7) to pycharm for `pyproject.toml`, you can try the IDE
support already:


![pycharm](https://github.com/astral-sh/uv/assets/6826232/599082c7-6be5-41c1-a3cd-516092382f8d)


[dove.webm](https://github.com/astral-sh/uv/assets/6826232/c293c272-c80b-459d-8c95-8c46a8d198a1)
2024-05-03 21:10:50 +00:00
Zanie Blue 630d3fde5c
Merge `uv-toolchain` and `uv-interpreter` (#3265)
Moves all of `uv-toolchain` into `uv-interpreter`. We may split these
out in the future, but the refactoring I want to do for interpreter
discovery is easier if I don't have to deal with entanglement. Includes
some restructuring of `uv-interpreter`.

Part of #2386
2024-04-30 17:49:46 +00:00
Ibraheem Ahmed 1d2c57a259
Run resolve/install benchmarks in ci (#3281)
## Summary

Runs resolver benchmarks in CI with CodSpeed.
2024-04-30 13:39:42 -04:00
Andrew Gallant d2e7c0554b
uv-resolver: add initial version of universal lock file format (#3314)
This is meant to be a base on which to build. There are some parts
which are implicitly incomplete and others which are explicitly
incomplete. The latter are indicated by TODO comments.

Here is a non-exhaustive list of incomplete things. In many cases, these
are incomplete simply because the data isn't present in a
`ResolutionGraph`. Future work will need to refactor our resolver so
that this data is correctly passed down.

* Not all wheels are included. Only the "selected" wheel for the current
  distribution is included.
* Marker expressions are always absent.
* We don't emit hashes for certainly kinds of distributions (direct
  URLs, git, and path).
* We don't capture git information from a dependency specification.
  Right now, we just always emit "default branch."

There are perhaps also other changes we might want to make to the format
of a more cosmetic nature. Right now, all arrays are encoded using
whatever the `toml` crate decides to do. But we might want to exert more
control over this. For example, by using inline tables or squashing more
things into strings (like I did for `Source` and `Hash`). I think the
main trade-off here is that table arrays are somewhat difficult to read
(especially without indentation), where as squashing things down into a
more condensed format potentially makes future compatible additions
harder.

I also went pretty light on the documentation here than what I would
normally do. That's primarily because I think this code is going to
go through some evolution and I didn't want to spend too much time
documenting something that is likely to change.

Finally, here's an example of the lock file format in TOML for the
`anyio` dependency. I generated it with the following command:

```
cargo run -p uv -- pip compile -p3.10 ~/astral/tmp/reqs/anyio.in --unstable-uv-lock-file
```

And that writes out a `uv.lock` file:

```toml
version = 1

[[distribution]]
name = "anyio"
version = "4.3.0"
source = "registry+https://pypi.org/simple"

[[distribution.wheel]]
url = "2f20c40b45242c0b33774da0e2e34f/anyio-4.3.0-py3-none-any.whl"
hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"

[[distribution.dependencies]]
name = "exceptiongroup"
version = "1.2.1"
source = "registry+https://pypi.org/simple"

[[distribution.dependencies]]
name = "idna"
version = "3.7"
source = "registry+https://pypi.org/simple"

[[distribution.dependencies]]
name = "sniffio"
version = "1.3.1"
source = "registry+https://pypi.org/simple"

[[distribution.dependencies]]
name = "typing-extensions"
version = "4.11.0"
source = "registry+https://pypi.org/simple"

[[distribution]]
name = "exceptiongroup"
version = "1.2.1"
source = "registry+https://pypi.org/simple"

[[distribution.wheel]]
url = "79fe92dd414cadab75055b0ae00b33/exceptiongroup-1.2.1-py3-none-any.whl"
hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"

[[distribution]]
name = "idna"
version = "3.7"
source = "registry+https://pypi.org/simple"

[[distribution.wheel]]
url = "741d8c8280948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl"
hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"

[[distribution]]
name = "sniffio"
version = "1.3.1"
source = "registry+https://pypi.org/simple"

[[distribution.wheel]]
url = "75a9c94214239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl"
hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"

[[distribution]]
name = "typing-extensions"
version = "4.11.0"
source = "registry+https://pypi.org/simple"

[[distribution.wheel]]
url = "936e2092671b43269810cd589ceaf5/typing_extensions-4.11.0-py3-none-any.whl"
hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"
```
2024-04-29 14:03:17 -04:00
konsti 1344cfae4b
Use fs_err for cachedir errors (#3304)
When running

```
set UV_CACHE_DIR=%LOCALAPPDATA%\uv\cache-foo && uv venv venv
```

in windows CMD, the error would be just

```
error: The system cannot find the path specified. (os error 3)
```

The problem is that the first action in the cache dir is adding the tag,
and the `cachedir` crate is using `std::fs` instead of `fs_err`. I've
copied the two functions we use from the crate and changed the import
from `std::fs` to `fs_err`.

The new error is

```
error: failed to open file `C:\Users\Konstantin\AppData\Local\uv\cache-foo \CACHEDIR.TAG`
  Caused by: The system cannot find the path specified. (os error 3)
```

which correctly explains the problem.

Closes #3280
2024-04-29 16:33:10 +02:00
renovate[bot] 22d8619c37
Update Rust crate data-encoding to v2.6.0 (#3302) 2024-04-29 09:31:59 -05:00
renovate[bot] f014bb60ce
Update Rust crate zip to v1.1.2 (#3300) 2024-04-29 09:31:06 -05:00
renovate[bot] f5214a2f73
Update Rust crate unicode-width to v0.1.12 (#3299) 2024-04-29 09:30:35 -05:00
renovate[bot] d66f5590f6
Update Rust crate serde to v1.0.199 (#3298) 2024-04-29 09:30:01 -05:00
renovate[bot] e25dbd9cfb
Update Rust crate schemars to v0.8.17 (#3297) 2024-04-29 09:29:45 -05:00
renovate[bot] 4f8017a0c6
Update Rust crate mimalloc to v0.1.41 (#3296) 2024-04-29 09:29:32 -05:00
renovate[bot] 8f3bc97146
Update Rust crate async-compression to v0.4.9 (#3294) 2024-04-29 09:29:15 -05:00
renovate[bot] af3be68be3
Update Rust crate flate2 to v1.0.30 (#3295) 2024-04-29 09:26:23 -05:00
Charlie Marsh 028b407411
Bump version to v0.1.39 (#3286) 2024-04-27 07:18:16 -04:00
Zanie Blue 0b23caa18d
Bump version to 0.1.38 (#3251) 2024-04-24 13:28:50 -05:00
Zanie Blue c22e15f07d
Warn when an unsupported Python version is encountered (#3250)
I rebased https://github.com/astral-sh/uv/pull/2757 then realized that
we want to implement this for more than `uv venv`.

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

```
❯ cargo run -q -- pip install -p /Users/mz/bin/python3.7 anyio
warning: uv is only compatible with Python 3.8+, found Python 3.7.17.
Audited 1 package in 84ms

❯ cargo run -q -- venv -p /Users/mz/bin/python3.7
warning: uv is only compatible with Python 3.8+, found Python 3.7.17.
Using Python 3.7.17 interpreter at: /Users/mz/bin/python3.7
Creating virtualenv at: .venv
Activate with: source .venv/bin/activate
```

---------

Co-authored-by: Stevie Gayet <stegayet@users.noreply.github.com>
2024-04-24 17:51:57 +00:00
Zanie Blue e92b38cfb9
Only perform fetches of credentials for a realm once (#3237)
Closes https://github.com/astral-sh/uv/issues/3205

Tested with

`RUST_LOG=uv=trace cargo run -- pip install -r
scripts/requirements/trio.in --index-url
https://oauth2accesstoken@us-central1-python.pkg.dev/zb-test-project-421213/pypyi/simple/
--no-cache --keyring-provider subprocess -vv --reinstall 2>&1 | grep
keyring`

On `main` you can see a dozen keyring attempts at once. Here, the other
requests wait for the first attempt and only a single keyring call is
performed.
2024-04-24 09:53:44 -05:00
konsti 3783292c43
Remove unused dependencies (#3236)
`cargo shear --fix` and some manual fixing for tokio and flate2.

I wanted to prepare my branch and realized main also needs this.
2024-04-24 11:18:24 +00:00
samypr100 308f95fce1
chore: use uv-version in uv-virtualenv (#3221)
## Summary

This is mainly a cleanup PR to leverage uv-version in uv-virtualenv
instead of passing it via `uv`.
In #1852 I introduced the ability to pass extra cfg to `gourgeist` for
the primary purpose of passing the uv version, but since the dawn of the
uv-version crate dynamically passing more values to pyvenv.cfg is no
longer needed.

## Test Plan

Existing `uv` tests should still verify `uv = <version>` exists in the
venv and make sure no regressions were introduced.
2024-04-23 16:18:40 -04:00
Zanie Blue 645d0399fd
Bump version to 0.1.37 (#3208) 2024-04-23 14:35:27 +00:00
哇呜哇呜呀咦耶 65efaf70da
Make KeyringProvider::fetch_* async (#3089)
To resolve #3073
2024-04-23 07:58:00 -05:00
renovate[bot] 054fa3e439
Update Rust crate zip to v1 (#3175) 2024-04-22 22:17:44 -04:00
Zanie Blue 78cd9991d7
Bump version to 0.1.36 (#3193) 2024-04-22 13:55:55 -05:00
renovate[bot] 04eaee7e19
Update Rust crate pyo3 to 0.21.0 (#2911) 2024-04-22 18:27:22 +00:00
Zanie Blue f98eca8843
Fix authentication for URLs with a shared realm (#3130)
In #2976 I made some changes that led to regressions:

- We stopped tracking URLs that we had not seen credentials for in the
cache
- This means the cache no longer returns a value to indicate we've seen
a realm before
- We stopped seeding the cache with URLs 
- Combined with the above, this means we no longer had a list of
locations that we would never attempt to fetch credentials for
- We added caching of credentials found on requests
- Previously the cache was only populated from the seed or credentials
found in the netrc or keyring
- This meant that the cache was populated for locations that we
previously did not cache, i.e. GitHub artifacts(?)

Unfortunately this unveiled problems with the granularity of our cache.
We cache credentials per realm (roughly the hostname) but some realms
have mixed authentication modes i.e. different credentials per URL or
URLs that do not require credentials. Applying credentials to a URL that
does not require it can lead to a failed request, as seen in #3123 where
GitHub throws a 401 when receiving credentials.

To resolve this, the cache is expanded to supporting caching at two
levels:

- URL, cached URL must be a prefix of the request URL
- Realm, exact match required

When we don't have URL-level credentials cached, we attempt the request
without authentication first. On failure, we'll search for realm-level
credentials or fetch credentials from external services. This avoids
providing credentials to new URLs unless we know we need them.

Closes https://github.com/astral-sh/uv/issues/3123
2024-04-22 13:06:57 -05:00
renovate[bot] 79d4a6556a
Update Rust crate rmp-serde to v1.2.0 (#3173) 2024-04-22 13:27:30 -04:00
konsti 82c4772e89
Move unnamed requirements to their own pep508_rs module and requirements-txt (#3186)
Another refactoring in preparation of using a richer requirements type.
No functional changes, only moves code around
2024-04-22 14:02:39 +00:00
konsti f29c991e21
Dedicated error type for direct url parsing (#3181)
Add a dedicated error type for direct url parsing. This change is broken
out from the new uv requirement type, which uses direct url parsing
internally.
2024-04-22 11:57:36 +00:00
renovate[bot] 5f5e7b574e
Update Rust crate hyper to v1.3.1 (#3168) 2024-04-21 22:53:55 -05:00
renovate[bot] e6a790b3d5
Update Rust crate axoupdater to v0.5.1 (#3167) 2024-04-21 22:53:42 -05:00
renovate[bot] b15fe1836e
Update Rust crate thiserror to v1.0.59 (#3172) 2024-04-21 21:30:16 -05:00
renovate[bot] 80f4f36a4f
Update Rust crate serde_json to v1.0.116 (#3171) 2024-04-21 21:30:06 -05:00
renovate[bot] 0e7000e894
Update Rust crate serde to v1.0.198 (#3170) 2024-04-21 21:29:56 -05:00
renovate[bot] 79540003fc
Update Rust crate reflink-copy to v0.1.17 (#3169) 2024-04-21 21:29:47 -05:00
Charlie Marsh b4ee7d7359
Bump version to v0.1.35 (#3153) 2024-04-19 19:58:15 -04:00
Charlie Marsh 70b6bde254
Add `--python-platform` to configuration (#3147)
## Summary

Just for consistency with `--python-version`.
2024-04-19 23:08:03 +00:00
Charlie Marsh 9f2bc19eaf
Enforce HTTP timeouts on a per-read (rather than per-request) basis (#3144)
## Summary

This leverages the new `read_timeout` property, which ensures that (like
pip) our timeout is not applied to the _entire_ request, but rather, to
each individual read operation.

Closes: #1921.

See: #1912.
2024-04-19 16:49:53 -04:00
Charlie Marsh 9259eceebc
Bump version to v0.1.34 (#3134) 2024-04-19 02:15:04 +00:00
Charlie Marsh dfccdb0e39
Enable global configuration files (#3049)
## Summary

Enables `uv` to read configuration from (e.g.)
`/Users/crmarsh/.config/uv/uv.toml` on macOS and Linux, and
`C:\Users\Charlie\AppData\Roaming\uv\uv.toml` on Windows.

This differs slightly from Ruff, which uses the `Application Support`
directory on macOS. But I've deviated here. based on the preferences
expressed in https://github.com/astral-sh/ruff/issues/10739.
2024-04-17 13:59:50 -04:00
Charlie Marsh 7fb2bf816f
Add JSON Schema support (#3046)
## Summary

This PR adds JSON Schema support. The setup mirrors Ruff's own.
2024-04-17 17:24:41 +00:00
Zanie Blue 2cee7525c7
Bump version to 0.1.33 (#3094) 2024-04-17 10:34:13 -05:00
Charlie Marsh b1cb193d12
Add some tracing to workspace discovery (#3084) 2024-04-17 01:54:08 +00:00
Sergey Kolosov d2551bb2bd
Add support for .tar.bz2 source distributions (#3069)
## Summary

Source distributions in the .tar.bz2 format are still relatively common
within the existing code-bases, namely, the most common examples are the
Twisted source distributions up to the version 20.3.0. As quite so often
the ability to upgrade Twisted to a more recent version is not available
for a given project, we add the support for .tar.bz2 here to still allow
`uv` to be a drop-in replacement for `pip` in these projects.

## Test Plan

The feature was tested both by adding the corresponding test coverage,
and by directly installing a package of interest under a Python version
that doesn't have the corresponding wheel:

```sh
cargo run venv -p python3.8
cargo run pip install Twisted==20.3.0 --no-cache
```

The `--no-cache` argument in the example above serves the purpose of
cleaning the cached information regarding the unsatisfiability of the
requirements, as it may have been cached during some previous attempt to
install this package by `uv` version that didn't implement this feature
yet.
2024-04-16 18:34:55 +00:00
Charlie Marsh 295b58ad37
Add `uv-workspace` crate with settings discovery and deserialization (#3007)
## Summary

This PR adds basic struct definitions along with a "workspace" concept
for discovering settings. (The "workspace" terminology is used to match
Ruff; I did not invent it.)

A few notes:

- We discover any `pyproject.toml` or `uv.toml` file in any parent
directory of the current working directory. (We could adjust this to
look at the directories of the input files.)
- We don't actually do anything with the configuration yet; but those
PRs are large and I want this to be reviewed in isolation.
2024-04-16 13:56:47 -04:00
Zanie Blue c0efeeddf6
Rewrite `uv-auth` (#2976)
Closes 

- #2822 
- https://github.com/astral-sh/uv/issues/2563 (via #2984)

Partially address:

- https://github.com/astral-sh/uv/issues/2465
- https://github.com/astral-sh/uv/issues/2464

Supersedes:

- https://github.com/astral-sh/uv/pull/2947
- https://github.com/astral-sh/uv/pull/2570 (via #2984)

Some significant refactors to the whole `uv-auth` crate:

- Improving the API
- Adding test coverage
- Fixing handling of URL-encoded passwords
- Fixing keyring authentication
- Updated middleware (see #2984 for more)
2024-04-16 11:48:37 -05:00
Alex Waygood 66e420f34b
Enable auto-wrapping of `--help` output (#3058)
## Summary

Fixes #3057

On `main`, with a narrow terminal:

- <details>


![image](https://github.com/astral-sh/uv/assets/66076021/2453dcbc-739c-4174-ba2e-029cff3227a2)

  </details>

- <details>


![image](https://github.com/astral-sh/uv/assets/66076021/02553e90-fe35-4828-b50f-71f926a1e347)

  </details>

- <details>


![image](https://github.com/astral-sh/uv/assets/66076021/b33eac26-f2fe-4328-8aa0-c51235b7c4c3)

  </details>

- <details>


![image](https://github.com/astral-sh/uv/assets/66076021/e731f647-3519-4c54-ab33-b42500faf544)

  </details>

With PR:

- <details>


![image](https://github.com/astral-sh/uv/assets/66076021/0f1aaec0-960a-4060-95ba-f49bec2f6995)

  </details>

- <details>


![image](https://github.com/astral-sh/uv/assets/66076021/b8078125-bd57-41a9-9c09-1966c8971c92)

  </details>

- <details>


![image](https://github.com/astral-sh/uv/assets/66076021/c2f38eb0-5f67-46ee-8a09-47da9e9ce0a5)

  </details>

- <details>


![image](https://github.com/astral-sh/uv/assets/66076021/31b9fdca-938a-47ca-96ba-751d987c269e)

  </details>

## Test Plan

See screenshots in the summary
2024-04-16 08:54:40 -04:00
Zanie Blue 37a43f4b48
Bump version to 0.1.32 (#3039)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-04-15 15:16:47 -05:00
renovate[bot] eec49ca2b7
chore(deps): update rust crate hyper to v1.3.0 (#3036) 2024-04-15 10:38:11 -05:00
renovate[bot] 348f489081
chore(deps): update rust crate chrono to v0.4.38 (#3035) 2024-04-15 14:54:08 +00:00
konsti eded6c9fae
Use link mode for builds, in `uv pip compile` and for `uv venv` seed packages (#3016)
Use the user specified link mode for temporary build venvs, too. It
seems consistent to respect the user's link mode for all installations
we perform
2024-04-15 08:49:41 +00:00
renovate[bot] aa855ee729
chore(deps): update rust crate async-trait to v0.1.80 (#3024) 2024-04-14 22:11:22 -04:00
renovate[bot] 22d9471a59
chore(deps): update rust crate either to v1.11.0 (#3027) 2024-04-14 22:09:56 -04:00
renovate[bot] b4a79b9ee2
chore(deps): update rust crate axoupdater to 0.5.0 (#3026) 2024-04-14 22:09:25 -04:00
renovate[bot] 8b39c6b2c7
chore(deps): update rust crate platform-info to v2.0.3 (#3025) 2024-04-14 22:09:02 -04:00
renovate[bot] 2e34d7aa6d
chore(deps): update rust crate async-channel to v2.2.1 (#3023) 2024-04-14 22:07:12 -04:00
Charlie Marsh c43757ad4c
Avoid calling `normalize_path` with relative paths that extend beyond the current directory (#3013)
## Summary

It turns out that `normalize_path` (sourced from Cargo) has a subtle
bug. If you pass it a relative path that traverses beyond the root, it
silently drops components. So, e.g., passing `../foo/bar`, it will just
drop the leading `..` and return `foo/bar`.

This PR encodes that behavior as a `Result` and avoids using it in such
cases.

Closes https://github.com/astral-sh/uv/issues/3012.
2024-04-12 14:48:03 -04:00
Charlie Marsh 96c3c2e774
Support unnamed requirements in `--require-hashes` (#2993)
## Summary

This PR enables `--require-hashes` with unnamed requirements. The key
change is that `PackageId` becomes `VersionId` (since it refers to a
package at a specific version), and the new `PackageId` consists of
_either_ a package name _or_ a URL. The hashes are keyed by `PackageId`,
so we can generate the `RequiredHashes` before we have names for all
packages, and enforce them throughout.

Closes #2979.
2024-04-11 11:26:50 -04:00
samypr100 7c7f06f62b
feat: convert linehaul tests to use snapshots (#2923)
<!--
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

Closes #2564

## Test Plan

1. Changed existing linehaul tests to leverage insta.
2. Ran tests in various linux distros (Debian, Ubuntu, Centos, Fedora,
Alpine) to ensure they also pass locally again.

---------

Co-authored-by: konstin <konstin@mailbox.org>
2024-04-11 09:41:09 +00:00
Charlie Marsh 1f3b5bb093
Add hash-checking support to `install` and `sync` (#2945)
## Summary

This PR adds support for hash-checking mode in `pip install` and `pip
sync`. It's a large change, both in terms of the size of the diff and
the modifications in behavior, but it's also one that's hard to merge in
pieces (at least, with any test coverage) since it needs to work
end-to-end to be useful and testable.

Here are some of the most important highlights:

- We store hashes in the cache. Where we previously stored pointers to
unzipped wheels in the `archives` directory, we now store pointers with
a set of known hashes. So every pointer to an unzipped wheel also
includes its known hashes.
- By default, we don't compute any hashes. If the user runs with
`--require-hashes`, and the cache doesn't contain those hashes, we
invalidate the cache, redownload the wheel, and compute the hashes as we
go. For users that don't run with `--require-hashes`, there will be no
change in performance. For users that _do_, the only change will be if
they don't run with `--generate-hashes` -- then they may see some
repeated work between resolution and installation, if they use `pip
compile` then `pip sync`.
- Many of the distribution types now include a `hashes` field, like
`CachedDist` and `LocalWheel`.
- Our behavior is similar to pip, in that we enforce hashes when pulling
any remote distributions, and when pulling from our own cache. Like pip,
though, we _don't_ enforce hashes if a distribution is _already_
installed.
- Hash validity is enforced in a few different places:
1. During resolution, we enforce hash validity based on the hashes
reported by the registry. If we need to access a source distribution,
though, we then enforce hash validity at that point too, prior to
running any untrusted code. (This is enforced in the distribution
database.)
2. In the install plan, we _only_ add cached distributions that have
matching hashes. If a cached distribution is missing any hashes, or the
hashes don't match, we don't return them from the install plan.
3. In the downloader, we _only_ return distributions with matching
hashes.
4. The final combination of "things we install" are: (1) the wheels from
the cache, and (2) the downloaded wheels. So this ensures that we never
install any mismatching distributions.
- Like pip, if `--require-hashes` is provided, we require that _all_
distributions are pinned with either `==` or a direct URL. We also
require that _all_ distributions have hashes.

There are a few notable TODOs:

- We don't support hash-checking mode for unnamed requirements. These
should be _somewhat_ rare, though? Since `pip compile` never outputs
unnamed requirements. I can fix this, it's just some additional work.
- We don't automatically enable `--require-hashes` with a hash exists in
the requirements file. We require `--require-hashes`.

Closes #474.

## Test Plan

I'd like to add some tests for registries that report incorrect hashes,
but otherwise: `cargo test`
2024-04-10 19:09:03 +00:00
Charlie Marsh ddf02e7d5f
Remove unused `task-local-extensions` dependency (#2974)
## Summary

Made obsolete with the `reqwest` upgrade.
2024-04-10 14:56:39 -04:00
Charlie Marsh 48ba7df98a
Move `FlatIndex` into the `uv-resolver` crate (#2972)
## Summary

This lets us remove circular dependencies (in the future, e.g., #2945)
that arise from `FlatIndex` needing a bunch of resolver-specific
abstractions (like incompatibilities, required hashes, etc.) that aren't
necessary to _fetch_ the flat index entries.
2024-04-10 14:38:42 -04:00
Zanie Blue 44e39bdca3
Replace Python bootstrapping script with Rust implementation (#2842)
See https://github.com/astral-sh/uv/issues/2617

Note this also includes:
- #2918 
- #2931 (pending)

A first step towards Python toolchain management in Rust.

First, we add a new crate to manage Python download metadata:

- Adds a new `uv-toolchain` crate
- Adds Rust structs for Python version download metadata
- Duplicates the script which downloads Python version metadata
- Adds a script to generate Rust code from the JSON metadata
- Adds a utility to download and extract the Python version

I explored some alternatives like a build script using things like
`serde` and `uneval` to automatically construct the code from our
structs but deemed it to heavy. Unlike Rye, I don't generate the Rust
directly from the web requests and have an intermediate JSON layer to
speed up iteration on the Rust types.

Next, we add add a `uv-dev` command `fetch-python` to download Python
versions per the bootstrapping script.

- Downloads a requested version or reads from `.python-versions`
- Extracts to `UV_BOOTSTRAP_DIR`
- Links executables for path extension

This command is not really intended to be user facing, but it's a good
PoC for the `uv-toolchain` API. Hash checking (via the sha256) isn't
implemented yet, we can do that in a follow-up.

Finally, we remove the `scripts/bootstrap` directory, update CI to use
the new command, and update the CONTRIBUTING docs.

<img width="1023" alt="Screenshot 2024-04-08 at 17 12 15"
src="https://github.com/astral-sh/uv/assets/2586601/57bd3cf1-7477-4bb8-a8e9-802a00d772cb">
2024-04-10 11:22:41 -05:00
Charlie Marsh a01143980a
Upgrade `reqwest` to v0.12.3 (#2817)
## Summary

Closes #2814.
2024-04-10 11:20:44 -04:00
Aria Beingessner 997f3c9161
chore: update axoupdater to 0.4.0 and add a test (#2938)
## Summary

This updates to the version of axoupdater used in cargo-dist 0.13.0's
own selfupdate command, with all relevant fixes for platforms. It also
tentatively introduces a mildly dangerous self-runtest that runs `uv
self update` and checks that the binary is installed and executable.

I *believe* some adjustments need to be made to your CI to have this new
test run, because it requires the `self-update` feature to be enabled,
and I didn't want to just start messing with how you do feature coverage
in your CI. **As a result I haven't yet had a chance to actually fully
run this in CI**, though I've locally tested it on windows (with the
guard disabled).


## Test Plan

Most of the machinery here is provided by axoupdater itself (cargo-dist
also includes a variant of these tests in its codebase). This initial
implementation has a couple major limitations:

* This is For Reals modifying the system that runs the test (so it's off
unless it detects it's running in CI, and if you want variations on this
test they'll need to be [run in
serial](5e7826f7b0/cargo-dist/tests/cli-tests.rs (L235))).
Since many of the testing issues were surrounding precise details of
Actual Deployed Executions, this seemed worth the tradeoff.
* The actual installer *script* it's ultimately invoking is the one you
last published, and *not* the one that cargo-dist will make when you
next publish.

We're already working on implementing some logic for "get cargo-dist to
generate a fresh installer script too", which is in fact the basis of a
huge amount of cargo-dist's own testsuite. Now that we're dogfooding
this stuff, it should be quite hard for this stuff to break without
cargo-dist's own codebase noticing it first.


<!-- How was it tested? -->
2024-04-09 23:41:16 -04:00
Charlie Marsh 7ae06b3b46
Surface invalid metadata as hints in error reports (#2850)
## Summary

Closes #2847.
2024-04-09 23:12:10 -04:00
Charlie Marsh 7bcca28b12
Bump version to v0.1.31 (#2944) 2024-04-09 19:20:43 +00:00
Zanie Blue 1512e07a2e
Split configuration options out of `uv-types` (#2924)
Needed to prevent circular dependencies in my toolchain work (#2931). I
think this is probably a reasonable change as we move towards persistent
configuration too?

Unfortunately `BuildIsolation` needs to be in `uv-types` to avoid
circular dependencies still. We might be able to resolve that in the
future.
2024-04-09 11:35:53 -05:00
Charlie Marsh a4f5a7d233
Bump version to v0.1.30 (#2934) 2024-04-09 12:06:11 -04:00
Zanie Blue f42013214a
Restore lockfile (#2914)
Accidentally reverted the lockfile in
538c88130e

Closes #2912 
Closes #2910 
Closes #2913
2024-04-08 21:25:33 +00:00
Zanie Blue 538c88130e
Group `pyo3` dependency updates (#2889)
Seems needed for https://github.com/astral-sh/uv/pull/2879
2024-04-08 16:06:55 -05:00
Zanie Blue bdeab55193
Add extract support for zstd (#2861)
We need this to extract toolchain downloads
2024-04-08 15:34:08 -05:00
renovate[bot] 47333c985b
Update Rust crate tokio to v1.37.0 (#2886) 2024-04-08 09:35:00 -04:00
Zanie Blue b181907ad2
Fix linehaul tests (#2891)
Cleans up the assertions a bit. I looked into snapshot tests per #2564
but it didn't seem worth it for cross-platform tests.

Closes #2564 
Closes https://github.com/astral-sh/uv/pull/2878
2024-04-07 23:42:19 -05:00
renovate[bot] 61e06bb2c3
Update Rust crate rayon to v1.10.0 (#2880) 2024-04-07 22:54:40 -05:00
renovate[bot] a866cb2f32
Update Rust crate insta to v1.38.0 (#2877) 2024-04-07 22:54:16 -05:00
renovate[bot] f0c83a4ded
Update Rust crate base64 to 0.22.0 (#2874) 2024-04-08 03:02:35 +00:00
renovate[bot] f5334a4914
Update Rust crate which to v6.0.1 (#2873) 2024-04-07 22:38:15 -04:00
renovate[bot] 74371ede8d
Update Rust crate tokio-stream to v0.1.15 (#2872) 2024-04-07 22:37:59 -04:00
renovate[bot] a4bbe6602f
Update Rust crate serde_json to v1.0.115 (#2871) 2024-04-07 22:37:51 -04:00
renovate[bot] 56555b9911
Update Rust crate indexmap to v2.2.6 (#2868) 2024-04-07 22:37:39 -04:00
renovate[bot] 78d64bfc86
Update Rust crate axoupdater to v0.3.6 (#2866) 2024-04-08 02:29:03 +00:00
renovate[bot] 14ef0e044c
Update Rust crate regex to v1.10.4 (#2870) 2024-04-08 02:28:47 +00:00
renovate[bot] 8e7f9b18c5
Update Rust crate git2 to v0.18.3 (#2867) 2024-04-08 02:28:21 +00:00
renovate[bot] d34c90150d
Update Rust crate async-compression to v0.4.8 (#2865) 2024-04-08 02:28:04 +00:00
Charlie Marsh 00934044aa
Backtrack on distributions with invalid metadata (#2834)
## Summary

Closes https://github.com/astral-sh/uv/issues/2821.
2024-04-05 18:00:48 -04:00
Charlie Marsh 365cb16fd6
Bump version to v0.1.29 (#2825) 2024-04-04 15:50:52 -04:00
Charlie Marsh dc2c289dff
Upgrade `rs-async-zip` to support data descriptors (#2809)
## Summary

Upgrading `rs-async-zip` enables us to support data descriptors in
streaming. This both greatly improves performance for indexes that use
data descriptors _and_ ensures that we support them in a few other
places (e.g., zipped source distributions created in Finder).

Closes #2808.
2024-04-04 01:31:40 +00:00
Charlie Marsh 34341bd6e9
Allow package lookups across multiple indexes via explicit opt-in (#2815)
## Summary

This partially revives https://github.com/astral-sh/uv/pull/2135 (with
some modifications) to enable users to opt-in to looking for packages
across multiple indexes.

The behavior is such that, in version selection, we take _any_
compatible version from a "higher-priority" index over the compatible
versions of a "lower-priority" index, even if that means we might accept
an "older" version.

Closes https://github.com/astral-sh/uv/issues/2775.
2024-04-03 23:23:37 +00:00
Zanie Blue 0046a0d596
Bump version to 0.1.28 (#2785) 2024-04-02 21:39:35 +00:00
Charlie Marsh f60e7495ca
Bump version to v0.1.27 (#2758) 2024-04-01 14:54:50 -04:00
renovate[bot] 9df6e33b85
Update Rust crate clap to v4.5.4 (#2754) 2024-04-01 09:12:52 +01:00
renovate[bot] 35aa80c149
Update Rust crate chrono to v0.4.37 (#2753) 2024-04-01 08:27:11 +01:00
renovate[bot] 0c13eaabe0
Update Rust crate cargo-util to v0.2.10 (#2748) 2024-04-01 02:14:30 +00:00
renovate[bot] ca2a6bb728
Update Rust crate async-trait to v0.1.79 (#2747) 2024-04-01 02:13:23 +00:00
Charlie Marsh 6d5b5ae9a2
Use distinct `Constraints` and `Overrides` types more widely (#2741)
## Summary

No functional changes.
2024-03-31 13:46:37 -04:00
Zanie Blue e1878c8359
Consider installed packages during resolution (#2596)
Previously, we did not consider installed distributions as candidates
while performing resolution. Here, we update the resolver to use
installed distributions that satisfy requirements instead of pulling new
distributions from the registry.

The implementation details are as follows:

- We now provide `SitePackages` to the `CandidateSelector`
- If an installed distribution satisfies the requirement, we prefer it
over remote distributions
- We do not want to allow installed distributions in some cases, i.e.,
upgrade and reinstall
- We address this by introducing an `Exclusions` type which tracks
installed packages to ignore during selection
- There's a new `ResolvedDist` wrapper with `Installed(InstalledDist)`
and `Installable(Dist)` variants
- This lets us pass already installed distributions throughout the
resolver

The user-facing behavior is thoroughly covered in the tests, but
briefly:

- Installing a package that depends on an already-installed package
prefers the local version over the index
- Installing a package with a name that matches an already-installed URL
package does not reinstall from the index
- Reinstalling (--reinstall) a package by name _will_ pull from the
index even if an already-installed URL package is present
- To reinstall the URL package, you must specify the URL in the request

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

Addresses:

- https://github.com/astral-sh/uv/issues/1476
- https://github.com/astral-sh/uv/issues/1856
- https://github.com/astral-sh/uv/issues/2093
- https://github.com/astral-sh/uv/issues/2282
- https://github.com/astral-sh/uv/issues/2383
- https://github.com/astral-sh/uv/issues/2560

## Test plan

- [x] Reproduction at `charlesnicholson/uv-pep420-bug` passes
- [x] Unit test for editable package
([#1476](https://github.com/astral-sh/uv/issues/1476))
- [x] Unit test for previously installed package with empty registry
- [x] Unit test for local non-editable package
- [x] Unit test for new version available locally but not in registry
([#2093](https://github.com/astral-sh/uv/issues/2093))
- ~[ ] Unit test for wheel not available in registry but already
installed locally
([#2282](https://github.com/astral-sh/uv/issues/2282))~ (seems
complicated and not worthwhile)
- [x] Unit test for install from URL dependency then with matching
version ([#2383](https://github.com/astral-sh/uv/issues/2383))
- [x] Unit test for install of new package that depends on installed
package does not change version
([#2560](https://github.com/astral-sh/uv/issues/2560))
- [x] Unit test that `pip compile` does _not_ consider installed
packages
2024-03-28 13:49:17 -05:00
Zanie Blue ffa1b01176
Bump version to 0.1.26 (#2713) 2024-03-28 12:55:36 -05:00
Zanie Blue 4e59bfd16e
Bump version to 0.1.25 (#2709)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-03-28 10:17:52 -05:00
Charlie Marsh 4b69ad4281
Remove some unused dependencies (#2698) 2024-03-27 17:50:55 -04:00
Charlie Marsh 8c7a6038fd
Update Rust to v1.77 (#2591) 2024-03-27 14:41:27 +00:00
Charlie Marsh 365c292525
Read package metadata from `pyproject.toml` when statically defined (#2676)
## Summary

Now that we're resolving metadata more aggressively for local sources,
it's worth doing this. We now pull metadata from the `pyproject.toml`
directly if it's statically-defined.

Closes https://github.com/astral-sh/uv/issues/2629.
2024-03-27 14:34:18 +00:00
Charlie Marsh ffd78d0821
Add an in-memory cache for Git references (#2682)
## Summary

Ensures that, even if we try to resolve the same Git reference twice
within an invocation, it always returns a (cached) consistent result.

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

## Test Plan

```
❯ cargo run pip install git+https://github.com/pallets/flask.git --reinstall --no-cache
   Compiling uv-distribution v0.0.1 (/Users/crmarsh/workspace/uv/crates/uv-distribution)
   Compiling uv-resolver v0.0.1 (/Users/crmarsh/workspace/uv/crates/uv-resolver)
   Compiling uv-installer v0.0.1 (/Users/crmarsh/workspace/uv/crates/uv-installer)
   Compiling uv-dispatch v0.0.1 (/Users/crmarsh/workspace/uv/crates/uv-dispatch)
   Compiling uv-requirements v0.1.0 (/Users/crmarsh/workspace/uv/crates/uv-requirements)
   Compiling uv v0.1.24 (/Users/crmarsh/workspace/uv/crates/uv)
    Finished dev [unoptimized + debuginfo] target(s) in 3.95s
     Running `target/debug/uv pip install 'git+https://github.com/pallets/flask.git' --reinstall --no-cache`
 Updated https://github.com/pallets/flask.git (b90a4f1)
Resolved 7 packages in 280ms
   Built flask @ git+https://github.com/pallets/flask.git@b90a4f1f4a370e92054b9cc9db0efcb864f87ebe                                                                                                                                            Downloaded 7 packages in 212ms
Installed 7 packages in 9ms
```
2024-03-27 01:39:01 +00:00
Charlie Marsh 32d8ee8ba3
Add `--no-binary` and `--only-binary` support to `requirements.txt` (#2680)
## Summary

Closes https://github.com/astral-sh/uv/issues/1461.
2024-03-27 01:12:29 +00:00
Zanie Blue 0b08ba1e67
Rename `uv-traits` and split into separate modules (#2674)
This is driving me a little crazy and is becoming a larger problem in
#2596 where I need to move more types (like `Upgrade` and `Reinstall`)
into this crate. Anything that's shared across our core resolver,
install, and build crates needs to be defined in this crate to avoid
cyclic dependencies. We've outgrown it being a single file with some
shared traits.

There are no behavioral changes here.
2024-03-26 15:39:43 -05:00
Charlie Marsh 39769d82a0
Fall back to PEP 517 hooks for non-compliant PEP 621 metadata (#2662)
If you pass a `pyproject.toml` that use Hatch's context formatting API,
we currently fail because the dependencies aren't valid under PEP 508.
This PR makes the static metadata parsing a little more relaxed, so that
we appropriately fall back to PEP 517 there.
2024-03-26 02:28:39 +00:00
Charlie Marsh 71428f7d74
Use PEP 517 to extract non-static `pyproject.toml` metadata (#2633)
## Summary

When a user passes a `pyproject.toml` to `pip compile` (e.g., `uv pip
compile pyproject.toml`), we extract the requirements from the
`pyproject.toml` directly. However... that isn't always possible (as
seen in the linked issues). When it's _not_, we instead need to run the
PEP 517 build hooks to identify the metadata.

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

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

## Test Plan

`cargo test`
2024-03-25 20:27:41 +00:00
Charlie Marsh f3753347e0
Add `rustc-hash` to `uv` crate (#2660)
## Summary

This is required as of https://github.com/astral-sh/uv/pull/2589, but
isn't a direct dependency. I'm not sure how that PR passed CI exactly.
2024-03-25 20:21:43 +00:00
konsti 33bde826a0
Update pubgrub to use a dependency provider (#2648)
With https://github.com/pubgrub-rs/pubgrub/pull/190, pubgrub attaches
all types to a dependency provider to reduce the number of generics. We
need a dummy dependency provider now to emulate this. On the plus side,
pep440_rs drops its pubgrub dependency.
2024-03-25 15:51:31 +01:00
Hans Baker a632d2485b
Don't error on multiple matching index URLs (#2627)
## Summary

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

## Test Plan

```
cargo run -- pip install -r dev-requirements.txt -r requirements.txt
```
where both requirements files have same `--index-url`
2024-03-22 23:37:02 +00:00
Zanie Blue a5cae02922
Bump version to 0.1.24 (#2621) 2024-03-22 14:58:10 -05:00
konsti 48bd02b8a8
Update miette v7, pubgrub and small Cargo.toml cleanup (#2610)
I was going through the output of `cargo tree --duplicate -p uv`, not
much success except these small cleanups.
2024-03-22 10:42:48 +00:00
konsti 375b33ff0c
Remove unused deps with cargo machete (#2609) 2024-03-22 10:01:17 +00:00
Charlie Marsh 0ea51d43f5
Add progress reporting for named requirement resolution (#2605) 2024-03-22 04:01:10 +00:00
Charlie Marsh 31743f2bd8
Use PEP 517 build hooks to resolve unnamed requirements (#2604) 2024-03-22 03:20:40 +00:00
Charlie Marsh 5d7d7dce24
Enable PEP 517 builds for unnamed requirements (#2600)
## Summary

This PR enables the source distribution database to be used with unnamed
requirements (i.e., URLs without a package name). The (significant)
upside here is that we can now use PEP 517 hooks to resolve unnamed
requirement metadata _and_ reuse any computation in the cache.

The changes to `crates/uv-distribution/src/source/mod.rs` are quite
extensive, but mostly mechanical. The core idea is that we introduce a
new `BuildableSource` abstraction, which can either be a distribution,
or an unnamed URL:

```rust
/// A reference to a source that can be built into a built distribution.
///
/// This can either be a distribution (e.g., a package on a registry) or a direct URL.
///
/// Distributions can _also_ point to URLs in lieu of a registry; however, the primary distinction
/// here is that a distribution will always include a package name, while a URL will not.
#[derive(Debug, Clone, Copy)]
pub enum BuildableSource<'a> {
    Dist(&'a SourceDist),
    Url(SourceUrl<'a>),
}
```

All the methods on the source distribution database now accept
`BuildableSource`. `BuildableSource` has a `name()` method, but it
returns `Option<&PackageName>`, and everything is required to work with
and without a package name.

The main drawback of this approach (which isn't a terrible one) is that
we can no longer include the package name in the cache. (We do continue
to use the package name for registry-based distributions, since those
always have a name.). The package name was included in the cache route
for two reasons: (1) it's nice for debugging; and (2) we use it to power
`uv cache clean flask`, to identify the entries that are relevant for
Flask.

To solve this, I changed the `uv cache clean` code to look one level
deeper. So, when we want to determine whether to remove the cache entry
for a given URL, we now look into the directory to see if there are any
wheels that match the package name. This isn't as nice, but it does work
(and we have test coverage for it -- all passing).

I also considered removing the package name from the cache routes for
non-registry _wheels_, for consistency... But, it would require a cache
bump, and it didn't feel important enough to merit that.
2024-03-21 22:46:39 -04:00
Charlie Marsh 63a8bc2b8f
Bump axoupdater to v0.3.3 to fix Windows self-updates (#2598)
Closes #2585.
2024-03-21 16:58:57 -04:00
Zanie Blue c6e181d233
Respect HTTP client options when reading remote requirements files (#2434)
Uses the base client introduced in #2431 to restore use of our fully
configured client when reading remote requirements files.

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

## Test plan

```
npx http-server --username user --password password
cargo run -- pip install -r http://user:password@127.0.0.1:8080/requirements.txt
```

Fails on main succeeds on branch.
2024-03-21 13:48:57 -05:00
Charlie Marsh 0f96386032
Add a garbage collection mechanism to the CLI (#1217)
## Summary

Detects unused cache entries, which can come in a few forms:

1. Directories that are out-dated via our versioning scheme.
2. Old source distribution builds (i.e., we have a more recent version).
3. Old wheels (stored in `archive-v0`, but not symlinked-to from
anywhere in the cache).

Closes https://github.com/astral-sh/puffin/issues/1059.
2024-03-21 18:07:48 +00:00
Zanie Blue 7ee90dc71f
Fix authentication with JFrog artifactories (#2592)
Closes #2566 

We were storing the username e.g. `charlie@astral.sh` as a
percent-encoded string `charlie%40astral.sh` which resulted in different
headers and broke JFrog's artifactory which apparently does not decode
usernames.

Tested with a JFrog artifactory and AWS CodeArtifact although it is
worth noting that AWS does _not_ have a username with an `@` — it'd be
nice to test another artifactory with percent-encoded characters in the
username and/or password.
2024-03-21 12:10:43 -05:00
Charlie Marsh f91ce521c5
Move requirements resolution into its own crate (#2579)
## Summary

No functional changes, but this was a lot of core logic in the `uv`
crate, which is mostly meant to be the CLI.
2024-03-21 13:52:47 +00:00
Charlie Marsh 2979918320
Add support for unnamed Git and HTTP requirements (#2578)
## Summary

Enables, e.g., `uv pip install
git+https://github.com/pallets/flask.git`.

Part of: https://github.com/astral-sh/uv/issues/313.
2024-03-21 13:44:54 +00:00
Charlie Marsh e5b0cf7f89
Add support for unnamed local directory requirements (#2571)
## Summary

For example: `cargo run pip install .`

The strategy taken here is to attempt to extract the package name from
the distribution without executing the PEP 517 build steps. We could
choose to do that in the future if this proves lacking, but it adds
complexity.

Part of: https://github.com/astral-sh/uv/issues/313.
2024-03-21 03:46:11 +00:00
Charlie Marsh 4d96255ade
Enable unnamed requirements for direct URLs (#2569)
## Summary

This PR enables `uv pip install` to accept unnamed requirements, as long
as the requirement ends with the wheel or source distribution archive
name. For example: `cargo run pip install
~/Downloads/anyio-4.3.0.tar.gz`.

In subsequent PRs, I'll expand the scope of supported archives and
patterns.

Part of: https://github.com/astral-sh/uv/issues/313.
2024-03-21 03:39:02 +00:00
Charlie Marsh 0af6a3d41d
Bump version to v0.1.23 (#2580) 2024-03-21 02:51:21 +00:00
Charlie Marsh 00fc44012c
Use relative paths for user display (#2559)
## Summary

This PR changes our user-facing representation for paths to use relative
paths, when the path is within the current working directory. This
mirrors what we do in Ruff. (If the path is _outside_ the current
working directory, we print an absolute path.)

Before:

```shell
❯ uv venv .venv2
Using Python 3.12.2 interpreter at: /Users/crmarsh/workspace/uv/.venv/bin/python3
Creating virtualenv at: .venv2
Activate with: source .venv2/bin/activate
```

After:

```shell
❯ cargo run venv .venv2
    Finished dev [unoptimized + debuginfo] target(s) in 0.15s
     Running `target/debug/uv venv .venv2`
Using Python 3.12.2 interpreter at: .venv/bin/python3
Creating virtualenv at: .venv2
Activate with: source .venv2/bin/activate
```

Note that we still want to use the existing `.simplified_display()`
anywhere that the path is being simplified, but _still_ intended for
machine consumption (e.g., when passing to `.current_dir()`).
2024-03-20 09:52:50 -04:00
konsti 32b9eeb532
Use mac version from python for linehaul information (#2509)
See
https://github.com/astral-sh/uv/pull/2493#pullrequestreview-1942899151.

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2024-03-20 10:55:50 +01:00
Charlie Marsh 1bf48c91f2
Add a `uv self update` command (#2228)
## Summary

Powered by Axo: https://github.com/axodotdev/axoupdater.

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

## Test Plan

To test locally:

- `rm -f ~/.config/uv/uv-receipt.json /Users/crmarsh/.cargo/bin/uv`
- `curl --proto '=https' --tlsv1.2 -LsSf
https://github.com/astral-sh/uv/releases/download/0.1.14/uv-installer.sh
| sh`
- `cargo run self update`

Up-to-date:

![Screenshot 2024-03-06 at 12 13
36 AM](https://github.com/astral-sh/uv/assets/1309177/04bb7a11-6557-4317-8e86-18288fbc13c6)

Updated:

![Screenshot 2024-03-06 at 12 13
54 AM](https://github.com/astral-sh/uv/assets/1309177/c08ad739-5a2b-47cf-bf13-018a8d708330)

No receipt:

![Screenshot 2024-03-06 at 12 14
13 AM](https://github.com/astral-sh/uv/assets/1309177/317bbfaf-a787-4cbf-9f93-a4ce8ca7a988)
2024-03-19 16:02:49 -04:00
Micha Reiser acbee166c0
Remove unused dependencies (#2543)
## Summary

I tried out `cargo shear` to see if there are any unused dependencies
that `cargo udeps` isn't reporting. It turned out, there are a few. This
PR removes those dependencies.

## Test Plan

`cargo build`
2024-03-19 13:10:10 -04:00
Charlie Marsh d0789fc078
Preserve hashes for pinned packages (#2532)
## Summary

When a user runs with `--output-file` and `--generate-hashes`, we should
_only_ update the hashes if the pinned version itself changes.

Closes https://github.com/astral-sh/uv/issues/1530.
2024-03-19 01:02:18 +00:00
dependabot[bot] 1d10014b2d
Bump clap from 4.5.2 to 4.5.3 (#2524)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.2 to 4.5.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/clap-rs/clap/releases">clap's
releases</a>.</em></p>
<blockquote>
<h2>v4.5.3</h2>
<h2>[4.5.3] - 2024-03-15</h2>
<h3>Internal</h3>
<ul>
<li><em>(derive)</em> Update <code>heck</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/clap-rs/clap/blob/master/CHANGELOG.md">clap's
changelog</a>.</em></p>
<blockquote>
<h2>[4.5.3] - 2024-03-15</h2>
<h3>Internal</h3>
<ul>
<li><em>(derive)</em> Update <code>heck</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="4e07b43858"><code>4e07b43</code></a>
chore: Release</li>
<li><a
href="8247c7ddf0"><code>8247c7d</code></a>
docs: Update changelog</li>
<li><a
href="677c52ce08"><code>677c52c</code></a>
chore: Update <code>heck</code> requirement (<a
href="https://redirect.github.com/clap-rs/clap/issues/5396">#5396</a>)</li>
<li>See full diff in <a
href="https://github.com/clap-rs/clap/compare/v4.5.2...v4.5.3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=clap&package-manager=cargo&previous-version=4.5.2&new-version=4.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-18 17:16:36 -05:00
dependabot[bot] 5d5eddbf8d
Bump async-trait from 0.1.77 to 0.1.78 (#2525) 2024-03-18 21:54:17 +00:00
dependabot[bot] c5f7678fcb
Bump toml from 0.8.11 to 0.8.12 (#2523) 2024-03-18 17:52:28 -04:00
Charlie Marsh 9afb360524
Bump version to v0.1.21 (#2517) 2024-03-18 13:51:06 -04:00
samypr100 42973cd9cb
feat: add linehaul info to uv-client (#2493)
## Summary

Closes #1958

This adds linehaul metadata to uv's user-agent when pep 508 markers are
provided to the RegistryClientBuilder. Thanks to #2381, we were able to
leverage most information from markers and avoid inconsistency.

Linehaul is meant to be accompanying metadata pip sends in it's user
agent when talking to registries. You can see this output by running
something like `python -c 'from pip._internal.network.session import
user_agent; print(user_agent())'`.
In PyPI, this metadata processed by the
[linehaul-cloud-function](https://github.com/pypi/linehaul-cloud-function).
More info about linehaul can be found in #1958.

Below are some examples from pip:

* Linux GHA: `pip/24.0
{"ci":true,"cpu":"x86_64","distro":{"id":"jammy","libc":{"lib":"glibc","version":"2.35"},"name":"Ubuntu","version":"22.04"},"implementation":{"name":"CPython","version":"3.12.2"},"installer":{"name":"pip","version":"24.0"},"openssl_version":"OpenSSL
3.0.2 15 Mar
2022","python":"3.12.2","rustc_version":"1.76.0","system":{"name":"Linux","release":"6.5.0-1016-azure"}}`
* Windows GHA: `pip/24.0
{"ci":true,"cpu":"AMD64","implementation":{"name":"CPython","version":"3.12.2"},"installer":{"name":"pip","version":"24.0"},"openssl_version":"OpenSSL
3.0.13 30 Jan
2024","python":"3.12.2","rustc_version":"1.76.0","system":{"name":"Windows","release":"2022Server"}}`
* OSX GHA: `pip/24.0
{"ci":true,"cpu":"arm64","distro":{"name":"macOS","version":"14.2.1"},"implementation":{"name":"CPython","version":"3.12.2"},"installer":{"name":"pip","version":"24.0"},"openssl_version":"OpenSSL
3.0.13 30 Jan
2024","python":"3.12.2","rustc_version":"1.76.0","system":{"name":"Darwin","release":"23.2.0"}}`



Here's how uv results look like (sorry for the keys not having the same
order):

* Linux GHA: `uv/0.1.21
{"installer":{"name":"uv","version":"0.1.21"},"python":"3.12.2","implementation":{"name":"CPython","version":"3.12.2"},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":"Linux","release":"6.5.0-1016-azure"},"cpu":"x86_64","openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}`
* Windows GHA: `uv/0.1.21
{"installer":{"name":"uv","version":"0.1.21"},"python":"3.12.2","implementation":{"name":"CPython","version":"3.12.2"},"distro":null,"system":{"name":"Windows","release":"2022Server"},"cpu":"AMD64","openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}`
* OSX GHA: `uv/0.1.21
{"installer":{"name":"uv","version":"0.1.21"},"python":"3.12.2","implementation":{"name":"CPython","version":"3.12.2"},"distro":{"name":"macOS","version":"14.2.1","id":null,"libc":null},"system":{"name":"Darwin","release":"23.2.0"},"cpu":"arm64","openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}`

Distro information (such as the one pip uses `from pip._vendor import
distro` to retrieve instead of `platform` module) was not retrieved from
markers. Instead, the linux release codename/name/version uses
`sys-info` crate, adding about 50us of extra overhead on linux. The
distro osx version re-used the [mac_os version
implementation](99c992e38b/crates/platform-host/src/mac_os.rs)
from #2381 which adds about 20us of overhead on osx. I tried to use
other crates to avoid re-introducing `mac_os.rs` but most of them didn't
yield satisfactory performance (40ms-60ms~) or had the wrong values
needed (e.g. darwin version vs osx version).

I also didn't add libc retrieval or rustc retrieval as those seem to add
substantial overhead due to querying `ldd` or `rustc`. PyPy version
detection was also not added to avoid adding extra overhead to [support
PyPy for
linehaul](https://github.com/pypa/pip/blob/24.0/src/pip/_internal/network/session.py#L123).
All other behavior was kept 1-1 to match what pip's linehaul
implementation does (as of 24.0). This also aligns with what was
discussed in #1958.

## Test Plan

Added new integration test to uv-client.

---------

Co-authored-by: konstin <konstin@mailbox.org>
2024-03-18 10:46:58 +00:00
Zanie Blue eac23512f6
Add snapshot test for platform tags (#2482)
Adding ordering test coverage as a preface to fixing
https://github.com/astral-sh/uv/issues/2477 (see #2483)
2024-03-16 17:20:57 -05:00
Charlie Marsh db5898bd67
Add support for Hatch's `{root:uri}` paths in editable installs (#2492)
## Summary

If a package uses Hatch's `root.uri` feature, we currently error:

```toml
dependencies = [
  "black @ {root:uri}/../black_editable"
]
```

Even though we're using PEP 517 hooks to get the metadata, which
_should_ support this. The problem is that we load the full
`PyProjectToml`, which means we parse the requirements, which means we
reject what looks like a relative URL in dependencies.

Instead, we should only enforce a limited subset of `pyproject.toml`
(arguably none).

Closes https://github.com/astral-sh/uv/issues/2475.
2024-03-16 19:06:42 +00:00
Zanie Blue e9c12c52fd
Bump version to 0.1.21 (#2457) 2024-03-14 09:43:39 -05:00
Charlie Marsh ea8fc8280a
Bump version to v0.1.20 (#2448) 2024-03-13 23:58:21 -04:00
Zanie Blue 3825c95472
Bump version to 0.1.19 (#2435) 2024-03-13 18:43:53 -05:00
konsti 6e5a737e7a
Update pubgrub for faster range operations (#2421)
This update pulls in https://github.com/pubgrub-rs/pubgrub/pull/177,
optimizing common range operations in pubgrub. Please refer to this PR
for a more extensive description and discussion of the changes.

The changes optimize that last remaining pathological case,
`bio_embeddings[all]` on python 3.12, which has to try 100k versions,
from 12s to 3s in the cached case. It should also enable smarter
prefetching in batches (https://github.com/astral-sh/uv/issues/170),
even though a naive attempt didn't show better network usage.

**before** 12s


![image](https://github.com/pubgrub-rs/pubgrub/assets/6826232/80ffdc49-1159-453d-a3ea-0dd431df6d3b)

**after** 3s


![image](https://github.com/pubgrub-rs/pubgrub/assets/6826232/69508c29-73ab-4593-a588-d8c722242513)

```
$  taskset -c 0 hyperfine --warmup 1 "../uv/target/profiling/main-uv pip compile ../uv/scripts/requirements/bio_embeddings.in"  "../uv/target/profiling/branch-uv pip compile ../uv/scripts/requirements/bio_embeddings.in"
Benchmark 1: ../uv/target/profiling/main-uv pip compile ../uv/scripts/requirements/bio_embeddings.in
  Time (mean ± σ):     12.321 s ±  0.064 s    [User: 12.014 s, System: 0.300 s]
  Range (min … max):   12.224 s … 12.406 s    10 runs

Benchmark 2: ../uv/target/profiling/branch-uv pip compile ../uv/scripts/requirements/bio_embeddings.in
  Time (mean ± σ):      3.109 s ±  0.004 s    [User: 2.782 s, System: 0.321 s]
  Range (min … max):    3.103 s …  3.116 s    10 runs

Summary
  ../uv/target/profiling/branch-uv pip compile ../uv/scripts/requirements/bio_embeddings.in ran
    3.96 ± 0.02 times faster than ../uv/target/profiling/main-uv pip compile ../uv/scripts/requirements/bio_embeddings.in
```

It also adds `bio_embeddings[all]` as a requirements test case.
2024-03-13 17:48:24 -05:00
Zanie Blue 22a52391be
Refactor `AuthenticationStore` to inline credentials (#2427) 2024-03-13 17:48:02 -05:00
Hans Baker 9159731792
Add support for retrieving credentials from `keyring` (#2254)
<!--
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

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

Adds basic keyring auth support for `uv` commands. Adds clone of `pip`'s
`--keyring-provider subprocess` argument (using CLI `keyring` tool).

See issue: https://github.com/astral-sh/uv/issues/1520

## Test Plan

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

Hard to write full-suite unit tests due to reliance on
`process::Command` for `keyring` cli

Manually tested end-to-end in a project with GCP artifact registry using
keyring password:
```bash
➜  uv pip uninstall watchdog
Uninstalled 1 package in 46ms
 - watchdog==4.0.0

➜  cargo run -- pip install --index-url https://<redacted>/python/simple/ --extra-index-url https://<redacted>/pypi-mirror/simple/ watchdog
    Finished dev [unoptimized + debuginfo] target(s) in 0.18s
     Running `target/debug/uv pip install --index-url 'https://<redacted>/python/simple/' --extra-index-url 'https://<redacted>/pypi-mirror/simple/' watchdog`
error: HTTP status client error (401 Unauthorized) for url (https://<redacted>/pypi-mirror/simple/watchdog/)

➜  cargo run -- pip install --keyring-provider subprocess --index-url https://<redacted>/python/simple/ --extra-index-url https://<redacted>/pypi-mirror/simple/ watchdog
    Finished dev [unoptimized + debuginfo] target(s) in 0.17s
     Running `target/debug/uv pip install --keyring-provider subprocess --index-url 'https://<redacted>/python/simple/' --extra-index-url 'https://<redacted>/pypi-mirror/simple/' watchdog`
Resolved 1 package in 2.34s
Installed 1 package in 27ms
 + watchdog==4.0.0
```

`requirements.txt`
```
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    .bin/generate-requirements
#
--index-url https://<redacted>/python/simple/
--extra-index-url https://<redacted>/pypi-mirror/simple/

...
```

```bash
➜  cargo run -- pip install --keyring-provider subprocess -r requirements.txt
    Finished dev [unoptimized + debuginfo] target(s) in 0.19s
     Running `target/debug/uv pip install --keyring-provider subprocess -r requirements.txt`
Resolved 205 packages in 23.52s
   Built <redacted>
   ...
Downloaded 47 packages in 19.32s
Installed 195 packages in 276ms
 + <redacted>
  ...
```

---------

Co-authored-by: Thomas Gilgenast <thomas@vant.ai>
Co-authored-by: Zanie Blue <contact@zanie.dev>
2024-03-13 15:02:18 -05:00
Charlie Marsh d9b160b405
Add backoff for transient Windows failures (#2419)
## Summary

This may be required elsewhere, but all the traces in that issue are
related to persisting the temporary directory to our persistent cache,
so lets start there.

See: https://github.com/astral-sh/uv/issues/1491.
2024-03-13 13:16:26 -04:00
konsti 7964bfbb2b
Move architecture and operating system probing to Python (#2381)
The architecture of uv does not necessarily match that of the python
interpreter (#2326). In cross compiling/testing scenarios the operating
system can also mismatch. To solve this, we move arch and os detection
to python, vendoring the relevant pypa/packaging code, preventing
mismatches between what the python interpreter was compiled for and what
uv was compiled for.

To make the scripts more manageable, they are now a directory in a
tempdir and we run them with `python -m` . I've simplified the
pypa/packaging code since we're still building the tags in rust. A
`Platform` is now instantiated by querying the python interpreter for
its platform. The pypa/packaging files are copied verbatim for easier
updates except a `lru_cache()` python 3.7 backport.

Error handling is done by a `"result": "success|error"` field that allow
passing error details to rust:

```console
$ uv venv --no-cache
  × Can't use Python at `/home/konsti/projects/uv/.venv/bin/python3`
  ╰─▶ Unknown operation system `linux`
```

I've used the [maturin sysconfig
collection](855f6d2cb1/sysconfig)
as reference. I'm unsure how to test these changes across the wide
variety of platforms.

Fixes #2326
2024-03-13 11:51:14 +00:00
Charlie Marsh 99c992e38b
Run `cargo update` (#2399) 2024-03-13 03:20:23 +00:00
Charlie Marsh 43dc9c87a6
Bump version to v0.1.18 (#2398) 2024-03-13 00:25:41 +00:00
konsti 90a60bc4f2
Update pubgrub (#2384)
Rebase pubgrub onto upstream changes, reducing our divergencies with
upstream.
2024-03-12 16:14:50 +00:00
Charlie Marsh e9c16e9aa2
Enable TLS native root toggling at runtime (#2362)
## Summary

It turns out that on macOS, reading the native certificates can add
hundreds of milliseconds to client initialization. This PR makes
`--native-tls` a command-line flag, to toggle (at runtime) the choice of
the `webpki` roots or the native system roots.

You can't accomplish this kind of configuration with the `reqwest`
builder API, so instead, I pulled out the heart of that logic from the
crate
(e319263851/src/async_impl/client.rs (L498)),
and modified it to allow toggling a choice of root.

Note that there's an open PR for this in reqwest
(https://github.com/seanmonstar/reqwest/pull/1848), along with an issue
(https://github.com/seanmonstar/reqwest/issues/1843), which I may ping,
but it's been around for a while and I believe reqwest is focused on its
next major release.

Closes https://github.com/astral-sh/uv/issues/2346.
2024-03-12 04:05:49 +00:00
dependabot[bot] c159a262f2
Bump walkdir from 2.4.0 to 2.5.0 (#2365)
Bumps [walkdir](https://github.com/BurntSushi/walkdir) from 2.4.0 to
2.5.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="4f26be4d45"><code>4f26be4</code></a>
2.5.0</li>
<li><a
href="3be5734033"><code>3be5734</code></a>
api: implement <code>FusedIterator</code></li>
<li><a
href="b0d16b759a"><code>b0d16b7</code></a>
ci: fix it</li>
<li>See full diff in <a
href="https://github.com/BurntSushi/walkdir/compare/2.4.0...2.5.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=walkdir&package-manager=cargo&previous-version=2.4.0&new-version=2.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-11 19:37:08 -04:00
dependabot[bot] 6d67c93e0b
Bump reflink-copy from 0.1.14 to 0.1.15 (#2364) 2024-03-11 17:47:44 -04:00
dependabot[bot] 01533ab939
Bump indexmap from 2.2.3 to 2.2.5 (#2367) 2024-03-11 21:43:34 +00:00
dependabot[bot] 36ff8e0506
Bump ctrlc from 3.4.2 to 3.4.4 (#2366) 2024-03-11 21:42:04 +00:00
konsti f70ae72874
Add a `-vv` log level and make `-v` more readable (#2301)
Behind error messages, the debug log is the second most important
resource to finding out what and why went wrong when there was a problem
with uv. It is important to see which paths it has found and how the
decisions in the resolver were made. I'm trying to improve the
experience interacting with the debug log.

The hierarchical layer is verbose and hard to follow, so it's moved to
the `-vv` extra verbose setting, while `-v` works like
`RUST_LOG=uv=debug`.

For installing jupyter with a warm cache:

* Default:
https://gist.github.com/konstin/4de6e466127311c5a5fc2f99c56a8e11
* `-v`: https://gist.github.com/konstin/e7bafe0ec7d07e47ba98a3865ae2ef3e
* `-vv`:
https://gist.github.com/konstin/3ee1aaff37f91cceb6275dd5525f180e
Ideally, we would have `-v`, `-vv` and `-vvv`, but we're lacking the the
`info!` layer for `-v`, so there's only two layers for now.

The `tracing_subcriber` formatter always print the current span, so i
replaced it with a custom formatter.


![image](https://github.com/astral-sh/uv/assets/6826232/75f5cfd1-da7b-432e-b090-2f3916930dd1)

Best read commit-by-commit.
2024-03-11 08:58:31 +01:00
Charlie Marsh b9b4109ad8
Initialize client lazily for remote requirements files (#2350)
## Summary

We now initialize an HTTP client in advance for remote requirements
files. It turns out this adds a significant overhead, even for
operations like auditing the environment (at least on macOS).

This PR makes initialization lazy. After a lot of evaluation, I took the
easiest route, which is: we just pass in `Connectivity`, and then use
the default HTTP client. So we won't respect netrc files and anything
else that we get from our registry client. If we want to keep using the
registry client, we _can_, it's just way more ceremony to pass down a
closure.

See: https://github.com/astral-sh/uv/issues/2346.

## Test Plan

- Verified that `cargo run pip compile
https://raw.githubusercontent.com/ansible/ansible/f1ded0f41759235eb15a7d13dbc3c95dce5d5acd/requirements.txt`
completed without error.
- Verified that `cargo run pip compile
https://raw.githubusercontent.com/ansible/ansible/f1ded0f41759235eb15a7d13dbc3c95dce5d5acd/requirements.txt
--offline` failed with an error.
- Verified that `./target/release/uv pip install requests` completed in
0-2ms, rather than hundreds.
2024-03-11 00:42:38 +00:00
Charlie Marsh bb2d06cbb2
Bump version to v0.1.17 (#2344) 2024-03-10 15:07:11 -04:00
Charlie Marsh 67fb023f10
Avoid duplicating authorization header with netrc (#2325)
## Summary

The netrc middleware we added in
https://github.com/astral-sh/uv/pull/2241 has a slight problem. If you
include credentials in your index URL, _and_ in the netrc file, the
crate blindly adds the netrc credentials as a header. And given the
`ReqwestBuilder` API, this means you end up with _two_ `Authorization`
headers, which always leads to an invalid request, though the exact
failure can take different forms.

This PR removes the middleware crate in favor of our own middleware.
Instead of using the `RequestInitialiser` API, we have to use the
`Middleware` API, so that we can remove the header on the request
itself.

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

## Test Plan

- Verified that running against a private index with credentials in the
URL (but no netrc file) worked without error.
- Verified that running against a private index with credentials in the
netrc file (but not the URL) worked without error.
- Verified that running against a private index with a mix of
credentials in both _also_ worked without error.
2024-03-10 15:02:24 +00:00
Zanie Blue 10c4effbd3
Refactor incompatiblity tracking for distributions (#1298)
Extends the "compatibility" types introduced in #1293 to apply to source
distributions as well as wheels.

- We now track the most-relevant incompatible source distribution
- Exclude newer, Python requirements, and yanked versions are all
tracked as incompatibilities in the new model (this lets us remove
`DistMetadata`!)
2024-03-08 11:02:31 -06:00
Andrew Gallant b3b5afaf78 uv-fs: transparently support reading UTF-16 files
This PR tweaks uv to support reading `requirements.txt` regardless of
whether it is encoded as UTF-8 or UTF-16. This is particularly relevant
on Windows where `uv pip freeze > requirements.txt` will likely write a
UTF-16 encoded `requirements.txt` file.

There is some discussion on #1666 where it's suggested that perhaps
we should explicitly not support this. I didn't see that until I
had already put this PR together, but even so, I think it's worth
considering this. UTF-16 is predominant on Windows. It is very easy
to produce a UTF-16 encoded file. Moreover, there is an easy and well
specified way to recognize and transcode UTF-16 encoded data to UTF-8.

I think the downside of this is that it could encourage the use UTF-16
encoded `requirements.txt` files *in addition* to UTF-8 encoded
files, and it would probably be nice to converge and standardize on
one encoding. One possible alternative to this PR is that we provide
a better error message. Another alternative is to ensure that a
`-o/--output` flag exists for all commands (neither `uv pip freeze` nor
`pip freeze` have such a flag) so that users can always write output
to a file without relying on their environment's piping behavior.
(Although this last alternative seems a little sad to me.)

It's also worth noting the [PEP-0508] doesn't seem to mention file
encoding at all. So I think from a "do the standards allow this"
perspective, this change is OK.

Finally, `pip` itself seems to work with UTF-16 encoded
`requirements.txt` files.

I think I personally overall lean towards supporting UTF-16 for
`requirements.txt` files. In part because I think it smoothes out the
UX a little bit, in part because there is no obvious specification
(that I'm aware of) that mandates that these files are UTF-8, and
finally in part because `pip` supports it too.

Fixes #1666, Fixes #2276

[PEP-0508]: https://peps.python.org/pep-0508/
2024-03-08 09:10:14 -05:00
Charlie Marsh 26f6919465
Move source distribution unpacking out of `build` (#2294)
## Summary

If a user provides a source distribution via a direct path, it can
either be an archive (like a `.tar.gz` or `.zip` file) or a directory.
If the former, we need to extract (e.g., unzip) the contents at some
point. Previously, this extraction was in `uv-build`; this PR lifts it
up to the distribution database.

The first benefit here is that various methods that take the
distribution are now simpler, as they can assume a directory.

The second benefit is that we no longer extract _multiple times_ when
working with a source distribution. (Previously, if we tried to get the
metadata, then fell back and built the wheel, we'd extract the wheel
_twice_.)
2024-03-08 03:40:11 +00:00
Charlie Marsh 9f1452cb72
Bump version to v0.1.16 (#2289) 2024-03-07 18:12:18 -05:00
Charlie Marsh 996a859b29
Use reparse points to detect Windows installer shims (#2284)
## Summary

This PR enables use of the Windows Store Pythons even with `py` is not
installed. Specifically, we need to ensure that the `python.exe` and
`python3.exe` executables installed into the
`C:\Users\crmar\AppData\Local\Microsoft\WindowsApp` directory _are_ used
when they're not "App execution aliases" (which merely open the Windows
Store, to help you install Python).

When `py` is installed, this isn't strictly necessary, since the
"resolved" executables are discovered via `py`. These look like
`C:\Users\crmar\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.11_qbs5n2kfra8p0\python.exe`.

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

## Test Plan

- Removed all Python installations from my Windows machine.
- Uninstalled `py`.
- Enabled "App execution aliases".
- Verified that for both `cargo run venv --python python.exe` and `cargo
run venv --python python3.exe`, `uv` exited with a failure that no
Python could be found.
- Installed Python 3.10 via the Windows Store.
- Verified that the above commands succeeded without error.
- Verified that `cargo run venv --python python3.10.exe` _also_
succeeded.
2024-03-07 15:47:32 -05:00
konsti d249574a47
Use insta in pep508_rs (#2275)
Quality of life improvement that aligns pep508_rs with the rest of our
testing.
2024-03-07 08:54:05 -05:00
Bas Schoenmaeckers e7742070c1
feat: Add netrc authentication to uv-client (#2241)
## Summary

Add netrc support to the uv-client.

closes #1405 

## Test Plan

I've added a corresponding test case to validate the correct header.
Furthermore a tested it against a real world private repository.
2024-03-06 20:48:30 +00:00
konsti 97b4526825
Update pubgrub onto upstream (#2243)
No functional changes, just pulling in the upstream changes in
preparation of new changes.
2024-03-06 16:06:35 +00:00
Charlie Marsh 3ca777673f
Make `Client` optional in `requirements-txt` (#2229) 2024-03-06 05:49:09 +00:00
jannisko 71626e8dec
Support remote `https://` requirements files (#1332) (#2081)
## Summary

Allow using http(s) urls for constraints and requirements files handed
to the CLI, by handling paths starting with `http://` or `https://`
differently. This allows commands for such as: `uv pip install -c
https://raw.githubusercontent.com/apache/airflow/constraints-2.8.1/constraints-3.8.txt
requests`.

closes #1332

## Test Plan

Testing install using a `constraints.txt` file hosted on github in the
airflow repository:

fbdc2eba8e/crates/uv/tests/pip_install.rs (L1440-L1484)

## Advice Needed

- filesystem/http dispatch is implemented at a relatively low level (at
`crates/uv-fs/src/lib.rs#read_to_string`). Should I change some naming
here so it is obvious that the function is able to dispatch?
- I kept the CLI argument for -c and -r as a PathBuf, even though now it
is technically either a path or a url. We could either keep this as is
for now, or implement a new enum for this case? The enum could then
handle dispatch to files/http.
- Using another abstraction layer like
https://docs.rs/object_store/latest/object_store/ for the
files/urls/[s3] could work as well, though I ran into a bug during
testing which I couldn't debug
2024-03-06 04:18:11 +00:00
Charlie Marsh 0f6fc117c1
Query interpreter to determine correct `virtualenv` paths (#2188)
## Summary

This PR migrates our virtualenv creation from a setup that assumes prior
knowledge of the correct paths, to a technique borrowed from
`virtualenv` whereby we use `sysconfig` and `distutils` to determine the
paths. The general trick is to grab the expected paths with `sysconfig`,
then make them all relative, then make them absolute for a given
directory.

Closes #2095.
Closes #2153.
2024-03-05 16:13:24 -05:00
Charlie Marsh 043d72646d
Bump version to v0.1.15 (#2217) 2024-03-05 14:47:10 -05:00
konsti 2a53e789b0
Add an option to bytecode compile during installation (#2086)
Add a `--compile` option to `pip install` and `pip sync`.

I chose to implement this as a separate pass over the entire venv. If we
wanted to compile during installation, we'd have to make sure that
writing is exclusive, to avoid concurrent processes writing broken
`.pyc` files. Additionally, this ensures that the entire site-packages
are bytecode compiled, even if there are packages that aren't from this
`uv` invocation. The disadvantage is that we do not update RECORD and
rely on this comment from [PEP 491](https://peps.python.org/pep-0491/):

> Uninstallers should be smart enough to remove .pyc even if it is not
mentioned in RECORD.

If this is a problem we can change it to run during installation and
write RECORD entries.

Internally, this is implemented as an async work-stealing subprocess
worker pool. The producer is a directory traversal over site-packages,
sending each `.py` file to a bounded async FIFO queue/channel. Each
worker has a long-running python process. It pops the queue to get a
single path (or exists if the channel is closed), then sends it to
stdin, waits until it's informed that the compilation is done through a
line on stdout, and repeat. This is fast, e.g. installing `jupyter
plotly` on Python 3.12 it processes 15876 files in 319ms with 32 threads
(vs. 3.8s with a single core). The python processes internally calls
`compileall.compile_file`, the same as pip.

Like pip, we ignore and silence all compilation errors
(https://github.com/astral-sh/uv/issues/1559). There is a 10s timeout to
handle the case when the workers got stuck. For the reviewers, please
check if i missed any spots where we could deadlock, this is the hardest
part of this PR.

I've added `uv-dev compile <dir>` and `uv-dev clear-compile <dir>`
commands, mainly for my own benchmarking. I don't want to expose them in
`uv`, they almost certainly not the correct workflow and we don't want
to support them.

Fixes #1788
Closes #1559
Closes #1928
2024-03-05 03:35:24 +00:00
dependabot[bot] e66afa8767
Bump insta from 1.35.1 to 1.36.1 (#2180) 2024-03-04 23:01:49 +00:00
dependabot[bot] bc43f609b9
Bump http from 0.2.11 to 0.2.12 (#2179) 2024-03-04 22:22:45 +00:00
dependabot[bot] 5aedcffdf0
Bump log from 0.4.20 to 0.4.21 (#2178) 2024-03-04 16:16:20 -06:00
dependabot[bot] 9fcffae084
Bump anstream from 0.6.12 to 0.6.13 (#2177) 2024-03-04 16:16:10 -06:00
Charlie Marsh 5fed1f6259
Use simpler pip-like `Scheme` for install paths (#2173)
## Summary

This will make it easier to use the paths returned by `distutils.py`
(for some cases). No code or behavior changes; just removing some fields
we don't need.
2024-03-04 15:50:13 -05:00
samypr100 93f5609476
feat: add uv version to user agent (#2136)
## Summary

Closes #1977

This allows us to send uv's version in the `uv-client` User Agent
header.

Here's how request headers look like to a server now:
```
...
Accept: application/vnd.pypi.simple.v1+json, application/vnd.pypi.simple.v1+html;q=0.2, text/html;q=0.01
User-Agent: uv/0.1.13
...
```

~~I went for a mix of Option 1 and 2 from #1977.~~ Open to alternative
naming as well, not tied too strongly here to the names picked.

~~Another possibility for this new crate is that we can use it to
consolidate metadata that exists across crates to ultimately be able to
create linehaul information described in #1958, but I haven't looked
into what those changes might look like.~~

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

## Test Plan

<!-- How was it tested? -->
Added initial tests in the new crate to exercise its public API and
added a new test to uv-client to validate the headers using a 1-time
disposable server.
2024-03-04 19:48:41 +00:00
Charlie Marsh c525fdf2b5
Bump version to v0.1.14 (#2157) 2024-03-04 15:42:33 +00:00
Charlie Marsh 6f54aacfea
Remove `camino` from `uv-virtualenv` (#2119)
## Summary

I think Camino is nice but it makes it much harder to work in
`uv-virtualenv`, since it's the _only_ crate that uses it. If we want to
use Camino, we should use it everywhere IMO.
2024-03-01 19:36:56 +00:00
Charlie Marsh 59c7a10c4b
Rename `gourgeist` to `uv-virtualenv` (#2118)
As agreed on Discord!
2024-03-01 14:02:40 -05:00
Charlie Marsh 9ce5170e64
Bump version to v0.1.13 (#2090) 2024-02-29 17:39:28 +00:00
Tim de Jager 0fbfa11013
Add option pass environment variables for SDist building (#2039)
<!--
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

With this PR I've added the option environment variables to the wheel
building process, through the `BuildDispatch`. When integrating uv with
our project pixi (https://github.com/prefix-dev/pixi/pull/863). We ran
into this missing requirement, I've made a rough version here, could
maybe use some refinement.

### Why do we need this?

Because pixi allow the user to use a conda activated prefix for wheel
building, this comes with a number of environment variables, like `PATH`
but also `CONDA_PREFIX` amongst others. This allows the user to use
system dependencies from conda-forge to use during an sdist build.
Because we use `uv` as a library we need to pass in the options
programatically. Additionally, in general there is nothing holding a
python sdist back from actually depending on an environment variable,
see
e.g the test package: https://pypi.org/project/env-test-package/

### What about `ConfigSettings`

I think `ConfigSettings` does not suffice because e.g. CMake could
function differently when the `CONDA_PREFIX` is set. Also, we do not
know if the user supplied backend actually support these settings.

### Path handling

Because the user can now also supply a PATH in the environment map, the
logic I had was the following, I format the path so that it has the
following precedence

1. venv scripts dir.
2. user supplied path.
3. system path.

### Improvements

There is some path modification and copying happening everytime we use
the `run_python_script` function, I think we could improve this but
would like some pointers where to best put the maybe split and cached
version, we might also want to use some types to split these things up.


### Finally

I did not add any of these options to the uv executables, I first would
like to know if this is a direction we would want to go in. I'm happy to
do this or make any changes that you feel would benefit this project.

Also tagging @wolfv to keep track of this as well.  

## Test Plan

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

---------

Co-authored-by: konsti <konstin@mailbox.org>
2024-02-29 10:55:10 +00:00
Charlie Marsh f68b2d1d5e
Bump version to v0.1.12 (#2051) 2024-02-28 15:36:22 -05:00
Charlie Marsh 995fba8fec
Surface the `EXTERNALLY-MANAGED` message to users (#2032)
## Summary

Per the
[spec](https://packaging.python.org/en/latest/specifications/externally-managed-environments/),
this message should be surfaced to users:

![Screenshot 2024-02-27 at 10 42
52 PM](https://github.com/astral-sh/uv/assets/1309177/dac3bd6b-dd05-4146-8faa-f046492e8a26)
2024-02-27 23:18:45 -05:00
Charlie Marsh 10175143d1
Add a `--python` flag to allow installation into arbitrary Python interpreters (#2000)
## Summary

This PR adds a `--python` flag that allows users to provide a specific
Python interpreter into which `uv` should install packages. This would
replace the `VIRTUAL_ENV=` workaround that folks have been using to
install into arbitrary, system environments, while _also_ actually being
correct for installing into non-virtual environments, where the bin and
site-packages paths can differ.

The approach taken here is to use `sysconfig.get_paths()` to get the
correct paths from the interpreter, and then use those for determining
the `bin` and `site-packages` directories, rather than constructing them
based on hard-coded expectations for each platform.

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

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

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

## Test Plan

- Verified that, on my Windows machine, I was able to install `requests`
into a global environment with: `cargo run pip install requests --python
'C:\\Users\\crmarsh\\AppData\\Local\\Programs\\Python\\Python3.12\\python.exe`,
then `python` and `import requests`.
- Verified that, on macOS, I was able to install `requests` into a
global environment installed via Homebrew with: `cargo run pip install
requests --python $(which python3.8)`.
2024-02-28 02:10:29 +00:00
Charlie Marsh 72a5ebada3
Un-cache editable requirements with dynamic metadata (#2029)
Closes https://github.com/astral-sh/uv/issues/1991.
2024-02-28 01:56:25 +00:00
Charlie Marsh 5997d0da3d
Remove some unused code from `install-wheel-rs` (#2001)
I need to make a bunch of changes to this crate, and I'm finding that
the existing unused interfaces are really getting in the way.
2024-02-27 04:27:25 +00:00
dependabot[bot] 6678d545fb
Bump serde_json from 1.0.113 to 1.0.114 (#1996) 2024-02-26 23:12:54 +00:00
dependabot[bot] 78d8bdc2d5
Bump assert_cmd from 2.0.13 to 2.0.14 (#1995) 2024-02-26 17:01:22 -06:00
dependabot[bot] abbdad1856
Bump anstream from 0.6.11 to 0.6.12 (#1994) 2024-02-26 17:01:16 -06:00
dependabot[bot] ae525d4720
Bump serde from 1.0.196 to 1.0.197 (#1993) 2024-02-26 17:01:09 -06:00
dependabot[bot] 22fb373ab2
Bump target-lexicon from 0.12.13 to 0.12.14 (#1992) 2024-02-26 17:01:01 -06:00
Charlie Marsh 4fdf230c2f
Support recursive extras in direct `pyproject.toml` files (#1990)
## Summary

When a `pyproject.toml` is provided directly to `uv pip compile`, we
were failing to resolve recursive extras. The solution I settled on here
is to flatten them recursively when determining the requirements
upfront.

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

## Test Plan

`cargo test`
2024-02-26 15:44:25 -05:00
Charlie Marsh 32e5cacdd6
Bump version to v0.1.11 (#1976) 2024-02-26 10:46:17 -05:00
Taniguchi Yasufumi 70e877d11c
Add `fs_err` to `disallowed_method` in clippy.toml (#1950)
## Summary

Resolve #1916

---------

Co-authored-by: konsti <konstin@mailbox.org>
2024-02-26 14:15:07 +00:00
Simon Brugman 0f1377bb08
`uv pip list` (#1662)
Hi, love your work on `uv` 👋! 

Opening a Draft PR early to check if there are any existing rust table
formatting libs that I am unaware of (either already in `uv`/`ruff`, or
the rust ecosystem) before spending much time on inventing the wheel
myself and cleaning it up. Any other pointers are also welcome (e.g. on
the editable filtering).

Editable project locations in `uv pip list` include the file scheme
(`file://`), where they are omitted in `pip list`. Is this desired, or
should it replicate pip?

## Summary

Implementation for #1401 
`--editable` flag is implemented.

`--outdated` and `--uptodate` out of scope for this PR (requires latest
version information, and type wheel/sdist)

## Test Plan

Not yet implemented as I couldn't locate the tests for `uv pip freeze`.
We can compare to `pip` in
`scripts/compare_with_pip/compare_with_pip.py`?
2024-02-25 19:42:27 +00:00
Charlie Marsh a1f50418fd
Avoid erroring for source distributions with symlinks in archive (#1944)
## Summary

For context, we have three extraction paths:

- untar (async) - used for any `.tar.gz`, local or remote.
- unzip (async) - used to unzip remote wheels, or local or remote source
distributions.
- unzip (sync) - used to untar locally-available wheels into the cache.

We use three different crates for these:

- [`tokio-tar`](https://github.com/vorot93/tokio-tar)
- [`async-zip`](https://github.com/Majored/rs-async-zip)
- [`zip-rs`](https://github.com/zip-rs/zip)

These all seem to have different support for symlinks:

- `tokio-tar` tries to create a symlink (which works fine on Unix but
errors on Windows, since we typically don't have elevated permissions).
- `async-zip` _seems_ to write the target contents directly to the file
(which is what we want).
- `zip-rs` _apparently_ writes the _name_ of the target to the file
(which isn't what we want).

Thankfully, symlinks are not allowed in wheels
(https://github.com/pypa/pip/issues/5919,
https://discuss.python.org/t/symbolic-links-in-wheels/1945), so we can
ignore `zip-rs`.

For `tokio-tar`, we now _skip_ (and warn) if we see a symlink on
Windows. We could do what pip does, and recursively copy, but it's
difficult because we don't have `Seek` on the file. (Alternatively, we
could use hard links and junctions, though those also might need to
exist already.) Let's see how far this gets us.

(We also no longer attempt to set permissions on symlinks on Unix, which
caused another failure.)

Closes https://github.com/astral-sh/uv/issues/1858.
2024-02-24 03:22:13 +00:00
dependabot[bot] 019e2fd1b5
Bump insta from 1.34.0 to 1.35.1 (#1942) 2024-02-23 21:00:35 +00:00
dependabot[bot] 8ff6182815
Bump anyhow from 1.0.79 to 1.0.80 (#1941) 2024-02-23 14:01:40 -06:00
dependabot[bot] 7e0d9b2cea
Bump pyo3 from 0.20.2 to 0.20.3 (#1940) 2024-02-23 14:01:18 -06:00
dependabot[bot] fee79aea7d
Bump itertools from 0.10.5 to 0.12.1 (#1939) 2024-02-23 14:01:11 -06:00
dependabot[bot] 086e58e54a
Bump textwrap from 0.16.0 to 0.16.1 (#1938) 2024-02-23 14:01:05 -06:00
Zanie Blue af39bbde75
Add long-form version output (#1930)
Similar to https://github.com/astral-sh/ruff/pull/8034

Adds more version information so it's clear what revision the user is on

```
❯ cargo run -q -- --version
uv 0.1.10 (daa8565a7 2024-02-23)
❯ cargo run -q -- -V
uv 0.1.10
❯ cargo run -q -- version
uv 0.1.10 (daa8565a7 2024-02-23)
❯ cargo run -q -- version --output-format json
{
  "version": "0.1.10",
  "commit_info": {
    "short_commit_hash": "daa8565a7",
    "commit_hash": "daa8565a75249305821fdc34ace085060c082ba3",
    "commit_date": "2024-02-23",
    "last_tag": null,
    "commits_since_last_tag": 0
  }
}
```
2024-02-23 13:45:01 -06:00
Zanie Blue daa8565a75
Bump version to 0.1.10 (#1923) 2024-02-23 11:40:36 -06:00
Zanie Blue fe1847561c
Retain authentication when making range requests (#1902)
Needs https://github.com/prefix-dev/async_http_range_reader/pull/9
Closes https://github.com/astral-sh/uv/issues/1709
2024-02-23 15:21:10 +00:00
Charlie Marsh 0212cb72e9
Bump version to v0.1.9 (#1891) 2024-02-23 01:32:48 +00:00
Charlie Marsh aa73a4f0ea
Add support for `config_settings` in PEP 517 hooks (#1833)
## Summary

Adds `--config-setting` / `-C` (with a `--config-settings` alias for
convenience) to the CLI.

Closes https://github.com/astral-sh/uv/issues/1460.
2024-02-23 00:53:45 +00:00
Zanie Blue 8a12b2ebf9
Ensure authentication is passed from the index url to distribution files (#1886)
Closes https://github.com/astral-sh/uv/issues/1709
Closes https://github.com/astral-sh/uv/issues/1371

Tested with the reproduction provided in #1709 which gets past the HTTP
401.

Reuses the same copying logic we introduced in
https://github.com/astral-sh/uv/pull/1874 to ensure authentication is
attached to file URLs with a realm that matches that of the index. I had
to move the authentication logic into a new crate so it could be used in
`distribution-types`.

We will want to something more robust in the future, like track all
realms with authentication in a central store and perform lookups there.
That's what `pip` does and it allows consolidation of logic like netrc
lookups. That refactor feels significant though, and I'd like to get
this fixed ASAP so this is a minimal fix.
2024-02-22 18:10:17 -06:00
Zanie Blue f0b39a36b4
Bump version to 0.1.8 (#1880) 2024-02-22 13:11:58 -06:00
Charlie Marsh 12462e5730
Bump version to v0.1.7 (#1851) 2024-02-21 22:31:23 -05:00
Charlie Marsh 7eaed07f6c
Move conflicting dependencies into PubGrub (#1796)
## Summary

This revives a PR from long ago
(https://github.com/astral-sh/uv/pull/383 and
https://github.com/zanieb/pubgrub/pull/24) that modifies how we deal
with dependencies that are declared multiple times within a single
package.

To quote from the originating PR:

> Uses an experimental pubgrub branch (#370) that allows us to handle
multiple version ranges for a single dependency to the solver which
results in better error messages because the derivation tree contains
all of the relevant versions. Previously, the version ranges were merged
(by us) in the resolver before handing them to pubgrub since only one
range could be provided per package. Since we don't merge the versions
anymore, we no longer give the solver an empty range for conflicting
requirements; instead the solver comes to that conclusion from the
provided versions. You can see the improved error message for direct
dependencies in [this
snapshot](https://github.com/astral-sh/puffin/pull/383/files#diff-a0437f2c20cde5e2f15199a3bf81a102b92580063268417847ec9c793a115bd0).

The main issue with that PR was around its handling of URL dependencies,
so this PR _also_ refactors how we handle those. Previously, we stored
URL dependencies on `PubGrubPackage`, but they were omitted from the
hash and equality implementations of `PubGrubPackage`. This led to some
really careful codepaths wherein we had to ensure that we always visited
URLs before non-URL packages, so that the URL-inclusive versions were
included in any hashmaps, etc. I considered preserving this approach,
but it would require us to rely on lots of internal details of PubGrub
(since we'd now be relying on PubGrub to merge those packages in the
"right" order).

So, instead, we now _always_ set the URL on a given package, whenever
that package was _given_ a URL upfront. I think this is easier to reason
about: if the user provided a URL for `flask`, then we should just
always add the URL for `flask`. If we see some other URL for `flask`, we
error, like before. If we see some unknown URL for `flask`, we error,
like before.

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

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

Closes https://github.com/astral-sh/uv/issues/1615.
2024-02-21 21:27:58 -05:00
Micha Reiser fac9d843dc
Normalize `VIRTUAL_ENV` path in activation scripts (#1817) 2024-02-21 15:52:32 +00:00
Charlie Marsh 88a0c13865
Use async unzip for local source distributions (#1809)
## Summary

We currently maintain separate untar methods for sync and async, but we
only use the sync version when the user provides a local source
distribution. (Otherwise, we untar as we download the distribution.) In
my testing, this is actually slower anyway:

```
❯ python -m scripts.bench \
        --uv-path ./target/release/main \
        --uv-path ./target/release/uv \
        ./requirements.in --benchmark resolve-cold --min-runs 50
Benchmark 1: ./target/release/main (resolve-cold)
  Time (mean ± σ):     835.2 ms ± 107.4 ms    [User: 346.0 ms, System: 151.3 ms]
  Range (min … max):   639.2 ms … 1051.0 ms    50 runs

Benchmark 2: ./target/release/uv (resolve-cold)
  Time (mean ± σ):     750.7 ms ±  91.9 ms    [User: 345.7 ms, System: 149.4 ms]
  Range (min … max):   637.9 ms … 905.7 ms    50 runs

Summary
  './target/release/uv (resolve-cold)' ran
    1.11 ± 0.20 times faster than './target/release/main (resolve-cold)'
```
2024-02-21 14:11:37 +00:00
Charlie Marsh a2a1b2fb0f
Avoid enforcing URL correctness for installed distributions (#1793)
## Summary

Allows the corresponding `pypi_types` struct to use any URL, since other
installers can put those into the environment, and Poetry seems to write
invalid URLs.

If we see a distribution with an invalid URL, we just treat it as a
registry distribution, which isn't ideal, but is better than (1)
erroring, and (2) changing `Url` to `String` everywhere internally. (I'm
torn on this second option.)

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

## Test Plan

- Added `flask = { git = "git@github.com:pallets/flask.git", rev =
"b90a4f1f4a370e92054b9cc9db0efcb864f87ebe" }` to
`scripts/editable-installs/poetry_editable/pyproject.toml`.
- Ran `poetry install`.
- Ran `cargo pip freeze`. Verified that it errored on `main`, but passed
here.
- Ran `cargo run pip install "flask==3.0.0"`. Verified that it
uninstalled the existing Flask, and installed a new version from the
registry.
2024-02-21 09:06:31 -05:00
Zanie Blue d07b587f3f
Retain passwords in Git URLs (#1717)
Fixes handling of GitHub PATs in HTTPS URLs, which were otherwise
dropped. We now supporting the following authentication schemes:

```
git+https://<user>:<token>/...
git+https://<token>/...
```

On Windows, the username is required. We can consider adding a
special-case for this in the future, but this just matches libgit2's
behavior.

I tested with fine-grained tokens, OAuth tokens, and "classic" tokens.
There's test coverage for fine-grained tokens in CI where we use a real
private repository and PAT. Yes, the PAT is committed to make this test
usable by anyone. It has read-only permissions to the single repository,
expires Feb 1 2025, and is in an isolated organization and GitHub
account.

Does not yet address SSH authentication.

Related:
- https://github.com/astral-sh/uv/issues/1514
- https://github.com/astral-sh/uv/issues/1452
2024-02-21 00:12:56 +00:00
konsti 2928c6e574
Backport changes from publish crates (#1739)
Backport of changes for the published new versions of pep440_rs and
pep508_rs to make it easier to keep them in sync.
2024-02-20 19:33:27 +01:00
Charlie Marsh ede2828fde
Bump version to v0.1.6 (#1736) 2024-02-20 12:22:26 -05:00
Di-Is 36edaeecf2
Control pip timeout duration via environment variable (#1694)
<!--
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

Add the environment variable `UV_REQUEST_TIMEOUT` to allow control over
pip timeouts.

Closes #1549 

## Test Plan

I built uv in the repository top Dockerfile, set the timeout to 3
seconds, and ran `uv pip install torch`.
I measured the execution time with the time command and confirmed that
the process finished at a value close to the timeout we set.

```bash
root@037c69228cdc:~# time UV_REQUEST_TIMEOUT=3 /uv pip install torch
Resolved 22 packages in 25ms
error: Failed to download distributions
  Caused by: Failed to fetch wheel: nvidia-cusolver-cu12==11.4.5.107
  Caused by: Failed to extract source distribution
  Caused by: request or response body error: operation timed out
  Caused by: operation timed out

real    0m3.064s
user    0m0.225s
sys     0m0.240s
```
2024-02-19 22:37:56 -06:00
Charlie Marsh 034f62b24f
Respect `--index-url` provided via requirements.txt (#1719)
## Summary

When we read `--index-url` from a `requirements.txt`, we attempt to
respect the `--index-url` provided by the CLI if it exists.
Unfortunately, `--index-url` from the CLI has a default value... so we
_never_ respect the `--index-url` in the requirements file.

This PR modifies the CLI to use `None`, and moves the default into logic
in the `IndexLocations `struct.

Closes https://github.com/astral-sh/uv/issues/1692.
2024-02-20 00:02:26 +00:00
Alexander Gherm 4dfcf32e4c
Add shell completions generation (#1675)
<!--
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 cli command / flag (`generate-shell-completion <SHELL>` /
`--generate-shell-completion <SHELL>`) to generate the completion script
for the given shell. Implemented in exactly the same way as it is done
in ruff
(https://github.com/astral-sh/ruff/blob/main/crates/ruff/src/lib.rs#L197)

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

## Test Plan

I've normally tested the generated script manually only for bash shell
on Ubuntu 22.04.3
```bash
$ uv --generate-shell-completion bash > /usr/share/bash-completion/completions/uv
$ uv # <TAB>
-q                         -h                         --verbose                  --no-cache                 --version                  clean
-v                         -V                         --no-color                 --cache-dir                pip                        generate-shell-completion
-n                         --quiet                    --color                    --help                     venv                       help
$ uv pip # <TAB>
-q           -n           -V           --verbose    --color      --cache-dir  --version    sync         uninstall    help
-v           -h           --quiet      --no-color   --no-cache   --help       compile      install      freeze
```
2024-02-18 21:43:18 -06:00
Zanie Blue 07349e39e8
Bump version to v0.1.5 (#1671) 2024-02-18 20:18:07 -06:00
Charlie Marsh 5cdc6de4a9
Add `CACHEDIR.TAG` to uv-created virtualenvs (#1653)
## Summary

Just as we mark virtualenvs as `gitignore`d by default, we should also
mark them as `CACHEDIR.TAG`, to ensure that they aren't included in
backups, etc.

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

## Test Plan

Ran `cargo run venv` and:

```
❯ ls .venv
CACHEDIR.TAG bin          lib          pyvenv.cfg
```
2024-02-18 13:32:11 -05:00
Charlie Marsh ea62ae4ebd
Bump version to v0.1.4 (#1608) 2024-02-17 15:22:07 -05:00
Charlie Marsh facc60f3a8
Add graceful fallback for Artifactory indexes (#1574)
## Summary

There are more details in https://github.com/astral-sh/uv/issues/1370,
but it looks like Artifactory servers have incorrect behavior when it
comes to HTTP range requests, in that they return `Accept-Ranges:
bytes`, but then incorrectly return 200 requests when you actually ask
for a given range.

This PR ensures that we fallback gracefully in this case. It's built on
https://github.com/prefix-dev/async_http_range_reader/pull/5. Assuming
that gets merged upstream, we can then remove the Git dependency.

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

## Test Plan

`cargo run pip install requests -i
https://killjoyuvbug.jfrog.io/artifactory/api/pypi/pypi/simple
--verbose`
2024-02-17 14:37:06 +00:00
Charlie Marsh 1110489c29
Bump version to v0.1.3 (#1557) 2024-02-16 19:45:29 -05:00
Charlie Marsh 9e0336c28a
Remove URL encoding when determining file name (#1555)
## Summary

Closes https://github.com/astral-sh/uv/issues/1553.
2024-02-16 19:15:24 -05:00
Charlie Marsh 4f216f3a74
Apply percent-decoding to filepaths in HTML find-links (#1544)
## Summary

Closes https://github.com/astral-sh/uv/issues/1542.
2024-02-16 16:47:04 -05:00
Charlie Marsh 01ffc36520
Apply percent-decoding to file-based URLs (#1541)
## Summary

Closes https://github.com/astral-sh/uv/issues/1537.
2024-02-16 16:11:16 -05:00
Zanie Blue 9737b93b79
Use the system trust store for HTTPS requests (#1512)
Closes #1474 

Using the `rustls-tls-native-roots` feature

> `rustls-tls`: Enables TLS functionality provided by rustls. Equivalent
to rustls-tls-webpki-roots.
>
> `rustls-tls-webpki-roots`: Enables TLS functionality provided by
rustls, while using root certificates from the webpki-roots crate.
>
> `rustls-tls-native-roots`: Enables TLS functionality provided by
rustls, while using root certificates from the rustls-native-certs
crate.

Additional context:

- https://github.com/seanmonstar/reqwest/issues/1554
- https://github.com/encode/httpx/issues/302
- [Should I use the native certs or
webpki-roots?](https://github.com/rustls/rustls-native-certs#should-i-use-this-or-webpki-roots)

Prior discussion at https://github.com/astral-sh/uv/pull/609
2024-02-16 14:07:18 -05:00
Zanie Blue 2ea44d863a
Add warning for empty requirements files (#1519)
Also, improve tracing of requirements file parsing.

Per my confusion in #1334
2024-02-16 18:19:09 +00:00
Charlie Marsh 659327f24a
Bump version to v0.1.2 (#1439) 2024-02-16 01:17:19 -05:00
Zanie Blue e0885b7c8e
Bump version to 0.1.1 (#1359) 2024-02-15 15:38:22 -06:00
Charlie Marsh 27177613d4
Bump version to v0.1.0 (#1325) 2024-02-15 14:12:23 -05:00
Charlie Marsh 0579a04014
Bump to v0.0.5 for pre-release (#1324)
This is easier than figuring out the version parsing.
2024-02-15 18:33:34 +00:00
Charlie Marsh ad12d97e71
Set crate to prerelease (#1320) 2024-02-15 18:21:09 +00:00
Charlie Marsh 06f2b6eee2
Bump version and update pyproject.toml metadata (#1316)
Also ensures that we no longer clear the README when uploading to PyPI
:)
2024-02-15 18:03:35 +00:00
Zanie Blue 2586f655bb
Rename to `uv` (#1302)
First, replace all usages in files in-place. I used my editor for this.
If someone wants to add a one-liner that'd be fun.

Then, update directory and file names:

```
# Run twice for nested directories
find . -type d -print0 | xargs -0 rename s/puffin/uv/g
find . -type d -print0 | xargs -0 rename s/puffin/uv/g

# Update files
find . -type f -print0 | xargs -0 rename s/puffin/uv/g
```

Then add all the files again

```
# Add all the files again
git add crates
git add python/uv

# This one needs a force-add
git add -f crates/uv-trampoline
```
2024-02-15 11:19:46 -06:00
Andrew Gallant 8102980192 puffin-resolver: make VersionMap construction lazy
That is, a `PrioritizedDistribution` for a specific version of a
package is not actually materialized in memory until a corresponding
`VersionMap::get` call is made for that version. Similarly, iteration
lazily materializes distributions as it moves through the map. It
specifically does not materialize everything first.

The main reason why this is effective is that an
`OwnedArchive<SimpleMetadata>` represents a zero-copy (other than
reading the source file) version of `SimpleMetadata` that is really just
a `Vec<u8>` internally. The problem with `VersionMap` construction
previously is that it had to eagerly materialize a `SimpleMetadata` in
memory before anything else, which defeats a large part of the purpose
of zero-copy deserialization. By making more of `VersionMap`
construction itself lazy, we permit doing some parts of resolution
without necessarily fully deserializing a `SimpleMetadata` into memory.
Indeed, with this commit, in the warm cached case, a `SimpleMetadata` is
itself never materialized fully in memory.

This does not completely and totally fully realize the benefits of
zero-copy deserialization. For example, we are likely still building
lots of distributions in memory that we don't actually need in some
cases. Perhaps in cases where no resolution exists, or when one needs to
iterate over large portions of the total versions published for a
package.
2024-02-15 08:10:32 -05:00
Andrew Gallant bdb491baf6 deps: bump pubgrub
This brings in a [PR] that makes `Range::as_singleton` return a
borrow.

[PR]: https://github.com/zanieb/pubgrub/pull/23
2024-02-15 08:10:32 -05:00
Zanie Blue b5dd8b7de2
Track yanked versions as incompatibilities (#1290)
Moves yanked version filtering from `VersionMap::from_metadata` to the
resolver and tracks it as a PubGrub unavailable incompatibility so
yanked versions are reflected in error messages.

e.g. before
```
╰─▶ Because only albatross<=0.1.0 is available and you require albatross>0.1.0, 
       we can conclude that the requirements are unsatisfiable.
```

after

```
╰─▶ Because only the following versions of albatross are available:
            albatross<=0.1.0
            albatross==1.0.0
      and albatross==1.0.0 is unusable because it was yanked, we can conclude that albatross>0.1.0 cannot be used.
      And because you require albatross>0.1.0, we can conclude that the requirements are unsatisfiable.
```
2024-02-12 22:01:17 -06:00
Charlie Marsh 16bb80132f
Add an `--offline` mode (#1270)
## Summary

This PR adds an `--offline` flag to Puffin that disables network
requests (implemented as a Reqwest middleware on our registry client).
When `--offline` is provided, we also allow the HTTP cache to return
stale data.

Closes #942.
2024-02-13 03:35:23 +00:00
Charlie Marsh c75eef28b5
Upgrade to miette v6.0.0 (#1272) 2024-02-11 23:23:27 -05:00
Charlie Marsh ba4c6e1a55
Remove unused deps (#1273) 2024-02-11 18:53:58 +00:00
Charlie Marsh 32aacc35a9
Bump version to v0.0.4 (#1269) 2024-02-09 16:42:17 -05:00
konsti ab45485eb5
Reduce stack sizes further and ignore remaining tests (#1261)
This PR reduces the stack sizes a windows a little further using the
stack traces from stack overflows combined with looking at the type
sizes. Ultimately, it ignore the three remaining tests failing in debug
on windows due to stack overflows to unblock `cargo test` for windows on
CI.

444 tests run: 444 passed (39 slow), 1 skipped
2024-02-06 23:08:18 +01:00
Charlie Marsh 62416286e2
Remove `add` and `remove` commands (#1259)
## Summary

These add and remove dependencies from a `pyproject.toml` -- but they're
currently hidden, and don't match the rest of the workflow. We can
re-add them when the time is right.
2024-02-06 14:18:27 -05:00
Andrew Gallant d4b4c21133
initial implementation of zero-copy deserialization for SimpleMetadata (#1249)
(Please review this PR commit by commit.)

This PR closes an initial loop on zero-copy deserialization. That
is, provides a way to get a `Archived<SimpleMetadata>` (spelled
`OwnedArchive<SimpleMetadata>` in the code) from a `CachedClient`. The
main benefit of zero-copy deserialization is that we can read bytes
from a file, cast those bytes to a structured representation without
cost, and then start using that type as any other Rust type. The
"catch" is that the structured representation is not the actual type
you started with, but the "archived" version of it.

In order to make all this work, we ended up needing to shave a rather
large yak: we had to re-implement HTTP cache semantics. Previously,
we were using the `http-cache-semantics` crate. While it does support
Serde, it doesn't support `rkyv`. Moreover, even simple support for
`rkyv` wouldn't be enough. What we actually want is for the HTTP cache
semantics to be implemented on the *archived* type so that we can
decide whether our cached response is stale or not without needing to
do a full deserialization into the unarchived type. This is why, in
this PR, you'll see `impl ArchivedCachePolicy { ... }` instead of
`impl CachePolicy { ... }`. (The `derive(rkyv::Archive)` macro
automatically introduces the `ArchivedCachePolicy` type into the
current namespace.)

Unfortunately, this PR does not fully realize the dream that is
zero-copy deserialization. Namely, while a `CachedClient` can now
provide an `OwnedArchive<SimpleMetadata>`, the rest of our code
doesn't really make use of it. Indeed, as soon as we go to build a
`VersionMap`, we eagerly convert our archived metadata into an owned
`SimpleMetadata` via deserialization (that *isn't* zero-copy). After
this change, a lot of the work now shifts to `rkyv` deserialization
and `VersionMap` construction. More precisely, the main thing we drop
here is `CachePolicy` deserialization (which is now truly zero-copy)
and the parsing of the MessagePack format for `SimpleMetadata`. But we
are still paying for deserialization. We're just paying for it in a
different place.

This PR does seem to bring a speed-up, but it is somewhat underwhelming.
My measurements have been pretty noisy, but I get a 1.1x speedup fairly
often:

```
$ hyperfine -w5 "puffin-main pip compile --cache-dir ~/astral/tmp/cache-main ~/astral/tmp/reqs/home-assistant-reduced.in -o /dev/null" "puffin-test pip compile --cache-dir ~/astral/tmp/cache-test ~/astral/tmp/reqs/home-assistant-reduced.in -o /dev/null" ; A kang
Benchmark 1: puffin-main pip compile --cache-dir ~/astral/tmp/cache-main ~/astral/tmp/reqs/home-assistant-reduced.in -o /dev/null
  Time (mean ± σ):     164.4 ms ±  18.8 ms    [User: 427.1 ms, System: 348.6 ms]
  Range (min … max):   131.1 ms … 190.5 ms    18 runs

Benchmark 2: puffin-test pip compile --cache-dir ~/astral/tmp/cache-test ~/astral/tmp/reqs/home-assistant-reduced.in -o /dev/null
  Time (mean ± σ):     148.3 ms ±  10.2 ms    [User: 357.1 ms, System: 319.4 ms]
  Range (min … max):   136.8 ms … 184.4 ms    19 runs

Summary
  puffin-test pip compile --cache-dir ~/astral/tmp/cache-test ~/astral/tmp/reqs/home-assistant-reduced.in -o /dev/null ran
    1.11 ± 0.15 times faster than puffin-main pip compile --cache-dir ~/astral/tmp/cache-main ~/astral/tmp/reqs/home-assistant-reduced.in -o /dev/null
```

One downside is that this does increase cache size (`rkyv`'s
serialization format is not as compact as MessagePack). On disk size
increases by about 1.8x for our `simple-v0` cache.

```
$ sort-filesize cache-main
4.0K    cache-main/CACHEDIR.TAG
4.0K    cache-main/.gitignore
8.0K    cache-main/interpreter-v0
8.7M    cache-main/wheels-v0
18M     cache-main/archive-v0
59M     cache-main/simple-v0
109M    cache-main/built-wheels-v0
193M    cache-main
193M    total

$ sort-filesize cache-test
4.0K    cache-test/CACHEDIR.TAG
4.0K    cache-test/.gitignore
8.0K    cache-test/interpreter-v0
8.7M    cache-test/wheels-v0
18M     cache-test/archive-v0
107M    cache-test/simple-v0
109M    cache-test/built-wheels-v0
242M    cache-test
242M    total
```

Also, while I initially intended to do a simplistic implementation of
HTTP cache semantics, I found that everything was somewhat
inter-connected. I could have wrote code that _specifically_ only worked
with the present behavior of PyPI, but then it would need to be special
cased and everything else would need to continue to use
`http-cache-sematics`. By implementing what we need based on what Puffin
actually is (which is still less than what `http-cache-semantics` does),
we can avoid special casing and use zero-copy deserialization for our
cache policy in _all_ cases.
2024-02-05 16:47:53 -05:00
Zanie Blue d090acf13d
Improve error messaging when a dependency is not found (#1241)
Previously, whenever we encountered a missing package we would throw an
error without information about why the package was requested. This
meant that if a transitive dependency required a missing package, the
user would have no idea why it was even selected. Here, we track
`NotFound` and `NoIndex` errors as `NoVersions` incompatibilities with
an attached reason. Improves our test coverage for `--no-index` without
`--find-links`.

The
[snapshots](https://github.com/astral-sh/puffin/pull/1241/files#diff-3eea1658f165476252f1f061d0aa9f915aabdceafac21611cdf45019447f60ec)
show a nice improvement.

I think this will also enable backtracking to another version if some
version of transitive dependency has a missing dependency. I'll write a
scenario for that next.

Requires https://github.com/zanieb/pubgrub/pull/22
2024-02-05 08:43:05 -06:00
konsti f10f902570
Yield after channel send and move cpu tasks to thread (#1163)
## Summary

Previously, we were blocking operations that could run in parallel. We
would send request through our main requests channel, but not yield so
that the receiver could only start processing requests much later than
necessary. We solve this by switching to the async
`tokio::sync::mpsc::channel`, where send is an async functions that
yields.

Due to the increased parallelism cache deserialization and the
conversion from simple api request to version map became bottlenecks, so
i moved them to `spawn_blocking`. Together these result in a 30-60%
speedup for larger warm cache resolution. Small cases such as black
already resolve in 5.7 ms on my machine so there's no speedup to be
gained, refresh and no cache were to noisy to get signal from.

Note for the future: Revisit the bounded channel if we want to produce
requests from `process_request`, too, (this would be good for
prefetching) to avoid deadlocks.

## Details

We can look at the behavior change through the spans:

```
RUST_LOG=puffin=info TRACING_DURATIONS_FILE=target/traces/jupyter-warm-branch.ndjson cargo run --features tracing-durations-export --bin puffin-dev --profile profiling -- resolve jupyter 2> /dev/null
```

Below, you can see how on main, we have discrete phases: All (cached)
simple api requests in parallel, then all (cached) metadata requests in
parallel, repeat until done. The solver is mostly waiting until it has
it's version map from the simple API query to be able to choose a
version. The main thread is blocked by process requests.

In the PR branch, the simple api requests succeeds much earlier,
allowing the solver to advance and also to schedule more prefetching.
Due to that `parse_cache` and `from_metadata` became bottlenecks, so i
moved them off the main thread (green color, and their spans can now
overlap because they can run on multiple threads in parallel). The main
thread isn't blocked on `process_request` anymore, instead it has
frequent idle times. The spans are all much shorter, which indicates
that on main they could have finished much earlier, but a task didn't
yield so they weren't scheduled to finish (though i haven't dug deep
enough to understand the exact scheduling between the process request
stream and the solver here).

**main**


![jupyter-warm-main](https://github.com/astral-sh/puffin/assets/6826232/693c53cc-1090-41b7-b02a-a607fcd2cd99)

**PR**


![jupyter-warm-branch](https://github.com/astral-sh/puffin/assets/6826232/33435f34-b39b-4b0a-a9d7-4bfc22f55f05)

## Benchmarks

```
$ hyperfine --warmup 3 "target/profiling/main-dev resolve jupyter" "target/profiling/branch-dev resolve jupyter"
Benchmark 1: target/profiling/main-dev resolve jupyter
  Time (mean ± σ):      29.1 ms ±   0.7 ms    [User: 22.9 ms, System: 11.1 ms]
  Range (min … max):    27.7 ms …  32.2 ms    103 runs
 
Benchmark 2: target/profiling/branch-dev resolve jupyter
  Time (mean ± σ):      18.8 ms ±   1.1 ms    [User: 37.0 ms, System: 22.7 ms]
  Range (min … max):    16.5 ms …  21.9 ms    154 runs
 
Summary
  target/profiling/branch-dev resolve jupyter ran
    1.55 ± 0.10 times faster than target/profiling/main-dev resolve jupyter

$ hyperfine --warmup 3 "target/profiling/main-dev resolve meine_stadt_transparent" "target/profiling/branch-dev resolve meine_stadt_transparent"
Benchmark 1: target/profiling/main-dev resolve meine_stadt_transparent
  Time (mean ± σ):      37.8 ms ±   0.9 ms    [User: 30.7 ms, System: 14.1 ms]
  Range (min … max):    36.6 ms …  41.5 ms    79 runs
 
Benchmark 2: target/profiling/branch-dev resolve meine_stadt_transparent
  Time (mean ± σ):      24.7 ms ±   1.5 ms    [User: 47.0 ms, System: 39.3 ms]
  Range (min … max):    21.5 ms …  28.7 ms    113 runs
 
Summary
  target/profiling/branch-dev resolve meine_stadt_transparent ran
    1.53 ± 0.10 times faster than target/profiling/main-dev resolve meine_stadt_transparent

$ hyperfine --warmup 3 "target/profiling/main pip compile scripts/requirements/home-assistant.in" "target/profiling/branch pip compile scripts/requirements/home-assistant.in"
Benchmark 1: target/profiling/main pip compile scripts/requirements/home-assistant.in
  Time (mean ± σ):     229.0 ms ±   2.8 ms    [User: 197.3 ms, System: 63.7 ms]
  Range (min … max):   225.8 ms … 234.0 ms    13 runs
 
Benchmark 2: target/profiling/branch pip compile scripts/requirements/home-assistant.in
  Time (mean ± σ):      91.4 ms ±   5.3 ms    [User: 289.2 ms, System: 176.9 ms]
  Range (min … max):    81.0 ms … 104.7 ms    32 runs
 
Summary
  target/profiling/branch pip compile scripts/requirements/home-assistant.in ran
    2.50 ± 0.15 times faster than target/profiling/main pip compile scripts/requirements/home-assistant.in
```
2024-02-02 18:18:24 +01:00
konsti b16422a108
Remove insta_cmd (#1225)
We need more flexible filters than those `inta` offers, and `insta_cmd`
makes it impossible to plug in programmatic filters. At the same time we
use barely any of `insta_cmd`'s features. We can replace the subset we
need in about 50 loc.
2024-02-02 09:37:04 +00:00
Charlie Marsh d77d129e8d
Run `cargo update` (#1230) 2024-02-01 11:14:38 -05:00
Charlie Marsh c4bfb6efee
Add a `BENCHMARKS.md` with rendered benchmarks (#1211)
As a precursor to the release, I want to include a structured document
with detailed benchmarks.

Closes https://github.com/astral-sh/puffin/issues/1210.
2024-01-31 20:11:52 +00:00
Charlie Marsh 01258c1bb3
Report number of bytes deleted when clearing cache (#1203)
## Summary

This is based on Cargo's `clean` implementation, with modifications
based on some of my own preferences, and to better adhere to patterns we
use in our codebase:

![Screenshot 2024-01-31 at 1 31
10 AM](https://github.com/astral-sh/puffin/assets/1309177/38704798-b17f-4972-ab67-00484ce63d62)
2024-01-31 10:48:28 -05:00
Charlie Marsh b2f1bbaa63
Add a Ctrl+C handler to the confirm workflow (#1202)
Fixes an issue whereby exiting the confirmation prompt can lead to your
cursor disappearing: https://github.com/console-rs/dialoguer/issues/294.

See:
b839a2c5b7/rye/src/main.rs (L36-L48).
2024-01-31 02:08:27 +00:00
Charlie Marsh 3f5e7306a5
Remove `WaitMap` dependency (#1183)
## Summary

This is an attempt to https://github.com/astral-sh/puffin/pull/1163 by
removing the `WaitMap` and gaining more granular control over the values
that we hold over `await` boundaries.
2024-01-30 15:25:22 -05:00
Charlie Marsh aa3b79ec63
Prompt user for missing `-r` and `-e` flags in `pip install` (#1180)
## Summary

If the user runs a command like `pip install requirements.txt`, we now
prompt them to ask if they meant to include the `-r` flag:

![Screenshot 2024-01-29 at 8 38
29 PM](https://github.com/astral-sh/puffin/assets/1309177/82b9f7a2-2526-4144-b200-a5015e5b8a4b)

![Screenshot 2024-01-29 at 8 38
33 PM](https://github.com/astral-sh/puffin/assets/1309177/bd8ebb51-2537-4540-a0e0-718e66a1c69c)

The specific logic is: if the requirement ends in `.txt` or `.in`, and
the file exists locally, prompt the user for `-r`. If the requirement
contains a directory separator, and the directory exists locally, prompt
the user for `-e`.

Closes #1166.
2024-01-30 18:58:45 +00:00
konsti 614bb0cf52
Update async_http_range_reader to 0.5.0 (#1189)
Removes a git dep and removes itertools 0.11
2024-01-30 16:32:53 +00:00
konsti ab27913f68
Instrument the main function and add jupyter.in (#1186)
Instrument the main function as anchor span for checking overhead and
update tracing-durations-export to 0.2.0 for differentiating
blocking/non-blocking tasks.

Add a `jupyter.in` requirement since `pip install jupyter` is a common
operation. I tried `jupyterlab` too but there is no difference in
performance (1.00 ± 0.07).
2024-01-30 11:03:24 +00:00
Charlie Marsh 61a3060383
Run `cargo update` (#1178) 2024-01-29 21:01:37 -05:00
Charlie Marsh fa3c9afdc1
Deduplicate `pep440_rs` in dependency tree (#1177)
## Summary

Closes https://github.com/astral-sh/puffin/issues/1176.

## Test Plan

`cargo tree -p puffin -i pep440_rs` runs without error. Previously, it
errored due to multiple versions.
2024-01-29 16:11:42 -05:00
Charlie Marsh 67a09649f2
Support parsing `--find-links`, `--index-url`, and `--extra-index-url` in `requirements.txt` (#1146)
## Summary

This PR adds support for `--find-links`, `--index-url`, and
`--extra-index-url` arguments when specified in a `requirements.txt`.

It's a mostly-straightforward change. The only uncertain piece is what
to do when multiple files include these flags, and/or when we include
them on the CLI and in other files.

In general:

- If _anything_ specifies `--no-index`, we respect it.
- We combine all `--extra-index-url` and `--find-links` across all
sources, since those are just vectors.
- If we see multiple `--index-url` in requirements files, we error.
- We respect the `--index-url` from the command line over any provided
in a requirements file.

(`pip-compile` seems to just pick one semi-arbitrarily when multiple are
provided.)

Closes https://github.com/astral-sh/puffin/issues/1143.
2024-01-29 15:06:40 +00:00
Charlie Marsh 4b9daf9604
Use tokio_tar instead of async_tar (#1170)
## Summary

`tokio_tar` is a fork of `async_tar` that uses Tokio instead of
`async-std`. Using it removes a significant dependency from our tree.

(There is an open PR
(https://github.com/dignifiedquire/async-tar/pull/41) in `async-tar` to
add Tokio support, but it's over a year old.)

See:
https://github.com/astral-sh/puffin/pull/1157#discussion_r1469190249.
2024-01-29 10:00:30 -05:00
Charlie Marsh d88ce76979
Stream unpacking of source distribution downloads (#1157)
This PR migrates our source distribution downloads to unzip as we
stream, similar to our approach for wheels.

In my testing, this showed a consistent speedup (e.g., 6% here for a few
representative source distributions):

```text
❯ python -m scripts.bench --puffin-path ./target/release/main --puffin-path ./target/release/puffin --benchmark install-cold requirements.in
Benchmark 1: ./target/release/main (install-cold)
  Time (mean ± σ):      1.503 s ±  0.039 s    [User: 1.479 s, System: 0.537 s]
  Range (min … max):    1.466 s …  1.605 s    10 runs

Benchmark 2: ./target/release/puffin (install-cold)
  Time (mean ± σ):      1.421 s ±  0.024 s    [User: 1.505 s, System: 0.593 s]
  Range (min … max):    1.381 s …  1.454 s    10 runs

Summary
  './target/release/puffin (install-cold)' ran
    1.06 ± 0.03 times faster than './target/release/main (install-cold)'
```
2024-01-28 20:09:24 -05:00
Andrew Gallant 5219d37250
add initial rkyv support (#1135)
This PR adds initial support for [rkyv] to puffin. In particular,
the main aim here is to make puffin-client's `SimpleMetadata` type
possible to deserialize from a `&[u8]` without doing any copies. This
PR **stops short of actuallying doing that zero-copy deserialization**.
Instead, this PR is about adding the necessary trait impls to a variety
of types, along with a smattering of small refactorings to make rkyv
possible to use.

For those unfamiliar, rkyv works via the interplay of three traits:
`Archive`, `Serialize` and `Deserialize`. The usual flow of things is
this:

* Make a type `T` implement `Archive`, `Serialize` and `Deserialize`.
rkyv
helpfully provides `derive` macros to make this pretty painless in most
  cases.
* The process of implementing `Archive` for `T` *usually* creates an
entirely
new distinct type within the same namespace. One can refer to this type
without naming it explicitly via `Archived<T>` (where `Archived` is a
clever
  type alias defined by rkyv).
* Serialization happens from `T` to (conceptually) a `Vec<u8>`. The
serialization format is specifically designed to reflect the in-memory
layout
  of `Archived<T>`. Notably, *not* `T`. But `Archived<T>`.
* One can then get an `Archived<T>` with no copying (albeit, we will
likely
need to incur some cost for validation) from the previously created
`&[u8]`.
This is quite literally [implemented as a pointer cast][rkyv-ptr-cast].
* The problem with an `Archived<T>` is that it isn't your `T`. It's
something
  else. And while there is limited interoperability between a `T` and an
`Archived<T>`, the main issue is that the surrounding code generally
demands
a `T` and not an `Archived<T>`. **This is at the heart of the tension
for
  introducing zero-copy deserialization, and this is mostly an intrinsic
problem to the technique and not an rkyv-specific issue.** For this
reason,
  given an `Archived<T>`, one can get a `T` back via an explicit
deserialization step. This step is like any other kind of
deserialization,
although generally faster since no real "parsing" is required. But it
will
  allocate and create all necessary objects.

This PR largely proceeds by deriving the three aforementioned traits
for `SimpleMetadata`. And, of course, all of its type dependencies. But
we stop there for now.

The main issue with carrying this work forward so that rkyv is actually
used to deserialize a `SimpleMetadata` is figuring out how to deal
with `DataWithCachePolicy` inside of the cached client. Ideally, this
type would itself have rkyv support, but adding it is difficult. The
main difficulty lay in the fact that its `CachePolicy` type is opaque,
not easily constructable and is internally the tip of the iceberg of
a rat's nest of types found in more crates such as `http`. While one
"dumb"-but-annoying approach would be to fork both of those crates
and add rkyv trait impls to all necessary types, it is my belief that
this is the wrong approach. What we'd *like* to do is not just use
rkyv to deserialize a `DataWithCachePolicy`, but we'd actually like to
get an `Archived<DataWithCachePolicy>` and make actual decisions used
the archived type directly. Doing that will require some work to make
`Archived<DataWithCachePolicy>` directly useful.

My suspicion is that, after doing the above, we may want to mush
forward with a similar approach for `SimpleMetadata`. That is, we want
`Archived<SimpleMetadata>` to be as useful as possible. But right
now, the structure of the code demands an eager conversion (and thus
deserialization) into a `SimpleMetadata` and then into a `VersionMap`.
Getting rid of that eagerness is, I think, the next step after dealing
with `DataWithCachePolicy` to unlock bigger wins here.

There are many commits in this PR, but most are tiny. I still encourage
review to happen commit-by-commit.

[rkyv]: https://rkyv.org/
[rkyv-ptr-cast]:
https://docs.rs/rkyv/latest/src/rkyv/util/mod.rs.html#63-68
2024-01-28 12:14:59 -05:00
Charlie Marsh 6f2c235d21
Avoid re-creating directories during unzip (#1154)
## Summary

We have this optimization in `wheel.rs`, in the installer, but it makes
a huge difference for zips with many small files:

```
Benchmarking file_reader/Django-5.0.1-py3-none-any.whl: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 74.2s, or reduce sample count to 10.
file_reader/Django-5.0.1-py3-none-any.whl
                        time:   [751.63 ms 757.78 ms 764.27 ms]
                        change: [-1.0290% +0.0841% +1.2289%] (p = 0.88 > 0.05)
                        No change in performance detected.
Found 4 outliers among 100 measurements (4.00%)
  4 (4.00%) high mild

Benchmarking buffered_reader/Django-5.0.1-py3-none-any.whl: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 53.4s, or reduce sample count to 10.
buffered_reader/Django-5.0.1-py3-none-any.whl
                        time:   [529.86 ms 536.44 ms 543.35 ms]
                        change: [+0.0293% +1.5543% +3.1426%] (p = 0.05 > 0.05)
                        No change in performance detected.
Found 3 outliers among 100 measurements (3.00%)
  3 (3.00%) high mild
```

That's almost 30% faster...
2024-01-28 00:07:54 -05:00
Charlie Marsh d6795da0ea
Set permissions after streaming unzip (#1151)
## Summary

When we migrated to an "unzip while we stream" solution, we lost the
logic to set permissions on the extracted files, so executables in
wheels were no longer executable. It turns out this is a little tricky,
since the permissions metadata is in the central directory at the _end_
of the zip file, and the async ZIP reader explicitly stops iteration
once it hits the central directory. (Specifically, it goes 4 bytes into
the central directory, since it sees the 4-byte signature header and
then stops.)

So, to solve that, I've added a `CentralDirectoryReader` that continues
where that iterator left off. This required forking the async zip crate:
https://github.com/charliermarsh/rs-async-zip/pull/1. It took a lot of
fiddling but I'm quite confident in the code now, especially since the
async zip crate validates the signature kind on every read.

The central directory is typically quite small (even for the Zig wheel,
which is enormous, it's just around 1MB), so I don't expect this to have
a high cost.

Closes https://github.com/astral-sh/puffin/issues/1148.
2024-01-27 19:22:44 -05:00
Charlie Marsh 50057cd5f2
Re-add Cargo's known hosts checking (#1118)
## Summary

This ensures that (like Cargo) we don't suffer from
https://github.com/advisories/GHSA-r5w3-xm58-jv6j, by way of checking
known hosts when fetching via `libgit2`.

The implementation is taken from Cargo itself, modified to remove all
configuration, since we don't yet support configuration for known hosts,
etc.

Closes #285.
2024-01-25 22:29:36 -05:00
Charlie Marsh 77351c7874
Use snapshots for requirements.txt error tests (#1115)
## Summary

I find these too difficult to edit and maintain. This brings them closer
to the rest of our testing setups.
2024-01-25 20:35:52 -05:00
Charlie Marsh 5ad2e60561
Use `same-file` to detect interpreter shims (#1099)
Our existing detection doesn't work on Windows, because we canoncalize
the interpreter path but not `info.sys_executable`, so the former
includes the UNC prefix, etc. This is cross-platform and gets at the
intent of the check.
2024-01-25 12:27:49 -05:00
Charlie Marsh f4939e50a6
Remove UNC prefixes on Windows (#1086)
## Summary

This PR adds a `NormalizedDisplay` trait that we can use for user-facing
paths, to strip the UNC prefix on Windows.

On other platforms, the implementation is a no-op (vs. `Display`).

I audited all usages of `.display()`, and changed any that were
user-facing, either via `println!` or `eprintln!`, or by way of being
included in error messages. I did _not_ change uses that were only in
tests or only went to tracing.

Closes https://github.com/astral-sh/puffin/issues/1084.
2024-01-25 11:44:22 -05:00
Zanie Blue 272555e915
Switch to ref on `main` for PubGrub (#1094)
Just fixing the wrong merge order from
https://github.com/astral-sh/puffin/pull/1088
2024-01-25 14:50:12 +00:00
Charlie Marsh 904db967af
Use junctions instead of symlinks on Windows (#1087)
## Summary

When we unzip wheels in the cache, we write the directories out to an
`archive-v0` bucket, and then symlink into that bucket from the
`wheels-v0` and `built-wheels-v0` buckets.

On Windows, symlinks are not well supported. Specifically, they need to
be explicitly enabled by the user. So, instead of symlinks, we now use
junctions, which are well-supported on Windows, and allow you to
(effectively) symlink a directory to another directory. This PR
implements said junction support, which gets the core installer working
on Windows.

In the past, we also used symlinks to implement another primitive: we
wanted to be able to replace a directory "atomically" (I put
"atomically" in quotes because I don't know if it's actually a
guaranteed atomic operation), in case someone was trying to use the
directory while we were replacing it (as opposed to deleting the
directory, then moving it into place).

On Windows, it doesn't appear to be possible to atomically replace a
junction. So instead, I'm using a new design, whereby the cache always
returns canonicalized paths. We know these canonicalized paths are
unique and won't be replaced, so they're safe for writers to rely on. In
general, when we write new data to the cache, we now return the
canonicalized path. When we read from the cache, and try to identify
(e.g.) the set of wheels available to us, we canonicalize the links
immediately and consider them non-existent if that operation fails.

Closes #1085.

---------

Co-authored-by: konstin <konstin@mailbox.org>
2024-01-25 10:06:38 +01:00
Zanie Blue ed1ac640b9
Consolidate `UnusableDependencies` into a generic `Unavailable` incompatibility (#1088)
Requires https://github.com/zanieb/pubgrub/pull/20

In short, `UnusableDependencies` can be generalized into `Unavailable`
which encompasses incompatibilities where a package range which is
unusable for some inherent reason as well as when its dependencies are
unusable. We can eventually use this to track more incompatibilities in
the solver. I made the reason string required because I can't see a case
where we should leave it out.

Additionally, this improves the display of conflicts in the root
requirements.
2024-01-24 22:10:44 -06:00
konsti 2e0ce70d13
Initial windows support (#940)
## Summary

First batch of changes for windows support. Notable changes:

* Fixes all compile errors and added windows specific paths.
* Working venv creation on windows, both from a base interpreter and
from a venv. This requires querying `stdlib` from the sysconfig paths to
find the launcher.
* Basic url/path conversion handling for windows.
* `if cfg!(...)` instead of `#[cfg()]`. This should make it easier to
keep everything compiling across platforms.

## Outlook

Test summary: 402 tests run: 299 passed (15 slow), 103 failed, 1 skipped

There are various reason for the remaining test failure:
* Windows-specific colorama and tzdata dependencies that change the
snapshot slightly. This is by far the biggest batch.
* Some url-path handling issues. I fixed some in the PR, some remain.
* Lack of the latest python patch versions for older pythons on my
machine, since there are no builds for windows and we need to register
them in the registry for them to be picked up for `py --list-paths` (CC
@zanieb RE #1070).
* Lack of entrypoint launchers.
* ... likely more
2024-01-24 18:27:49 +01:00
Charlie Marsh 0519375bd6
Remove some unused dependencies (#1077) 2024-01-24 11:58:21 -05:00
Charlie Marsh 63f3434b21
Use nanoid instead of uuid (#1074)
## Summary

Gives us equivalent randomness with ~half as many characters.
2024-01-24 05:05:14 +00:00
Andrew Gallant eebc2f340a
make some things guaranteed to be deterministic (#1065)
This PR replaces a few uses of hash maps/sets with btree maps/sets and
index maps/sets. This has the benefit of guaranteeing a deterministic
order of iteration.

I made these changes as part of looking into a flaky test.
Unfortunately, I'm not optimistic that anything here will actually fix
the flaky test, since I don't believe anything was actually dependent
on the order of iteration.
2024-01-23 20:30:33 -05:00
Charlie Marsh 5621c414cf
Use symlinks for directories entries in cache (#1037)
## Summary

One problem we have in the cache today is that we can't overwrite
entries atomically, because we store unzipped _directories_ in the cache
(which makes installation _much_ faster than storing zipped
directories). So, if you ignore the existing contents of the cache when
writing, you might run into an error, because you might attempt to write
a directory where a directory already exists.

This is especially annoying for cache refresh, because in order to
refresh the cache, we have to purge it (i.e., delete a bunch of stuff),
which is also highly unsafe if Puffin is running across multiple threads
or multiple processes.

The solution I'm proposing here is that whenever we persist a
_directory_ to the cache, we persist it to a special "archive" bucket.
Then, within the other buckets, directory entries are actually symlinks
into that "archive" bucket. With symlinks, we can atomically replace,
which means we can easily overwrite cache entries without having to
delete from the cache.

The main downside is that we'll now accumulate dangling entries in the
"archive" bucket, and so we'll need to implement some form of garbage
collection to ensure that we remove entries with no symlinks. Another
downside is that cache reads and writes will be a bit slower, since we
need to deal with creating and resolving these symlinks.

As an example... after this change, the cache entry for this unzipped
wheel is actually a symlink:

![Screenshot 2024-01-22 at 11 56
18 AM](https://github.com/astral-sh/puffin/assets/1309177/99ff6940-5096-4246-8d16-2a7bdcdd8d4b)

Then, within the archive directory, we actually have two unique entries
(since I intentionally ran the command twice to ensure overwrites were
safe):

![Screenshot 2024-01-22 at 11 56
22 AM](https://github.com/astral-sh/puffin/assets/1309177/717d04e2-25d9-4225-b190-bad1441868c6)
2024-01-23 19:52:37 +00:00
Charlie Marsh 6561617c56
Store source distribution builds under a unique manifest ID (#1051)
## Summary

This is a refactor of the source distribution cache that again aims to
make the cache purely additive. Instead of deleting all built wheels
when the cache gets invalidated (e.g., because the source distribution
changed on PyPI or something), we now treat each invalidation as its own
cache directory. The manifest inside of the source distribution
directory now becomes a pointer to the "latest" version of the source
distribution cache.

Here's a visual example:

![Screenshot 2024-01-22 at 5 35
41 PM](https://github.com/astral-sh/puffin/assets/1309177/ca103c83-e116-4956-b91c-8434fe62cffe)

With this change, we avoid deleting built distributions that might be
relied on elsewhere and maintain our invariant that the cache is purely
additive. The cost is that we now preserve stale wheels, but we should
add a garbage collection mechanism to deal with that.
2024-01-23 19:49:11 +00:00
konsti 1131341cbc
Support more formats in `puffin venv`, incl. windows support (#1039)
Mirroring `virtualenv -p` and driven by the lack of `pythonx.y` in
`PATH` on windows, this PR adds `-p x.y` support to `puffin venv` (first
commit).

Supported formats:
* NEW: `-p 3.10` searches for an installed Python 3.10 (Looking for
`python3.10` on linux/mac).
  Specifying a patch version is not supported
* `-p python3.10` or `-p python.exe` looks for a binary in `PATH`
* `-p /home/ferris/.local/bin/python3.10` uses this exact Python

In the second commit, we add python interpreter search on windows using
`py --list-paths`. On windows, all python are called `python.exe` so the
unix trick of looking for `python{}.{}` in `PATH` doesn't work. Instead,
we ask the python launcher for windows to tell us about all installed
packages. We should eventually migrate this to [PEP
514](https://peps.python.org/pep-0514/) by reading the registry entries
ourselves.
2024-01-23 15:35:07 +00:00
Charlie Marsh b0e73d796c
Add support for PyPy wheels (#1028)
## Summary

This PR adds support for PyPy wheels by changing the compatible tags
based on the implementation name and version of the current interpreter.

For now, we only support CPython and PyPy, and explicitly error out when
given other interpreters. (Is this right? Should we just fallback to
CPython tags...? Or skip the ABI-specific tags for unknown
interpreters?)

The logic is based on
4d85340613/src/packaging/tags.py (L247).
Note, however, that `packaging` uses the `EXT_SUFFIX` variable from
`sysconfig`... Instead, I looked at the way that PyPy formats the tags,
and recreated them based on the Python and implementation version. For
example, PyPy wheels look like
`cchardet-2.1.7-pp37-pypy37_pp73-win_amd64.whl` -- so that's `pp37` for
PyPy with Python version 3.7, and then `pypy37_pp73` for PyPy with
Python version 3.7 and PyPy version 7.3.

Closes https://github.com/astral-sh/puffin/issues/1013.

## Test Plan

I tested this manually, but I couldn't find macOS universal PyPy
wheels... So instead I added `cchardet` to a `requirements.in`, ran
`cargo run pip sync requirements.in --index-url
https://pypy.kmtea.eu/simple --verbose`, and added logging to verify
that the platform tags matched (even if the architecture didn't).
2024-01-22 14:22:27 +00:00
Charlie Marsh e09a51653e
Propagate cancellation errors in `OnceMap` (#1032)
## Summary

Ensures that if an operation is cancelled in one thread, we propagate it
to others rather than panicking.

Related to https://github.com/astral-sh/puffin/issues/1005.
2024-01-22 09:00:21 -05:00
Charlie Marsh b3954f2449
Enable PowerPC builds (#1017)
Closes #1015.
2024-01-19 17:29:11 -05:00
Zanie Blue 33b35f7020
Add support for disabling installation from pre-built wheels (#956)
Adds support for disabling installation from pre-built wheels i.e. the
package must be built from source locally.
We will still always use pre-built wheels for metadata during
resolution.

Available via `--no-binary` and `--no-binary-package <name>` flags in
`pip install` and `pip sync`. There is no flag for `pip compile` since
no installation happens there.

```
--no-binary

    Don't install pre-built wheels.
    
    When enabled, all installed packages will be installed from a source distribution. 
    The resolver will still use pre-built wheels for metadata.


--no-binary-package <NO_BINARY_PACKAGE>

    Don't install pre-built wheels for a specific package.
    
    When enabled, the specified packages will be installed from a source distribution. 
    The resolver will still use pre-built wheels for metadata.
```

When packages are already installed, the `--no-binary` flag will have no
affect without the `--reinstall` flag. In the future, I'd like to change
this by tracking if a local distribution is from a pre-built wheel or a
locally-built wheel. However, this is significantly more complex and
different than `pip`'s behavior so deferring for now.

For reference, `pip`'s flag works as follows:

```
--no-binary <format_control>

    Do not use binary packages. Can be supplied multiple times, and each time adds to the
    existing value. Accepts either ":all:" to disable all binary packages, ":none:" to empty the
    set (notice the colons), or one or more package names with commas between them (no colons).
    Note that some packages are tricky to compile and may fail to install when this option is
    used on them.
```

Note we are not matching the exact `pip` interface here because it seems
complicated to use. I think we may want to consider adjusting our
interface for this behavior since we're not entirely compatible anyway
e.g. I think `--force-build` and `--force-build-package` are clearer
names. We could also consider matching the `pip` interface or only
allowing `--no-binary <package>` for compatibility. We can of course do
whatever we want in our _own_ install interfaces later.

Additionally, we may want to further consider the semantics of
`--no-binary`. For example, if I run `pip install pydantic --no-binary`
I expect _just_ Pydantic to be installed without binaries but by default
we will build all of Pydantic's dependencies too.

This work was prompted by #895, as it is much easier to measure
performance gains from building source distributions if we have a flag
to ensure we actually build source distributions. Additionally, this is
a flag I have used frequently in production to debug packages that ship
Cythonized wheels.
2024-01-19 11:24:27 -06:00
Charlie Marsh 5adb08a304
Allow relative paths and environment variables in all editable representations (#1000)
## Summary

I don't know if this is actually a good change, but it tries to make the
editable install experience more consistent. Specifically, we now
support...

```
# Use a relative path with a `file://` prefix.
# Prior to this PR, we supported `file:../foo`, but not `file://../foo`, which felt inconsistent.
-e file://../foo

# Use environment variables with paths, not just URLs.
# Prior to this PR, we supported `file://${PROJECT_ROOT}/../foo`, but not the below.
-e ${PROJECT_ROOT}/../foo
```

Importantly, `-e file://../foo` is actually not supported by pip... `-e
file:../foo` _is_ supported though. We support both, as of this PR. Open
to feedback.
2024-01-19 09:00:37 -05:00
Charlie Marsh c8285cb5ef
Bump version to v0.0.3 (#999) 2024-01-18 23:39:35 -05:00
Charlie Marsh 732ef7adb7
Bump version to v0.0.2 (#987)
Bumping the version so that I can test the release process again
(including PyPI publish).
2024-01-18 20:56:09 -05:00
Charlie Marsh 5e2b715366
Rename `puffin-cli` crate to `puffin` (#976)
## Summary

Like in Ruff, this simplifies a few things.
2024-01-18 19:02:52 -05:00
Charlie Marsh 96a61fb351
Remove RFC2047 decoder (#967)
## Summary

- This was inherited from
d719988323/src/metadata.rs (LL78C2-L91C26)
- ...which introduced this code here:
9cd1d43f7c
- ...with the originating issue here:
https://github.com/PyO3/maturin/issues/612
- ...and the upstream issue here:
https://github.com/staktrace/mailparse/issues/50

It seems like the goal was to support Unicode in certain header fields,
but I don't think this is necessary for us. We only use
`get_first_value` for `Requires-Python`, which has to be ASCII, doesn't
it?

In my testing, it seems like the `charset` hack can also be removed. The
tests I copied over actually work without it, which makes me a bit
skeptical.

The main benefit here is that we get to a remove a _big_ dependency
stack, including Chumsky and Stacker and psm which have limited
cross-platform support.
2024-01-18 15:09:45 -05:00
Charlie Marsh bb55fc19b3
Run `cargo update` (#951) 2024-01-17 13:15:47 -05:00
Charlie Marsh b8fbd529a1
Move `OnceMap` into its own crate (#946)
## Summary

This is extremely generic (like `WaitMap`), and I want to use it in the
cache.
2024-01-17 04:09:15 +00:00
Charlie Marsh 9a3f3d385c
Remove `PubGrubVersion` (#924)
## Summary

I'm running into some annoyances converting `&Version` to
`&PubGrubVersion` (which is just a wrapper type around `Version`), and I
realized... We don't even need `PubGrubVersion`?

The reason we "need" it today is due to the orphan trait rule: `Version`
is defined in `pep440_rs`, but we want to `impl
pubgrub::version::Version for Version` in the resolver crate.

Instead of introducing a new type here, which leads to a lot of
awkwardness around conversion and API isolation, what if we instead just
implement `pubgrub::version::Version` in `pep440_rs` via a feature? That
way, we can just use `Version` everywhere without any confusion and
conversion for the wrapper type.
2024-01-15 08:51:12 -05:00
konsti e9b6b6fa36
Implement `--find-links` as flat indexes (directories in pip-compile) (#912)
Add directory `--find-links` support for local paths to pip-compile.

It seems that pip joins all sources and then picks the best package. We
explicitly give find links packages precedence if the same exists on an
index and locally by prefilling the `VersionMap`, otherwise they are
added as another index and the existing rules of precedence apply.

Internally, the feature is called _flat index_, which is more meaningful
than _find links_: We're not looking for links, we're picking up local
directories, and (TBD) support another index format that's just a flat
list of files instead of a nested index.

`RegistryBuiltDist` and `RegistrySourceDist` now use `WheelFilename` and
`SourceDistFilename` respectively. The `File` inside `RegistryBuiltDist`
and `RegistrySourceDist` gained the ability to represent both a url and
a path so that `--find-links` with a url and with a path works the same,
both being locked as `<package_name>@<version>` instead of
`<package_name> @ <url>`. (This is more of a detail, this PR in general
still work if we strip that and have directory find links represented as
`<package_name> @ file:///path/to/file.ext`)

`PrioritizedDistribution` and `FlatIndex` have been moved to locations
where we can use them in the upstack PR.

I added a `scripts/wheels` directory with stripped down wheels to use
for testing.

We're lacking tests for correct tag priority precedence with flat
indexes, i only confirmed this manually since it is not covered in the
pip-compile or pip-sync output.

Closes #876
2024-01-15 02:04:10 +00:00
konsti 5ffbfadf66
Make hashes optional (#910)
There is no guarantee that indexes provide hashes at all or the sha256
we support specifically. [PEP
503](https://peps.python.org/pep-0503/#specification):

> The URL SHOULD include a hash in the form of a URL fragment with the
following syntax: #<hashname>=<hashvalue>, where <hashname> is the
lowercase name of the hash function (such as sha256) and <hashvalue> is
the hex encoded digest.

We instead use the url as input to generate a hash when caching.
2024-01-14 16:32:55 -05:00
Charlie Marsh 231686e71b
Remove `incompatibilities` from index (#905)
This isn't really part of the "index", it's part of the resolution.
2024-01-13 02:57:15 +00:00
bojanserafimov 10227a74f8
Unzip while downloading (#856) 2024-01-11 09:41:46 -05:00
Charlie Marsh 4123a35228
Run `cargo update` (#873) 2024-01-11 09:10:07 -05:00
konsti 8c2b7d55af
Cleanup deps and docs (#882)
Fix warnings from `cargo +nightly udeps` and `cargo doc`.

Removes all mentions of regex from pep440_rs.
2024-01-11 10:43:40 +00:00
Zanie Blue 93d3093a2a
Improve formatting of package ranges in error messages (#864)
Closes #810
Closes https://github.com/astral-sh/puffin/issues/812
Requires https://github.com/zanieb/pubgrub/pull/19 and
https://github.com/zanieb/pubgrub/pull/18

- Always pair package ranges with names e.g. `... of a matching a<1.0`
instead of `... of a matching <1.0`
- Split range segments onto multiple lines when not a singleton as
suggested in
[#850](https://github.com/astral-sh/puffin/pull/850#discussion_r1446419610)
- Improve formatting when ranges are split across multiple lines e.g. by
avoiding extra spaces and improving wording

Note review will require expanding the hidden files as there are
significant changes to the report formatter and snapshots.

Bear with me here as these are definitely not perfect still.

The following changes build on top of this independently for further
improvements:
- #868 
- #867 
- #866 
- #871
2024-01-10 14:16:23 -06:00
konsti 1203f8f9e8
Gourgeist updates (#862)
* Use caching again
* Make clap feature only required for the cli/bin optional
2024-01-09 23:04:15 +00:00
bojanserafimov e67b7858e6
Use zlib-ng for faster decompression (#859) 2024-01-09 16:13:36 -05:00
Zanie Blue 2b0c2e294b
Fix formatting of negated singleton versions in error messages (#836)
Closes #805 
Requires https://github.com/zanieb/pubgrub/pull/17
2024-01-08 12:33:01 -06:00
konsti b6338b5e4a
Use tracing-durations-export to visualize parallelism bottlenecks (dev commands) (#816)
Example usage:

```
# Cached
TRACING_DURATIONS_FILE=target/traces/black.ndjson RUST_LOG=puffin=info cargo run --bin puffin-dev --profile profiling -- resolve black
TRACING_DURATIONS_FILE=target/traces/meine_stadt_transparent.ndjson RUST_LOG=puffin=info cargo run --bin puffin-dev --profile profiling -- resolve meine_stadt_transparent
TRACING_DURATIONS_FILE=target/traces/jupyter.ndjson RUST_LOG=puffin=info cargo run --bin puffin-dev --profile profiling -- resolve jupyter

# No cache
TRACING_DURATIONS_FILE=target/traces/black-no-cache.ndjson RUST_LOG=puffin=info cargo run --bin puffin-dev --profile profiling -- resolve --no-cache black
TRACING_DURATIONS_FILE=target/traces/meine_stadt_transparent-no-cache.ndjson RUST_LOG=puffin=info cargo run --bin puffin-dev --profile profiling -- resolve --no-cache meine_stadt_transparent
TRACING_DURATIONS_FILE=target/traces/jupyter-no-cache.ndjson RUST_LOG=puffin=info cargo run --bin puffin-dev --profile profiling -- resolve --no-cache jupyter
```

Uncached black output example:


![black-no-cache](https://github.com/astral-sh/puffin/assets/6826232/38497b89-7214-453b-9456-c9d9cbf7d2d5)
2024-01-08 16:20:38 +01:00
Charlie Marsh 54838914be
Migrate back to `owo-colors` (#824)
In the past, I moved us to `owo-colors`
(https://github.com/astral-sh/puffin/pull/121); then, we moved back,
because we ran into issues with overriding the settings to force-disable
colors. But `anstream` solved those problems, so I'm moving us _back_ to
`owo-colors`, since it's what `anstream` recommends, and it's already
used by many of our dependencies (`miette`, `configparser`).

---------

Co-authored-by: konstin <konstin@mailbox.org>
2024-01-08 08:54:57 +00:00
Charlie Marsh e6fcb9c4d3
Use `anstream` for all color control (#823)
## Summary

We can use `anstream` for all color control, rather than going through
`colored`. Note that we still need the `colored` crate, since `colored`
and `anstream` solve different problems. (`anstream` recommends using
`owo-colors` alongside it, but `colored` seems to work fine?)

Resolves the issue raised in
https://github.com/astral-sh/puffin/pull/742 via `anstream` rather than
`colored`.

Closes https://github.com/astral-sh/puffin/issues/782.
2024-01-06 20:44:05 -05:00
konsti 5820a9d937
Update dependencies (#794)
Pull in a bunch of updates so they get some testing before we announce
the project. textwrap 0.16 is blocked on miette updating, http 1.0 on
reqwest.
2024-01-05 11:40:12 -05:00
konsti 673bece595
Allow `pip-compile` without a venv (#494)
The semantics are a bit unintuitive because `--python-version` is a
preference when looking for a python version without a venv, but if we
don't find that exact version we'll take `python3` and patch the
markers. This will make more sense once we start provisioning python
builds.

We can now resolve black with both python 3.8 and 3.12, with or without
that python version being in scope. In the example below,
`PATH=$HOME/.cargo/bin:/usr/bin` removes the pyenv builds and leaves
only `python3`, which is python 3.11.

```console
$ RUST_LOG=puffin::commands=debug cargo run --bin puffin -q -- pip-compile -v scripts/benchmarks/requirements/black.in --python-version py38
    0.004108s DEBUG puffin::commands::pip_compile Using Python 3.8 at /home/konsti/.local/bin/python3.8
Resolved 8 packages in 44ms
# This file was autogenerated by Puffin v0.0.1 via the following command:
#    puffin pip-compile -v scripts/benchmarks/requirements/black.in --python-version py38
black==23.11.0
[...]
platformdirs==4.0.0
    # via black
tomli==2.0.1
    # via black
typing-extensions==4.8.0
    # via black
$ PATH=$HOME/.cargo/bin:/usr/bin RUST_LOG=puffin::commands=debug cargo run --bin puffin -q -- pip-compile -v scripts/benchmarks/requirements/black.in --python-version py38
    0.004315s DEBUG puffin::commands::pip_compile Using Python 3.11 at /usr/bin/python3
Resolved 8 packages in 43ms
# This file was autogenerated by Puffin v0.0.1 via the following command:
#    puffin pip-compile -v scripts/benchmarks/requirements/black.in --python-version py38
black==23.11.0
[...]
platformdirs==4.0.0
    # via black
tomli==2.0.1
    # via black
typing-extensions==4.8.0
    # via black
```

```console
$ RUST_LOG=puffin::commands=debug cargo run --bin puffin -q -- pip-compile -v scripts/benchmarks/requirements/black.in --python-version py312
    0.004216s DEBUG puffin::commands::pip_compile Using Python 3.12 at /home/konsti/.local/bin/python3.12
Resolved 6 packages in 37ms
# This file was autogenerated by Puffin v0.0.1 via the following command:
#    puffin pip-compile -v scripts/benchmarks/requirements/black.in --python-version py312
black==23.11.0
[...]
platformdirs==4.0.0
    # via black
$ PATH=$HOME/.cargo/bin:/usr/bin RUST_LOG=puffin::commands=debug cargo run --bin puffin -q -- pip-compile -v scripts/benchmarks/requirements/black.in --python-version py312
    0.004190s DEBUG puffin::commands::pip_compile Using Python 3.11 at /usr/bin/python3
Resolved 6 packages in 39ms
# This file was autogenerated by Puffin v0.0.1 via the following command:
#    puffin pip-compile -v scripts/benchmarks/requirements/black.in --python-version py312
black==23.11.0
[...]
platformdirs==4.0.0
    # via black
```

Fixes #235.

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-01-05 15:01:06 +00:00
Zanie Blue 5e04a95c45
Disable line wrapping during scenario tests (#784)
Adds support for a `PUFFIN_NO_WRAP` environment variable which disables
line wrapping in `miette` output.

We set this variable in the scenario tests to improve the readability of
snapshots.

I contributed the ability to disable line wrapping upstream at
https://github.com/zkat/miette/pull/328
2024-01-04 19:07:16 +00:00
konsti 2db9135c51
Update pubgrub to 78b8add6942766e5fb070bbda1de570e93d6399f (#783)
Pull in the latest perf improvements
2024-01-04 15:55:35 +00:00
konsti cd43708369
Flag to force latest version in resolve-many (#741)
Also fixes color when redirecting puffin-dev to a log file.
2024-01-02 11:04:26 +00:00
konsti 3f8dc9f5bb
Update pubgrub (#737)
Pull in https://github.com/pubgrub-rs/pubgrub/pull/170 and
https://github.com/pubgrub-rs/pubgrub/pull/171
2023-12-28 21:13:27 +00:00
Charlie Marsh 188ab75769
Split `File` into internal and external type (#729)
## Summary

This PR makes the `pypi_types::File` a response-only type (i.e., a type
that's only used when deserializing over the wire), and adds a separate
internal `File` type. Right now, the representations are similar, but
already, we can avoid the "lenient" deserialization on our internal
`File` type, and avoid the special-casing of the property names that's
required in the JSON. Over time, we can evolve this representation
entirely separately from the representation we receive from PyPI and
other indexes.
2023-12-25 15:42:28 -05:00
Charlie Marsh 6ff21374dc
Split `puffin-cache` into Puffin-specific and generic utilities (#728)
This crate started off as generic caching utilities, but we started
adding a lot of Puffin-specific stuff (like the cache buckets
abstraction that knows about Git vs. direct URL vs. indexes and so on).
This PR moves the generic stuff into a new `cache-key` crate.
2023-12-25 14:38:56 +00:00
Charlie Marsh 187ccef4e1
Cache `Tags` on `Interpreter` (#726) 2023-12-25 13:41:10 +00:00
Charlie Marsh 5b2e381f87
Remove `platform-tags` dependency on `puffin-interpreter` (#725)
Cuts off a large internal dependency chain from what is otherwise a very
general crate.
2023-12-24 23:06:50 +00:00
Charlie Marsh 343880820b
Un-escape HTML entities when decoding (#723)
I don't have a good testing strategy here (I'm manually testing against
`devpi` via `packse`), but the HTML index uses (e.g.)
`data-requires-python="&gt;=3.8"`, so we need to decode.
2023-12-24 16:35:45 -05:00
konsti e23292641f
Add pypi 10k packages with most dependents dataset (#711)
From manual inspection, this dataset generated through the [libraries.io
API](https://libraries.io/api#project-search) seems more mainstream than
the current 8k one, which is also preserved. I've added the dataset to
the repo because the API requires an API key.
2023-12-24 18:31:52 +00:00
Charlie Marsh 5bce699ee1
Add support for HTML indexes (#719)
## Summary

This PR adds support for HTML index responses (as with
`--index-url=https://download.pytorch.org/whl`).

Closes https://github.com/astral-sh/puffin/issues/412.
2023-12-24 16:04:00 +00:00
konsti e60f0ec732
Update pubgrub (#713)
Easier than i expected: We simply never construct the pubgrub error
variants since we have our own main loop. The `unreachable!()`s can be
removed when never is stabilized
2023-12-20 23:56:59 +01:00
Charlie Marsh 98fcb76015
Lock entire virtualenv during modifying commands (#695)
These commands all assume that the `site-packages` are constant
throughout.

Closes #691.
2023-12-18 16:44:45 -05:00
konsti 89ca0d68b9
`exclude_newer` in puffin-dev resolve-cli (#684)
Internal dev tool change.
2023-12-18 14:06:54 +00:00
konsti f059c6e6a6
Support editable in pip-sync and pip-compile (#587)
Support `-e path/do/dir` in pip-sync and and pip-compile.
2023-12-16 22:37:34 +00:00
konsti 71964ec7a8
Switch to msgpack in the cached client (#662)
This gives a 1.23 speedup on transformers-extras. We could change to
msgpack for the entire cache if we want. I only tried this format and
postcard so far, where postcard was much slower (like 1.6s).

I don't actually want to merge it like this, i wanted to figure out the
ballpark of improvement for switching away from json.

```
hyperfine --warmup 3 --runs 10 "target/profiling/puffin pip-compile --cache-dir cache-msgpack scripts/requirements/transformers-extras.in" "target/profiling/branch pip-compile scripts/requirements/transformers-extras.in"
Benchmark 1: target/profiling/puffin pip-compile --cache-dir cache-msgpack scripts/requirements/transformers-extras.in
  Time (mean ± σ):     179.1 ms ±   4.8 ms    [User: 157.5 ms, System: 48.1 ms]
  Range (min … max):   174.9 ms … 188.1 ms    10 runs

Benchmark 2: target/profiling/branch pip-compile scripts/requirements/transformers-extras.in
  Time (mean ± σ):     221.1 ms ±   6.7 ms    [User: 208.1 ms, System: 46.5 ms]
  Range (min … max):   213.5 ms … 235.5 ms    10 runs

Summary
  target/profiling/puffin pip-compile --cache-dir cache-msgpack scripts/requirements/transformers-extras.in ran
    1.23 ± 0.05 times faster than target/profiling/branch pip-compile scripts/requirements/transformers-extras.in
```

Disadvantage: We can't manually look into the cache anymore to debug
things

- [ ] Check more formats, i currently only tested json, msgpack and
postcard, there should be other formats, too
- [x] Switch over `CachedByTimestamp` serialization (for the interpreter
caching)
- [x] Switch over error handling and make sure puffin is still resilient
to cache failure
2023-12-16 21:01:35 +00:00
konsti 620f73b38b
Speed up version parsing for a 1.27±0.03 speedup in transformers-extras with conservative changes (#660)
Two low-hanging fruits as optimizations for version parsing: A fast path
for release only versions and removing the regex from version specifiers
(still calling into version's parsing regex if required). This enables
optimizing the serde format since we now see the serde part instead of
only PEP 440 parsing. I intentionally didn't rewrite the full PEP 440 at
this step.

```console
$ hyperfine --warmup 5 --runs 50 "target/profiling/puffin pip-compile scripts/requirements/transformers-extras.in" "target/profiling/main pip-compile scripts/requirements/transformers-extras.in"
  Benchmark 1: target/profiling/puffin pip-compile scripts/requirements/transformers-extras.in
    Time (mean ± σ):     217.1 ms ±   3.2 ms    [User: 194.0 ms, System: 55.1 ms]
    Range (min … max):   211.0 ms … 228.1 ms    50 runs

  Benchmark 2: target/profiling/main pip-compile scripts/requirements/transformers-extras.in
    Time (mean ± σ):     276.7 ms ±   5.7 ms    [User: 252.4 ms, System: 54.6 ms]
    Range (min … max):   268.9 ms … 303.5 ms    50 runs

  Summary
    target/profiling/puffin pip-compile scripts/requirements/transformers-extras.in ran
      1.27 ± 0.03 times faster than target/profiling/main pip-compile scripts/requirements/transformers-extras.in
```

---------

Co-authored-by: Andrew Gallant <andrew@astral.sh>
2023-12-15 14:03:35 -05:00
Charlie Marsh 9470c20e7a
Avoid double resolution during source builds (#656)
## Summary

This PR ensures that we re-use the resolution to install the build
dependencies when building a source distribution. Currently, we only
pass along the list of requirements, and then use the `Finder` to map
each requirement to a distribution. But we already determine the correct
distribution when resolving!

Closes https://github.com/astral-sh/puffin/issues/655.
2023-12-15 17:27:16 +00:00
Charlie Marsh ed8dfbfcf7
Preserve verbatim URLs (#639)
## Summary

This PR adds a `VerbatimUrl` struct to preserve verbatim URLs throughout
the resolution and installation pipeline. In short, alongside the parsed
`Url`, we also keep the URL as written by the user. This enables us to
display the URL exactly as written by the user, rather than the
serialized path that we use internally.

This will be especially useful once we start expanding environment
variables since, at that point, we'll be able to write the version of
the URL that includes the _unexpected_ environment variable to the
output file.
2023-12-14 15:03:39 +00:00
Charlie Marsh db7e2dedbb
Move archive extraction into its own crate (#647)
We have some shared utilities beyond `puffin-build` and
`puffin-distribution`, and further, I want to be able to access the
sdist archive extraction logic from `puffin-distribution`. This is
really generic, so moving into its own crate.
2023-12-14 04:49:09 +00:00
Charlie Marsh 920e10fc8f
Use `FxHash` consistently (#632) 2023-12-13 05:36:03 +00:00
Charlie Marsh a24eb57e93
Make warnings user-facing (#628)
## Summary

Now, `puffin_warnings::warn_once` and `puffin_warnings::warn` will go to
`stderr`, as long as the user isn't running under `--quiet`. Previously,
these went through `tracing`, and so were only visible when running
under `--verbose`.
2023-12-12 21:24:38 -05:00
Zanie Blue 490fb55ac5
Use available versions to simplify unsat error reports (#547)
Uses https://github.com/pubgrub-rs/pubgrub/pull/156 to consolidate
version ranges in error reports using the actual available versions for
each package.

Alternative to https://github.com/zanieb/pubgrub/pull/8 which implements
this behavior as a method in the `Reporter` — here it's implemented in
our custom report formatter (#521) instead which requires no upstream
changes.

Requires https://github.com/zanieb/pubgrub/pull/11 to only retrieve the
versions for packages that will be used in the report.

This is a work in progress. Some things to do:
- ~We may want to allow lazy retrieval of the version maps from the
formatter~
- [x] We should probably create a separate error type for no solution
instead of mixing them with other resolve errors
- ~We can probably do something smarter than creating vectors to hold
the versions~
- [x] This degrades error messages when a single version is not
available, we'll need to special case that
- [x] It seems safer to coerce the error type in `resolve` instead of
`solve` if feasible
2023-12-12 23:25:16 +00:00
Charlie Marsh 1181288078
Download, build, and install in a single pipeline phase (#605)
## Summary

At present, we have two separate phases within the installation pipeline
related to populating wheels into the cache. The first phase downloads
the distribution, and then builds any source distributions into wheels;
the second phase unzips all the built wheels into the cache.

This PR merges those two phases into one, such that we seamlessly
download, build, and unzip wheels in one pass. This is more efficient,
since we can start unzipping while we build. It also ensures that if the
install _fails_ partway through, we don't end up with a bunch of
downloaded wheels that we never had a chance to unzip. The code is also
much simpler.

The main downside is that the user-facing feedback isn't as granular,
since we only have one phase and one progress bar for what was
originally three distinct phases.

Closes https://github.com/astral-sh/puffin/issues/571.

## Test Plan

I ran the benchmark script on two separate requirements files, and saw a
7% and 31% speedup respectively:

```text
+ TARGET=./scripts/benchmarks/requirements.txt
+ hyperfine --runs 100 --warmup 10 --prepare 'virtualenv --clear .venv' './target/release/main pip-sync ./scripts/benchmarks/requirements.txt --no-cache' --prepare 'virtualenv --clear .venv' './target/release/puffin pip-sync ./scripts/benchmarks/requirements.txt --no-cache'
Benchmark 1: ./target/release/main pip-sync ./scripts/benchmarks/requirements.txt --no-cache
  Time (mean ± σ):     269.4 ms ±  33.0 ms    [User: 42.4 ms, System: 117.5 ms]
  Range (min … max):   221.7 ms … 446.7 ms    100 runs

Benchmark 2: ./target/release/puffin pip-sync ./scripts/benchmarks/requirements.txt --no-cache
  Time (mean ± σ):     250.6 ms ±  28.3 ms    [User: 41.5 ms, System: 127.4 ms]
  Range (min … max):   207.6 ms … 336.4 ms    100 runs

Summary
  './target/release/puffin pip-sync ./scripts/benchmarks/requirements.txt --no-cache' ran
    1.07 ± 0.18 times faster than './target/release/main pip-sync ./scripts/benchmarks/requirements.txt --no-cache'
```

```text
+ TARGET=./scripts/benchmarks/requirements-large.txt
+ hyperfine --runs 100 --warmup 10 --prepare 'virtualenv --clear .venv' './target/release/main pip-sync ./scripts/benchmarks/requirements-large.txt --no-cache' --prepare 'virtualenv --clear .venv' './target/release/puffin pip-sync ./scripts/benchmarks/requirements-large.txt --no-cache'
Benchmark 1: ./target/release/main pip-sync ./scripts/benchmarks/requirements-large.txt --no-cache
  Time (mean ± σ):      5.053 s ±  0.354 s    [User: 1.413 s, System: 6.710 s]
  Range (min … max):    4.584 s …  6.333 s    100 runs

Benchmark 2: ./target/release/puffin pip-sync ./scripts/benchmarks/requirements-large.txt --no-cache
  Time (mean ± σ):      3.845 s ±  0.225 s    [User: 1.364 s, System: 6.970 s]
  Range (min … max):    3.482 s …  4.715 s    100 runs

Summary
  './target/release/puffin pip-sync ./scripts/benchmarks/requirements-large.txt --no-cache' ran
```
2023-12-11 15:42:29 +00:00
Charlie Marsh 32f54a5947
Use async `Command` for wheel build operations (#601)
Incredibly, this speeds up the install on a large project from 2m6s to
50s.
2023-12-09 16:20:52 +00:00
Charlie Marsh a24534b0ce
Use `rustc-hash` instead of `fxhash` crate (#594)
`fxhash` is the old, less maintained version of this crate
(`rustc-hash`). We use the latter in Ruff.
2023-12-08 20:27:49 +00:00
konsti 6005d7a552
Keep track of in flight unzips using `OnceMap` (#544)
I saw warnings when we were e.g. unzipping wheel and setuptools in two
tasks at the same time. We now keep track of in flight unzips.

This introduces a `OnceMap` abstraction which we also use in the
resolver.
2023-12-08 20:18:11 +00:00
Charlie Marsh 4b8642c6f7
Enable selective cache purging in `puffin clean` (#589)
## Summary

This PR enables `puffin clean` to accept package names as command line
arguments, and selectively purge entries from the cache tied to the
given package.

Relate to #572.

## Test Plan

Modified all the caching tests to run an additional step to (1) purge
the cache, and (2) re-install the package.
2023-12-08 19:51:32 +00:00
Zanie Blue ef7be9103c
Parse `SimpleJson` into categorized data in the client (#522)
Extends #517 with a suggestion from @konstin to parse the `SimpleJson`
into an intermediate type `SimpleMetadata(BTreeMap<Version,
VersionFiles>)` before converting to a `VersionMap`. This reduces the
number of times we need to parse the response. Additionally, we cache
the parsed response now instead of `SimpleJson`.

`VersionFiles` stores two vectors with
`WheelFilename`/`SourceDistFilename` and `File` tuples. These can be
iterated over together or separately. A new enum `DistFilename` was
added to capture the `SourceDistFilename` and `WheelFilename` variants
allowing iteration over both vectors.
2023-12-07 11:04:47 -06:00
Charlie Marsh aa065f5c97
Modify install plan to support all distribution types (#581)
This PR adds caching support for built wheels in the installer.
Specifically, the `RegistryWheelIndex` now indexes both downloaded and
built wheels (from registries), and we have a new `BuiltWheelIndex` that
takes a subdirectory and returns the "best-matching" compatible wheel.

Closes #570.
2023-12-07 04:43:34 +00:00
konsti 366c389385
Parse editable installs (#564)
Parse `-e` for editable installs in `requirements.txt`.

Unlike all the other requirements, editable installs don't have the name
of the package specified.
2023-12-06 18:21:15 +01:00
konsti 3f4d7b7826
Improve path source dist caching (#578)
Path distribution cache reading errors are no longer fatal.

We now invalidate the path file source dists if its modification
timestamp changed, and invalidate path dir source dists if
`pyproject.toml` or alternatively `setup.py` changed, which seems good
choices since changing pyproject.toml should trigger a rebuild and the
user can `touch` the file as part of their workflow.

`CachedByTimestamp` is now a shared util. It doesn't have methods as i
don't think it's worth it yet for two users.

Closes #478

TODO(konstin): Write a test. This is probably twice as much work as that
fix itself, so i made that PR without one for now.
2023-12-06 11:47:01 -05:00
Charlie Marsh a15da36d74
Avoid removing local wheels when unzipping (#560)
## Summary

When installing a local wheel, we need to avoid removing the zipped
wheel (since it lives outside of the cache), _and_ need to ensure that
we unzip the wheel into the cache (rather than replacing the zipped
wheel, which may even live outside of the project).

Closes https://github.com/astral-sh/puffin/issues/553.
2023-12-05 17:50:08 +00:00
Charlie Marsh 6f055ecf3b
Remove existing built wheels when building source distributions (#559)
This PR modifies the source distribution building to replace any
existing targets after building the new wheel. In some cases, the
existence of an existing target may be indicative of a bug, so we warn.
It's partially a workaround for some (but not all) of the errors in
https://github.com/astral-sh/puffin/issues/554.
2023-12-05 12:45:24 -05:00
Zanie Blue 37ca2e2928
Bump pubgrub for latest upstream (#525)
https://github.com/pubgrub-rs/pubgrub/pull/157
2023-12-04 09:09:30 -06:00
konsti 6dc8ebcb90
Test interpreter cache invalidation (#540)
Add missing test for #529/#508.
2023-12-04 10:03:43 +00:00
Charlie Marsh ee2fca3a48
Add CACHEDIR and .gitignore tags to cache directories (#526)
## Summary

Even if this will typically be in the user's application folder (rather
than a local directory), it's still a good practice.

Closes https://github.com/astral-sh/puffin/issues/280.
2023-12-02 00:37:51 +00:00
konsti 9806901a16
Consolidate wheel caches (#524)
After this change, two wheel caches remain: `built-wheels-v0` and
`wheels-v0`, docs screenshots below. Each contains both the wheel
metadata, cache policy and zip or unzipped wheels under the same name.

The zipped/unzipped strategy is as follows: In `pip-compile`, when we
build a wheel, we store it zipped. When `pip-sync` or a source dist
build in `pip-compile` need to install the wheel, we unzip it, remove
the file and replace it with the unzipped wheel.

This removes `WheelCache` and `UrlIndex` in favor of `Cache` plus
`WheelCache`. The non-built wheel cache now considers index urls and the
url for url wheels.

I'm unsure if we need the `Unzipper` type, this could just be a
function.

I move `no_index` into `IndexUrls` and started using `IndexUrl` up to
the clap level.

I left a number of TODOs in the code, namely performing the actual
invalidation of unzipped wheels and making the `InstallPlan` understand
cache invalidation (i.e. uninstall wheels when their remote changed).


![image](https://github.com/astral-sh/puffin/assets/6826232/c4d45979-485b-4954-848d-fd3347ee2510)
2023-12-01 20:16:33 +00:00
Zanie Blue 2a8544df9e
Use a custom pubgrub report formatter (#521)
Uses https://github.com/zanieb/pubgrub/pull/10 to drastically simplify
our reporter implementation. This will allow us to make use of upstream
improvements to the reporter e.g.
https://github.com/zanieb/pubgrub/pull/8 without multiple duplicative
pull requests.
2023-12-01 13:36:12 -06:00
Zanie Blue efcc4f1409
Use upstream commit for reflink-copy requirement (#523)
https://github.com/cargo-bins/reflink-copy/pull/51 was merged
2023-12-01 10:58:24 +00:00
Zanie Blue 5f1f207628
Recursively merge existing package directories on installation (#516)
Previously, when installing a package we would delete the target
directory before copying (or linking) the contents of the package.
However, this means that we do not properly support namespace packages
which can share a target directory. Instead the last package to be
installed would be override existing packages. Since we install packages
in parallel, this could result in a race condition where the target
directory already exists which is not allowed when using `clonefile`.
See example error in #515.
c7e63d2dce
provides a regression test for this — it fails on `main`.

Here, we implement a recursive merge when the target directory already
exists. Both packages will be installed into the same directory. We no
longer delete the target directory, which seems okay since we uninstall
packages before installing now.

When files conflict, we will likely throw an error still. The correct
behavior to implement in this case is unclear, as if we just take "first
write wins" or "last write wins" we could end up with some files from
one package and some from another resulting in two broken packages. A
possible solution here is to lock the target directories while copying.
2023-11-30 10:14:51 -06:00
konsti 929df586fb
Skip tf-models-nightly in resolve-many dev script for now (#510)
`tf-models-nightly` has pathologic backtracking behaviour, skip it for
now so we can benchmark the rest.
2023-11-28 18:25:32 +00:00
konsti d89fbeb642
Migrate interpreter query to custom caching (#508)
This removes the last usage of cacache by replacing it with a custom,
flat json caching keyed by the digest of the executable path.


![image](https://github.com/astral-sh/puffin/assets/6826232/8f777c4c-1f1b-4656-ba7b-002175270556)

A step towards #478. I've made `CachedByTimestamp<T>` generic over `T`
but intentionally not moved it to `puffin-cache` yet.
2023-11-28 17:14:59 +00:00
konsti 5435d44756
Introduce `Cache`, `CacheBucket` and `CacheEntry` (#507)
This is mostly a mechanical refactor that moves 80% of our code to the
same cache abstraction.

It introduces cache `Cache`, which abstracts away the path of the cache
and the temp dir drop and is passed throughout the codebase. To get a
specific cache bucket, you need to requests your `CacheBucket` from
`Cache`. `CacheBucket` is the centralizes the names of all cache
buckets, moving them away from the string constants spread throughout
the crates.

Specifically for working with the `CachedClient`, there is a
`CacheEntry`. I'm not sure yet if that is a strict improvement over
`cache_dir: PathBuf, cache_file: String`, i may have to rotate that
later.

The interpreter cache moved into `interpreter-v0`.

We can use the `CacheBucket` page to document the cache structure in
each bucket:


![image](https://github.com/astral-sh/puffin/assets/6826232/b023fdfb-e34d-4c2d-8663-b5f73937a539)
2023-11-28 17:11:14 +00:00
konsti 8855f44b5f
Move simple index queries to `CachedClient` (#504)
Replaces the usage of `http-cache-reqwest` for simple index queries with
our custom cached client, removing `http-cache-reqwest` altogether.

The new cache paths are `<cache>/simple-v0/<index>/<package_name>.json`.
I could not test with a non-pypi index since i'm not aware of any other
json indices (jax and torch are both html indices).

In a future step, we can transform the response to be a
`HashMap<Version, {source_dists: Vec<(SourceDistFilename, File)>,
wheels: Vec<(WheeFilename, File)>}` (independent of python version, this
cache is used by all environments together). This should speed up cache
deserialization a bit, since we don't need to try source dist and wheel
anymore and drop incompatible dists, and it should make building the
`VersionMap` simpler. We can speed this up even further by splitting
into a version lists and the info for each version. I'm mentioning this
because deserialization was a major bottleneck in the rust part of the
old python prototype.

Fixes #481
2023-11-28 00:11:03 +00:00