Version
pulp_python 3.29.0
pulpcore 3.108.0
- Installation: container image (Pulp operator on Kubernetes)
Describe the bug
On a pull-through PyPI distribution, when a client requests <wheel>.whl.metadata (PEP 658), pulp-content raises ValueError: True is not in list in pulp_python/app/utils.py:get_project_metadata_from_file and returns a 5xx / aborted stream. A direct GET also surfaces a misleading 404 with an upstream URL that doesn't exist (https://pypi.org/simple/<package>/<wheel>.whl.metadata — PEP 658 metadata files live next to the wheel on files.pythonhosted.org/packages/<hash>/..., not under the simple index path).
This appears to be a residual case of #1083. PR #1086 fixed the .whl fetch path by passing suffix=filename into the temp file, so endswith(".whl") matches. But when the requested artifact is the .whl.metadata companion, init_from_artifact_and_relative_path is still called, path.name ends in .metadata, the temp file ends in .metadata, and DIST_EXTENSIONS has no .metadata entry — so .index(True) raises.
To Reproduce
- Configure a pull-through PyPI distribution:
pulp python remote create --name pypi --url https://pypi.org/ --policy on_demand
pulp python distribution create --name pypi-proxy --base-path pypi --remote pypi
- From a clean state (no cached package), request the PEP 658 metadata file directly:
curl -sk -o - -w "HTTP %{http_code}\n" \
"https://<pulp>/pulp/content/<domain>/pypi/simple/ruff/ruff-0.12.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata"
Equivalent: run uv lock / uv sync against this distribution from a cold uv cache — uv issues .whl.metadata requests per PEP 658.
3. Observe a 404 to the client and the following traceback in pulp-content logs:
File "pulpcore/content/handler.py", line 1033, in _save_artifact
content = c_type.init_from_artifact_and_relative_path(artifact, rel_path)
File "pulp_python/app/models.py", line 223, in init_from_artifact_and_relative_path
data = artifact_to_python_content_data(path.name, artifact, domain=get_domain())
File "pulp_python/app/utils.py", line 273, in artifact_to_python_content_data
metadata = get_project_metadata_from_file(temp_file.name)
File "pulp_python/app/utils.py", line 195, in get_project_metadata_from_file
pkg_type_index = [filename.endswith(ext) for ext in extensions].index(True)
ValueError: True is not in list
Expected behavior
Either:
- The
.metadata companion is served from upstream (fetched alongside / extracted from the wheel) so PEP 658 works through the pull-through cache, or
- The request returns a clean 404 without invoking the python-package metadata extractor on a non-package file.
In both cases get_project_metadata_from_file should not be called with a filename whose extension isn't in DIST_EXTENSIONS.
Additional context
Version
pulp_python3.29.0pulpcore3.108.0Describe the bug
On a pull-through PyPI distribution, when a client requests
<wheel>.whl.metadata(PEP 658),pulp-contentraisesValueError: True is not in listinpulp_python/app/utils.py:get_project_metadata_from_fileand returns a 5xx / aborted stream. A direct GET also surfaces a misleading 404 with an upstream URL that doesn't exist (https://pypi.org/simple/<package>/<wheel>.whl.metadata— PEP 658 metadata files live next to the wheel onfiles.pythonhosted.org/packages/<hash>/..., not under the simple index path).This appears to be a residual case of #1083. PR #1086 fixed the
.whlfetch path by passingsuffix=filenameinto the temp file, soendswith(".whl")matches. But when the requested artifact is the.whl.metadatacompanion,init_from_artifact_and_relative_pathis still called,path.nameends in.metadata, the temp file ends in.metadata, andDIST_EXTENSIONShas no.metadataentry — so.index(True)raises.To Reproduce
Equivalent: run
uv lock/uv syncagainst this distribution from a cold uv cache — uv issues.whl.metadatarequests per PEP 658.3. Observe a 404 to the client and the following traceback in
pulp-contentlogs:Expected behavior
Either:
.metadatacompanion is served from upstream (fetched alongside / extracted from the wheel) so PEP 658 works through the pull-through cache, orIn both cases
get_project_metadata_from_fileshould not be called with a filename whose extension isn't inDIST_EXTENSIONS.Additional context
artifact_to_python_content_dataconfirms thesuffix=filenamefix from Fix pull-through metadata serving and saving #1086 is present, so the.whlpath works; the.whl.metadatapath bypasses that protection becausefilenameitself ends in.metadata..metadatacase beforeartifact_to_python_content_datais called (e.g. ininit_from_artifact_and_relative_pathwhenrelative_pathends in.metadata), since those bytes already are the metadata and don't need extracting.uvresolutions against the pull-through distribution silently report "only<old-cached-version>is available" because per-version metadata fetches all crash server-side; only versions whose metadata happens to already be cached in Postgres remain visible.