Repository navigation
feat(pypi): generate requirements.bzl in the unified @pypi hub - #4223
Merged
rickeylev merged 5 commits intoOct 7, 2026
Merged
Conversation
The unified `@pypi` hub generates no `requirements.bzl`. A repo whose hub
was named `pypi` has to rename it now that the name is reserved, and once
it does, every `load("@pypi//:requirements.bzl", "requirement")` stops
resolving at the same moment, so the rename can't be split into smaller
changes. Flipping `RULES_PYTHON_PYPI_HUB_RESERVED` on by default would
cause the same breakage for every such repo.
Generate a `requirements.bzl` in the unified hub from the same template
as a concrete hub's. `requirement()`, `whl_requirement()`,
`data_requirement()` and `dist_info_requirement()` return labels in the
unified hub, so they route through
`--@rules_python//python/config_settings:venv` like `@pypi//<pkg>`.
The `all_*` lists are fixed at loading time, before the venv flag is
known, so they list the default hub's packages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
They are fixed at loading time, before the venv flag is known, so they could only ever list one hub's packages and would not follow the flag like the rest of the unified hub. Load them from a concrete hub. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Generate the unified hub's requirements.bzl only when the root module sets `pip.default(unified_hub_requirements_bzl = True)`. The docs steer users to `@pypi//<pkg>` labels over the requirement() helper, so keep the helper on the unified hub a deliberate choice for repos migrating a hub that used to be named `pypi`, not a default surface. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…_pypi MODULE.bazel Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rickeylev
approved these changes
Oct 7, 2026
rickeylev
left a comment
Collaborator
There was a problem hiding this comment.
Nice PR and fix. Thanks!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The unified
@pypihub (#3837) does not generate arequirements.bzl. That makes renaming a hub away from the now-reservedpypiname an all-at-once change: the moment the concrete hub stops being@pypi, everyload("@pypi//:requirements.bzl", "requirement")in the repo fails to load. In our monorepo that is ~940 BUILD files, and any BUILD file that lands on main mid-migration re-breaks it. The same thing would happen to every such repo ifRULES_PYTHON_PYPI_HUB_RESERVEDis flipped on by default, as discussed in #3837.This adds an opt-in,
pip.default(unified_hub_requirements_bzl = True)(root module only, off by default), that generates arequirements.bzlin the unified hub with the per-package macros of a concrete hub's. It's opt-in because the docs already steer users to@pypi//<pkg>labels overrequirement(); this is a migration aid for repos whose hub used to be namedpypi, not a new default surface. With it on:requirement(),whl_requirement(),data_requirement()anddist_info_requirement()return labels in the unified hub (@@<unified>//<pkg>:pkgetc., the same canonical-name form the concrete hubs use), so they route through--@rules_python//python/config_settings:venvexactly like a plain@pypi//<pkg>label. All of those targets already exist in every unified package (_STANDARD_ALIASES).all_*lists (all_requirements,all_whl_requirements(_by_package),all_data_requirements) are deliberately not generated. They are fixed at loading time, before the venv flag is known, so they could only list one hub's packages and would silently not follow the flag like the rest of the unified hub. Code that wants a whole lock loads them from that concrete hub, and a staleload("@pypi//:requirements.bzl", "all_requirements")fails loudly instead.Before: after renaming
hub_name = "pypi"to e.g."pypi_main"withpip.default(default_hub = "pypi_main"),load("@pypi//:requirements.bzl", ...)fails with "no such file". After, with the opt-in: it keeps working and resolves to the same wheels, and targets can migrate to"@pypi//<pkg>"labels incrementally (we're moving our own repo to labels and gating newrequirement()calls in CI). Without the opt-in nothing changes.Tests:
tests/pypi/extension: the setting is off by default, on when the root module sets it, and ignored from a non-root module.tests/integration/unified_pypi(which now opts in):requirement()with a non-normalized name on the default hub,requirement()under a venv transition, and loading@pypi//:requirements.bzlfailing once the opt-in is removed. Passes onbazel_selfandbazel_7.7.0.Context: we're carrying this as a local patch in a large monorepo, where renaming our main hub and loading
requirementfrom the unified hub leaves the resolved wheel set unchanged. #4172 also touchestests/integration/unified_pypi; the two should merge independently, but one of them may need a trivial rebase.(Done with help from an agent.)
🤖 Generated with Claude Code