Commit Graph

1076 Commits

Author SHA1 Message Date
Charlie Marsh b4bc40627c
Sort output when installing seed packages (#1822)
This output is technically non-deterministic right now.
2024-02-21 18:33:06 +00:00
Micha Reiser 39ee3969d9
Upgrade to Rust 1.76 (#1820) 2024-02-21 17:53:41 +00:00
Andrew Gallant deef6c102d
platform-host: check /bin/sh, then /bin/dash and then /bin/ls (#1818)
Previously, we were only checking /bin/sh. While that works in most
cases, it seems like there are still scenarios where /bin/sh isn't an
executable itself, and is instead just a shell script that calls
/bin/dash. (See #1810 for example.)

In this PR, we make the `ld` detection a bit more robust by trying
multiple paths. As with previous changes, we emit copious logs to help
debug this in the future.

It's not totally clear how to test this. I'm not sure how to reproduce
the environment mentions in #1810 specifically since it seems like an
internal variant of WSL Ubuntu.

Fixes #1810
2024-02-21 11:49:28 -05:00
Micha Reiser fac9d843dc
Normalize `VIRTUAL_ENV` path in activation scripts (#1817) 2024-02-21 15:52:32 +00:00
Charlie Marsh cff16f5736
Use redirected URL as base for relative paths (#1816)
## Summary

If you review the setup in https://github.com/astral-sh/uv/issues/1747,
when we fetch `http://localhost:8000/simple/wheel/`, it gets redirected
to `http://localhost:8000/index/wheel/`. So any relative paths returned
need to be resolved relative to `http://localhost:8000/index/wheel/`.

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

## Test Plan

- Install `proxpi gunicorn pypiserver`
- `gunicorn proxpi.server:app --bind 0.0.0.0:8000`
- `pypi-server run -p 8080 ~/packages --fallback-url
"http://localhost:8000/index" --verbose`
- `echo "wheel" | cargo run pip compile - --index-url
http://localhost:8080/simple --verbose --no-cache`
2024-02-21 15:10:25 +00:00
Charlie Marsh c2b75b64d2
Wait for distribution metadata with `--no-deps` (#1812)
## Summary

We still need to wait for the distribution metadata (for direct
dependencies), even when resolving with `--no-deps`, since we rely on it
to report diagnostics to the user.

Closes https://github.com/astral-sh/uv/issues/1801.
2024-02-21 14:45:09 +00:00
Charlie Marsh 19890feb77
Preserve executable bit when untarring archives (#1790)
## Summary

Closes https://github.com/astral-sh/uv/issues/1767.
2024-02-21 14:18:44 +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
konsti 0f520d8716
Configurable bootstrap dir (#1772)
Add a `UV_BOOTSTRAP_DIR` option to configure the python bootstrap
directory. This is helpful when working across multiple platforms in a
single IDE session.
2024-02-21 13:46:23 +01:00
Charlie Marsh 5d53040465
Stream zip archive when fetching non-range-request metadata (#1792)
## Summary

If a registry doesn't support range requests, then today, we download
the entire wheel to disk and then read the metadata from the downloaded
archive. This PR instead modifies the registry client to stream the
zipfile and stop as soon as it's seen the metadata, which should be more
efficient.

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

## Test Plan

Made this the _only_ path for downloading metadata; verified that the
test suite passed.
2024-02-20 22:12:21 -05:00
Evgeniy Dubovskoy 31752bf4be
feat: Implement `--annotation-style` parameter for `uv pip compile` (#1679)
## Summary

Hello there! The motivation for this feature is described here #1678 

## Test Plan

I've added unit tests and also tested this manually on my work project
by comparing it to the original `pip-compile` output - it looks much
like the `pip-compile` generated lock file.
2024-02-21 02:08:34 +00:00
Zanie Blue 3cd51ffc92
Support setting request timeout with `UV_HTTP_TIMEOUT` and `HTTP_TIMEOUT` (#1780)
Follow-up to #1694 matching Cargo's environment variable names


https://doc.rust-lang.org/nightly/cargo/reference/config.html#httptimeout
2024-02-20 18:48:18 -06: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
Edgar Ramírez Mondragón 2e60c1d734
Use the right marker for the `implementation` field of `pyvenv.cfg` (#1785)
## Summary

The generated `pyvenv.cfg` file hardcodes `implementation = CPython`
even for PyPy venvs, created with `uv venv venv --python pypy3.10`, for
example.

```ini
home = /path/to/.pyenv/versions/pypy3.10-7.3.15/bin
implementation = CPython
version_info = 3.10
gourgeist = 0.0.4
include-system-site-packages = false
base-prefix = /path/to/.pyenv/versions/pypy3.10-7.3.15
base-exec-prefix = /path/to/.pyenv/versions/pypy3.10-7.3.15
base-executable = /path/to/.pyenv/versions/pypy3.10-7.3.15/bin/pypy3.10
```

## Test Plan

Manually verified that `pyvenv.cfg` now contains `implementation =
PyPy`. I can try refactoring `create_bare_venv` to make it more easily
testable, though.
2024-02-20 19:09:53 -05:00
Charlie Marsh f13d0adbcd
Ensure that builds within the cache aren't considered Git repositories (#1782)
## Summary

Some packages encode logic to embed the current commit SHA in the
version tag, when built within a Git repo. This typically results in an
invalid (non-compliant) version. Here's an example from `pylzma`:
ccb0e7cff3/version.py (L45).

This PR adds a phony, empty `.git` to the cache root, to ensure that any
`git` commands fail.

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

## Test Plan

- Create a tag on the current commit, like `v0.5.0`.
- Build `pylzma`, using a cache _within_ the repo:

```
rm -rf foo
cargo run venv
cargo run pip install "pylzma @ 10ef072c3c3b9ea77ebe9546499975/pylzma-0.5.0.tar.gz" --verbose  --cache-dir bar
```
2024-02-20 15:37:05 -05:00
Charlie Marsh d5a2a5fed3
Add support for `>dev` specifier (#1776)
## Summary

Not a fan of this one but we don't have a clear policy on it yet so
feels weird to discriminate.

Closes https://github.com/astral-sh/uv/issues/1686.
2024-02-20 20:27:30 +00:00
Charlie Marsh 8df48f035f
Fix pep508-rs tests without features (#1778) 2024-02-20 19:35:36 +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
Andrew Gallant 8480842d3e
strip trailing `+` from version number of local Python builds (#1771)
(This PR message is mostly copied from the comment in the code.)

For local builds of Python, at time of writing, the version numbers end
with
a `+`. This makes the version non-PEP-440 compatible since a `+`
indicates
the start of a local segment which must be non-empty. Thus, `uv` chokes
on it
and [spits out an error][1] when trying to create a venv using a "local"
build
of Python. Arguably, the right fix for this is for [CPython to use a
PEP-440
compatible version number][2].

However, as a work-around for now, [as suggested by pradyunsg][3] as one
possible direction forward, we strip the `+`.

This fix does unfortunately mean that one [cannot specify a Python
version
constraint that specifically selects a local version][4]. But at the
time of
writing, it seems reasonable to block such functionality on this being
fixed
upstream (in some way).

Another alternative would be to treat such invalid versions as strings
(which
is what PEP-508 suggests), but this leads to undesirable behavior in
this
case. For example, let's say you have a Python constraint of `>=3.9.1`
and
a local build of Python with a version `3.11.1+`. Using string
comparisons
would mean the constraint wouldn't be satisfied:

    >>> "3.9.1" < "3.11.1+"
    False

So in the end, we just strip the trailing `+`, as was done in the days
of old
for [legacy version numbers][5].

I tested this fix by manually confirming that

    uv venv --python local/python

failed before it and succeeded after it.

Fixes #1357

[1]: https://github.com/astral-sh/uv/issues/1357
[2]: https://github.com/python/cpython/issues/99968
[3]:
https://github.com/pypa/packaging/issues/678#issuecomment-1436033646
[4]: https://github.com/astral-sh/uv/issues/1357#issuecomment-1947645243
[5]:
085ff41692/packaging/version.py (L168-L193)
2024-02-20 12:57:28 -05:00
konsti a269766c27
If-let instead of unwrap (PR #1746 follow-up) (#1770)
Solves: https://github.com/astral-sh/uv/pull/1746#discussion_r1496139629
2024-02-20 17:32:01 +00:00
Charlie Marsh ede2828fde
Bump version to v0.1.6 (#1736) 2024-02-20 12:22:26 -05:00
Tim de Jager 8cbeab7107
feat: add installer to `InstalledDist` (#1762)
## Summary

Add `installer` method to `InstalledDist` to distinguish between
different installers. Might be nice to add an enum for all possible
installers, but this might be too hard to keep up to date :).

The `INSTALLER` file is a file that can be added to the `.dist-info`
folder with the installer name.

Closes: #1759 

## Test Plan

Not sure if there is a place I can automatically test it, if you have a
pointer I would be happy to add a test.
2024-02-20 17:07:08 +00:00
konsti a7513f4644
Better error message for missing space before semicolon in requirements (#1746)
PEP 508 requires a space between a URL and the semicolon separating it
from the markers to disambiguate it from a url ending with a semicolon.
This is easy to get wrong because the space is not required after a
plain name of PEP 440 specifier. The new error message explicitly points
out the missing space.

Fixes #1637
2024-02-20 16:38:36 +00:00
konsti db61d848a7
Skip compile_html test on musl (#1756)
The torch index has no musllinux wheel, so we need to skip the test on
alpine.
2024-02-20 16:36:03 +00:00
Bas Zalmstra 6ea49ef7bf
fix: expose DefaultResolverProvider (#1764)
## Summary

The `DefaultResolverProvider` struct was not public. This PR exposes it
so we can build our own and use this as a fallback.

## Test Plan

I did not explicitly test this trivial change.
2024-02-20 11:34:19 -05:00
Andrew Gallant 8bcb998af1 uv-extract: add regression test for a bunk zip file
This ensures we can install a source dist from a `zip`
file that has present but bunk permissions.

Fixes #1453
2024-02-20 10:57:51 -05:00
Andrew Gallant d6aaf7be30 uv-extract: call `target.as_ref()` once
This is just a style thing.
2024-02-20 10:57:51 -05:00
Andrew Gallant 634d593127 uv-client: remove benign WARN log message
A WARN log was being emitted for a "broken cache entry" in the case
where the cache entry simply doesn't exist. But this is totally fine and
expected. So we detect the kind of error that occurred and emit a TRACE
if the file simply didn't exist.
2024-02-20 10:57:51 -05:00
konsti 9a720a87c8
Only preserve the executable bit (#1743)
A file in a zip can set arbitrary unix permissions, but we, like pip,
want to preserve only the executable bit and otherwise use the OS
defaults.

This should be faster for wheels with many files since we now avoid the
blocking fs call to set the permissions in most cases.

Fixes #1740.
2024-02-20 16:41:05 +01:00
konsti f7722c02c1
Don't preserve timestamp in streaming unzip (#1749)
## Summary

Don't preserve mtime to work around alexcrichton/tar-rs#349. Same as
#634 except for the streaming unzip.

Fixes #1748.

## Test Plan

Added the tomli source dist as test case.
2024-02-20 14:54:28 +00:00
Viktor Szépe c191a83c5e
Fix typos configuration (#1742)
## Summary

Narrow down excludes for `typos` and fix 2 additional misspellings.

BTW pre-commit can be run in CI:
https://github.com/szepeviktor/pre-commit-on-you/actions/runs/7971275239/job/21760614908
2024-02-20 09:53:07 -05:00
Bas Zalmstra daf2800ddf
feat: allow passing in a custom reqwest Client (#1745)
## Summary

I am looking to instantiate a `RegistryClient`. However, when using the
`RegistryClientBuilder` a new reqwest client is always constructed. I
would like to pass in a custom `reqwest::Client` to be able to share the
http resources with other parts of my application.

## Test Plan

The uv codebase does not use my addition to the builder and all tests
still succeed. And in my code I can pass a custom Client.
2024-02-20 09:50:18 -05:00
Charlie Marsh dd7d533411
Set index URLs for seeding venv (#1755)
Just an oversight due to builder pattern.

Closes https://github.com/astral-sh/uv/issues/1752.
2024-02-20 14:49:16 +00:00
обоо 7741e1c51a
Print activation instructions for a venv after one has been created (#1580) 2024-02-20 12:39:42 +00:00
Charlie Marsh d05cb8464a
Allow `-f` alias for `--find-links` (#1735)
## Summary

`pip` supports this, and I keep expecting it to exist in my testing.
2024-02-20 00:56: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 692c00defe
Implement `uv cache dir` (#1734)
## Summary

Like `pip cache dir`, merely prints out the cache directory.

Closes https://github.com/astral-sh/uv/issues/1646.
2024-02-19 23:29:10 -05:00
Charlie Marsh bb876d95ed
Move `uv clean` to `uv cache clean` (#1733)
## Summary

This opens up space to add other cache-related commands. (`uv clean`
continues to work for backwards compatibility but is hidden from the
CLI.)
2024-02-20 04:14:05 +00:00
Charlie Marsh 254a94c40a
Use `httpx` instead of `anyio` for reinstall test (#1732)
This works on Windows.
2024-02-19 23:08:19 -05:00
Charlie Marsh 4b5b9835fd
Ensure extras trigger an install (#1727)
## Summary

We weren't respecting extras when auditing the existing environment.

Closes https://github.com/astral-sh/uv/issues/1726.
2024-02-20 03:37:35 +00:00
Charlie Marsh a5372d4e4d
Ignore invalid extras from PyPI (#1731)
## Summary

We don't control these, so it seems preferable _not_ to fail on them,
but rather, to just ignore them entirely. (I considered adding a long
allow-list, but then questioned the point of it? We'd end up having to
extend it if more invalid extras were published in the future.)

Closes https://github.com/astral-sh/uv/issues/1633.
2024-02-19 22:26:29 -05:00
Charlie Marsh 402edf1522
Improve Poetry warning (#1730)
Good feedback from:
https://github.com/astral-sh/uv/pull/1650#discussion_r1495140531
2024-02-19 22:08:49 -05:00
Charlie Marsh 505b99d9b6
Support recursive extras for URL dependencies (#1729)
Closes https://github.com/astral-sh/uv/issues/1680.
2024-02-19 21:56:21 -05:00
Charlie Marsh c05080a3e3
Add support for absolute paths on Windows (#1725)
## Summary

The main change is that we need to have an explicit list of protocols we
_do_ support (like `https`), so that when we see a Windows absolute path
(`C:\...`), we don't treat the `C` as a protocol itself.

Closes https://github.com/astral-sh/uv/issues/1539.
2024-02-20 01:36:53 +00:00
Taniguchi Yasufumi 8f739c9b23
Add warning when dependencies are empty with Poetry metadata (#1650)
Resolve #1630 

`PyProjectToml` doesn't seem to have a `tool` field, so instead of
checking it, I check if `requirements` is empty.


c04f597fae/crates/uv-build/src/lib.rs (L176-L184)
2024-02-20 00:08:25 +00: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
Zanie Blue f3ef55f879
Update the scenarios to use vendored build dependencies (#1605)
Uses `--find-links` to discover vendored scenario build dependencies and
allows us to use `--index-url` instead of `--extra-index-url` to avoid
hitting the real PyPI in scenario tests.
2024-02-19 21:55:03 +00:00
Charlie Marsh 1d9daa6de1
Preserve trailing slash for `--find-links` URLs (#1720)
## Summary

We should allow a `--find-links` URL to be provided as _either_ (e.g.)
`https://wheelhouse.acsone.eu/manylinux1` or
`https://wheelhouse.acsone.eu/manylinux1/`. By using the response URL,
we can "always do the right thing" (it will always have a trailing
slash, or always return a `.html` suffix) rather than attempting to
sniff out the URL kind in advance.

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

## Test Plan

- `cargo run pip install requests --force-reinstall --no-index
--find-links https://wheelhouse.acsone.eu/manylinux1 -n`
- `cargo run pip install requests --force-reinstall --no-index
--find-links https://wheelhouse.acsone.eu/manylinux1/ -n`
2024-02-19 21:26:12 +00:00
Olivier Le Floch 220bc46643
is_http_range_requests_unsupported should return true on Method Not Allowed (#1713)
## Summary

Azure Artifacts does not allow HEAD requests when attempting to download
packages. This expands error handling in
`is_http_range_requests_unsupported` to identify HTTP 405 (Method Not
Allowed) error codes, and return `true` (i.e. Range requests will not be
supported). This partially addresses #1458 – after this change, Azure
Artifacts downloads still fail, but due to 401 Not Authorized instead of
405 Method Not Allowed.

## Test Plan

I ran something akin to

```
RUST_LOG=trace cargo run -- pip install --index-url=https://REDACTED:REDACTED@pkgs.dev.azure.com/REDACTED/_packaging/REDACTED/pypi/simple/ --upgrade --verbose private-package
```

without this code, and got a 405 failure:

```
error: Failed to download: private-package==1.2.3
  Caused by: HTTP status client error (405 Method Not Allowed) for url (https://pkgs.dev.azure.com/REDACTED/_packaging/REDACTED/pypi/download/private-package/1.2.3/private_package-1.2.3-py3-none-any.whl#sha256=REDACTED)
  ```

with this code, I get a 401 failure:

```
error: Failed to download: private-package==1.2.3
Caused by: HTTP status client error (401 Unauthorized) for url
(https://pkgs.dev.azure.com/REDACTED/_packaging/REDACTED/pypi/download/private-package/1.2.3/private_package-1.2.3-py3-none-any.whl#sha256=REDACTED)
```

## Caveats

I'm not seeing a non HEAD request being reported as being fired, so I'm not sure I'm doing this correctly!
2024-02-19 15:40:25 -05:00
Henry Schreiner c6fd3d97fb
fix: remove uv version from uv pip compile header (#1716)
## Summary

This fixes https://github.com/astral-sh/uv/issues/1704 by removing the
version from the produced header.

## Test Plan

Checked with clippy, and tests are updated too.
2024-02-19 20:26:53 +00:00
Inada Naoki 9efbc1fc25
Add support for `venv --prompt` (#1570)
## Summary

This PR adds the `--prompt` option to `venv` subcommand.

The default behavior for `uv venv` is to create a virtual environment in
the current directory with `.venv` name. This is different from `venv` /
`virtualenv` where a user always needs to provide the virtual
environment path. This allows us to define our own behavior in the
default scenario (`uv venv`). We've decided to use the current
directory's name in that case.

Workflows:
| Command | Virtual Environment Name | Prompt |
|--------|--------|--------|
| `uv venv` | `.venv` (default) | Current directory name |
| `uv venv project` | `project` | `project` |
| `uv venv --prompt .` | `.venv` | Current directory name |
| `uv venv --prompt foobar` | `.venv` | `foobar` | 
| `uv venv project --prompt foobar` | `project` | `foobar` | 


Fixes #1445

## Test Plan

This is my first Rust code and I don't know how to write tests yet.
I just checked the behavior manually:

```
$ cargo build
$ mkdir t
$ cd t
$ ../target/debug/uv venv -p 3.11
$ rg -w t .venv/bin/acti*
.venv/bin/activate.csh
13:setenv VIRTUAL_ENV '/Users/inada-n/work/uv/t/.venv'
20:if ('t' != "") then
21:    setenv VIRTUAL_ENV_PROMPT 't'
23:    setenv VIRTUAL_ENV_PROMPT "$VIRTUAL_ENV:t:q"
38:    # in which case, $prompt is undefined and we wouldn't

.venv/bin/activate
48:VIRTUAL_ENV='/Users/inada-n/work/uv/t/.venv'
59:    VIRTUAL_ENV_PROMPT="t"

.venv/bin/activate.fish
61:set -gx VIRTUAL_ENV '/Users/inada-n/work/uv/t/.venv'
73:if test -n 't'
74:    set -gx VIRTUAL_ENV_PROMPT 't'

.venv/bin/activate.ps1
40:if ("t" -ne "") {
41:    $env:VIRTUAL_ENV_PROMPT = "t"

.venv/bin/activate.nu
6:# but then simply `deactivate` won't work because it is just an alias to hide
35:    let virtual_env = '/Users/inada-n/work/uv/t/.venv'
50:    let virtual_env_prompt = (if ('t' | is-empty) {
53:        't'
```

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2024-02-20 00:43:20 +05:30
Andrew Gallant cd1f619d21
re-introduce cache healing when we see an invalid cache entry (#1707)
This PR introduces more robust cache healing when `uv` fails to
deserialize an existing cache entry.

("Cache healing" in this context means that if `uv` fails to
deserialize a cache entry, then it will automatically invalidate that
entry and re-generate the data. Typically by sending an HTTP request.)

Previous to some optimizations I made around deserialization, we were
already doing this. After those optimizations, deserializing a cache
policy and the payload were split into two steps. While deserializing
a cache policy retained its cache healing behavior, deserializing the
payload did not. This became an issue when #1556 landed, which changed
one of our `rkyv` data types. This in turn made our internal types
incompatible with existing cache entries. One could work-around this
by clearing `uv`'s cache with `uv clean`, but we should just do it
automatically on a cache entry by entry basis.

This does technically introduce a new cost by pessimistically cloning
the HTTP request so that we can re-send it if necessary (see the commit
messages for the knot pushing me toward this approach). So I re-ran my
favorite ad-hoc benchmark:

```
$ hyperfine -w10 --runs 50 "uv-main pip compile --cache-dir ~/astral/tmp/cache-main ~/astral/tmp/reqs/home-assistant-reduced.in -o /dev/null" "uv-test pip compile --cache-dir ~/astral/tmp/cache-test ~/astral/tmp/reqs/home-assistant-reduced.in -o /dev/null" ; A bart
Benchmark 1: uv-main pip compile --cache-dir ~/astral/tmp/cache-main ~/astral/tmp/reqs/home-assistant-reduced.in -o /dev/null
  Time (mean ± σ):     114.4 ms ±   3.2 ms    [User: 149.4 ms, System: 221.5 ms]
  Range (min … max):   106.7 ms … 122.0 ms    50 runs

Benchmark 2: uv-test pip compile --cache-dir ~/astral/tmp/cache-test ~/astral/tmp/reqs/home-assistant-reduced.in -o /dev/null
  Time (mean ± σ):     114.0 ms ±   3.0 ms    [User: 146.0 ms, System: 223.3 ms]
  Range (min … max):   105.3 ms … 121.4 ms    50 runs

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

Which is about what I expected.

We should endeavor to have a better testing strategy for these kinds of
bugs, but I think it might be a little tricky to do. I created
https://github.com/astral-sh/uv/issues/1699 to track that.

Fixes #1571
2024-02-19 12:33:35 -05:00
markmmm b76efc62a7
Support dotted function paths for script entrypoints (#1622)
Co-authored-by: markm <mark.mcmahon@autodesk.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2024-02-19 10:09:12 +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
Daniel Reeves e923dba4b4
Move yank warnings to end of messages (#1669)
Resolves #1292.

## Summary

Move the yanked warnings for `uv pip sync` and `uv pip install` to the
end of the commands, as per #1292.

## Test Plan

I ran the unit tests: `cargo nextest run`
2024-02-18 18:01:00 -06:00
Arjun Munji 3ed386c0c5
Remove setuptools & wheel from seed packages (#1602) (#1613)
## Summary
Removed `wheel` and `setuptools` from seed packages list when creating a
virtual environment

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

## Test Plan
Ran the command `cargo nextest run` :
<img width="564" alt="image"
src="https://github.com/astral-sh/uv/assets/6116387/14ed2da6-1b3e-4598-a49f-29dd8c4cb19b">

---------

Co-authored-by: Zanie <contact@zanie.dev>
2024-02-18 21:20:21 +00:00
Zanie Blue 63c313425f
Build source distributions in the cache directory instead of the global temporary directory (#1628)
Addresses report in https://github.com/astral-sh/uv/issues/1444 where a
temporary directory is created outside of the cache directory or current
virtual environment.

There is one additional usage of bare `tempdir` outside of tests we may
want to change:


2586f655bb/crates/install-wheel-rs/src/wheel.rs (L567)
2024-02-18 15:05:39 -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
Alexander Gherm c04f597fae
Do not remove uv itself on pip sync (#1649)
## Summary

Added `uv` to the list of the preserved packages when building the
installer plan. In that case `uv` is not going to be removed when, for
example, using `python -m uv pip sync requirements.txt` when
requirements.txt does not contain `uv`, but `uv` is installed in that
venv.

Closes #1631 

## Test Plan

Got through the example attached to
https://github.com/astral-sh/uv/issues/1631 and did see the uv deletion
in the output
```
$ python -m uv pip sync requirements.txt
Installed 1 package in 20ms
 + ruff==0.2.2
```
2024-02-18 14:39:51 +00:00
Charlie Marsh fef1956c62
Bump simple metadata cache version (#1617)
## Summary

We made a breaking change to the cache representation, so some folks
have had to `uv clean`. Let's bump it for the next release.
2024-02-17 22:10:44 +00:00
Micha Reiser b296c04a67
Add CMD support (#1523)
## Sumamry

This PR adds the `activation.bat`, `deactivation.bat` and `pyenv.bat`
files to add support for using uv from CMD.

This PR further fixes an issue with our trampoline implementation where
calling an executable like `black` failed:

```
(venv) C:\Users\Micha\astral\test>where black
C:\Users\Micha\astral\test\.venv\Scripts\black.exe

(venv) C:\Users\Micha\astral\test>black
C:\Users\Micha\AppData\Local\Programs\Python\Python312\python.exe: can't open file 'C:\\Users\\Micha\\astral\\test\\black': [Errno 2] No such file or directory
```

The issue was that CMD doesn't extend `black` to its full path before
passing it to the trampoline and our trampoline generated the command
`<python> black` instead of `<python> .venv/Scripts/black`, and Python
can't find `black` in the project directory.

This PR fixes this by using the full executable name (that we already
parsed out to discover the Python version). This adds one complication,
we need to preserve the arguments without repeating the executable name
that is the first argument.
One option is to use
[`CommandLineToArgvW`](https://learn.microsoft.com/de-de/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw)
and then serialize the arguments 1.. to a string again. I decided
against that. Win32 API calls are easy to get wrong. That's why I
implemented the parsing rules specified in
[`CommandLineToArgvW`](https://learn.microsoft.com/de-de/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw)
to skip the first argument.

Fixes https://github.com/astral-sh/uv/issues/1471

## Test Plan


https://github.com/astral-sh/uv/assets/1203881/bdb537b6-97c8-4f7e-bb4a-3a614eb5e0f6

Powershell continues to work


https://github.com/astral-sh/uv/assets/1203881/6c806477-a7c6-4047-9ffc-5ed91c6f1c84

I haven't been able to test the aarch binaries.
2024-02-17 16:47:40 -05:00
Charlie Marsh ea62ae4ebd
Bump version to v0.1.4 (#1608) 2024-02-17 15:22:07 -05:00
Charlie Marsh 5c4cecaa85
Allow URL requirements in editable installs (#1614)
## Summary

If an editable package declares a direct URL requirement, we currently
error since it's not considered an "allowed" requirement. We need to add
those URLs to the allow-list.

Closes https://github.com/astral-sh/uv/issues/1603.
2024-02-17 15:20:23 -05:00
Micha Reiser 8675f66e74
Add license to activator scripts (#1610) 2024-02-17 20:37:26 +01:00
Charlie Marsh b5617198f3
Avoid propagating top-level options to sub-resolutions (#1607)
## Summary

It's incorrect to pass the resolution and dependency mode down to the
`BuildDispatch`, since it means that we'll use `--no-deps` when building
source distributions. If you set resolution to `lowest`, it also means
we end up using (e.g.) the lowest version of `wheel`, which also doesn't
make sense.

It's fine to pass `--exclude-newer`.

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

Closes https://github.com/astral-sh/uv/issues/1563.
2024-02-17 18:53:38 +00:00
Aarni Koskela bc14ed1613
Fix typos & add pre-commit configuration (#1487)
Co-authored-by: Zanie Blue <contact@zanie.dev>
2024-02-17 18:16:50 +01:00
Dhruv Manilawala e4389e537d
Consistent use of `BIN_NAME` in activation scripts (#1577)
This PR fixes the bug where the `BIN_NAME` replacement field wasn't
being used in the activator scripts.

fixes: #1518 

## Test plan

As I don't have a Windows machine, I switched the `bin_name` value here
to point to `Scripts` on `unix` platform:


2a76c59084/crates/gourgeist/src/bare.rs (L99-L105)

<details><summary>Code diff</summary>
<p>

```diff
```diff
diff --git a/crates/gourgeist/src/bare.rs b/crates/gourgeist/src/bare.rs
index 4c7808d3..0e0b41cf 100644
--- a/crates/gourgeist/src/bare.rs
+++ b/crates/gourgeist/src/bare.rs
@@ -97,9 +97,9 @@ pub fn create_bare_venv(location: &Utf8Path,
interpreter: &Interpreter) -> io::R
// TODO(konstin): I bet on windows we'll have to strip the prefix again
     let location = location.canonicalize_utf8()?;
     let bin_name = if cfg!(unix) {
-        "bin"
-    } else if cfg!(windows) {
         "Scripts"
+    } else if cfg!(windows) {
+        "bin"
     } else {
         unimplemented!("Only Windows and Unix are supported")
     };
```

</p>
</details> 

I then created the virtual environment as usual and tested out that the path modifications were correct:

```console
$ cargo run --bin uv -- venv
    Finished dev [unoptimized + debuginfo] target(s) in 0.13s
     Running `target/debug/uv venv`
Using Python 3.12.1 interpreter at
/Users/dhruv/.pyenv/versions/3.12.1/bin/python3.12
Creating virtualenv at: .venv

$ source .venv/Scripts/activate

$ echo $PATH
/Users/dhruv/work/astral/uv/.venv/Scripts:[...]

$ which python
/Users/dhruv/work/astral/uv/.venv/Scripts/python
```

I'm not sure how else to test this without having access to a Windows machine
2024-02-17 22:09:41 +05:30
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 12fea1d058
Always run `get_requires_for_build_wheel` (#1590)
## Summary

I want to revisit this as I think it's still skippable in some cases,
but for now, let's be more conservative.

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

## Test Plan

Cloned
`3aea423569/setup/mis_builder/setup.py (L4)`,
and ran `cargo run pip install -e mis_builder`.
2024-02-17 09:24:58 -05:00
Zanie Blue 563c636aa0
Improve tracing when encountering invalid `requires-python` values (#1568)
Unsure what the easiest way to test this is, it is hard to publish
invalid requires-python specifiers with hatchling
2024-02-17 07:40:13 -05:00
Shantanu 5d58d4fd2e
Better error messages on expect failures in resolver (#1583)
I ran into some (tricky to reproduce) panics while using uv, would be
useful to have a better error message to track down the source of the
problem
2024-02-17 07:39:10 -05:00
Zanie Blue bb7c3e6b58
Avoid using `white` coloring in terminal output (#1576)
Closes https://github.com/astral-sh/uv/issues/1489
2024-02-17 01:59:20 -06:00
Charlie Marsh 340cb67a8b
Allow non-nested archives for `hexdump` and others (#1564)
## Summary#1562 

It turns out that `hexdump` uses an invalid source distribution format
whereby the contents aren't nested in a top-level directory -- instead,
they're all just flattened at the top-level. In looking at pip's source
(51de88ca64/src/pip/_internal/utils/unpacking.py (L62)),
it only strips the top-level directory if all entries have the same
directory prefix (i.e., if it's the only thing in the directory). This
PR accommodates these "invalid" distributions.

I can't find any history on this method in `pip`. It looks like it dates
back over 15 years ago, to before `pip` was even called `pip`.

Closes https://github.com/astral-sh/uv/issues/1376.
2024-02-16 23:17:36 -05:00
Charlie Marsh 4a09889c80
Enforce URL constraints for non-URL dependencies (#1565)
## Summary

This was just a missing line -- we have `dependencies.remove(&package);`
in the ~identical branch above, but it must've been an oversight to omit
it here.

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

## Test Plan

`cargo test`
2024-02-17 03:11:28 +00:00
Charlie Marsh f897ee3f88
Allow repeated dependencies when installing (#1558)
## Summary

It turns out that it's not uncommon to end up with repeated packages in
requirements files when running `pip-sync`, e.g., you might have
`anyio==4.0.0` specified multiple times. This PR relaxes our assertions
in the install plan to allow such repeated packages, as long as the
requirement markers are exactly the same (i.e., they are truly
duplicates).

Closes https://github.com/astral-sh/uv/issues/1552.
2024-02-17 01:33:40 +00:00
Charlie Marsh 1110489c29
Bump version to v0.1.3 (#1557) 2024-02-16 19:45:29 -05:00
Charlie Marsh c1eb6130e1
Support MD5 hashes (#1556)
## Summary

We can add other hashes if necessary, but I don't know that they're
really used in practice.

Closes https://github.com/astral-sh/uv/issues/1547.
2024-02-17 00:25:16 +00: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 6392961f44
Add support for extras in editable requirements (#1531)
## Summary

If you're developing on a package like `attrs` locally, and it has a
recursive extra like `attrs[dev]`, it turns out that we then try to find
the `attrs` in `attrs[dev]` from the registry, rather than recognizing
that it's part of the editable.

This PR fixes the issue by making editables slightly more first-class
throughout the resolver. Instead of mocking metadata, we explicitly
check for extras in various places. Part of the problem here is that we
treated editables as URL dependencies, but when we saw an _extra_ like
`attrs[dev]`, we didn't map that back to the URL. So now, we treat them
as registry dependencies, but with the appropriate guardrails
throughout.

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

## Test Plan

- Cloned `attrs`.
- Ran `cargo run venv && cargo run pip install -e ".[dev]" -v`.
2024-02-16 18:48:35 -05:00
Charlie Marsh 4e0b6f8f84
Avoid attempting rename in copy fallback path (#1546)
## Summary

This _could_ fix https://github.com/astral-sh/uv/issues/1454, but I'm
not sure. I was able to replicate by forcing a bunch of error states.
But, in short, if we fail to hardlink on the initial copy due to a file
existing, and then fail _again_, we fallback to copying. But if we copy,
then the tempfile doesn't exist, and so the `fs_err::rename(&tempfile,
&out_path)?;` will fail with "File not found".

This PR just ensures that the cases are explicitly mutually exclusive:
we only attempt to rename if the hardlink succeeded.
2024-02-16 17:08:49 -05:00
David Szotten 8050370717
Fix trailing commas on `Requires-Python` in HTML indexes (#1507)
illustration and suggested fix for #1464
2024-02-16 22:05:28 +00: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
Andrew Gallant 3aa7a6b796
fix OS detection for Alpine Linux (#1545)
This PR fixes the OS detection for Alpine Linux such that the version
of musl available is correctly determined. The issue boiled down to
a regex that required 2 digits for each version component. But a
valid musl version is 1.2.4, which only has a single digit for each
component.

It's unclear how this was working for musl before this change. My
theory is that our other methods of OS detection were somehow working.

The first commit in this PR cleans up our Linux detection logic and adds
lots of tracing calls to make debugging issues like this easier in the
future. To do so, one can run:

    $ RUST_LOG=trace uv pip install -v whatever

The second commit has the actual fix.

Fixes #1427
2024-02-16 16:37:18 -05:00
Charlie Marsh b4ea48955b
Use comparable representation for `PackageId` (#1543)
## Summary

By using the display representation of `Version` to form a `PackageId`,
we run the risk (as seen in the linked issue) of thinking that versions
like `2021.1` and `2021.1.0` are not equivalent.

Closes https://github.com/astral-sh/uv/issues/1536
2024-02-16 16:30:54 -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
Andrew Gallant a97c207674
pypi-types: fix lenient requirement parsing (#1529)
This fixes a bug where `uv pip install` failed to install `polars`:

```
$ uv pip install polars==0.14.0
error: Failed to download: polars==0.14.0
  Caused by: Couldn't parse metadata of polars-0.14.0-cp37-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl from 749022b096cb7c1c2cc32b7f433c4f/polars-0.14.0-cp37-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl
  Caused by: Operator >= cannot be used with a wildcard version specifier
pyarrow>=4.0.*; extra == 'pyarrow'
       ^^^^^^^
```

Since `pyarrow>=4.0.*; extra == 'pyarrow'` is invalid *and* it comes
from the metadata of a dependency (that isn't under the control of the
end user), we actually attempt to "fix" it. Namely, wildcard
dependency specifications are only allowed with `==` and `!=`, as per
the [Version Specifiers spec]. (They aren't explicitly forbidden in
these cases, but instead only have specified behavior for the `==` and
`!=` operators.)

This is all fine, but it turns out that when we fix the `>=4.0.*`
component, we also strip the quotes around `pyarrow`. (Because some
dependency specifications include stray quotes.) We fix this by making
our quote stripping a bit more selective. (We require that it appear
adjacent to a digit or a `*`.)

Note that #1477 also reports this error:

```
$ uv pip install 'requests>=2.30.*'
error: Failed to parse `requests>=2.30.*`
  Caused by: Operator >= cannot be used with a wildcard version specifier
requests>=2.30.*
```

However, we specifically keep that error message since it's something
under the end user's control. And similarly for a dependency
specification in a `requirements.txt` file.

Fixes #1477

[Version Specifiers spec]:
https://packaging.python.org/en/latest/specifications/version-specifiers/
2024-02-16 15:52:44 -05:00
Zanie Blue d5e8531ae3
Add support for `UV_EXTRA_INDEX_URL` (#1515)
Closes https://github.com/astral-sh/uv/issues/1450
2024-02-16 12:54:58 -06: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
Zanie Blue 89ad1c6fa1
Add `pip install --constraint` test coverage (#1334)
Exploring behavior reported in
https://github.com/astral-sh/uv/issues/1332
2024-02-16 17:39:39 +00:00
Charlie Marsh f25781ff6c
Support recursive extras (#1435)
## Summary

We had a guard in the resolve to avoid "self-dependencies" (as in
`gps3==0.33.3`), but this guard was _unintentionally_ filtering out
recursive extras.

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

## Test Plan

Taken from https://github.com/astral-sh/uv/pull/1352.
2024-02-16 11:42:04 -05:00
Zanie Blue e6c4c77ba1
Use string display instead of debug for url parse trace (#1498)
e.g. 

`uv_client::html::parse
url=https://download.pytorch.org/whl/torch_stable.html`

instead of

`uv_client::html::parse url=Url { scheme: "https", cannot_be_a_base:
false, username: "", password: None, host:
Some(Domain("download.pytorch.org")), port: None, path:
"/whl/torch_stable.html", query: None, fragment: None }`
2024-02-16 15:13:16 +00:00
Andrew Gallant 67cde15420
only parse /bin/sh (not /bin/ls) (#1493)
It turns out that /bin/ls can sometimes be plain text file. For
example, in Rocky Linux 9:

```
$ cat /bin/ls
#!/usr/bin/coreutils --coreutils-prog-shebang=ls
```

However, `/bin/sh` is an ELF binary:

```
$ file /bin/sh
/bin/sh: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=7acbb41bf6f1b7d977f1b44675bf3ed213776835, for GNU/Linux 3.2.0, stripped
```

In a related issue (#1433), @zanieb fixed #1395 where, on NixOS,
`/bin/ls` doesn't exist but `/bin/sh` does. However, the fix attempts
`/bin/ls` first and only tries `/bin/sh` if `/bin/ls` doesn't exist. If
`/bin/ls` exists but isn't a valid ELF file, then the entire enterprise
gives up and `uv` fails to detect the version of `libc` that is
installed.

Instead of tweaking the logic to keep trying `/bin/ls` and then
`/bin/sh` after even if parsing `/bin/ls` fails, we just switch over to
reading `/bin/sh` only. It seems like a more fundamental thing to sniff
and likely less error prone.

We can adjust this heuristic as needed if it provdes to be problematic.

I tested this fix manually on Rocky Linux 9 via Docker:

```
$ cross b -r -p uv --target x86_64-unknown-linux-musl
$ cp target/x86_64-unknown-linux-musl/release/uv ~/astral/issues/uv/i1486/uv
$ docker run --rm -it --mount type=bind,src=/home/andrew/astral/issues/uv/i1486,dst=/host rockylinux:9 bash
[root@df2baa65d2f8 /]# /host/uv venv
Using Python 3.9.18 interpreter at /usr/bin/python3.9
Creating virtualenv at: .venv
[root@df2baa65d2f8 /]#
```

Fixes #1486, Ref #1433
2024-02-16 09:44:47 -05:00
Micha Reiser e913167849
Fix list rendering in `venv --help` output (#1459) 2024-02-16 15:36:36 +01:00
Aarni Koskela 3280562e3a
Loosen package script regexp to match spec (#1482)
Fixes #1479.
2024-02-16 09:25:32 -05:00
Zanie Blue d99c4cacdf
Read from `/bin/sh` if `/bin/ls` cannot be found when determing libc path (#1433)
I'm not sure if we should just switch to _always_ reading from sh
instead? I don't love that all these errors are strings and I if
`/bin/ls` exists but can't be parsed we still won't try `/bin/sh`. We
may want to address these things in the future.

Closes https://github.com/astral-sh/uv/issues/1395
2024-02-16 07:51:34 -05:00
Charlie Marsh c474370064
Allow empty fragments in HTML parser (#1443)
## Summary

It looks like `devpi` might add an empty fragment (`#`) at the end of
the URL. We expect it to contain the hash; this just makes
empty-fragment map to "no hash".

Closes https://github.com/astral-sh/uv/issues/1441.
2024-02-16 06:42:21 +00:00
Charlie Marsh 659327f24a
Bump version to v0.1.2 (#1439) 2024-02-16 01:17:19 -05:00
Charlie Marsh 0d005a2a71
Decode HTML escapes when extracting SHA (#1440)
## Summary

If a distribution contains a `+`, it'll be HTML-escaped; so when we try
to identify the `#`, we'll split in the wrong location.

Closes https://github.com/astral-sh/uv/issues/1338.
2024-02-16 06:15:51 +00:00
Charlie Marsh 958e88ddbf
Ignore invalid extra named `.none` (#1428)
## Summary

Some packages erroneously include an extra named `.none`. It turns out
that certain versions of `flit` included this by accident:
https://github.com/pypa/flit/issues/228/.

This PR adds leniency for that specific extra name.

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

Closes https://github.com/astral-sh/uv/issues/1399.
2024-02-16 05:01:21 +00:00
Zanie Blue 0bfce353fb
Fix broken URLs parsed from relative paths in registries (#1413)
Closes https://github.com/astral-sh/uv/issues/1388

Fixes incorrect handling of relative paths returned by indexes without
an explicit `<base>`.

`Url.join` will drop the last segment in an url e.g. `http://foo/bar` ->
`http://foo/baz` if there is not a trailing slash but what we want is
`http://foo/bar/baz`. We don't add the trailing `/` in
`base_url_join_relative` because flat indexes are `http://foo/bar.html`
and we _want_ `bar.html` to be replaced.
2024-02-15 22:37:09 -06:00
Charlie Marsh e48edf02fa
Parse `-r` and `-c` entries as relative to containing file (#1421)
## Summary

In a `requirements.txt` file, it turns out that the `-c` and `-r`
entries should be interpreted as relative to the file in which they're
declared, while the `-e` entries should be interpreted as relative to
the current working directory, no matter where they're defined.

Previously, we always used the current working directory; now, we use
the declaring file's directory for `-c` and `-r`.

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

Closes https://github.com/astral-sh/uv/issues/1416.
2024-02-15 23:19:43 -05:00
Charlie Marsh 1837641138
Add fix-up for invalid star comparison with major-only version (#1410)
## Summary

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

## Test Plan

Ran `cargo run pip install junos-eznc==2.6.5`, which still fails for me,
but fails identically to `pip` (and not on the `requires-python`):

```
/private/var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmp7mxT9L/built-wheels-v0/pypi/ncclient/0.6.13/4vvPwmDC_CL2OUXd68Zqb/ncclient-0.6.13.tar.gz/versioneer.py:421: SyntaxWarning: invalid escape sequence '\s'
  LONG_VERSION_PY['git'] = '''
Traceback (most recent call last):
  File "<string>", line 10, in <module>
  File "/private/var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmplD5mMO/.venv/lib/python3.12/site-packages/setuptools/build_meta.py", line 366, in prepare_metadata_for_build_wheel
    self.run_setup()
  File "/private/var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmplD5mMO/.venv/lib/python3.12/site-packages/setuptools/build_meta.py", line 480, in run_setup
    super().run_setup(setup_script=setup_script)
  File "/private/var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmplD5mMO/.venv/lib/python3.12/site-packages/setuptools/build_meta.py", line 311, in run_setup
    exec(code, locals())
  File "<string>", line 45, in <module>
  File "/private/var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmp7mxT9L/built-wheels-v0/pypi/ncclient/0.6.13/4vvPwmDC_CL2OUXd68Zqb/ncclient-0.6.13.tar.gz/versioneer.py", line 1480, in get_version
    return get_versions()["version"]
           ^^^^^^^^^^^^^^
  File "/private/var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmp7mxT9L/built-wheels-v0/pypi/ncclient/0.6.13/4vvPwmDC_CL2OUXd68Zqb/ncclient-0.6.13.tar.gz/versioneer.py", line 1412, in get_versions
    cfg = get_config_from_root(root)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/nt/6gf2v7_s3k13zq_t3944rwz40000gn/T/.tmp7mxT9L/built-wheels-v0/pypi/ncclient/0.6.13/4vvPwmDC_CL2OUXd68Zqb/ncclient-0.6.13.tar.gz/versioneer.py", line 342, in get_config_from_root
    parser = configparser.SafeConfigParser()
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: module 'configparser' has no attribute 'SafeConfigParser'. Did you mean: 'RawConfigParser'?
```
2024-02-16 02:12:10 +00:00
Charlie Marsh 7994b68654
Add fix-up for trailing comma with trailing space (#1409)
## Summary

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

## Test Plan

```text
Resolved 3 packages in 243ms
Downloaded 3 packages in 193ms
Installed 3 packages in 6ms
 + et-xmlfile==1.1.0
 + jdcal==1.4.1
 + openpyxl==3.0.5
```
2024-02-16 02:08:05 +00:00
Zanie Blue 0f554b0913
Add `-U`/`-P` short flags for `--upgrade`/`--upgrade-package` (#1394)
Closes https://github.com/astral-sh/uv/issues/1340
2024-02-16 01:34:19 +00:00
Zanie Blue 896ab1c54f
Add `--upgrade` support to `pip install` (#1379)
Adds support for `--upgrade` — similar to `--reinstall`.

Closes https://github.com/astral-sh/uv/issues/1391
2024-02-15 19:25:28 -06:00
Shantanu e9d82cf0fa
Avoid import contextlib in `_virtualenv` (#1406)
No need to pay 3ms on basically every Python invocation. I opened a PR
upstream last week: https://github.com/pypa/virtualenv/pull/2688
2024-02-15 20:23:05 -05:00
Robin Krahl f9a9f53476
Improve error message for invalid sdist archives (#1389)
This PR improves the error message for the problem described in
https://github.com/astral-sh/uv/issues/1376. The original output
duplicates the actual error message and includes lots of noise
(`DirEntry { inner: DirEntry(...) }`).

```
$ uv pip install hexdump==3.3
error: Failed to download and build: hexdump==3.3
  Caused by: Failed to extract source distribution: The top level of the archive must only contain a list directory, but it contains: [DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/__main__.py") }, DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/hexdump.py") }, DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/data") }, DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/PKG-INFO") }, DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/setup.py") }, DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/README.txt") }]
  Caused by: The top level of the archive must only contain a list directory, but it contains: [DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/__main__.py") }, DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/hexdump.py") }, DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/data") }, DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/PKG-INFO") }, DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/setup.py") }, DirEntry { inner: DirEntry("/home/robin/.cache/uv/.tmpgSvTCk/README.txt") }]
```

This PR removes the duplication and `DirEntry` internals so that the
error message is easier to grasp:

```
$ uv pip install hexdump==3.3
error: Failed to download and build: hexdump==3.3
  Caused by: Failed to extract source distribution
  Caused by: The top level of the archive must only contain a list directory, but it contains: ["__main__.py", "hexdump.py", "data", "PKG-INFO", "setup.py", "README.txt"]
```
2024-02-15 18:03:23 -06:00
Zanie Blue c6a43e92f9
Add `UV_NO_CACHE` environment variable (#1383)
It's a little picky about the value, but that seems okay.

```
❯ ./target/debug/uv pip install trio
Audited 1 package in 4ms
❯ UV_NO_CACHE=true ./target/debug/uv pip install trio
Audited 1 package in 50ms
```

Closes #1382
2024-02-15 23:34:42 +00:00
mikcl fbd6d87214
uv-cache: Add hidden alias for --no-cache-dir (#1380)
This is for compatability with pip install --no-cache-dir

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

Signed-off-by: mikcl <mikesmikes400@gmail.com>
2024-02-15 23:26:16 +00:00
Zanie Blue 18a7c079de
Fix search for `python.exe` on Windows (#1381)
A la #1351
2024-02-15 17:25:20 -06:00
Zanie Blue e0885b7c8e
Bump version to 0.1.1 (#1359) 2024-02-15 15:38:22 -06:00
Yannik Sander 36544e1678
Fix diagram alignment (#1354)
Drive by alignment PR for the trait structure diagram
2024-02-15 15:32:33 -06:00
Zanie Blue 102e5ddfbe
Fix bug where `python3` is not found in the global path (#1351)
When we refactored handling for Windows tests, we accidentally dropped
`python3` from path searches.
2024-02-15 15:29:33 -06:00
Charlie Marsh 27177613d4
Bump version to v0.1.0 (#1325) 2024-02-15 14:12:23 -05:00
Zanie Blue 0780afff95
Rename `PUFFIN` environment variables to `UV` (#1319)
A couple of these are actually user-facing although undocumented
2024-02-15 12:49:27 -06: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
Charlie Marsh 55808a451f
Regenerate benchmarks (#1305) 2024-02-15 17:54:04 +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
Zanie Blue e9e3e573a2
Report incompatible distributions to users (#1293)
Instead of dropping versions without a compatible distribution, we track
them as incompatibilities in the solver. This implementation follows
patterns established in https://github.com/astral-sh/puffin/pull/1290.

This required some significant refactoring of how we track incompatible
distributions. Notably:

- `Option<TagPriority>` is now `WheelCompatibility` which allows us to
track the reason a wheel is incompatible instead of just `None`.
- `Candidate` now has a `CandidateDist` with `Compatible` and
`Incompatibile` variants instead of just `ResolvableDist`; candidates
are not strictly compatible anymore
- `ResolvableDist` was renamed to `CompatibleDist`
- `IncompatibleWheel` was given an ordering implementation so we can
track the "most compatible" (but still incompatible) wheel. This allows
us to collapse the reason a version cannot be used to a single
incompatibility.
- The filtering in the `VersionMap` is retained, we still only store one
incompatible wheel per version. This is sufficient for error reporting.
- A `TagCompatibility` type was added for tracking which part of a wheel
tag is incompatible
- `Candidate::validate_python` moved to
`PythonRequirement::validate_dist`

I am doing more refactoring in #1298 — I think a couple passes will be
necessary to clarify the relationships of these types.

Includes improved error message snapshots for multiple incompatible
Python tag types from #1285 — we should add more scenarios for coverage
of behavior when multiple tags with different levels are present.
2024-02-15 10:48:15 -06:00
Andrew Gallant b6fba00153
cli: conventionally treat `-` as "read from stdin" (#1314)
Basically, when a path to a requirements file is `-`, then we should
read its contents from `stdin` instead of the file path named `-`.

Fixes #1313
2024-02-15 11:25:56 -05:00
Armin Ronacher bf2ee6bc31
Adds support for --no-deps to pip compile (#1311)
Mostly throwing this up here as a discussion topic. Having something
like this is primarily useful for enabling use cases similar to `rye
add` where I want to use this currently. One can accomplish something
similar with `unearth` today or by abusing regular `pip install`:

```
$ ~/.rye/self/bin/pip install --no-deps --dry-run flask --report - -q | jq '.install[0].metadata | {name, version}'
{
  "name": "Flask",
  "version": "3.0.2"
}
```

Another option would be to have a `puffin resolve` command or similar
that works like `pip compile` without dependencies, takes the
requirements as arguments and returns a line for each resolution. That
would be a larger change.
2024-02-15 09:01:31 -05:00
Andrew Gallant 94437175c7 puffin-resolver: make VersionMap::iter even lazier
This rollbacks the optimization in the previous commit to be more
general. That is, instead of specializing the case of a range for a
singleton version, we make iteration over the distributions in a
`VersionMap` more explicitly lazy. Iteration now provides a `Version`
(like it did previously) and a _handle_ to a distribution that can be
turned into a `ResolvableDist`.

Doing things this way permits callers to iterate over the versions and
only materialize a distribution if they actually need one. In cases like
candidate selection, one can often rule out use of a distribution
through its version alone, and thus skip construction of that
distribution entirely.
2024-02-15 08:10:32 -05:00
Andrew Gallant ed000d0dd5 puffin-resolver: add singleton fast path
In many cases, version ranges are actually just pins to a
specific and single version. And we can detect that statically
by examining the range. If we do have a range that is just one
version, then we can ask a `VersionMap` for just that version
instead of iterating over what's in the map until we find one
that satisfies the range.

I had tried this before making `VersionMap` construction lazy,
but it didn't seem to matter much. But helps a lot more now
with a lazy `VersionMap` because it lets us avoid creating a
lot of distributions in memory that we won't ultimately use.
2024-02-15 08:10:32 -05: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 e2f3ad0e28 puffin-resolver: add some trace calls
This commit adds some logging to candidate selection during
resolution. The idea with these logs is to get a signal on
how much "exploring" the resolver does in specific examples.

For example, this logs helped me realize that at least in
some cases, candidate selection was looking through a long list
of versions even when its range consisted of exactly one
version. We'll use this fact in a later commit.
2024-02-15 08:10:32 -05:00
Andrew Gallant 1cff7c3774 platform-tags: make Tags use an Arc internally
This makes cloning and thus sharing across multiple threads much
cheaper. Since Tags is conceptually immutable once it is constructed,
this doesn't pose an issue and shouldn't introduce any additional
costs.
2024-02-15 08:10:32 -05:00
Charlie Marsh e4fffc15f5
Remove Cargo-specific error messages (#1306)
We're leveraging Cargo's git implementation, but we left in some
Cargo-specific error messages for features we don't yet support.
2024-02-15 06:04:22 +00:00
Zanie Blue 9808c6b500
Reset all of the snapshots for consistent indentation (#1300)
This is really annoying, but the snapshots keep changing indentation
when updated.

I could not get insta to update them. So I added a print statement to
`main` and updated the snapshots, then removed the statement and updated
the snapshots again to force them all to refresh.
2024-02-14 12:50:28 -06:00
Charlie Marsh 40b74fb0fb
Replace `MarkupSafe` for no-binary tests (#1296) 2024-02-14 04:44:07 +00:00
Zanie Blue 7fec2a311a
Refactor storage of distribution metadata needed in resolver (#1291)
Follows #1290 and https://github.com/astral-sh/puffin/pull/912 with some
minor clean-up.
2024-02-13 04:19:21 +00:00
Zanie Blue 3bff8d5f79
Add scenario coverage for wheels with incompatible ABI and Python tags (#1285)
We use

- An arbitrary ABI hash: `MMMMMM` (six base64 characters)
- An unlikely Jython27 Python tag

For cases that are valid but are never going to be available during
tests.

See https://github.com/zanieb/packse/pull/109
2024-02-12 22:14:38 -06: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 d8619f668a
Surface errors for offline `--find-links` URLs (#1271)
## Summary

Ensures that if the user passes `--no-index` with `--find-links`, and
we're unable to access the HTML page, we show an appropriate hint.
2024-02-13 03:41:00 +00: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
Zanie Blue 0cd6b7be8c
Fix incompatible wheel test scenarios (#1284)
I had specified the tags incorrectly
https://github.com/zanieb/packse/pull/105
2024-02-12 18:51:49 +00:00
Zanie Blue 6d24d998e0
Add scenarios for yanked packages (#1283) 2024-02-12 12:44:59 -06:00
Zanie Blue 336d12556c
Add scenario tests for `--only-binary` and `--no-binary` (#1279) 2024-02-12 11:21:14 -06:00
Charlie Marsh b386590b3c
Add some compatibility arguments to `puffin venv` (#1282)
See: https://github.com/astral-sh/puffin/issues/1276.
2024-02-12 03:19:55 +00:00
Charlie Marsh 93b7a1140f
Allow virtualenv creation at existing, empty directories (#1281)
## Summary

If the directory exists but is empty, we should allow `puffin venv`
without erroring.

Also adds test cases for a variety of error cases.
2024-02-12 03:13:13 +00:00
Charlie Marsh b7e3933fe7
Place editable requirements before non-editable requirements (#1278)
## Summary

`pip-compile` puts the editable requirements first.

Closes https://github.com/astral-sh/puffin/issues/1275.
2024-02-12 02:26:40 +00:00
Charlie Marsh a16ec45d1f
Set an exclude cutoff for virtualenv tests (#1280)
## Summary

This test is failing since a new version of one of the seed packages was
uploaded.
2024-02-12 02:21:05 +00:00
Zanie Blue a37b08808e
Implement pip compatible `--no-binary` and `--only-binary` options (#1268)
Updates our `--no-binary` option and adds a `--only-binary` option for
compatibility with `pip` which uses `:all:`, `:none:` and `<name>` for
specifying packages.

This required adding support for `--only-binary <name>` into our
resolver, previously it was only a boolean toggle.

Retains`--no-build` which is equivalent to `--only-binary :all:`. This
is common enough for safety that I would prefer it is available without
pip's awkward `:all:` syntax.

---------

Co-authored-by: konsti <konstin@mailbox.org>
2024-02-11 19:31:41 -06:00
Charlie Marsh d98b3c3070
Strip UNC prefix when setting working directory (#1277)
## Summary

For PEP 517 builds, the current working directory needs to be set to the
directory of the source distribution. It turns out that on Windows, if
you use a UNC path for the working directory, then relative paths are
interpreted relative to the root of the current drive
([source](https://www.fileside.app/blog/2023-03-17_windows-file-paths/#paths-relative-to-the-root-of-the-current-drive)).
So, when builds attempted to resolve relative paths, they always
errored...

This PR ensures that we remove the UNC prefix when setting the current
working directory.

Closes #1238.

## Test Plan

I tested this on my Windows machine by installing `ujson` with
`--no-binary ujson`. (I don't want to add that specific test, since it's
really slow to build.)
2024-02-12 00:51:36 +00: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 561e33e353
Validate instead of discovering python patch version (#1266)
Contrary to our prior assumption, we can't reliably select a specific
patch version. With the deadsnakes PPA for example, `python3.12` is
installed into `PATH`, but `python3.12.1` isn't. Based on the assumption
(or rather, observation) that users have a single python patch version
per python minor version installed, generally the latest, we only check
if the installed patch version matches the selected patch version, if
any, instead of search for one.

In the process, i deduplicated the python discovery logic.
2024-02-08 22:38:00 +01:00
konsti 1dc9904f8c
Run the test suite on windows in CI (#1262)
Run `cargo test` on windows in CI, pulling the switch on tier 1 windows
support.

These changes make the bootstrap script virtually required for running
the tests. This gives us consistency between and CI, but it also locks
our tests to python-build-standalone and an articificial `PATH`.

I've deleted the shell bootstrap script in favor of only the python one,
which also runs on windows. I've left the (sym)link creation of the
bootstrap in place, even though it is not used by the tests anymore.

I've reactivated the three tests that would previously stack overflow by
doubling their stack sizes. The stack overflows only happen in debug
mode, so this is neither a user facing problem nor an actual problem
with our code and this workaround seems better than optimizing our code
for case that the (release) compiler can optimize much better for.

The handling of patch versions will be fixed in a follow-up PR.

Closes #1160 
Closes #1161

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-02-08 22:09:55 +01:00
Andrew Gallant 96276d9e3e
puffin-resolver: simplify version map construction (#1267)
In the process of making VersionMap construction lazy, I realized this
refactoring would be useful to me. It also simplifies a fair bit of case
analysis and does fewer BTreeMap lookups during construction. With that
said, this doesn't seem to matter for perf:

```
$ hyperfine -w10 --runs 50 \
    "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"
Benchmark 1: puffin-main pip compile --cache-dir ~/astral/tmp/cache-main ~/astral/tmp/reqs/home-assistant-reduced.in -o /dev/null
  Time (mean ± σ):     146.8 ms ±   4.1 ms    [User: 350.1 ms, System: 314.2 ms]
  Range (min … max):   140.7 ms … 158.0 ms    50 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 ± σ):     146.8 ms ±   4.5 ms    [User: 359.8 ms, System: 308.3 ms]
  Range (min … max):   138.2 ms … 160.1 ms    50 runs

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

But the simplification is still nice, and will decrease the delta
between what we have now and a lazy version map.
2024-02-08 15:33:33 -05:00
Zanie Blue fc2ab611d5
Use "locations" instead of "listings" for find links errors (#1263) 2024-02-07 10:28:22 -06: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
konsti e0cdf1a16f
Use anstream consistently and remove clippy lints (#1260)
We need to use the anstream print macros instead of the std print
macros, otherwise we risk wrong color behavior
(https://github.com/astral-sh/puffin/pull/1258#discussion_r1480428236).
Luckily, the `print_stderr` and `print_stdout` lints catch usages of the
std prints.

This PR switches over to anstream consistently and removes the now
redundant clippy lints. The lints should catch missing anstream usage in
the future.
2024-02-06 22:16:26 +01:00
konsti f4ca175df4
Search and replace windows specific tests in deps (#1255)
Remove windows-only dependencies from the snapshot output using regex.
We now do the filtering entirely on our without relying on insta
settings.

435 tests run: 430 passed (30 slow), 5 failed, 1 skipped
2024-02-06 19:31:42 +00:00
konsti ac49dec4a2
Multiple entries in PUFFIN_PYTHON_PATH for windows tests (#1254)
There are no binary installers for the latests patch versions of cpython
for windows, and building them is hard. As an alternative, we download
python-build-standanlone cpythons and put them into `<project
root>/bin`. On unix, we can symlink `pythonx.y.z` into this directory
and point `PUFFIN_PYTHON_PATH` to it. On windows, all pythons are called
`python.exe` and they don't like being linked. Instead, we add the path
to each directory containing a `python.exe` to `PUFFIN_PYTHON_PATH`,
similar to the regular `PATH`. The python discovery on windows was
extended to respect `PUFFIN_PYTHON_PATH` where needed.

These changes mean that we don't need to (sym)link pythons anymore and
could drop that part to the script.

435 tests run: 389 passed (21 slow), 46 failed, 1 skipped
2024-02-06 20:28:30 +01:00
Charlie Marsh 91118a962a
Offer tip when users omits pip prefix (#1257)
## Summary

Open to other opinions here. We could just continue (and warn), prompt
the user with a confirmation, etc.

(The weird thing about those two options is we might need to validate
the command-line arguments _before_ we do that -- so you could get
errors for bad arguments, and then get a warning that your subcommand is
wrong. I can probably avoid that with more work if it feels like a
better out come though.)

Closes https://github.com/astral-sh/puffin/issues/1256.
2024-02-06 19:25:07 +00: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
Zanie Blue d4bbaf1755
Add hint for `--no-index` without `--find-links` (#1258)
Since unavailable packages with `--no-index` can be confusing when the
user does not also provide `--find-links` we add a hint for this case.
Required some plumbing to get the required information to the
`NoSolution` error.

---------

Co-authored-by: konstin <konstin@mailbox.org>
2024-02-06 11:04:14 -06:00
konsti b2a810fe37
Add windows specific filters for tests (#1231)
Add more windows specific filters in various places.

435 tests run: 333 passed (21 slow), 102 failed, 1 skipped
2024-02-06 15:58:16 +01: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
Charlie Marsh 398659a9b0
Show yank warnings for `pip install` (#1253)
Closes https://github.com/astral-sh/puffin/issues/1252.
2024-02-05 17:15:44 +00: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
Charlie Marsh be9125b0f0
Remove unnecessary `is_dir` in `clone_recursive` (#1247) 2024-02-04 23:54:22 +00:00
Charlie Marsh 9d42cfd09b
Clarify documentation for `--no-index` (#1243)
Closes #1242.
2024-02-04 18:46:01 -05:00
Andrew Gallant 586eeb6eca
tests: update snapshot for new `pip` release (#1245)
See: https://pypi.org/project/pip/#history
2024-02-03 15:44:13 -05:00
Zanie Blue bc2f8f5b1e
Fix direct use of `range.simplify` (#1236) 2024-02-02 18:08:25 +00:00
Zanie Blue 6db9db0079
Invert display of "no versions" incompatibilities with multiple ranges (#1233)
Closes #884 

e.g.

```
❯ cargo run -q -- pip compile --python-version 3.12 requirements.in
  × No solution found when resolving dependencies:
  ╰─▶ Because the requested Python version (3.12) does not satisfy Python>=3.6,<3.10 and recommenders==1.0.0 depends on Python>=3.6,<3.9, we can conclude that recommenders==1.0.0 cannot be used.
      And because only the following versions of recommenders are available:
          recommenders<=0.7
          recommenders==1.0.0
          recommenders==1.1.0
          recommenders==1.1.1
      we can conclude that recommenders>0.7,<1.1.0 cannot be used. (1)

      Because the requested Python version (3.12) does not satisfy Python>=3.6,<3.10 and recommenders>=1.1.0 depends on Python>=3.6,<3.10, we can conclude that recommenders>=1.1.0 cannot be used.
      And because we know from (1) that recommenders>0.7,<1.1.0 cannot be used, we can conclude that recommenders>0.7 cannot be used.
      And because you require recommenders>0.7, we can conclude that the requirements are unsatisfiable.
```
2024-02-02 12:00:25 -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 3771f6656e
Allow additional assertions on command output (#1226)
In the scenario tests, we want to make sure we're actually conforming to
the scenario's expectations, so we now have an extra assertion on
whether resolution failed or succeeded as well as that it includes the
given packages.

Closes #1112
Closes #1030
2024-02-02 09:41:35 +00: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
konsti 0925e446a8
Refactor remaining integration tests (#1220)
Mostly a mechanical refactor to use the `puffin_snapshot!` and
`TestContext` infrastructure in the add, remove, venv and pip uninstall
tests, in preparation for adding programmatic windows testing filters.
The is only one remaining usage of `assert_cmd_snapshot!` now in the
`puffin_snapshot!` macro.
2024-02-02 10:26:59 +01:00
konsti 6b050a1972
Refactor pip install and sync tests (#1213)
Mostly a mechanical refactor to use the `puffin_snapshot!` and
`TestContext` infrastructure in the pip install and pip sync tests, in
preparation for adding programmatic windows testing filters.
2024-02-02 10:26:31 +01:00
Charlie Marsh d77d129e8d
Run `cargo update` (#1230) 2024-02-01 11:14:38 -05:00
Charlie Marsh bb49ebee1e
Avoid race condition in clone file replacement (#1229)
## Summary

I've never seen this in practice but in theory it is possible, and we
have the same guardrail in the hardlink path.
2024-02-01 10:55:23 -05:00
konsti 809c6d676f
Use normalized display in tests and other small windows fixes (#1228)
Split out from the large test refactoring PR. Use `normalized_display`
in tests and two more thiserror derives to match snapshots and output,
and other small windows fixes.
2024-02-01 16:12:30 +01:00
Charlie Marsh 9487378ef9
Avoid TOCTOU errors in data directory installations (#1227)
## Summary

See: https://github.com/astral-sh/puffin/issues/1224

## Test Plan

Ran `python -m scripts.bench --puffin
scripts/requirements/compiled/jupyter.txt --min-runs 100 --benchmark
install-warm --verbose` several times, which failed eventually on `main`
but not on this branch.
2024-02-01 14:55:29 +00:00
konsti ea0bfc565d
Refactor pip scenario tests (#1212)
Mostly a mechanical refactor to use the `puffin_snapshot!` and
`TestContext` infrastructure in the pip compile and pip install
scenarios, in preparation for adding programmatic windows testing
filters.
2024-02-01 10:31:40 +01:00
Charlie Marsh 0757862a7a
Accommodate minute-level filters in Insta (#1219)
I don't know why `compile_editable` took over a minute in this case, but
seems like it did? Hard to test this fix.


https://github.com/astral-sh/puffin/actions/runs/7734769259/job/21089338951?pr=1216
2024-02-01 09:43:09 +01:00
Charlie Marsh 8cbe1d220c
Remove double-download for source distributions (#1218)
## Summary

Oops -- this was using a different cache key than the route above (this
is the wheel _metadata_ route vs. the wheel build route), so we were
saving and building source distributions twice in `pip install`.
2024-02-01 04:41:29 +00:00
Charlie Marsh 51e8609ee8
Use Python 3.12 in benchmarks (#1215)
I originally used Python 3.10, since 3.10 and 3.11 are by far the most
common (at least for [Ruff](https://pypistats.org/packages/ruff)). But
3.12 should give Python tools the most favorable benchmarks.
2024-01-31 15:51:13 -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
Andrew Gallant b9d89e7624
puffin-client: generalize SimpleMetadaRaw into OwnedArchive<A> (#1208)
It turns out that the pattern I coded up for SimpleMetadataRaw is
generally useful when working with rkyv. This commit makes it generic by
supporting any type that implements rkyv's traits, and makes a few
simplifying assumptions by picking a concrete serializer, validator and
deserializer. In effect, this lets use own any archived value.

We also rejigger the API a little bit and double-down on
`OwnedArchive<A>` just being a owned wrapper for `Archived<A>`. Namely,
we implement `Deref` and turn its inherent methods into methods that
require fully qualified syntax. (As is standard for things that
implement `Deref` to avoid ambiguity with the deref target's methods.)

(This PR also makes a couple small simplifications to our custom rkyv
serializer since we no longer need to use it directly. We do still need
to name the type in trait bounds, so it has to be public.)
2024-01-31 11:56:34 -05:00
konsti 234e8d0bb7
Abstract away test duplication in pip-compile (#1187)
In preparation for the new windows handling, i want to introduce a
`TestContext` and `puffin_snapshot!` abstraction. This PR applies those
changes for pip-compile. My plan is to use those for all venv-based
integration tests and build the custom windows filters on top of
`puffin_snapshot!`.
2024-01-31 16:11:10 +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 8f9258fae3
Invert default feature for testing (#1200)
## Summary

We have some flags in Puffin that enable us to opt-in to certain tests.
To date, they've been opt-in, so we've run our tests with
`--all-features`. This PR makes them opt-out, and we now run tests with
default features.

The main motivation here is that I want to get tests working for macOS
on CI, but for unknown reasons, macOS can't compile the PyO3 features at
the same time as everything else due to strange linker issues. By
avoiding `--all-features` for tests, we thus avoid unnecessarily
including features that we don't actually use in Puffin.

I verified that the exact same number of tests (439) are run before and
after this change. For users, the primary difference is that you now
need to specify `--no-default-features --features pypi --features
python` to avoid (e.g.) including the Git tests.
2024-01-31 09:44:26 -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 262f29b558
Add missing `--exclude-newer` to executable tests (#1201)
A new version of `platformdirs` came out, which broke these.
2024-01-30 20:26:11 -05:00
Charlie Marsh b88b9e1f3d
Remove dedicated `flate2` features from Puffin (#1199)
We should be able to enable and disable these without crate-internal
features.
2024-01-30 19:41:08 -05:00
Andrew Gallant b47f70917f
puffin-client: simplify use of http-cache-semantics (#1197)
The `http-cache-semantics` crate is polymorphic on the types of requests
and responses it accepts. We had previously been explicitly converting
between `http` and `reqwest` types, but this isn't necessary. We can
provide impls of the traits in `http-cache-semantics` for `reqwest`'s
types (via a wrapper). This saves us from the awkward request/response
type conversions.

While this does clone the request, this is:

1. Not new. We were previously cloning the request to do the conversion.
2. An artifact (I believe) of http-cache-semantics API. (It kind of
   seems like an API bug to me?)

There is also a little bit of messiness around inter-operating between
http::uri::Uri and url::Url. But overall shouldn't be a big deal.
2024-01-30 18:20:44 -05: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 c129717b41
Add support for `--no-deps` to `pip install` (#1191)
## Summary

Closes https://github.com/astral-sh/puffin/issues/1188.
2024-01-30 19:54:57 +00:00
Charlie Marsh 8305acc584
Add a builder for resolution options (#1192) 2024-01-30 19:50:16 +00: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
Charlie Marsh 7a937e0f60
Error when parsing `requirements.txt`-like packages in `requirements.txt` file (#1179)
## Summary

Like https://github.com/astral-sh/puffin/pull/1180, this PR adds logic
for `requirements.txt` parsing whereby if a requirement _looks like_ a
local requirements file or an editable directory, we prompt the user to
correct the error (typically, by adding `-r`).
2024-01-30 18:55:11 +00:00
konsti 4ad0dc8b9e
Add windows aarch64 trampolines (#1190)
Lacking windows compatible aarch64 hardware, i cross compiled the
trampoline from x86_64 linux to aarch64-pc-windows-msvc; I added the
instructions to the puffin-trampoline readme. With some testing on an
aarch64 windows machine, this should be sufficient to build working
win_arm64 tagged wheels.

i686-pc-windows-msvc is failing with an error:

```
error: linking with `lld-link` failed: exit status: 1
  = note: lld-link: error: undefined symbol: __aulldiv
          >>> referenced by libcompiler_builtins-2fb09dee087e9f64.rlib(compiler_builtins-2fb09dee087e9f64.compiler_builtins.597f0152646f1b8-cgu.0.rcgu.o):(compiler_builtins::int::specialized_div_rem::u128_div_rem::h06aed1e23a3f8f5c)
          >>> referenced by libcompiler_builtins-2fb09dee087e9f64.rlib(compiler_builtins-2fb09dee087e9f64.compiler_builtins.597f0152646f1b8-cgu.0.rcgu.o):(compiler_builtins::int::specialized_div_rem::u128_div_rem::h06aed1e23a3f8f5c)
          >>> referenced by libcompiler_builtins-2fb09dee087e9f64.rlib(compiler_builtins-2fb09dee087e9f64.compiler_builtins.597f0152646f1b8-cgu.0.rcgu.o):(compiler_builtins::int::specialized_div_rem::u128_div_rem::h06aed1e23a3f8f5c)
          >>> referenced 4 more times

          lld-link: error: undefined symbol: __aullrem
          >>> referenced by libcompiler_builtins-2fb09dee087e9f64.rlib(compiler_builtins-2fb09dee087e9f64.compiler_builtins.597f0152646f1b8-cgu.0.rcgu.o):(compiler_builtins::int::specialized_div_rem::u128_div_rem::h06aed1e23a3f8f5c)
          >>> referenced by libcompiler_builtins-2fb09dee087e9f64.rlib(compiler_builtins-2fb09dee087e9f64.compiler_builtins.597f0152646f1b8-cgu.0.rcgu.o):(compiler_builtins::int::specialized_div_rem::u128_div_rem::h06aed1e23a3f8f5c)
          >>> referenced by libcompiler_builtins-2fb09dee087e9f64.rlib(compiler_builtins-2fb09dee087e9f64.compiler_builtins.597f0152646f1b8-cgu.0.rcgu.o):(compiler_builtins::int::specialized_div_rem::u128_div_rem::h06aed1e23a3f8f5c)
          >>> referenced 4 more times
```
2024-01-30 17:51:27 +00:00
Charlie Marsh c479c26cab
Add compatibility arguments for `pip sync` (#1185)
## Summary

As with `pip compile`, we can provide useful error messages and warnings
when people pass `pip sync` arguments.

Closes https://github.com/astral-sh/puffin/issues/1184.
2024-01-30 08:48:55 -05: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
konsti a6c4cbfe55
Cleanup puffin interpreter errors (#1169)
Use `virtualenv` consistently, remove unused error variants and hint the
user towards installing missing python versions.

I didn't touch the Readme but i replaced `virtualenv environment` with
`virtualenv` in the strings i found.

Fixes https://github.com/astral-sh/puffin/issues/1167
2024-01-30 10:52:46 +01:00