Commit graph

681 commits

Author SHA1 Message Date
Zanie
f2659b92b1 Link hookd.py to create 2024-01-18 11:36:01 -06:00
Zanie
cc8459ecb5 Use a channel to read stdout 2024-01-17 11:24:36 -06:00
Zanie
cabb9f4ba2 Refactor IO into separate type 2024-01-17 10:58:41 -06:00
Zanie
cfb73f5d71 Add build docs 2024-01-17 10:31:36 -06:00
Zanie
002b731ab2 Refactor error handling 2024-01-17 10:29:17 -06:00
Zanie
a8fa91bfc5 Move daemon to its own module 2024-01-17 09:20:28 -06:00
Zanie
744b546a85 Sort imports 2024-01-17 09:11:28 -06:00
Zanie
9bd18bbaf4 WIP: Remove dead Rust code, display tracebacks 2024-01-17 09:01:40 -06:00
Zanie
87f62f9d92 Add test coverage for subprocess stdout 2024-01-17 09:01:17 -06:00
Zanie
b8fd8bfb4b Fix module reloading 2024-01-17 09:00:55 -06:00
Zanie
9c25fc9787 Avoid crashing on setup tools fatal errors 2024-01-17 08:11:42 -06:00
Zanie
4c9de3883c Fix stdout/err redirects for subprocesses 2024-01-17 08:11:42 -06:00
Zanie
d2959a06b2 Invalidate cached packages to fix missing imports 2024-01-17 08:11:42 -06:00
Zanie
4ab7176b74 WIP: Rust implementation 2024-01-17 08:11:39 -06:00
Zanie
d1a485e547 Add support for PEP 660 hooks 2024-01-17 08:06:24 -06:00
Zanie
0914965c37 Flush on each write; allow empty lines when parsing action 2024-01-17 08:06:24 -06:00
Zanie
d1e39076bf WIP: Rust implementation in puffin-build 2024-01-17 08:06:24 -06:00
Zanie
277e274462 Improve readability of debug output 2024-01-17 08:06:24 -06:00
Zanie
032902c22d Use - in some names to match the PEP 2024-01-17 08:06:24 -06:00
Zanie
d6b77adc03 Add support for backend-path 2024-01-17 08:06:24 -06:00
Zanie
9b55ebe8f5 Move tmpfile docs 2024-01-17 08:06:24 -06:00
Zanie
1070f9064a Python 3.7 support 2024-01-17 08:06:24 -06:00
Zanie
47a87e46b9 Fixups; restructure 2024-01-17 08:06:24 -06:00
Zanie
73b1aa85a2 Defer import of traceback 2024-01-17 08:06:24 -06:00
Zanie
f9bea6bba0 Defer import of JSON; generate a UUID manually 2024-01-17 08:06:24 -06:00
Zanie
6123a94326 Remove pathlib for faster startup 2024-01-17 08:06:23 -06:00
Zanie
da92e69bd2 Remove unused global 2024-01-17 08:06:23 -06:00
Zanie
ff5b18f8e3 Optimize temporary file creation 2024-01-17 08:06:23 -06:00
Zanie
4ca8775372 Add docs 2024-01-17 08:06:23 -06:00
Zanie
cf700dfe2c Add more test coverage; send tracebacks 2024-01-17 08:06:23 -06:00
Zanie
6242a09477 Implement stdout and stderr capturing 2024-01-17 08:06:23 -06:00
Zanie
572a990a9d Initial commit of daemon for running Python build hooks 2024-01-17 08:06:23 -06:00
Charlie Marsh
b8fbd529a1
Move OnceMap into its own crate (#946)
## Summary

This is extremely generic (like `WaitMap`), and I want to use it in the
cache.
2024-01-17 04:09:15 +00:00
konsti
5051b2c004
Use tempfile to prevent install io race crashes (#929)
On ubuntu and python 3.10,

```
cargo run -q -- pip-install --find-links https://storage.googleapis.com/jax-releases/jax_cuda_releases.html "jax[cuda12_pip]==0.4.23"
```

non-deterministically but for me consistently fails to install with
messages such as

```
error: Failed to install: nvidia_nccl_cu12-2.19.3-py3-none-manylinux1_x86_64.whl (nvidia-nccl-cu12==2.19.3)
  Caused by: failed to remove file `/home/konsti/projects/puffin/.venv/lib/python3.10/site-packages/nvidia/__init__.py`
  Caused by: No such file or directory (os error 2)
```

```
error: Failed to install: nvidia_cublas_cu12-12.3.4.1-py3-none-manylinux1_x86_64.whl (nvidia-cublas-cu12==12.3.4.1)
  Caused by: Replacing an existing file or directory failed
```

```
error: Failed to install: nvidia_cuda_nvcc_cu12-12.3.107-py3-none-manylinux1_x86_64.whl (nvidia-cuda-nvcc-cu12==12.3.107)
  Caused by: failed to hardlink file from /home/konsti/.cache/puffin/wheels-v0/pypi/nvidia-cuda-nvcc-cu12/nvidia_cuda_nvcc_cu12-12.3.107-py3-none-manylinux1_x86_64/nvidia/__init__.py to /home/konsti/projects/puffin/.venv/lib/python3.10/site-packages/nvidia/__init__.py
  Caused by: File exists (os error 17)
```

We install a lot of nvidia package, that all contain
`nvidia/__init__.py`, since they all install themselves into the
`nvidia` module:

```
nvidia-cublas-cu12==12.3.4.1
nvidia-cuda-cupti-cu12==12.3.101
nvidia-cuda-nvcc-cu12==12.3.107
nvidia-cuda-nvrtc-cu12==12.3.107
nvidia-cuda-runtime-cu12==12.3.101
nvidia-cudnn-cu12==8.9.7.29
nvidia-cufft-cu12==11.0.12.1
nvidia-cusolver-cu12==11.5.4.101
nvidia-cusparse-cu12==12.2.0.103
nvidia-nccl-cu12==2.19.3
nvidia-nvjitlink-cu12==12.3.101
```

```
$  tree -L 1 .venv/lib/python3.10/site-packages/nvidia
.venv/lib/python3.10/site-packages/nvidia
├── cublas
├── cuda_cupti
├── cuda_nvcc
├── cuda_nvrtc
├── cuda_runtime
├── cudnn
├── cufft
├── cusolver
├── cusparse
├── __init__.py
├── nccl
└── nvjitlink
```

When installing we get a race condition, each package installation is
its own thread:
* Installer Thread 1 creates `nvidia/__init__.py`
* Installer Thread 2 sees an existing  `nvidia/__init__.py`
* Installer Thread 3 sees an existing  `nvidia/__init__.py`
* Installer Thread 2 removes `nvidia/__init__.py`
* Installer Thread 3 tries to remove `nvidia/__init__.py`, it doesn't
exist anymore -> failure.

We switch to a new strategy: When the target files exists, we don't
remove it, but instead hardlink the source file to a tempfile first,
then renaming the tempfile to the target file. Renaming is considered an
atomic operation.

I've put the logging on debug level because they cases indicate a
conflict between two packages while being rare.

Closes #925

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-01-16 21:07:39 +00:00
Zanie Blue
73fccdd5c6
Add new features to the highlights in README (#939) 2024-01-16 14:03:44 -05:00
Charlie Marsh
b50e5fcbc5
Fetch --find-links indexes in parallel (#934)
## Summary

Removes a TODO.

## Test Plan

Tested manually with:

```shell
cargo run -p puffin-cli -- \
    pip compile requirements.in -n \
    --find-links 'https://download.pytorch.org/whl/torch_stable.html' \
    --find-links 'https://storage.googleapis.com/jax-releases/jax_cuda_releases.html' \
    --verbose
```

And inspecting the logs to ensure that the two requests were kicked off
concrurently.
2024-01-16 11:37:35 +01:00
Charlie Marsh
2f8f126f2f
Share a single Index across resolutions (#906)
## Summary

This PR uses a single `Index` that's shared between the top-level
resolver and any sub-resolutions happen in the course of that top-level
resolution (namely, to resolve build dependencies for any source
distributions).

In theory it's an optimization, since (e.g.) if we have two packages
that both need the `flit-core` build system, and we attempt to build
them both at once, we'll only fetch its metadata _once_, and share it
across the two resolutions. In practice, I haven't been able to get this
to show up in benchmarks. I suspect you'd need a _lot_ of source
distributions for it to matter... Though it may still be worth doing, it
strikes me as a cleaner design.

Closes #200.

Closes #541.
2024-01-16 05:37:15 +00:00
Charlie Marsh
0f592b67bb
Remove clone from RegistryWheelIndex (#937)
Doesn't need to own the package names.
2024-01-15 16:18:12 -05:00
Charlie Marsh
2a69b273ce
Use a standalone error type for --find-links registry (#936) 2024-01-15 19:48:48 +00:00
Charlie Marsh
e71e3e8dd1
Refresh BuildDispatch when running pip install with --reinstall (#933)
## Summary

This fixes an extremely subtle bug in `pip install --reinstall`, whereby
if you depend on `setuptools` at the top level, we end up uninstalling
it after resolving, which breaks some cached state. If we have
`--reinstall`, we need to reset that cached state between resolving and
installing.

## Test Plan

Running `pip install --reinstall` with:

```txt
setuptools
devpi @ e334eb4dc9/devpi-2.2.0.tar.gz
```

Fails on `main`, but passes.
2024-01-15 18:56:18 +00:00
Charlie Marsh
116da6b7de
Share in-flight map across resolutions (#932)
## Summary

This PR fixes a subtle bug in `pip install` when using `--reinstall`. If
a package depends on a build system directly (e.g., `waitress` depends
on `setuptools`), and then you have other packages that also need the
build system to build a source distribution, right now, we don't share
the `OnceMap` between those cases.

This lifts the `InFlight` tracking up a level, so that it's initialized
once per command, then shared everywhere.

## Test Plan

I'm having trouble coming up with an identical test-case and hesitant to
add this slow test to the suite... But if you run `pip install
--reinstall` with:

```
waitress @ git+https://github.com/zanieb/waitress
devpi-server @ git+https://github.com/zanieb/devpi#subdirectory=server
```

It fails consistently on `main` and passes here.
2024-01-15 13:11:22 -05:00
Charlie Marsh
249ca10765
Move Puffin subcommands to a pip namespace (#921)
## Summary

This makes the separation clearer between the legacy `pip` API and the
API we'll add in the future for the package manager itself. It also
enables seamless `puffin pip` aliasing for those that want it.

Closes #918.
2024-01-15 16:36:45 +00:00
Charlie Marsh
e54fdea93f
Continue to respect --find-links with --no-index (#931)
Like `pip`, we should allow `--find-links` with `--no-index`.
2024-01-15 16:19:27 +00:00
Charlie Marsh
42888a9609
Share flat index across resolutions (#930)
## Summary

This PR restructures the flat index fetching in a few ways:

1. It now lives in its own `FlatIndexClient`, since it felt a bit
awkward (in my opinion) for it to live in `RegistryClient`.
2. We now fetch the `FlatIndex` outside of the resolver. This has a few
benefits: (1) the resolver construct is no longer `async` and no longer
returns `Result`, which feels better for a resolver; and (2) we can
share the `FlatIndex` across resolutions rather than re-fetching it for
every source distribution build.
2024-01-15 11:02:02 -05:00
Charlie Marsh
e6d7124147
Add an extra struct around the package-to-flat index map (#923)
## Summary

`FlatIndex` is now the thing that's keyed on `PackageName`, while
`FlatDistributions` is what used to be called `FlatIndex` (a map from
version to `PrioritizedDistribution`, for a single package). I find this
a bit clearer, since we can also remove the `from_files` that doesn't
return `Self`, which I had trouble following.
2024-01-15 14:48:10 +00:00
Charlie Marsh
9a3f3d385c
Remove PubGrubVersion (#924)
## Summary

I'm running into some annoyances converting `&Version` to
`&PubGrubVersion` (which is just a wrapper type around `Version`), and I
realized... We don't even need `PubGrubVersion`?

The reason we "need" it today is due to the orphan trait rule: `Version`
is defined in `pep440_rs`, but we want to `impl
pubgrub::version::Version for Version` in the resolver crate.

Instead of introducing a new type here, which leads to a lot of
awkwardness around conversion and API isolation, what if we instead just
implement `pubgrub::version::Version` in `pep440_rs` via a feature? That
way, we can just use `Version` everywhere without any confusion and
conversion for the wrapper type.
2024-01-15 08:51:12 -05:00
konsti
8860a9c29e
Add flat index urls to registry wheel index (#928)
Previously, we were missing flat index wheels in the cache.
2024-01-15 10:21:59 +00:00
konsti
95f3cca28d
Use fs_err in more places (#926)
Before:

```
error: Failed to download distributions
  Caused by: Failed to fetch wheel: jaxlib==0.4.23+cuda12.cudnn89
  Caused by: Directory not empty (os error 39)
```

After:

```
error: Failed to download distributions
  Caused by: Failed to fetch wheel: jaxlib==0.4.23+cuda12.cudnn89
  Caused by: failed to rename file from /home/konsti/.cache/puffin/.tmpcG7tVP/jaxlib-0.4.23+cuda12.cudnn89-cp310-cp310-manylinux2014_x86_64.whl to /home/konsti/.cache/puffin/wheels-v0/index/9ff50b883297fa9d/jaxlib/jaxlib-0.4.23+cuda12.cudnn89-cp310-cp310-manylinux2014_x86_64
  Caused by: Directory not empty (os error 39)
```
2024-01-15 09:39:33 +00:00
Charlie Marsh
05029d219f
Remove --find-links limitation from README (#922)
These are now supported.
2024-01-15 03:09:15 +00:00
konsti
82ff136a74
Add find links supports to pip-sync (#914)
Closes #877
2024-01-15 03:04:55 +00:00