bazel-contrib / bazel-contrib/rules_python

py_wheel: support PEP 639 license metadata (License-Expression / License-File)

Abierto
#4,042 6 comentarios 0 reacciones 0 asignados Ver en GitHub
Good first issue help wanted
Lenguaje dominante
Starlark
Estrellas
688
Forks
721
Merge medio
15 h 7 min
PR fusionados (30 d)
76

Descripción

# 🚀 feature request

### Relevant Rules

`py_wheel` (`python/private/py_wheel.bzl`) — extending an existing rule.

### Description

`py_wheel` cannot produce a wheel whose `METADATA` conforms to PEP 639, which is now Final.

On `main` today:

- `Metadata-Version` is hardcoded to `2.1` (`python/private/py_wheel.bzl:422`); the PEP 639 fields require `2.4`.
- The only license-related attribute is the legacy free-text `license` (`:250`), emitted as the `License:` field (`:432`). PEP 639 deprecates that field.
- There is no way to emit `License-Expression`, no way to emit `License-File`, and no way to place license texts under `-.dist-info/licenses/`.
- There is no escape hatch for appending arbitrary `METADATA` lines either, so this cannot be worked around from a `BUILD` file.

The practical impact is that a `py_wheel` cannot declare its license as an SPDX expression, and cannot ship the license texts of its bundled third-party dependencies in the location PEP 639 defines. For anyone who has to produce auditable license metadata for a redistributed wheel, that is a hard blocker.

Other backends have already moved: setuptools 77.0.0 emits `License-Expression`, stores `License-File`s in `.dist-info/licenses/`, and bumps core metadata to 2.4.

### Describe the solution you'd like

Two new attributes on `py_wheel`:

- `license_expression` (string) — an SPDX license expression, emitted as `License-Expression`.
- `license_files` (label-keyed string dict) — license file targets mapped to their destination path relative to `.dist-info/licenses/`. Each entry emits one `License-File` line and packages the file at that path.

`Metadata-Version` would be raised to `2.4` only when one of the two is set, so existing users are unaffected and the change stays backwards compatible. `license` and `license_expression` would be mutually exclusive, as PEP 639 intends.

```python
py_wheel(
name = "my_wheel",
distribution = "my_package",
version = "1.0.0",
license_expression = "Apache-2.0 AND MIT",
license_files = {
"//:LICENSE": "LICENSE",
"//third_party:some_dep_license.txt": "third_party/some_dep.txt",
},
)
```

produces:

```
Metadata-Version: 2.4
Name: my_package
Version: 1.0.0
License-Expression: Apache-2.0 AND MIT
License-File: LICENSE
License-File: third_party/some_dep.txt
```

with both files packaged under `my_package-1.0.0.dist-info/licenses/`.

### Describe alternatives you've considered

- **The legacy `license` attribute** — deprecated by PEP 639, carries no SPDX semantics, and does not package license files at all.
- **`extra_distinfo_files`** — can place files inside `.dist-info/`, but `Metadata-Version` stays `2.1` and no `License-File` lines are emitted. The files end up present but undeclared, which is not PEP 639 conformant.
- **Post-processing the built wheel in a separate rule** — means unzipping and rezipping the artifact just to rewrite `METADATA`; awkward, and easy to get wrong for reproducibility.
- **Carrying a local patch to `python/private/py_wheel.bzl`** — what we do today. It works, but it has to be rebased on every `rules_python` bump, which is exactly what we would rather not carry.

I have this implemented and working locally and would be glad to send a PR. I need to clear the CLA on my employer's side first, so I am opening the issue now to check whether the approach and the attribute shape are acceptable before going down that route.

Guía de contribución

Abrir la guía de contribución

Línea de trabajo

Empieza en python/private/py_wheel.bzl, especialmente en el atributo license alrededor de la línea 250 y en la generación de metadatos alrededor de las líneas 422 y 432. Rastrea cómo se empaquetan los extra_distinfo_files existentes, luego implementa los atributos PEP 639 solicitados y asegúrate de que Metadata-Version, License-Expression, License-File y los archivos bajo .dist-info/licenses/ coincidan con el ejemplo del issue, preservando el comportamiento existente.

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

Evaluación

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

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.