Repository: pex-tool/pex

Issue:
Regression of artifact URL due to change since pip 23.3
Looks like there is a "breaking" change from pip in this [commit](https://github.com/pypa/pip/commit/b47f77d330bb7a8642af5490c0f03642f039974c), which applies the build_tracker [conditionally](https://github.com/pypa/pip/commit/b47f77d330bb7a8642af5490c0f03642f039974c#diff-5225c8e359020adb25dfc8c7a505950fd649c6c5775789c6f6517f7913f94542). The result is that there will be no log info from the build tracker module, including the item like [this](https://github.com/pypa/pip/blob/911bf995927aaf56993887225917ba7200df4e7c/src/pip/_internal/operations/build/build_tracker.py#L112) that is used in [pex](https://github.com/pex-tool/pex/blob/36dd2374569b5f3fbef54918e6ba3bd1ff852b61/pex/resolve/locker.py#L314). It seems as a result of this change, the URL for artifacts from private python package index hit the same issue as raised in https://github.com/pex-tool/pex/issues/2156.

It affects pip >= 23.3. Lower versions seem fine with pex generating proper URLs for those artifacts.

As an example, this is the log from pip `23.2.1` for installing `requests`:

<img width="559" alt="image" src="https://github.com/pex-tool/pex/assets/60371004/ec4ca256-8f03-4509-8830-0456844f6640">

and this is from pip `23.3`:

<img width="548" alt="image" src="https://github.com/pex-tool/pex/assets/60371004/161735ae-3780-4674-bd78-1adf6a19dc3e">




Discussion:
@tachikoma-li most useful would be log text (instead of screen shots) and an example of the lock file generated with both versions of Pip. Even better, just the full pex command line (and input requirements files, if any). I'm not exactly sure what problem you are encountering. The #2156 issue was moot, since the querystring that user needed was _dynamic_ and changed over time (an auth token with an expiry). Pex currently absolutely does not support dynamic URLs. Whatever artifact URL is written down in the lockfile when it is created must be good forever after or the lockfile must be regenerated. If your lockfile artifact URLs are missing _static_ querystring data they need, that's different and we can use this issue to track a fix. I look forward to hearing more details about your case.
Hi @jsirois, we have some internal Python packages (in both wheel and sdist format) host in the private PyPI. When we try to generate the lockfile with pex, we have some issues with the URLs for those internal packages. In particular, Pex uses the impermanent URLs for those packages which causes the installation to fail later, and the issue only happens with pip >= 23.3.1. With pip 23.2 (or any lower version), the lockfile can pick up the URL pointing to the private PyPI (instead of the impermanent URLs that have the token for authentication), which allows us to use `.netrc` to access the PyPI for downloading. For example, this would generate the expected lock
```shell
pex3 lock create --use-pip-config <internal_pkg> --pip-version 23.2
```
but the following fails
```shell
pex3 lock create --use-pip-config <internal_pkg> --pip-version 23.3.1
```
From what I understand, pants needs static URLs for downloading packages in parallel when resolving dependencies. But the behavior seems to be inconsistent with different configurations:
- pants can generate expected lock for pip <23.3.1, but fail with higher version of pip
- however, with higher versions of pip, pants can also generate the expected lock for sdist, but fail for wheel.
For example,  if we run
```shell
pex3 lock create --use-pip-config <internal_pkg> --pip-version 24.0 --only-build <internal_pkg>
```
we can also get the expected lock.

It seems Pex relies on log from pip to get the information of the artifacts. One thing we notice is this [change](https://github.com/pypa/pip/commit/b47f77d330bb7a8642af5490c0f03642f039974c) from pip can affect the log. For example, all logs related to build tracker are only available for sdist (which is part of the release of pip 23.3), but not for wheel, which seems to explain the inconsistence mentioned above.

Just wondering, is this the intended behavior, is there any plan to fix the issue for wheel (or the make the behavior for sdist similar to wheel?
@tachikoma-li the Pip change you identify may or may not have to do with the issue you see. That said, it should only affect sdists (and VCS URLs and local project paths) and not wheels - exactly the opposite of the problem you're having if I understand correctly.

> Just wondering, is this the intended behavior, is there any plan to fix the issue for wheel (or the make the behavior for sdist similar to wheel?

The Pex integration tests are extensive and include locks of wheels, sdists, VCS URLs and even local projects across the full range of supported Pip versions. As such, you're hitting a corner here that almost certainly involves the specifics of the private PyPI setup you use. Note that Pex CI itself uses a "private" devpi mirror instead of PyPI directly - although there is no auth used.

More to the point, I really need to be able to reproduce your issue to solve it. Can you please provide all of the details from either the "Indirect" or "Direct" lists below?

Indirect:
+ The full Pip log (add `--preserve-pip-download-log` to your `pex3 lock create` command line, observe a line like: `pex: Preserving `pip download` log at /tmp/pex-pip-log.1zil7ou6/pip.log` and then grab that fil and search / replace any sensitive info you need to redact.
+ The full before (good) and after (bad) lock files - again redacted as needed.

Direct:
+ The private PyPI server implementation you use and its setup.
+ How you think you're passing credentials to the private PyPI server (you mention `~/.netrc` but you also pass `--use-pip-config` to Pex which is potentially another source of auth info).
@jsirois Unfortunately, we can't provide the full pip log for now. Our internal server will redirect to AWS to fetch the packages when recieving download requests, which seems to have the same behavior as `devpi`. We tried `devpi` today and did find something similar to our case, which hopefully can help clarify the issue. 
Steps to reproduce:
- define the index in ~/.pip/pip.conf as
```shell
[global]
index-url=https://m.devpi.net/root/pypi/+simple/
```
 - run `pex3 lock create --use-pip-config wheel --pip-version 23.3.1` which outputs
 ```shell
{"allow_builds": true, "allow_prereleases": false, "allow_wheels": true, "build_isolation": true, "constraints": [], "locked_resolves": [{"locked_requirements": [{"artifacts": [{"algorithm": "sha256", "hash": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81", "url": "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl"}], "project_name": "wheel", "requires_dists": ["pytest>=6.0.0; extra == \"test\"", "setuptools>=65; extra == \"test\""], "requires_python": ">=3.8", "version": "0.43.0"}], "platform_tag": ["cp310", "cp310", "macosx_14_0_arm64"]}], "only_builds": [], "only_wheels": [], "path_mappings": {}, "pex_version": "2.3.1", "pip_version": "23.3.1", "prefer_older_binary": false, "requirements": ["wheel"], "requires_python": [], "resolver_version": "pip-2020-resolver", "style": "strict", "target_systems": [], "transitive": true, "use_pep517": null}
```
Note that the URL is the redirected one.

-  run `pex3 lock create --use-pip-config wheel --only-build wheel --pip-version 23.3.1` for `sdist`, which outputs:
```shell
{"allow_builds": true, "allow_prereleases": false, "allow_wheels": true, "build_isolation": true, "constraints": [], "locked_resolves": [{"locked_requirements": [{"artifacts": [{"algorithm": "sha256", "hash": "465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85", "url": "https://m.devpi.net/root/pypi/%2Bf/465/ef92c69fa5c5d/wheel-0.43.0.tar.gz"}], "project_name": "wheel", "requires_dists": ["pytest>=6.0.0; extra == \"test\"", "setuptools>=65; extra == \"test\""], "requires_python": ">=3.8", "version": "0.43.0"}], "platform_tag": ["cp310", "cp310", "macosx_14_0_arm64"]}], "only_builds": ["wheel"], "only_wheels": [], "path_mappings": {}, "pex_version": "2.3.1", "pip_version": "23.3.1", "prefer_older_binary": false, "requirements": ["wheel"], "requires_python": [], "resolver_version": "pip-2020-resolver", "style": "strict", "target_systems": [], "transitive": true, "use_pep517": null}
```
Now note the URL is not the redirected one.

- run with pip 23.2 `pex3 lock create --use-pip-config wheel --pip-version 23.2`  which outputs
```shell
{"allow_builds": true, "allow_prereleases": false, "allow_wheels": true, "build_isolation": true, "constraints": [], "locked_resolves": [{"locked_requirements": [{"artifacts": [{"algorithm": "sha256", "hash": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81", "url": "https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl"}], "project_name": "wheel", "requires_dists": ["pytest>=6.0.0; extra == \"test\"", "setuptools>=65; extra == \"test\""], "requires_python": ">=3.8", "version": "0.43.0"}], "platform_tag": ["cp310", "cp310", "macosx_14_0_arm64"]}], "only_builds": [], "only_wheels": [], "path_mappings": {}, "pex_version": "2.3.1", "pip_version": "23.2", "prefer_older_binary": false, "requirements": ["wheel"], "requires_python": [], "resolver_version": "pip-2020-resolver", "style": "strict", "target_systems": [], "transitive": true, "use_pep517": null}`
```
Note that the URL is not the redirected one.

This is very close to our issue where the redirected URL is impermanent with auth tokens and causing trouble, while the original URL would work. And this would only affect pip version >= 23.3.1 (excluding the sdist case).
@tachikoma-liI thanks, I think your last post starts to help reveal the issue here - its use of `~/.pip/pip.conf` / `--use-pip-config`. The `--use-pip-config` flag prevents Pex from running Pip with `--isolated`, so Pip can read its `~/.pip/pip.conf` config, but, importantly, Pex does not read `~/.pip/pip.conf`. So when you tell Pip (and not Pex), that the index URL is https://m.devpi.net/root/pypi/+simple/, Pex still uses the default index URL of PyPI. As things stand, you need to duplicate that piece of config information so Pex knows. Like so:
```
pex3 lock create --use-pip-config --no-pypi --index https://m.devpi.net/root/pypi/+simple/ ...
```

This is a bug, but a long standing one (you can also specify extra indexes in a requirements.txt file and Pip will use those but Pex will not known about them - same bug). The idea of introducing --use-pip-config (which was introduce in September 2023 in v2.1.147) was to enable things like [Pip keyring support](https://pip.pypa.io/en/stable/topics/authentication/#keyring-support).

@tachikoma-li now that you know you must tell Pex directly about the indexes to use, does doing so fix your problem?
To explain what I think the issue really is here:

You're using Pants to run pex and Pants does this:
+ https://github.com/pantsbuild/pants/blob/aaf94df44063168771ade199da52a8fc6c73a84f/src/python/pants/backend/python/util_rules/pex_requirements.py#L354-L360
+ https://github.com/pantsbuild/pants/blob/aaf94df44063168771ade199da52a8fc6c73a84f/src/python/pants/backend/python/subsystems/repos.py#L15-L25

As such Pants ends up launching Pex like so:
```
pex3 lock create --no-pypi --index https://pypi.org/simple/ --use-pip-config ...
```

Which mean Pex ends up launching Pip like so:
```
pip download --index-url https://pypi.org/simple/ ...
```

So now Pip is configured with 2 `--index-url`s - the one from the command line and the other from `~/.pip/pip.conf`. When faced with multiple indexes, Pip is notorious for not defining a rule for the precedence they will be used in and that precedence has, in fact, shifted over time (see https://github.com/pypa/pip/issues/9484#issuecomment-764470437 for example). This shifting of precedence over Pip releases (and not the logging patch you suspected) likely explains why things worked for you under one Pip version and not another.
Hi @jsirois, thanks for the quick reply!
I just did some tests locally with a single index, but still seem to hit the same issue:
- run `pex3 lock create --index https://m.devpi.net/root/pypi/+simple/ wheel --pip-version 23.3.1` which outputs:
```
{"allow_builds": true, "allow_prereleases": false, "allow_wheels": true, "build_isolation": true, "constraints": [], "locked_resolves": [{"locked_requirements": [{"artifacts": [{"algorithm": "sha256", "hash": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81", "url": "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl"}], "project_name": "wheel", "requires_dists": ["pytest>=6.0.0; extra == \"test\"", "setuptools>=65; extra == \"test\""], "requires_python": ">=3.8", "version": "0.43.0"}], "platform_tag": ["cp310", "cp310", "macosx_14_0_arm64"]}], "only_builds": [], "only_wheels": [], "path_mappings": {}, "pex_version": "2.3.1", "pip_version": "23.3.1", "prefer_older_binary": false, "requirements": ["wheel"], "requires_python": [], "resolver_version": "pip-2020-resolver", "style": "strict", "target_systems": [], "transitive": true, "use_pep517": null}
```
with a redirected URL.

- run `pex3 lock create --index https://m.devpi.net/root/pypi/+simple/ wheel --pip-version 23.3.1 --only-build wheel` which outputs 
 ```
{"allow_builds": true, "allow_prereleases": false, "allow_wheels": true, "build_isolation": true, "constraints": [], "locked_resolves": [{"locked_requirements": [{"artifacts": [{"algorithm": "sha256", "hash": "465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85", "url": "https://m.devpi.net/root/pypi/%2Bf/465/ef92c69fa5c5d/wheel-0.43.0.tar.gz"}], "project_name": "wheel", "requires_dists": ["pytest>=6.0.0; extra == \"test\"", "setuptools>=65; extra == \"test\""], "requires_python": ">=3.8", "version": "0.43.0"}], "platform_tag": ["cp310", "cp310", "macosx_14_0_arm64"]}], "only_builds": ["wheel"], "only_wheels": [], "path_mappings": {}, "pex_version": "2.3.1", "pip_version": "23.3.1", "prefer_older_binary": false, "requirements": ["wheel"], "requires_python": [], "resolver_version": "pip-2020-resolver", "style": "strict", "target_systems": [], "transitive": true, "use_pep517": null}
```
with the original URL.

- run `pex3 lock create --index https://m.devpi.net/root/pypi/+simple/ wheel --pip-version 23.2` which outputs 
 ```
{"allow_builds": true, "allow_prereleases": false, "allow_wheels": true, "build_isolation": true, "constraints": [], "locked_resolves": [{"locked_requirements": [{"artifacts": [{"algorithm": "sha256", "hash": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81", "url": "https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl"}], "project_name": "wheel", "requires_dists": ["pytest>=6.0.0; extra == \"test\"", "setuptools>=65; extra == \"test\""], "requires_python": ">=3.8", "version": "0.43.0"}], "platform_tag": ["cp310", "cp310", "macosx_14_0_arm64"]}], "only_builds": [], "only_wheels": [], "path_mappings": {}, "pex_version": "2.3.1", "pip_version": "23.2", "prefer_older_binary": false, "requirements": ["wheel"], "requires_python": [], "resolver_version": "pip-2020-resolver", "style": "strict", "target_systems": [], "transitive": true, "use_pep517": null}
```
with the original URL. That is, it seems the issue remains for a single index.
@tachikoma-li `--index` is _not_ single index, it adds an index to the default (PyPI). Use `--no-pypi --index https://m.devpi.net/root/pypi/+simple/`.

Perhaps this is not clear from the `--help`:
```
pex --help
...
 --pypi, --no-pypi, --no-index
                        Whether to use PyPI to resolve dependencies. (default:
                        True)
  -f PATH/URL, --find-links PATH/URL, --repo PATH/URL
                        Additional repository path (directory or URL) to look
                        for requirements. (default: None)
  -i URL, --index URL, --index-url URL
                        Additional cheeseshop indices to use to satisfy
                        requirements. (default: None)
...
```

To see what is passed to Pip you can run Pex with `-vvv`:
```
:; pex --index https://m.devpi.net/root/pypi/+simple/ -vvv cowsay -c cowsay -- -t Moo!
pex: Searching for pyenv root...: 0.0ms
pex: Building pex :: Resolving distributions for requirements: cowsay :: Resolving requirements. :: Resolving for:
pex: Hashing pex: 16.2ms
pex: Isolating pex: 0.0ms
pex: Executing: SHELL=/bin/bash PYENV_SHELL=bash NVM_INC=/home/jsirois/.nvm/versions/node/v20.11.1/include/node WSL2_GUI_APPS_ENABLED=1 WSL_DISTRO_NAME=Ubuntu-22.04 WT_SESSION=c5fa7451-c22b-458b-ae43-44059ac829e1 SSH_AUTH_SOCK=/tmp/ssh-XXXXXX8BU6xC/agent.575 SSH_AGENT_PID=579 GPG_TTY=/dev/pts/5 NAME=Gill-Windows PWD=/home/jsirois LOGNAME=jsirois HOME=/home/jsirois LANG=C.UTF-8 LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:' STARSHIP_SHELL=bash WAYLAND_DISPLAY=wayland-0 STARSHIP_SESSION_KEY=1098223452111492 NVM_DIR=/home/jsirois/.nvm LESSCLOSE='/usr/bin/lesspipe %s %s' TERM=xterm-256color LESSOPEN='| /usr/bin/lesspipe %s' USER=jsirois DISPLAY=:0 SHLVL=1 NVM_CD_FLAGS='' XDG_RUNTIME_DIR=/run/user/1000/ PYENV_ROOT=/home/jsirois/.pyenv WSLENV=WT_SESSION:WT_PROFILE_ID: XDG_DATA_DIRS=/usr/local/share:/usr/share:/var/lib/snapd/desktop PATH=/home/jsirois/.local/bin:/home/jsirois/bin:/home/jsirois/.nvm/versions/node/v20.11.1/bin:/home/jsirois/bin:/home/jsirois/.cargo/bin:/home/jsirois/.pyenv/shims:/home/jsirois/.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/snap/bin DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus NVM_BIN=/home/jsirois/.nvm/versions/node/v20.11.1/bin HOSTTYPE=x86_64 PULSE_SERVER=unix:/mnt/wslg/PulseServer WT_PROFILE_ID='{e5a83caa-4c73-52b3-ae6b-bc438d721ef9}' _=/home/jsirois/bin/pex TMPDIR=/home/jsirois/.pex/pip/23.2/pip_cache/.tmp PEX_ROOT=/home/jsirois/.pex PEX_VERBOSE=3 __PEX_UNVENDORED__=1 /home/jsirois/.pex/venvs/88f819b2277ee3d08ec0884bf56b5d4b0ca451b9/0de1795ad4486f45ee94cecd983e9905b6b11dc9/bin/python -sE /home/jsirois/.pex/venvs/88f819b2277ee3d08ec0884bf56b5d4b0ca451b9/0de1795ad4486f45ee94cecd983e9905b6b11dc9/pex --disable-pip-version-check --no-python-version-warning --exists-action a --no-input --isolated -v --cache-dir /home/jsirois/.pex/pip/23.2/pip_cache --log /tmp/pex-pip-log.nomn3piw/pip.log download --dest /home/jsirois/.pex/downloads/resolver_download.25q2kwsg/home.jsirois.bin.pex.venv.bin.python3.12 cowsay --index-url https://pypi.org/simple --extra-index-url https://m.devpi.net/root/pypi/+simple/ --retries 5 --timeout 15
...
```

N.B. that pip subprocess is run with `--index-url https://pypi.org/simple --extra-index-url https://m.devpi.net/root/pypi/+simple/` - 2 indexes.
@jsirois, thanks. Just tried with `--no-pypi --index`, but still got the same result as reported above.
That is, `pex3 lock create --no-pypi --index https://m.devpi.net/root/pypi/+simple/ wheel --pip-version 23.3.1 --only-build wheel` outputs the right URL, but `pex3 lock create --no-pypi --index https://m.devpi.net/root/pypi/+simple/ wheel --pip-version 23.3.1` outputs the redirected one.

@tachikoma-li Ok, great - thanks. I repro that at the 23.2 / 23.3.1 boundary. This is enough to work with now.

Ok. It turns out the issue was in fact related to the build tracker logging change, but that just masked the real issue. Logging for re-directs has always looked like so (this is a Pip 23.2 example):
```
...
2024-06-07T08:00:38,033   Found link https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.8), version: 0.43.0
2024-06-07T08:00:38,033   Found link https://m.devpi.net/root/pypi/%2Bf/465/ef92c69fa5c5d/wheel-0.43.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.8), version: 0.43.0
2024-06-07T08:00:38,033 Skipping link: not a file: https://m.devpi.net/root/pypi/+simple/wheel/
2024-06-07T08:00:38,034 Given no hashes to check 132 links for project 'wheel': discarding no candidates
2024-06-07T08:00:38,036 Collecting wheel
2024-06-07T08:00:38,037   Created temporary directory: /home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-unpack-jio7spwe
2024-06-07T08:00:38,037   Found index url https://m.devpi.net/root/pypi/+simple/
2024-06-07T08:00:38,038   Looking up "https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl" in the cache
2024-06-07T08:00:38,038   No cache entry available
2024-06-07T08:00:38,228   https://m.devpi.net:443 "GET /root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl HTTP/1.1" 302 304
2024-06-07T08:00:38,230   Status code 302 not in (200, 203, 300, 301, 308)
2024-06-07T08:00:38,233   Looking up "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl" in the cache
2024-06-07T08:00:38,233   No cache entry available
2024-06-07T08:00:38,233   Starting new HTTPS connection (1): files.pythonhosted.org:443
2024-06-07T08:00:38,454   https://files.pythonhosted.org:443 "GET /packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl HTTP/1.1" 200 65775
2024-06-07T08:00:38,455   Downloading https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl (65 kB)
2024-06-07T08:00:38,543   Ignoring unknown cache-control directive: immutable
2024-06-07T08:00:38,543   Updating cache with response from "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl"
2024-06-07T08:00:38,543   etag object cached for 1209600 seconds
2024-06-07T08:00:38,543   Caching due to etag
2024-06-07T08:00:38,555   Added wheel from https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl to build tracker '/home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-build-tracker-b86f1klr'
2024-06-07T08:00:38,556   Removed wheel from https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl from build tracker '/home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-build-tracker-b86f1klr'
...
```

The lines tracked by the Pex Locker are - in order from the log snip above:
1. `2024-06-07T08:00:38,233   Looking up "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl" in the cache`
2. `2024-06-07T08:00:38,233   Looking up "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl" in the cache`
3. `2024-06-07T08:00:38,555   Added wheel from https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl to build tracker '/home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-build-tracker-b86f1klr'`
4. `2024-06-07T08:00:38,556   Removed wheel from https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl from build tracker '/home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-build-tracker-b86f1klr'`

Lines 3 and 4 exist for Pip 23.2 and older but do not for Pip 23.3 and newer. Line 3 in particular is the log line that masked a bug introduced in #2276 in the handling of lines 1 and 2. Lines 1, 2 and 3 all funnel to here:
https://github.com/pex-tool/pex/blob/27c2db2bf26039bef41323c964bc4e0317a7b4f5/pex/resolve/locker.py#L287-L301

On line 295 the `ResolvedRequirement` for the given `Pin` (project name + version; i.e.: wheel 0.43.0) blindly over-writes any prior `ResolvedRequirement` for that `Pin`. In short, **the last write wins**. For Pip 23.2 and older, this last write comes from line 3, which contains the original URL. For Pip 23.3 and newer, the last write comes from line 2, the re-directed URL.

So it seems the fix is to only record the 1st `ResolvedRequirement` which will always represent the original index URL.


Resolving patch:
diff --git a/pex/resolve/downloads.py b/pex/resolve/downloads.py
--- a/pex/resolve/downloads.py
+++ b/pex/resolve/downloads.py
@@ -11,6 +11,7 @@
 from pex.common import safe_mkdir, safe_mkdtemp
 from pex.hashing import Sha256
 from pex.jobs import Job, Raise, SpawnedJob, execute_parallel
+from pex.pip import foreign_platform
 from pex.pip.download_observer import DownloadObserver
 from pex.pip.installation import get_pip
 from pex.pip.tool import PackageIndexConfiguration, Pip
@@ -109,10 +110,10 @@ def _download(
                 break
 
         # Although we don't actually need to observe the download, we do need to patch Pip to not
-        # care about wheel tags, environment markers or Requires-Python. The locker's download
-        # observer does just this for universal locks with no target system or requires python
-        # restrictions.
-        download_observer = DownloadObserver(
+        # care about wheel tags, environment markers or Requires-Python if the lock target is
+        # either foreign or universal. The locker.patch below handles the universal case or else
+        # generates no patches if the lock is not universal.
+        download_observer = foreign_platform.patch(self.target) or DownloadObserver(
             analyzer=None,
             patch_set=locker.patch(lock_configuration=self.lock_configuration),
         )
diff --git a/pex/resolve/locker.py b/pex/resolve/locker.py
--- a/pex/resolve/locker.py
+++ b/pex/resolve/locker.py
@@ -258,6 +258,7 @@ def __init__(
         self._links = defaultdict(
             OrderedDict
         )  # type: DefaultDict[Pin, OrderedDict[ArtifactURL, PartialArtifact]]
+        self._known_fingerprints = {}  # type: Dict[ArtifactURL, Fingerprint]
         self._artifact_build_observer = None  # type: Optional[ArtifactBuildObserver]
         self._local_projects = OrderedSet()  # type: OrderedSet[str]
         self._lock_result = None  # type: Optional[LockResult]
@@ -276,6 +277,13 @@ def should_collect(self, returncode):
         # type: (int) -> bool
         return returncode == 0
 
+    def parse_url_and_maybe_record_fingerprint(self, url):
+        # type: (str) -> ArtifactURL
+        artifact_url = ArtifactURL.parse(url)
+        if artifact_url.fingerprint:
+            self._known_fingerprints[artifact_url] = artifact_url.fingerprint
+        return artifact_url
+
     @staticmethod
     def _extract_resolve_data(artifact_url):
         # type: (ArtifactURL) -> Tuple[Pin, PartialArtifact]
@@ -286,18 +294,26 @@ def _extract_resolve_data(artifact_url):
 
     def _maybe_record_wheel(self, url):
         # type: (str) -> ArtifactURL
-        artifact_url = ArtifactURL.parse(url)
+        artifact_url = self.parse_url_and_maybe_record_fingerprint(url)
         if artifact_url.is_wheel:
             pin, partial_artifact = self._extract_resolve_data(artifact_url)
 
-            additional_artifacts = self._links[pin]
-            additional_artifacts.pop(artifact_url, None)
-            self._resolved_requirements[pin] = ResolvedRequirement(
-                pin=pin,
-                artifact=partial_artifact,
-                additional_artifacts=tuple(additional_artifacts.values()),
-            )
-            self._selected_path_to_pin[os.path.basename(artifact_url.path)] = pin
+            # A wheel selected in a Pip download resolve can be noted more than one time. Notably,
+            # this occurs across all supported versions of Pip when an index serves re-directs.
+            # We want the original URL in the lock since that points to the index the user selected
+            # and not the re-directed final (implementation detail) URL that may change but should
+            # not affect the lock.
+            #
+            # See: https://github.com/pex-tool/pex/issues/2414
+            if pin not in self._resolved_requirements:
+                additional_artifacts = self._links[pin]
+                additional_artifacts.pop(artifact_url, None)
+                self._resolved_requirements[pin] = ResolvedRequirement(
+                    pin=pin,
+                    artifact=partial_artifact,
+                    additional_artifacts=tuple(additional_artifacts.values()),
+                )
+                self._selected_path_to_pin[os.path.basename(artifact_url.path)] = pin
         return artifact_url
 
     def analyze(self, line):
@@ -354,7 +370,7 @@ def analyze(self, line):
                     )
                     verified = True
                     selected_path = os.path.basename(archive_path)
-                    artifact_url = ArtifactURL.parse(
+                    artifact_url = self.parse_url_and_maybe_record_fingerprint(
                         self._vcs_url_manager.normalize_url(artifact_url.raw_url)
                     )
                     self._selected_path_to_pin[selected_path] = build_result.pin
@@ -466,7 +482,7 @@ def analyze(self, line):
                     ),
                     re.compile(r"WARNING: Discarding {url}".format(url=re.escape(file_url))),
                 ),
-                artifact_url=ArtifactURL.parse(file_url),
+                artifact_url=self.parse_url_and_maybe_record_fingerprint(file_url),
             )
             return self.Continue()
 
@@ -481,7 +497,7 @@ def analyze(self, line):
         if self.style in (LockStyle.SOURCES, LockStyle.UNIVERSAL):
             match = re.search(r"Found link (?P<url>[^\s]+)(?: \(from .*\))?, version: ", line)
             if match:
-                url = ArtifactURL.parse(match.group("url"))
+                url = self.parse_url_and_maybe_record_fingerprint(match.group("url"))
                 pin, partial_artifact = self._extract_resolve_data(url)
                 self._links[pin][url] = partial_artifact
                 return self.Continue()
@@ -496,15 +512,20 @@ def analysis_completed(self):
             if resolved_requirement.pin in self._saved
         ]
 
+        artifacts = []
+        for resolved_requirement in resolved_requirements:
+            for artifact in resolved_requirement.iter_artifacts():
+                if not artifact.fingerprint:
+                    fingerprint = self._known_fingerprints.get(artifact.url)
+                    if fingerprint:
+                        artifact = attr.evolve(artifact, fingerprint=fingerprint)
+                artifacts.append(artifact)
+
         fingerprinted_artifacts = {
             artifact.url: artifact
             for artifact in self._fingerprint_service.fingerprint(
                 endpoints=self._pep_691_endpoints,
-                artifacts=tuple(
-                    artifact
-                    for resolved_requirement in resolved_requirements
-                    for artifact in resolved_requirement.iter_artifacts()
-                ),
+                artifacts=tuple(artifacts),
             )
         }
 
diff --git a/pex/version.py b/pex/version.py
--- a/pex/version.py
+++ b/pex/version.py
@@ -1,4 +1,4 @@
 # Copyright 2015 Pex project contributors.
 # Licensed under the Apache License, Version 2.0 (see LICENSE).
 
-__version__ = "2.3.2"
+__version__ = "2.3.3"


Test patch:
diff --git a/testing/data/pip_logs/issue-2414.pip-23.2.log b/testing/data/pip_logs/issue-2414.pip-23.2.log
new file mode 100644
--- /dev/null
+++ b/testing/data/pip_logs/issue-2414.pip-23.2.log
@@ -0,0 +1,180 @@
+2024-06-07T14:20:11,127 Created temporary directory: /home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-build-tracker-4nk0agh3
+2024-06-07T14:20:11,127 Initialized build tracking at /home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-build-tracker-4nk0agh3
+2024-06-07T14:20:11,127 Created build tracker: /home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-build-tracker-4nk0agh3
+2024-06-07T14:20:11,127 Entered build tracker: /home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-build-tracker-4nk0agh3
+2024-06-07T14:20:11,127 Created temporary directory: /home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-download-ekv8xmtq
+2024-06-07T14:20:11,133 Looking in indexes: https://m.devpi.net/root/pypi/+simple/
+2024-06-07T14:20:11,133 1 location(s) to search for versions of wheel:
+2024-06-07T14:20:11,133 * https://m.devpi.net/root/pypi/+simple/wheel/
+2024-06-07T14:20:11,133 Fetching project page and analyzing links: https://m.devpi.net/root/pypi/+simple/wheel/
+2024-06-07T14:20:11,133 Getting page https://m.devpi.net/root/pypi/+simple/wheel/
+2024-06-07T14:20:11,133 Found index url https://m.devpi.net/root/pypi/+simple/
+2024-06-07T14:20:11,134 Looking up "https://m.devpi.net/root/pypi/+simple/wheel/" in the cache
+2024-06-07T14:20:11,134 Request header has "max_age" as 0, cache bypassed
+2024-06-07T14:20:11,135 Starting new HTTPS connection (1): m.devpi.net:443
+2024-06-07T14:20:12,140 https://m.devpi.net:443 "GET /root/pypi/+simple/wheel/ HTTP/1.1" 200 None
+2024-06-07T14:20:12,141 Updating cache with response from "https://m.devpi.net/root/pypi/+simple/wheel/"
+2024-06-07T14:20:12,141 Fetched page https://m.devpi.net/root/pypi/+simple/wheel/ as application/vnd.pypi.simple.v1+json
+2024-06-07T14:20:12,146   Found link https://m.devpi.net/root/pypi/%2Bf/2cc/0dd3d9465ae32/wheel-0.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.1
+2024-06-07T14:20:12,146   Found link https://m.devpi.net/root/pypi/%2Bf/820/26a421ca379af/wheel-0.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.2
+2024-06-07T14:20:12,146   Found link https://m.devpi.net/root/pypi/%2Bf/767/c011ae408983b/wheel-0.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.3
+2024-06-07T14:20:12,146   Found link https://m.devpi.net/root/pypi/%2Bf/d15/9b9b80abbb60c/wheel-0.4.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.4
+2024-06-07T14:20:12,146   Found link https://m.devpi.net/root/pypi/%2Bf/684/79e3af00ccb4d/wheel-0.4.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.4.1
+2024-06-07T14:20:12,147   Found link https://m.devpi.net/root/pypi/%2Bf/ca0/e82e12241a71b/wheel-0.4.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.4.2
+2024-06-07T14:20:12,147   Found link https://m.devpi.net/root/pypi/%2Bf/804/7cd7403336317/wheel-0.5.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.5
+2024-06-07T14:20:12,147   Found link https://m.devpi.net/root/pypi/%2Bf/c2a/e5ea88f47ed0b/wheel-0.6.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.6
+2024-06-07T14:20:12,147   Found link https://m.devpi.net/root/pypi/%2Bf/3bb/349bde3db626f/wheel-0.7.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.7
+2024-06-07T14:20:12,149   Skipping link: none of the wheel's tags (py27-none-any) are compatible (run pip debug --verbose to show compatible tags): https://m.devpi.net/root/pypi/%2Bf/583/831383bdf191f/wheel-0.8-py27-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/)
+2024-06-07T14:20:12,149   Found link https://m.devpi.net/root/pypi/%2Bf/855/4dad22e0fda18/wheel-0.8.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.8
+2024-06-07T14:20:12,149   Skipping link: none of the wheel's tags (py27-none-any) are compatible (run pip debug --verbose to show compatible tags): https://m.devpi.net/root/pypi/%2Bf/c98/9d0fa55662134/wheel-0.9-py27-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/)
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/469/8c1d702ca4aa5/wheel-0.9-py32-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/a50/92ad01848ab3b/wheel-0.9.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/930/a334a9df1e11b/wheel-0.9.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.1
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/a8a/d92542fa0a548/wheel-0.9.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.2
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/75e/69663f8817f23/wheel-0.9.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.3
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/3fa/176a44642d666/wheel-0.9.4.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.4
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/2fa/fe3ab14e79a5c/wheel-0.9.5-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.5
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/e9e/6395873fecf89/wheel-0.9.5.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.5
+2024-06-07T14:20:12,150   Skipping link: none of the wheel's tags (py27-none-any) are compatible (run pip debug --verbose to show compatible tags): https://m.devpi.net/root/pypi/%2Bf/890/20b5f151462bc/wheel-0.9.6-py27-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/)
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/a24/09a6300454bc5/wheel-0.9.6.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.6
+2024-06-07T14:20:12,150   Skipping link: none of the wheel's tags (py27-none-any) are compatible (run pip debug --verbose to show compatible tags): https://m.devpi.net/root/pypi/%2Bf/311/0450f09bd937a/wheel-0.9.7-py27-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/)
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/b8e/ef2651193edc4/wheel-0.9.7.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.7
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/dbd/b989fd7a99eac/wheel-0.10.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.0
+2024-06-07T14:20:12,150   Found link https://m.devpi.net/root/pypi/%2Bf/7b9/745941475a44c/wheel-0.10.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.0
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/28f/16c298102f358/wheel-0.10.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.1
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/d05/cad700d41c005/wheel-0.10.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.1
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/abf/dc3fb4427901d/wheel-0.10.2-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.2
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/d24/2e094b505073c/wheel-0.10.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.2
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/456/f150509b57b16/wheel-0.10.3-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.3
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/082/7c883b021ec89/wheel-0.10.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.3
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/10a/60ecaff2bde8b/wheel-0.11.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.11.0
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/5e7/4c552d747c630/wheel-0.11.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.11.0
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/351/b5f218032c882/wheel-0.12.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.12.0
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/ef6/468ae7f8e19dc/wheel-0.12.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.12.0
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/e22/c0ee13924fa77/wheel-0.13.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.13.0
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/54e/b152a88932f48/wheel-0.13.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.13.0
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/41a/973fa2d0a3b00/wheel-0.14.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.14.0
+2024-06-07T14:20:12,151   Found link https://m.devpi.net/root/pypi/%2Bf/76c/3c424dc79dde4/wheel-0.14.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.14.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/c71/9c414d4a192ee/wheel-0.15.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.15.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/052/2f7cbf7a658ab/wheel-0.15.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.15.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/145/1499fcc03da0d/wheel-0.16.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.16.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/490/7bf9c716264f0/wheel-0.16.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.16.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/b5a/ffc7301543258/wheel-0.17.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.17.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/c13/9e4acbc3c7c14/wheel-0.17.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.17.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/504/64317d6baf354/wheel-0.18.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.18.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/3a3/f6b1ee1e0e46d/wheel-0.18.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.18.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/c43/93edc51986db5/wheel-0.19.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.19.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/a1e/6118ca67ca0e7/wheel-0.19.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.19.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/b07/98123cd67a763/wheel-0.21.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.21.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/68a/d3e66560e9df1/wheel-0.21.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.21.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/4ac/0ec6404ef2dd3/wheel-0.22.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.22.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/dff/df998910de1fd/wheel-0.22.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.22.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/cbc/6b2e274557b5e/wheel-0.23.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.23.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/bf8/eed43df6c88fd/wheel-0.23.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.23.0
+2024-06-07T14:20:12,152   Found link https://m.devpi.net/root/pypi/%2Bf/53a/8b47d3db4ded8/wheel-0.24.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.24.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/ef8/32abfedea7ed8/wheel-0.24.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.24.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/11d/7473000053180/wheel-0.25.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.25.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/c7a/72676357e26dd/wheel-0.25.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.25.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/c92/ed3a2dd87c54a/wheel-0.26.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.26.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/eaa/d353805c180a4/wheel-0.26.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.26.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/b2e/5cf1b3e5ca787/wheel-0.27.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.27.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/0be/ae2ec3a20df54/wheel-0.27.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.27.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/7a8/3f0fd22ccf413/wheel-0.28.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.28.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/705/25cdda4fe80f3/wheel-0.28.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.28.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/ea8/033fc9905804e/wheel-0.29.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.29.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/1eb/b8ad7e26b448e/wheel-0.29.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.29.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/cd1/9aa9325d3af1c/wheel-0.30.0a0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.30.0a0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/98f/3e09b4ad7f564/wheel-0.30.0a0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.30.0a0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/e72/1e53864f084f9/wheel-0.30.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.30.0
+2024-06-07T14:20:12,153   Found link https://m.devpi.net/root/pypi/%2Bf/951/5fe0a94e823fd/wheel-0.30.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.30.0
+2024-06-07T14:20:12,154   Found link https://m.devpi.net/root/pypi/%2Bf/9cd/c8ab2cc9c3c2e/wheel-0.31.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.31.0
+2024-06-07T14:20:12,154   Found link https://m.devpi.net/root/pypi/%2Bf/1ae/8153bed701cb0/wheel-0.31.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.31.0
+2024-06-07T14:20:12,154   Found link https://m.devpi.net/root/pypi/%2Bf/800/44e51ec5bbf6c/wheel-0.31.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.31.1
+2024-06-07T14:20:12,154   Found link https://m.devpi.net/root/pypi/%2Bf/0a2/e54558a0628f2/wheel-0.31.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.31.1
+2024-06-07T14:20:12,154   Found link https://m.devpi.net/root/pypi/%2Bf/397/0f4130b7f8bf8/wheel-0.32.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.0
+2024-06-07T14:20:12,154   Found link https://m.devpi.net/root/pypi/%2Bf/a26/bc27230baaec9/wheel-0.32.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.0
+2024-06-07T14:20:12,155   Found link https://m.devpi.net/root/pypi/%2Bf/9fa/1f772f1a2df2b/wheel-0.32.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.1
+2024-06-07T14:20:12,155   Found link https://m.devpi.net/root/pypi/%2Bf/d21/5f4520a1ba185/wheel-0.32.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.1
+2024-06-07T14:20:12,155   Found link https://m.devpi.net/root/pypi/%2Bf/c93/e2d711f5f9841/wheel-0.32.2-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.2
+2024-06-07T14:20:12,155   Found link https://m.devpi.net/root/pypi/%2Bf/196/c9842d79262bb/wheel-0.32.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.2
+2024-06-07T14:20:12,155   Found link https://m.devpi.net/root/pypi/%2Bf/1e5/3cdb3f808d5cc/wheel-0.32.3-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.3
+2024-06-07T14:20:12,155   Found link https://m.devpi.net/root/pypi/%2Bf/029/703bf514e16c8/wheel-0.32.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.3
+2024-06-07T14:20:12,156   Found link https://m.devpi.net/root/pypi/%2Bf/b79/ffea026bc0dbd/wheel-0.33.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.0
+2024-06-07T14:20:12,156   Found link https://m.devpi.net/root/pypi/%2Bf/123/63e6df5678ecf/wheel-0.33.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.0
+2024-06-07T14:20:12,156   Found link https://m.devpi.net/root/pypi/%2Bf/8eb/4a788b3aec8ab/wheel-0.33.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.1
+2024-06-07T14:20:12,156   Found link https://m.devpi.net/root/pypi/%2Bf/66a/8fd76f28977bb/wheel-0.33.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.1
+2024-06-07T14:20:12,156   Found link https://m.devpi.net/root/pypi/%2Bf/5e7/9117472686ac0/wheel-0.33.4-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.4
+2024-06-07T14:20:12,156   Found link https://m.devpi.net/root/pypi/%2Bf/62f/cfa03d45b5b72/wheel-0.33.4.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.4
+2024-06-07T14:20:12,156   Found link https://m.devpi.net/root/pypi/%2Bf/fd8/5f7f5ba5b1337/wheel-0.33.5-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.5
+2024-06-07T14:20:12,157   Found link https://m.devpi.net/root/pypi/%2Bf/0f8/3c322fbe95b52/wheel-0.33.5.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.5
+2024-06-07T14:20:12,157   Found link https://m.devpi.net/root/pypi/%2Bf/f4d/a1763d3becf2e/wheel-0.33.6-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.6
+2024-06-07T14:20:12,157   Found link https://m.devpi.net/root/pypi/%2Bf/10c/9da68765315ed/wheel-0.33.6.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.6
+2024-06-07T14:20:12,157   Found link https://m.devpi.net/root/pypi/%2Bf/98a/7bd648493d21d/wheel-0.34.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.34.0
+2024-06-07T14:20:12,157   Found link https://m.devpi.net/root/pypi/%2Bf/a69/231973dccde85/wheel-0.34.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.34.0
+2024-06-07T14:20:12,158   Found link https://m.devpi.net/root/pypi/%2Bf/48e/082fac9a549bb/wheel-0.34.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*), version: 0.34.1
+2024-06-07T14:20:12,158   Found link https://m.devpi.net/root/pypi/%2Bf/664/b9c5033ee7cd5/wheel-0.34.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*), version: 0.34.1
+2024-06-07T14:20:12,158   Found link https://m.devpi.net/root/pypi/%2Bf/df2/77cb51e61359a/wheel-0.34.2-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*), version: 0.34.2
+2024-06-07T14:20:12,158   Found link https://m.devpi.net/root/pypi/%2Bf/878/8e9155fe14f54/wheel-0.34.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*), version: 0.34.2
+2024-06-07T14:20:12,159   Found link https://m.devpi.net/root/pypi/%2Bf/64a/0d73747636637/wheel-0.35.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.35.0
+2024-06-07T14:20:12,159   Found link https://m.devpi.net/root/pypi/%2Bf/625/e645aae0706ad/wheel-0.35.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.35.0
+2024-06-07T14:20:12,159   Found link https://m.devpi.net/root/pypi/%2Bf/497/add53525d16c1/wheel-0.35.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.35.1
+2024-06-07T14:20:12,159   Found link https://m.devpi.net/root/pypi/%2Bf/99a/22d87add3f634/wheel-0.35.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.35.1
+2024-06-07T14:20:12,159   Found link https://m.devpi.net/root/pypi/%2Bf/645/f81da70dcd993/wheel-0.36.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.0
+2024-06-07T14:20:12,159   Found link https://m.devpi.net/root/pypi/%2Bf/e17/f05e14282d0e6/wheel-0.36.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.0
+2024-06-07T14:20:12,159   Found link https://m.devpi.net/root/pypi/%2Bf/906/864fb722c0ab5/wheel-0.36.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.1
+2024-06-07T14:20:12,160   Found link https://m.devpi.net/root/pypi/%2Bf/aae/f9b8c36db72f8/wheel-0.36.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.1
+2024-06-07T14:20:12,160   Found link https://m.devpi.net/root/pypi/%2Bf/78b/5b185f0e5763c/wheel-0.36.2-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.2
+2024-06-07T14:20:12,160   Found link https://m.devpi.net/root/pypi/%2Bf/e11/eefd162658ea5/wheel-0.36.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.2
+2024-06-07T14:20:12,160   Found link https://m.devpi.net/root/pypi/%2Bf/210/14b2bd93c6d00/wheel-0.37.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.37.0
+2024-06-07T14:20:12,161   Found link https://m.devpi.net/root/pypi/%2Bf/e2e/f7239991699e3/wheel-0.37.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.37.0
+2024-06-07T14:20:12,161   Found link https://m.devpi.net/root/pypi/%2Bf/4bd/cd7d840138086/wheel-0.37.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.37.1
+2024-06-07T14:20:12,161   Found link https://m.devpi.net/root/pypi/%2Bf/e9a/504e793efbca1/wheel-0.37.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.37.1
+2024-06-07T14:20:12,161   Found link https://m.devpi.net/root/pypi/%2Bf/12b/e48b0b8684b51/wheel-0.38.0-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.0
+2024-06-07T14:20:12,161   Found link https://m.devpi.net/root/pypi/%2Bf/d52/844afee64cdd4/wheel-0.38.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.0
+2024-06-07T14:20:12,161   Found link https://m.devpi.net/root/pypi/%2Bf/7a9/5f9a8dc0924ef/wheel-0.38.1-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.1
+2024-06-07T14:20:12,161   Found link https://m.devpi.net/root/pypi/%2Bf/ea0/41edf63f4ccba/wheel-0.38.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.1
+2024-06-07T14:20:12,161   Found link https://m.devpi.net/root/pypi/%2Bf/7a5/a3095dceca97a/wheel-0.38.2-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.2
+2024-06-07T14:20:12,162   Found link https://m.devpi.net/root/pypi/%2Bf/3d4/92ef22379a156/wheel-0.38.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.2
+2024-06-07T14:20:12,162   Found link https://m.devpi.net/root/pypi/%2Bf/f3c/99240da8d2698/wheel-0.38.3-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.3
+2024-06-07T14:20:12,162   Found link https://m.devpi.net/root/pypi/%2Bf/406/6646ef77d0e56/wheel-0.38.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.3
+2024-06-07T14:20:12,162   Found link https://m.devpi.net/root/pypi/%2Bf/b60/533f3f5d530e9/wheel-0.38.4-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.4
+2024-06-07T14:20:12,162   Found link https://m.devpi.net/root/pypi/%2Bf/965/f5259b5667254/wheel-0.38.4.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.4
+2024-06-07T14:20:12,162   Found link https://m.devpi.net/root/pypi/%2Bf/d23/6b20e7cb522da/wheel-0.40.0-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.40.0
+2024-06-07T14:20:12,162   Found link https://m.devpi.net/root/pypi/%2Bf/cd1/196f3faee2b31/wheel-0.40.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.40.0
+2024-06-07T14:20:12,162   Found link https://m.devpi.net/root/pypi/%2Bf/7e9/be3bbd0078f61/wheel-0.41.0-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.0
+2024-06-07T14:20:12,162   Found link https://m.devpi.net/root/pypi/%2Bf/55a/0f0a5a84869bc/wheel-0.41.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.0
+2024-06-07T14:20:12,162   Found link https://m.devpi.net/root/pypi/%2Bf/473/219bd4cbedc62/wheel-0.41.1-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.1
+2024-06-07T14:20:12,162   Found link https://m.devpi.net/root/pypi/%2Bf/12b/911f083e876e1/wheel-0.41.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.1
+2024-06-07T14:20:12,163   Found link https://m.devpi.net/root/pypi/%2Bf/759/09db2664838d0/wheel-0.41.2-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.2
+2024-06-07T14:20:12,163   Found link https://m.devpi.net/root/pypi/%2Bf/0c5/ac5ff2afb79ac/wheel-0.41.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.2
+2024-06-07T14:20:12,163   Found link https://m.devpi.net/root/pypi/%2Bf/488/609bc63a29322/wheel-0.41.3-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.3
+2024-06-07T14:20:12,163   Found link https://m.devpi.net/root/pypi/%2Bf/4d4/987ce51a49370/wheel-0.41.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.3
+2024-06-07T14:20:12,163   Found link https://m.devpi.net/root/pypi/%2Bf/177/f9c9b0d45c478/wheel-0.42.0-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.42.0
+2024-06-07T14:20:12,163   Found link https://m.devpi.net/root/pypi/%2Bf/c45/be39f7882c9d3/wheel-0.42.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.42.0
+2024-06-07T14:20:12,163   Found link https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.8), version: 0.43.0
+2024-06-07T14:20:12,163   Found link https://m.devpi.net/root/pypi/%2Bf/465/ef92c69fa5c5d/wheel-0.43.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.8), version: 0.43.0
+2024-06-07T14:20:12,163 Skipping link: not a file: https://m.devpi.net/root/pypi/+simple/wheel/
+2024-06-07T14:20:12,164 Given no hashes to check 132 links for project 'wheel': discarding no candidates
+2024-06-07T14:20:12,166 Collecting wheel
+2024-06-07T14:20:12,167   Created temporary directory: /home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-unpack-u605d32b
+2024-06-07T14:20:12,167   Found index url https://m.devpi.net/root/pypi/+simple/
+2024-06-07T14:20:12,168   Looking up "https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl" in the cache
+2024-06-07T14:20:12,168   No cache entry available
+2024-06-07T14:20:12,388   https://m.devpi.net:443 "GET /root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl HTTP/1.1" 302 304
+2024-06-07T14:20:12,388   Status code 302 not in (200, 203, 300, 301, 308)
+2024-06-07T14:20:12,389   Looking up "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl" in the cache
+2024-06-07T14:20:12,390   No cache entry available
+2024-06-07T14:20:12,390   Starting new HTTPS connection (1): files.pythonhosted.org:443
+2024-06-07T14:20:12,524   https://files.pythonhosted.org:443 "GET /packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl HTTP/1.1" 200 65775
+2024-06-07T14:20:12,524   Downloading https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl (65 kB)
+2024-06-07T14:20:12,555   Ignoring unknown cache-control directive: immutable
+2024-06-07T14:20:12,555   Updating cache with response from "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl"
+2024-06-07T14:20:12,555   etag object cached for 1209600 seconds
+2024-06-07T14:20:12,555   Caching due to etag
+2024-06-07T14:20:12,567   Added wheel from https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl to build tracker '/home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-build-tracker-4nk0agh3'
+2024-06-07T14:20:12,567   Removed wheel from https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl from build tracker '/home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-build-tracker-4nk0agh3'
+2024-06-07T14:20:12,570 Created temporary directory: /home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-unpack-jf3j10vu
+2024-06-07T14:20:12,571 Saved /tmp/tmpfshaqpoi/home.jsirois.bin.pex.venv.bin.python3.12/wheel-0.43.0-py3-none-any.whl
+2024-06-07T14:20:12,571 Created temporary directory: /home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-unpack-woncm5kj
+2024-06-07T14:20:12,573 Successfully downloaded wheel
+2024-06-07T14:20:12,573 Removed build tracker: '/home/jsirois/.pex/pip/23.2/pip_cache/.tmp/pip-build-tracker-4nk0agh3'
diff --git a/testing/data/pip_logs/issue-2414.pip-23.3.1.log b/testing/data/pip_logs/issue-2414.pip-23.3.1.log
new file mode 100644
--- /dev/null
+++ b/testing/data/pip_logs/issue-2414.pip-23.3.1.log
@@ -0,0 +1,181 @@
+2024-06-07T14:18:30,096 Created temporary directory: /home/jsirois/.pex/pip/23.3.1/pip_cache/.tmp/pip-build-tracker-xqa2flrz
+2024-06-07T14:18:30,096 Initialized build tracking at /home/jsirois/.pex/pip/23.3.1/pip_cache/.tmp/pip-build-tracker-xqa2flrz
+2024-06-07T14:18:30,096 Created build tracker: /home/jsirois/.pex/pip/23.3.1/pip_cache/.tmp/pip-build-tracker-xqa2flrz
+2024-06-07T14:18:30,096 Entered build tracker: /home/jsirois/.pex/pip/23.3.1/pip_cache/.tmp/pip-build-tracker-xqa2flrz
+2024-06-07T14:18:30,097 Created temporary directory: /home/jsirois/.pex/pip/23.3.1/pip_cache/.tmp/pip-download-07_znuuq
+2024-06-07T14:18:30,101 Looking in indexes: https://m.devpi.net/root/pypi/+simple/
+2024-06-07T14:18:30,101 1 location(s) to search for versions of wheel:
+2024-06-07T14:18:30,101 * https://m.devpi.net/root/pypi/+simple/wheel/
+2024-06-07T14:18:30,101 Fetching project page and analyzing links: https://m.devpi.net/root/pypi/+simple/wheel/
+2024-06-07T14:18:30,101 Getting page https://m.devpi.net/root/pypi/+simple/wheel/
+2024-06-07T14:18:30,102 Found index url https://m.devpi.net/root/pypi/+simple/
+2024-06-07T14:18:30,102 Looking up "https://m.devpi.net/root/pypi/+simple/wheel/" in the cache
+2024-06-07T14:18:30,102 Request header has "max_age" as 0, cache bypassed
+2024-06-07T14:18:30,102 No cache entry available
+2024-06-07T14:18:30,102 Starting new HTTPS connection (1): m.devpi.net:443
+2024-06-07T14:18:31,650 https://m.devpi.net:443 "GET /root/pypi/+simple/wheel/ HTTP/1.1" 200 None
+2024-06-07T14:18:31,652 Updating cache with response from "https://m.devpi.net/root/pypi/+simple/wheel/"
+2024-06-07T14:18:31,653 Fetched page https://m.devpi.net/root/pypi/+simple/wheel/ as application/vnd.pypi.simple.v1+json
+2024-06-07T14:18:31,664   Found link https://m.devpi.net/root/pypi/%2Bf/2cc/0dd3d9465ae32/wheel-0.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.1
+2024-06-07T14:18:31,665   Found link https://m.devpi.net/root/pypi/%2Bf/820/26a421ca379af/wheel-0.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.2
+2024-06-07T14:18:31,665   Found link https://m.devpi.net/root/pypi/%2Bf/767/c011ae408983b/wheel-0.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.3
+2024-06-07T14:18:31,665   Found link https://m.devpi.net/root/pypi/%2Bf/d15/9b9b80abbb60c/wheel-0.4.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.4
+2024-06-07T14:18:31,666   Found link https://m.devpi.net/root/pypi/%2Bf/684/79e3af00ccb4d/wheel-0.4.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.4.1
+2024-06-07T14:18:31,666   Found link https://m.devpi.net/root/pypi/%2Bf/ca0/e82e12241a71b/wheel-0.4.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.4.2
+2024-06-07T14:18:31,666   Found link https://m.devpi.net/root/pypi/%2Bf/804/7cd7403336317/wheel-0.5.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.5
+2024-06-07T14:18:31,666   Found link https://m.devpi.net/root/pypi/%2Bf/c2a/e5ea88f47ed0b/wheel-0.6.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.6
+2024-06-07T14:18:31,666   Found link https://m.devpi.net/root/pypi/%2Bf/3bb/349bde3db626f/wheel-0.7.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.7
+2024-06-07T14:18:31,674   Skipping link: none of the wheel's tags (py27-none-any) are compatible (run pip debug --verbose to show compatible tags): https://m.devpi.net/root/pypi/%2Bf/583/831383bdf191f/wheel-0.8-py27-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/)
+2024-06-07T14:18:31,674   Found link https://m.devpi.net/root/pypi/%2Bf/855/4dad22e0fda18/wheel-0.8.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.8
+2024-06-07T14:18:31,674   Skipping link: none of the wheel's tags (py27-none-any) are compatible (run pip debug --verbose to show compatible tags): https://m.devpi.net/root/pypi/%2Bf/c98/9d0fa55662134/wheel-0.9-py27-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/)
+2024-06-07T14:18:31,674   Found link https://m.devpi.net/root/pypi/%2Bf/469/8c1d702ca4aa5/wheel-0.9-py32-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9
+2024-06-07T14:18:31,674   Found link https://m.devpi.net/root/pypi/%2Bf/a50/92ad01848ab3b/wheel-0.9.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9
+2024-06-07T14:18:31,674   Found link https://m.devpi.net/root/pypi/%2Bf/930/a334a9df1e11b/wheel-0.9.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.1
+2024-06-07T14:18:31,674   Found link https://m.devpi.net/root/pypi/%2Bf/a8a/d92542fa0a548/wheel-0.9.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.2
+2024-06-07T14:18:31,674   Found link https://m.devpi.net/root/pypi/%2Bf/75e/69663f8817f23/wheel-0.9.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.3
+2024-06-07T14:18:31,675   Found link https://m.devpi.net/root/pypi/%2Bf/3fa/176a44642d666/wheel-0.9.4.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.4
+2024-06-07T14:18:31,675   Found link https://m.devpi.net/root/pypi/%2Bf/2fa/fe3ab14e79a5c/wheel-0.9.5-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.5
+2024-06-07T14:18:31,675   Found link https://m.devpi.net/root/pypi/%2Bf/e9e/6395873fecf89/wheel-0.9.5.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.5
+2024-06-07T14:18:31,675   Skipping link: none of the wheel's tags (py27-none-any) are compatible (run pip debug --verbose to show compatible tags): https://m.devpi.net/root/pypi/%2Bf/890/20b5f151462bc/wheel-0.9.6-py27-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/)
+2024-06-07T14:18:31,675   Found link https://m.devpi.net/root/pypi/%2Bf/a24/09a6300454bc5/wheel-0.9.6.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.6
+2024-06-07T14:18:31,675   Skipping link: none of the wheel's tags (py27-none-any) are compatible (run pip debug --verbose to show compatible tags): https://m.devpi.net/root/pypi/%2Bf/311/0450f09bd937a/wheel-0.9.7-py27-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/)
+2024-06-07T14:18:31,675   Found link https://m.devpi.net/root/pypi/%2Bf/b8e/ef2651193edc4/wheel-0.9.7.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.9.7
+2024-06-07T14:18:31,675   Found link https://m.devpi.net/root/pypi/%2Bf/dbd/b989fd7a99eac/wheel-0.10.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.0
+2024-06-07T14:18:31,675   Found link https://m.devpi.net/root/pypi/%2Bf/7b9/745941475a44c/wheel-0.10.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.0
+2024-06-07T14:18:31,675   Found link https://m.devpi.net/root/pypi/%2Bf/28f/16c298102f358/wheel-0.10.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.1
+2024-06-07T14:18:31,675   Found link https://m.devpi.net/root/pypi/%2Bf/d05/cad700d41c005/wheel-0.10.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.1
+2024-06-07T14:18:31,675   Found link https://m.devpi.net/root/pypi/%2Bf/abf/dc3fb4427901d/wheel-0.10.2-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.2
+2024-06-07T14:18:31,675   Found link https://m.devpi.net/root/pypi/%2Bf/d24/2e094b505073c/wheel-0.10.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.2
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/456/f150509b57b16/wheel-0.10.3-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.3
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/082/7c883b021ec89/wheel-0.10.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.10.3
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/10a/60ecaff2bde8b/wheel-0.11.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.11.0
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/5e7/4c552d747c630/wheel-0.11.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.11.0
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/351/b5f218032c882/wheel-0.12.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.12.0
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/ef6/468ae7f8e19dc/wheel-0.12.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.12.0
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/e22/c0ee13924fa77/wheel-0.13.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.13.0
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/54e/b152a88932f48/wheel-0.13.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.13.0
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/41a/973fa2d0a3b00/wheel-0.14.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.14.0
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/76c/3c424dc79dde4/wheel-0.14.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.14.0
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/c71/9c414d4a192ee/wheel-0.15.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.15.0
+2024-06-07T14:18:31,676   Found link https://m.devpi.net/root/pypi/%2Bf/052/2f7cbf7a658ab/wheel-0.15.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.15.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/145/1499fcc03da0d/wheel-0.16.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.16.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/490/7bf9c716264f0/wheel-0.16.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.16.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/b5a/ffc7301543258/wheel-0.17.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.17.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/c13/9e4acbc3c7c14/wheel-0.17.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.17.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/504/64317d6baf354/wheel-0.18.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.18.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/3a3/f6b1ee1e0e46d/wheel-0.18.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.18.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/c43/93edc51986db5/wheel-0.19.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.19.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/a1e/6118ca67ca0e7/wheel-0.19.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.19.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/b07/98123cd67a763/wheel-0.21.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.21.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/68a/d3e66560e9df1/wheel-0.21.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.21.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/4ac/0ec6404ef2dd3/wheel-0.22.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.22.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/dff/df998910de1fd/wheel-0.22.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.22.0
+2024-06-07T14:18:31,677   Found link https://m.devpi.net/root/pypi/%2Bf/cbc/6b2e274557b5e/wheel-0.23.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.23.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/bf8/eed43df6c88fd/wheel-0.23.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.23.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/53a/8b47d3db4ded8/wheel-0.24.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.24.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/ef8/32abfedea7ed8/wheel-0.24.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.24.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/11d/7473000053180/wheel-0.25.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.25.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/c7a/72676357e26dd/wheel-0.25.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.25.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/c92/ed3a2dd87c54a/wheel-0.26.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.26.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/eaa/d353805c180a4/wheel-0.26.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.26.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/b2e/5cf1b3e5ca787/wheel-0.27.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.27.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/0be/ae2ec3a20df54/wheel-0.27.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.27.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/7a8/3f0fd22ccf413/wheel-0.28.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.28.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/705/25cdda4fe80f3/wheel-0.28.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.28.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/ea8/033fc9905804e/wheel-0.29.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.29.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/1eb/b8ad7e26b448e/wheel-0.29.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.29.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/cd1/9aa9325d3af1c/wheel-0.30.0a0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.30.0a0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/98f/3e09b4ad7f564/wheel-0.30.0a0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.30.0a0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/e72/1e53864f084f9/wheel-0.30.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.30.0
+2024-06-07T14:18:31,678   Found link https://m.devpi.net/root/pypi/%2Bf/951/5fe0a94e823fd/wheel-0.30.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/), version: 0.30.0
+2024-06-07T14:18:31,679   Found link https://m.devpi.net/root/pypi/%2Bf/9cd/c8ab2cc9c3c2e/wheel-0.31.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.31.0
+2024-06-07T14:18:31,679   Found link https://m.devpi.net/root/pypi/%2Bf/1ae/8153bed701cb0/wheel-0.31.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.31.0
+2024-06-07T14:18:31,679   Found link https://m.devpi.net/root/pypi/%2Bf/800/44e51ec5bbf6c/wheel-0.31.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.31.1
+2024-06-07T14:18:31,679   Found link https://m.devpi.net/root/pypi/%2Bf/0a2/e54558a0628f2/wheel-0.31.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.31.1
+2024-06-07T14:18:31,680   Found link https://m.devpi.net/root/pypi/%2Bf/397/0f4130b7f8bf8/wheel-0.32.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.0
+2024-06-07T14:18:31,680   Found link https://m.devpi.net/root/pypi/%2Bf/a26/bc27230baaec9/wheel-0.32.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.0
+2024-06-07T14:18:31,680   Found link https://m.devpi.net/root/pypi/%2Bf/9fa/1f772f1a2df2b/wheel-0.32.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.1
+2024-06-07T14:18:31,680   Found link https://m.devpi.net/root/pypi/%2Bf/d21/5f4520a1ba185/wheel-0.32.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.1
+2024-06-07T14:18:31,680   Found link https://m.devpi.net/root/pypi/%2Bf/c93/e2d711f5f9841/wheel-0.32.2-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.2
+2024-06-07T14:18:31,680   Found link https://m.devpi.net/root/pypi/%2Bf/196/c9842d79262bb/wheel-0.32.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.2
+2024-06-07T14:18:31,680   Found link https://m.devpi.net/root/pypi/%2Bf/1e5/3cdb3f808d5cc/wheel-0.32.3-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.3
+2024-06-07T14:18:31,681   Found link https://m.devpi.net/root/pypi/%2Bf/029/703bf514e16c8/wheel-0.32.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.32.3
+2024-06-07T14:18:31,681   Found link https://m.devpi.net/root/pypi/%2Bf/b79/ffea026bc0dbd/wheel-0.33.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.0
+2024-06-07T14:18:31,681   Found link https://m.devpi.net/root/pypi/%2Bf/123/63e6df5678ecf/wheel-0.33.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.0
+2024-06-07T14:18:31,681   Found link https://m.devpi.net/root/pypi/%2Bf/8eb/4a788b3aec8ab/wheel-0.33.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.1
+2024-06-07T14:18:31,681   Found link https://m.devpi.net/root/pypi/%2Bf/66a/8fd76f28977bb/wheel-0.33.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.1
+2024-06-07T14:18:31,681   Found link https://m.devpi.net/root/pypi/%2Bf/5e7/9117472686ac0/wheel-0.33.4-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.4
+2024-06-07T14:18:31,681   Found link https://m.devpi.net/root/pypi/%2Bf/62f/cfa03d45b5b72/wheel-0.33.4.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.4
+2024-06-07T14:18:31,682   Found link https://m.devpi.net/root/pypi/%2Bf/fd8/5f7f5ba5b1337/wheel-0.33.5-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.5
+2024-06-07T14:18:31,682   Found link https://m.devpi.net/root/pypi/%2Bf/0f8/3c322fbe95b52/wheel-0.33.5.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.5
+2024-06-07T14:18:31,682   Found link https://m.devpi.net/root/pypi/%2Bf/f4d/a1763d3becf2e/wheel-0.33.6-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.6
+2024-06-07T14:18:31,682   Found link https://m.devpi.net/root/pypi/%2Bf/10c/9da68765315ed/wheel-0.33.6.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*), version: 0.33.6
+2024-06-07T14:18:31,682   Found link https://m.devpi.net/root/pypi/%2Bf/98a/7bd648493d21d/wheel-0.34.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.34.0
+2024-06-07T14:18:31,682   Found link https://m.devpi.net/root/pypi/%2Bf/a69/231973dccde85/wheel-0.34.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.34.0
+2024-06-07T14:18:31,682   Found link https://m.devpi.net/root/pypi/%2Bf/48e/082fac9a549bb/wheel-0.34.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*), version: 0.34.1
+2024-06-07T14:18:31,683   Found link https://m.devpi.net/root/pypi/%2Bf/664/b9c5033ee7cd5/wheel-0.34.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*), version: 0.34.1
+2024-06-07T14:18:31,683   Found link https://m.devpi.net/root/pypi/%2Bf/df2/77cb51e61359a/wheel-0.34.2-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*), version: 0.34.2
+2024-06-07T14:18:31,683   Found link https://m.devpi.net/root/pypi/%2Bf/878/8e9155fe14f54/wheel-0.34.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*), version: 0.34.2
+2024-06-07T14:18:31,683   Found link https://m.devpi.net/root/pypi/%2Bf/64a/0d73747636637/wheel-0.35.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.35.0
+2024-06-07T14:18:31,683   Found link https://m.devpi.net/root/pypi/%2Bf/625/e645aae0706ad/wheel-0.35.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.35.0
+2024-06-07T14:18:31,683   Found link https://m.devpi.net/root/pypi/%2Bf/497/add53525d16c1/wheel-0.35.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.35.1
+2024-06-07T14:18:31,683   Found link https://m.devpi.net/root/pypi/%2Bf/99a/22d87add3f634/wheel-0.35.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.35.1
+2024-06-07T14:18:31,683   Found link https://m.devpi.net/root/pypi/%2Bf/645/f81da70dcd993/wheel-0.36.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.0
+2024-06-07T14:18:31,684   Found link https://m.devpi.net/root/pypi/%2Bf/e17/f05e14282d0e6/wheel-0.36.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.0
+2024-06-07T14:18:31,684   Found link https://m.devpi.net/root/pypi/%2Bf/906/864fb722c0ab5/wheel-0.36.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.1
+2024-06-07T14:18:31,684   Found link https://m.devpi.net/root/pypi/%2Bf/aae/f9b8c36db72f8/wheel-0.36.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.1
+2024-06-07T14:18:31,684   Found link https://m.devpi.net/root/pypi/%2Bf/78b/5b185f0e5763c/wheel-0.36.2-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.2
+2024-06-07T14:18:31,684   Found link https://m.devpi.net/root/pypi/%2Bf/e11/eefd162658ea5/wheel-0.36.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.36.2
+2024-06-07T14:18:31,684   Found link https://m.devpi.net/root/pypi/%2Bf/210/14b2bd93c6d00/wheel-0.37.0-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.37.0
+2024-06-07T14:18:31,684   Found link https://m.devpi.net/root/pypi/%2Bf/e2e/f7239991699e3/wheel-0.37.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.37.0
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/4bd/cd7d840138086/wheel-0.37.1-py2.py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.37.1
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/e9a/504e793efbca1/wheel-0.37.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7), version: 0.37.1
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/12b/e48b0b8684b51/wheel-0.38.0-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.0
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/d52/844afee64cdd4/wheel-0.38.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.0
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/7a9/5f9a8dc0924ef/wheel-0.38.1-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.1
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/ea0/41edf63f4ccba/wheel-0.38.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.1
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/7a5/a3095dceca97a/wheel-0.38.2-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.2
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/3d4/92ef22379a156/wheel-0.38.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.2
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/f3c/99240da8d2698/wheel-0.38.3-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.3
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/406/6646ef77d0e56/wheel-0.38.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.3
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/b60/533f3f5d530e9/wheel-0.38.4-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.4
+2024-06-07T14:18:31,685   Found link https://m.devpi.net/root/pypi/%2Bf/965/f5259b5667254/wheel-0.38.4.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.38.4
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/d23/6b20e7cb522da/wheel-0.40.0-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.40.0
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/cd1/196f3faee2b31/wheel-0.40.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.40.0
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/7e9/be3bbd0078f61/wheel-0.41.0-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.0
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/55a/0f0a5a84869bc/wheel-0.41.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.0
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/473/219bd4cbedc62/wheel-0.41.1-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.1
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/12b/911f083e876e1/wheel-0.41.1.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.1
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/759/09db2664838d0/wheel-0.41.2-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.2
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/0c5/ac5ff2afb79ac/wheel-0.41.2.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.2
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/488/609bc63a29322/wheel-0.41.3-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.3
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/4d4/987ce51a49370/wheel-0.41.3.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.41.3
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/177/f9c9b0d45c478/wheel-0.42.0-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.42.0
+2024-06-07T14:18:31,686   Found link https://m.devpi.net/root/pypi/%2Bf/c45/be39f7882c9d3/wheel-0.42.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.7), version: 0.42.0
+2024-06-07T14:18:31,687   Found link https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.8), version: 0.43.0
+2024-06-07T14:18:31,687   Found link https://m.devpi.net/root/pypi/%2Bf/465/ef92c69fa5c5d/wheel-0.43.0.tar.gz (from https://m.devpi.net/root/pypi/+simple/wheel/) (requires-python:>=3.8), version: 0.43.0
+2024-06-07T14:18:31,687 Skipping link: not a file: https://m.devpi.net/root/pypi/+simple/wheel/
+2024-06-07T14:18:31,688 Given no hashes to check 132 links for project 'wheel': discarding no candidates
+2024-06-07T14:18:31,690 Collecting wheel
+2024-06-07T14:18:31,690   Created temporary directory: /home/jsirois/.pex/pip/23.3.1/pip_cache/.tmp/pip-unpack-xhvc0bpr
+2024-06-07T14:18:31,690   Found index url https://m.devpi.net/root/pypi/+simple/
+2024-06-07T14:18:31,690   Looking up "https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl" in the cache
+2024-06-07T14:18:31,690   No cache entry available
+2024-06-07T14:18:31,690   No cache entry available
+2024-06-07T14:18:31,891   https://m.devpi.net:443 "GET /root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl HTTP/1.1" 302 304
+2024-06-07T14:18:31,892   Status code 302 not in (200, 203, 300, 301, 308)
+2024-06-07T14:18:31,893   Looking up "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl" in the cache
+2024-06-07T14:18:31,894   No cache entry available
+2024-06-07T14:18:31,894   No cache entry available
+2024-06-07T14:18:31,894   Starting new HTTPS connection (1): files.pythonhosted.org:443
+2024-06-07T14:18:32,007   https://files.pythonhosted.org:443 "GET /packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl HTTP/1.1" 200 65775
+2024-06-07T14:18:32,008   Downloading https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl (65 kB)
+2024-06-07T14:18:32,042   Ignoring unknown cache-control directive: immutable
+2024-06-07T14:18:32,042   Updating cache with response from "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl"
+2024-06-07T14:18:32,042   etag object cached for 1209600 seconds
+2024-06-07T14:18:32,042   Caching due to etag
+2024-06-07T14:18:32,059 Created temporary directory: /home/jsirois/.pex/pip/23.3.1/pip_cache/.tmp/pip-unpack-kjrc2jvu
+2024-06-07T14:18:32,059 Saved /tmp/tmpqueo20gi/home.jsirois.bin.pex.venv.bin.python3.12/wheel-0.43.0-py3-none-any.whl
+2024-06-07T14:18:32,059 Created temporary directory: /home/jsirois/.pex/pip/23.3.1/pip_cache/.tmp/pip-unpack-8503xlnd
+2024-06-07T14:18:32,061 Successfully downloaded wheel
+2024-06-07T14:18:32,061 Removed build tracker: '/home/jsirois/.pex/pip/23.3.1/pip_cache/.tmp/pip-build-tracker-xqa2flrz'
diff --git a/tests/integration/cli/commands/test_issue_2414.py b/tests/integration/cli/commands/test_issue_2414.py
new file mode 100644
--- /dev/null
+++ b/tests/integration/cli/commands/test_issue_2414.py
@@ -0,0 +1,93 @@
+# Copyright 2024 Pex project contributors.
+# Licensed under the Apache License, Version 2.0 (see LICENSE).
+
+import os.path
+
+import pytest
+
+from pex.pep_440 import Version
+from pex.pep_503 import ProjectName
+from pex.pip.log_analyzer import ErrorMessage
+from pex.requirements import parse_requirement_string
+from pex.resolve.configured_resolver import ConfiguredResolver
+from pex.resolve.locked_resolve import LockConfiguration, LockStyle
+from pex.resolve.locker import Locker, LockResult
+from pex.resolve.resolved_requirement import (
+    ArtifactURL,
+    Fingerprint,
+    PartialArtifact,
+    Pin,
+    ResolvedRequirement,
+)
+from pex.targets import LocalInterpreter
+from pex.typing import TYPE_CHECKING
+from testing import data
+
+if TYPE_CHECKING:
+    from typing import Any
+
+
+@pytest.fixture
+def locker(tmpdir):
+    # type: (Any) -> Locker
+    download_dir = os.path.join(str(tmpdir), "downloads")
+    return Locker(
+        target=LocalInterpreter.create(),
+        root_requirements=[parse_requirement_string("wheel")],
+        resolver=ConfiguredResolver.default(),
+        lock_configuration=LockConfiguration(style=LockStyle.SOURCES),
+        download_dir=download_dir,
+    )
+
+
+def analyze_log(
+    locker,  # type: Locker
+    log_name,  # type: str
+):
+    # type: (...) -> None
+    with open(data.path("pip_logs", log_name)) as fp:
+        for line in fp:
+            result = locker.analyze(line)
+            assert not isinstance(result.data, ErrorMessage)
+    locker.analysis_completed()
+
+
+@pytest.mark.parametrize("pip_version", ["23.2", "23.3.1"])
+def test_redirects_dont_stomp_original_index_urls(
+    pip_version,  # type: str
+    locker,  # type: Locker
+):
+    # type: (...) -> None
+
+    analyze_log(locker, "issue-2414.pip-{pip_version}.log".format(pip_version=pip_version))
+
+    expected_whl_artifact = PartialArtifact(
+        url=ArtifactURL.parse(
+            "https://m.devpi.net/root/pypi/%2Bf/55c/570405f142630/wheel-0.43.0-py3-none-any.whl"
+        ),
+        fingerprint=Fingerprint(
+            algorithm="sha256",
+            hash="55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81",
+        ),
+        verified=False,
+    )
+    expected_sdist_artifact = PartialArtifact(
+        url=ArtifactURL.parse(
+            "https://m.devpi.net/root/pypi/%2Bf/465/ef92c69fa5c5d/wheel-0.43.0.tar.gz"
+        ),
+        fingerprint=Fingerprint(
+            algorithm="sha256",
+            hash="465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85",
+        ),
+        verified=False,
+    )
+    expected_wheel_requirement = ResolvedRequirement(
+        pin=Pin(ProjectName("wheel"), Version("0.43.0")),
+        artifact=expected_whl_artifact,
+        additional_artifacts=tuple([expected_sdist_artifact]),
+    )
+    expected_lock_result = LockResult(
+        resolved_requirements=tuple([expected_wheel_requirement]),
+        local_projects=(),
+    )
+    assert expected_lock_result == locker.lock_result