Commit Graph

828 Commits

Author SHA1 Message Date
Zanie 4d9cdf2758 WIP: Dry run flag for pip install 2024-02-22 18:23:32 -06:00
Jacob Coffee b71ae74943
feat(pip-install): move dry run into `install` function 2024-02-20 17:25:07 -06:00
Jacob Coffee fd0b89f23e
test(pip-install): attempt to add (probably shitty) test 2024-02-16 01:52:54 -06:00
Jacob Coffee bc5dd30c95
feat(pip-install): properly print versions 2024-02-16 01:23:00 -06:00
Jacob Coffee 4aae07e914
feat(pip-install): add `--dry-run` flag 2024-02-15 23:39:20 -06: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