fix(pypi): normalize extras in requirement strings per PEP 685 (#3588) ## Summary Extras parsed from requirement strings (e.g., from `requirements.txt`) were not being normalized, causing mismatches when evaluating PEP 508 marker expressions. For example, `sqlalchemy[postgresql-psycopg2binary]` would fail to resolve `psycopg2-binary` as a transitive dependency because the wheel METADATA marker expression `extra == "postgresql_psycopg2binary"` uses the underscore-normalized form (per PEP 685), while the extras set retained the original hyphenated form from the requirement string. ## Before ``` # requirements.txt sqlalchemy[postgresql-psycopg2binary]==2.0.36 # Parsed extras: ["postgresql-psycopg2binary"] # Marker evaluation: "postgresql-psycopg2binary" != "postgresql_psycopg2binary" -> MISS # Result: psycopg2-binary NOT included as a dependency ``` ## After ``` # requirements.txt sqlalchemy[postgresql-psycopg2binary]==2.0.36 # Parsed extras: ["postgresql_psycopg2binary"] (normalized) # Marker evaluation: "postgresql_psycopg2binary" == "postgresql_psycopg2binary" -> MATCH # Result: psycopg2-binary correctly included as a dependency ``` ## Changes - **`python/private/pypi/pep508_requirement.bzl`**: Apply `normalize_name()` to each extra during requirement parsing, consistent with how the package name is already normalized. - **`tests/pypi/pep508/requirement_tests.bzl`**: Updated existing test expectation for case normalization and added test case for hyphenated extras (`sqlalchemy[asyncio,postgresql-psycopg2binary,postgresql-asyncpg]`). - **`tests/pypi/pep508/deps_tests.bzl`**: Added `test_extras_with_hyphens_are_normalized` integration test confirming that dependencies gated behind hyphenated extras are correctly resolved. - **`CHANGELOG.md`**: Added entry under Unreleased > Fixed. Fixes #3587 --------- Co-authored-by: Ignas Anikevicius <240938+aignas@users.noreply.github.com> (cherry picked from commit 9fe42b1f0badfc258b159dbc0a05a8392c0234e5)
This repository is the home of the core Python rules -- py_library, py_binary, py_test, py_proto_library, and related symbols that provide the basis for Python support in Bazel. It also contains package installation rules for integrating with PyPI and other indices.
Documentation for rules_python is at https://rules-python.readthedocs.io and in the Bazel Build Encyclopedia.
Examples live in the examples directory.
The core rules are stable. Their implementation is subject to Bazel's backward compatibility policy. This repository aims to follow semantic versioning.
The Bazel community maintains this repository. Neither Google nor the Bazel team provides support for the code. However, this repository is part of the test suite used to vet new Bazel releases. See How to contribute page for information on our development workflow.
For detailed documentation, see https://rules-python.readthedocs.io
See Bzlmod support for more details.