Skip to content

SHA256 does not match when using multiple extra index urls containing same package #2631

@MajerMartin

Description

@MajerMartin

Hi, we are using Pants build system with two private repositories - first one is for release versions, second one is for snapshots. Each of these repositories can contain package with same name and same version.

Pants setup:

[python-repos]
indexes.add = [
    "https://myindex/nexus/repository/pypi-hosted/simple/",
    "https://myindex/nexus/repository/pypi-hosted-snapshots/simple/",
]

Example package in our repos:

https://myindex/nexus/repository/pypi-hosted/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl
https://myindex/nexus/repository/pypi-hosted-snapshots/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl

When I try to create lock file using pants generate-lockfiles, Pants generates PEX create lock command which includes:

--no-pypi --index=https://pypi.org/simple/ --index=https://myindex/nexus/repository/pypi-hosted/simple/ --index=https://myindex/nexus/repository/pypi-hosted-snapshots/simple/

and which is then translated into these for Pip:

--index-url https://pypi.org/simple/ --extra-index-url https://myindex/nexus/repository/pypi-hosted/simple/ --extra-index-url https://myindex/nexus/repository/pypi-hosted-snapshots/simple/

This command crashes with

Expected sha256 hash of 3f009f055f42aba6b251e5bde1c1fae49d8b4805478002aeb417fa257a6babf3 when downloading mypackage but hashed to 4ca541b60a956f99ccc5fda61a58df774cc801a3260c2dea0d1245313b0b18f5.

The problem is that PEX takes hash of package from the first index, where the (resolvable) package is found, but Pip downloads from the last index, where the package is found.

PEX log:

pex: Indexing downloads :: Downloading FileArtifact(url=ArtifactURL(raw_url='https://myindexl/nexus/repository/pypi-hosted/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl#sha256=3f009f055f42aba6b251e5bde1c1fae49d8b4805478002aeb417fa257a6babf3', download_url='https://myindex/nexus/repository/pypi-hosted/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl', normalized_url='https://myindex/nexus/repository/pypi-hosted/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl', scheme='https', path='/nexus/repository/pypi-hosted/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl', fragment_parameters={}, fingerprints=(Fingerprint(algorithm='sha256', hash='3f009f055f42aba6b251e5bde1c1fae49d8b4805478002aeb417fa257a6babf3'),)), fingerprint=Fingerprint(algorithm='sha256', hash='3f009f055f42aba6b251e5bde1c1fae49d8b4805478002aeb417fa257a6babf3'), verified=False, filename='mypackage-1.2.3-py3-none-any.whl')
pex: Indexing downloads: 17.1ms
pex:   Downloading FileArtifact(url=ArtifactURL(raw_url='https://myindex/nexus/repository/pypi-hosted/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl#sha256=3f009f055f42aba6b251e5bde1c1fae49d8b4805478002aeb417fa257a6babf3', download_url='https://myindex/nexus/repository/pypi-hosted/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl', normalized_url='https://myindex/nexus/repository/pypi-hosted/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl', scheme='https', path='/nexus/repository/pypi-hosted/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl', fragment_parameters={}, fingerprints=(Fingerprint(algorithm='sha256', hash='3f009f055f42aba6b251e5bde1c1fae49d8b4805478002aeb417fa257a6babf3'),)), fingerprint=Fingerprint(algorithm='sha256', hash='3f009f055f42aba6b251e5bde1c1fae49d8b4805478002aeb417fa257a6babf3'), verified=False, filename='mypackage-1.2.3-py3-none-any.whl'): 0.4ms

Pip log:

