diff --git a/python/private/bzlmod/pip.bzl b/python/private/bzlmod/pip.bzl index 2ba275bb0e..9b1ea6d891 100644 --- a/python/private/bzlmod/pip.bzl +++ b/python/private/bzlmod/pip.bzl @@ -427,39 +427,45 @@ def _pip_impl(module_ctx): for mod in module_ctx.modules: for pip_attr in mod.tags.parse: hub_name = pip_attr.hub_name - if hub_name not in pip_hub_map: + # only override if the module is root. + override = mod.is_root and pip_attr.override + if hub_name not in pip_hub_map or override: pip_hub_map[pip_attr.hub_name] = struct( module_name = mod.name, python_versions = [pip_attr.python_version], + pip_attr = pip_attr, + override = override ) - elif pip_hub_map[hub_name].module_name != mod.name: - # We cannot have two hubs with the same name in different - # modules. - fail(( - "Duplicate cross-module pip hub named '{hub}': pip hub " + - "names must be unique across modules. First defined " + - "by module '{first_module}', second attempted by " + - "module '{second_module}'" - ).format( - hub = hub_name, - first_module = pip_hub_map[hub_name].module_name, - second_module = mod.name, - )) - - elif pip_attr.python_version in pip_hub_map[hub_name].python_versions: - fail(( - "Duplicate pip python version '{version}' for hub " + - "'{hub}' in module '{module}': the Python versions " + - "used for a hub must be unique" - ).format( - hub = hub_name, - module = mod.name, - version = pip_attr.python_version, - )) - else: - pip_hub_map[pip_attr.hub_name].python_versions.append(pip_attr.python_version) - - _create_whl_repos(module_ctx, pip_attr, hub_whl_map, whl_overrides, simpleapi_cache) + elif not pip_hub_map[hub_name].pip_attr.override: + if pip_hub_map[hub_name].module_name != mod.name: + # We cannot have two hubs with the same name in different + # modules. + fail(( + "Duplicate cross-module pip hub named '{hub}': pip hub " + + "names must be unique across modules. First defined " + + "by module '{first_module}', second attempted by " + + "module '{second_module}'" + ).format( + hub = hub_name, + first_module = pip_hub_map[hub_name].module_name, + second_module = mod.name, + )) + + elif pip_attr.python_version in pip_hub_map[hub_name].python_versions: + fail(( + "Duplicate pip python version '{version}' for hub " + + "'{hub}' in module '{module}': the Python versions " + + "used for a hub must be unique" + ).format( + hub = hub_name, + module = mod.name, + version = pip_attr.python_version, + )) + else: + pip_hub_map[pip_attr.hub_name].python_versions.append(pip_attr.python_version) + + for value in pip_hub_map.values(): + _create_whl_repos(module_ctx, value.pip_attr, hub_whl_map, whl_overrides, simpleapi_cache) for hub_name, whl_map in hub_whl_map.items(): pip_repository( @@ -557,6 +563,12 @@ A dict of labels to wheel names that is typically generated by the whl_modificat The labels are JSON config files describing the modifications. """, ), + "override": attr.bool( + default = False, + doc = """ +If the module is root, this may override any hub_name's listed in the dependencies. + """ + ), }, **pip_repository_attrs) attrs.update(AUTH_ATTRS)