Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Invalid wheel metadata when a direct-URL requirement has an environment marker

Abierto
#4,158 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
3/5
Tiempo estimado
1-2 días
Aptitud para principiantes
78/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
python
Área
build-system

Línea de trabajo

Empieza en tools/wheelmaker.py, en get_new_requirement_line, e inspecciona el manejo de extra_requires en python/private/py_wheel.bzl. Reproduce el problema con el ejemplo de BUILD.bazel proporcionado y pip install --dry-run; se considera terminado cuando los metadatos del wheel generado aceptan requisitos con URL directa y marcadores de entorno, incluidas las entradas de extra_requires.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

🐞 bug report

Affected Rule

The issue is caused by the rule: py_wheel (specifically get_new_requirement_line in tools/wheelmaker.py, and the extra_requires handling in python/private/py_wheel.bzl)

Is this a regression?

No — the bug was introduced together with URL-requirement support in wheelmaker (PR #3569). Direct-URL requirements with environment markers have never produced valid wheel metadata.

Description

When a py_wheel requires (or a line in requires_file) is a PEP 508 direct-URL requirement with an environment marker, e.g.

somepkg @ https://example.com/wheels/somepkg-1.0-none-none-linux_x86_64.whl ; sys_platform == 'linux'

wheelmaker re-serializes the requirement in get_new_requirement_line as:

base = f"Requires-Dist: {req.name}{req_extra_deps}{req_spec}"  # ends with the URL
...
return f"{base}; {req.marker}"   # no whitespace before ';'

producing a METADATA line without whitespace before the ; marker separator:

Requires-Dist: somepkg @ https://example.com/wheels/somepkg-1.0-none-none-linux_x86_64.whl; sys_platform == 'linux'

That is invalid PEP 508. Per the spec, whitespace after a URL is mandatory since ; is a valid URI character (sub-delims), so a strict parser greedily consumes whl; into the URL and then fails. pip rejects the wheel at install time:

ERROR: Requested urlmarker==0.1 from file:///.../urlmarker-0.1-py3-none-any.whl has invalid metadata: Expected semicolon (after URL and whitespace) or end
    somepkg @ https://example.com/wheels/somepkg-1.0-none-none-linux_x86_64.whl; sys_platform == 'linux'

Note that wheelmaker strips extra whitespace via Requirement(...) round-tripping, so there is no way to emit valid metadata for URL+marker requirements through py_wheel without patching wheelmaker.

For non-URL requirements (stim~=1.16.0; sys_platform != 'linux') the missing space happens to be harmless since the grammar allows version_end wsp* ';', so this only breaks direct URLs.

🔬 Minimal Reproduction

# BUILD.bazel
load("@rules_python//python:packaging.bzl", "py_wheel")

py_wheel(
    name = "wheel",
    distribution = "urlmarker",
    version = "0.1",
    requires = [
        "somepkg @ https://example.com/wheels/somepkg-1.0-none-none-linux_x86_64.whl ; sys_platform == 'linux'",
    ],
)
bazel build //:wheel
pip install --dry-run bazel-bin/urlmarker-0.1-py3-none-any.whl
# => ERROR: ... has invalid metadata: Expected semicolon (after URL and whitespace) or end

(The URL does not need to resolve — metadata validation fails before pip ever fetches it.)

🔥 Exception or Error


ERROR: Requested urlmarker==0.1 from file:///.../urlmarker-0.1-py3-none-any.whl has invalid metadata: Expected semicolon (after URL and whitespace) or end
    somepkg @ https://example.com/wheels/somepkg-1.0-cp312-cp312-macosx_15_0_arm64.whl; sys_platform == 'darwin'

Suggested fix

Emit a space before ; in all branches of get_new_requirement_line — valid for every requirement type and required for URLs:

     if req.marker:
         if extra:
-            return f"{base}; ({req.marker}) and {extra}"
+            return f"{base} ; ({req.marker}) and {extra}"
         else:
-            return f"{base}; {req.marker}"
+            return f"{base} ; {req.marker}"
     elif extra:
-        return f"{base}; {extra}"
+        return f"{base} ; {extra}"

(Note extra may itself be a marker expression such as extra == 'cuda', and base may end in a URL here too when extra_requires entries use direct URLs — see below.)

🌍 Your Environment

Operating System:

  
  Ubuntu (Linux x86_64)
  

Output of bazel version:

  
Bazelisk version: v1.29.0
Build label: 9.2.0
Build target: @@//src/main/java/com/google/devtools/build/lib/bazel:BazelServer
Build time: Mon Jul 13 18:15:04 2026 (1783966504)
Build timestamp: 1783966504
Build timestamp as int: 1783966504
  

Rules_python version:

  
  2.3.3 (still present on main at the time of writing)
  

Anything else relevant?

  1. The extra_requires path in python/private/py_wheel.bzl has the same missing-space problem: it emits

    metadata_contents.append(
        "Requires-Dist: %s; extra == '%s'" % (requirement, option),
    )
    

    If an extra's requirement is a direct URL (e.g. "somepkg @ https://example.com/pkg.whl" under extra_requires = {"cuda": [...]}), this produces ...pkg.whl; extra == 'cuda' — the same invalid metadata. These lines pass through get_new_requirement_line in wheelmaker (which fixes them if the suggested fix above is applied, since the URL ends up in base and extra == '...' becomes extra), but only because rpartition(";") splits off the extra marker; the raw "%s; extra == '%s'" formatting should arguably also include the space for consistency.

  2. pip/uv accept name @ url; marker in requirements files, which masks the issue during development — the failure only surfaces when installing the built wheel, because wheel metadata is validated strictly.

Lenguaje dominante
Starlark
Estrellas
688
Forks
723
Merge medio
2 d 4 h
PR fusionados (30 d)
38

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de bazel-contrib/rules_python

Todos los issues de bazel-contrib/rules_python

Issues similares

Más issues de Build System

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.