2024-12-17T13:52:37,423 Looking in indexes: https://pypi.org/simple/, https://myindex/nexus/repository/pypi-hosted/simple/, https://myindex/nexus/repository/pypi-hosted-snapshots/simple/
...
2024-12-17T13:53:27,376 3 location(s) to search for versions of mypackage:
2024-12-17T13:53:27,376 * https://pypi.org/simple/mypackage/
2024-12-17T13:53:27,376 * https://myindex/nexus/repository/pypi-hosted/simple/mypackage/
2024-12-17T13:53:27,376 * https://myindex/nexus/repository/pypi-hosted-snapshots/simple/mypackage/
2024-12-17T13:53:27,376 Fetching project page and analyzing links: https://pypi.org/simple/mypackage/
2024-12-17T13:53:27,376 Getting page https://pypi.org/simple/mypackage/
2024-12-17T13:53:27,376 Found index url https://pypi.org/simple/
2024-12-17T13:53:27,377 Looking up "https://pypi.org/simple/mypackage/" in the cache
2024-12-17T13:53:27,377 Request header has "max_age" as 0, cache bypassed
2024-12-17T13:53:27,377 No cache entry available
2024-12-17T13:53:27,487 https://pypi.org:443 "GET /simple/mypackage/ HTTP/1.1" 404 13
2024-12-17T13:53:27,492 Status code 404 not in (200, 203, 300, 301, 308)
2024-12-17T13:53:27,494 Could not fetch URL https://pypi.org/simple/mypackage/: 404 Client Error: Not Found for url: https://pypi.org/simple/mypackage/ - skipping
2024-12-17T13:53:27,494 Fetching project page and analyzing links: https://myindex/nexus/repository/pypi-hosted/simple/mypackage/
2024-12-17T13:53:27,495 Getting page https://myindex/nexus/repository/pypi-hosted/simple/mypackage/
2024-12-17T13:53:27,496 Found index url https://myindex/nexus/repository/pypi-hosted/simple/
2024-12-17T13:53:27,497 Looking up "https://myindex/nexus/repository/pypi-hosted/simple/mypackage/" in the cache
2024-12-17T13:53:27,497 Request header has "max_age" as 0, cache bypassed
2024-12-17T13:53:27,498 No cache entry available
2024-12-17T13:53:27,861 https://myindex:443 "GET /nexus/repository/pypi-hosted/simple/mypackage/ HTTP/1.1" 200 49361
2024-12-17T13:53:28,046 Updating cache with response from "https://myindex/nexus/repository/pypi-hosted/simple/mypackage/"
2024-12-17T13:53:28,048 Fetched page https://myindex/nexus/repository/pypi-hosted/simple/mypackage/ as text/html
...
2024-12-17T13:53:28,091   Found link https://myindex/nexus/repository/pypi-hosted/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl#sha256=3f009f055f42aba6b251e5bde1c1fae49d8b4805478002aeb417fa257a6babf3 (from https://myindex/nexus/repository/pypi-hosted/simple/sbsmypackagepark/) (requires-python:>=3.8,<3.12), version: 1.2.3
...
024-12-17T13:53:28,129 Fetching project page and analyzing links: https://myindex/nexus/repository/pypi-hosted-snapshots/simple/mypackage/
2024-12-17T13:53:28,129 Getting page https://myindex/nexus/repository/pypi-hosted-snapshots/simple/mypackage/
2024-12-17T13:53:28,129 Found index url https://myindex/nexus/repository/pypi-hosted-snapshots/simple/
2024-12-17T13:53:28,130 Looking up "https://myindex/nexus/repository/pypi-hosted-snapshots/simple/mypackage/" in the cache
2024-12-17T13:53:28,130 Request header has "max_age" as 0, cache bypassed
2024-12-17T13:53:28,130 No cache entry available
2024-12-17T13:53:28,317 https://myindex:443 "GET /nexus/repository/pypi-hosted-snapshots/simple/mypackage/ HTTP/1.1" 200 23324
2024-12-17T13:53:28,321 Updating cache with response from "https://myindex/nexus/repository/pypi-hosted-snapshots/simple/mypackage/"
2024-12-17T13:53:28,323 Fetched page https://myindex/nexus/repository/pypi-hosted-snapshots/simple/mypackage/ as text/html
...
2024-12-17T13:53:28,342   Found link https://myindex/nexus/repository/pypi-hosted-snapshots/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl#sha256=4ca541b60a956f99ccc5fda61a58df774cc801a3260c2dea0d1245313b0b18f5 (from https://myindex/nexus/repository/pypi-hosted-snapshots/simple/mypackage/) (requires-python:>=3.8,<3.12), version: 1.2.3
...
2024-12-17T13:53:28,384 Collecting mypackage
2024-12-17T13:53:28,384   Created temporary directory: /Users/myuser/.cache/pants/named_caches/pex_root/pip/1/24.2/pip_cache/.tmp/pip-unpack-yg18r5en
2024-12-17T13:53:28,384   Found index url https://myindex/nexus/repository/pypi-hosted-snapshots/simple/
2024-12-17T13:53:28,385   Looking up "https://myindex/nexus/repository/pypi-hosted-snapshots/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl" in the cache
2024-12-17T13:53:28,385   No cache entry available
2024-12-17T13:53:28,385   No cache entry available
2024-12-17T13:53:28,570   https://myindex:443 "GET /nexus/repository/pypi-hosted-snapshots/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl HTTP/1.1" 200 151289
2024-12-17T13:53:28,571   Downloading https://myindex/nexus/repository/pypi-hosted-snapshots/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl (151 kB)
2024-12-17T13:53:28,764   Updating cache with response from "https://myindex/nexus/repository/pypi-hosted-snapshots/packages/mypackage/1.2.3/mypackage-1.2.3-py3-none-any.whl"
2024-12-17T13:53:28,764   etag object cached for 1209600 seconds
2024-12-17T13:53:28,764   Caching due to etag

When I reverse the indexes in Pants, I get reversed hash results:

[python-repos]
indexes.add = [
    "https://myindex/nexus/repository/pypi-hosted-snapshots/simple/",
    "https://myindex/nexus/repository/pypi-hosted/simple/",
]
Expected sha256 hash of 4ca541b60a956f99ccc5fda61a58df774cc801a3260c2dea0d1245313b0b18f5 when downloading mypackage but hashed to 3f009f055f42aba6b251e5bde1c1fae49d8b4805478002aeb417fa257a6babf3.

I know this is well known Pip limitation (all indexes have same priority), but is there something that can be done on Pants/PEX side? Use hash of artifact from last index, where the package is found, to match Pip's selection process?

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions