From 0eaf95074d4f1a1a98c29224f2a6b4b19a7a8b08 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Mon, 9 Nov 2026 23:18:57 +0900 Subject: [PATCH 1/4] refactor(pypi): compute the whl extraction features without rules_python_internal The `patch_whl.bzl` and `whl_extract.bzl` files loaded the `@rules_python_internal` repository only to get the `supports_whl_extraction` and `extract_needs_chmod` values, which only depend on the Bazel version. Compute them from `native.bazel_version` in a new `extract_features` function, which `internal_config_repo` also uses. This allows loading `whl_library` from the files that are loaded before `py_repositories` defines `@rules_python_internal` in WORKSPACE, e.g. `python/repositories.bzl`. --- python/private/BUILD.bazel | 6 +++ python/private/extract_features.bzl | 38 +++++++++++++++++++ python/private/internal_config_repo.bzl | 17 +++------ python/private/pypi/BUILD.bazel | 4 +- python/private/pypi/patch_whl.bzl | 6 +-- python/private/pypi/whl_extract.bzl | 6 +-- tests/extract_features/BUILD.bazel | 3 ++ .../extract_features_tests.bzl | 35 +++++++++++++++++ 8 files changed, 95 insertions(+), 20 deletions(-) create mode 100644 python/private/extract_features.bzl create mode 100644 tests/extract_features/BUILD.bazel create mode 100644 tests/extract_features/extract_features_tests.bzl diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index dc0758efa5..7be464360b 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -410,6 +410,7 @@ bzl_library( name = "internal_config_repo", srcs = ["internal_config_repo.bzl"], deps = [ + ":extract_features", ":repo_utils", ":text_util", ], @@ -975,6 +976,11 @@ bzl_library( srcs = ["envsubst.bzl"], ) +bzl_library( + name = "extract_features", + srcs = ["extract_features.bzl"], +) + bzl_library( name = "full_version", srcs = ["full_version.bzl"], diff --git a/python/private/extract_features.bzl b/python/private/extract_features.bzl new file mode 100644 index 0000000000..8e07c69ed3 --- /dev/null +++ b/python/private/extract_features.bzl @@ -0,0 +1,38 @@ +"""The archive extraction features of the running Bazel version. + +This only uses `native.bazel_version`, so that the repository rules can use it +without loading the `@rules_python_internal` repository, which may not be +defined yet when the WORKSPACE macros are loaded. +""" + +def _major_minor(bazel_version): + # An empty version signifies a development build, which is treated as + # the latest version. + if not bazel_version: + return 99999, 99999 + + parts = bazel_version.split(".") + return int(parts[0]), int(parts[1]) + +def extract_features(bazel_version = None): + """Return the archive extraction features of the Bazel version. + + Args: + bazel_version: {type}`str | None` the Bazel version, defaults to + `native.bazel_version`. + + Returns: + {type}`struct` with: + * `supports_whl_extraction`: {type}`bool` whether `.whl` files can + be extracted, which requires Bazel 8.3.0 or later. + * `extract_needs_chmod`: {type}`bool` whether the extracted files need + their permissions fixed, which is the case before Bazel 8.6.0. + """ + if bazel_version == None: + bazel_version = native.bazel_version + + major, minor = _major_minor(bazel_version) + return struct( + supports_whl_extraction = major > 8 or (major == 8 and minor >= 3), + extract_needs_chmod = major < 8 or (major == 8 and minor < 6), + ) diff --git a/python/private/internal_config_repo.bzl b/python/private/internal_config_repo.bzl index 8f203bb89e..762160c839 100644 --- a/python/private/internal_config_repo.bzl +++ b/python/private/internal_config_repo.bzl @@ -18,6 +18,7 @@ such as globals available to Bazel versions, or propagating user environment settings for rules to later use. """ +load("//python/private:extract_features.bzl", "extract_features") load("//python/private:text_util.bzl", "render") load(":repo_utils.bzl", "repo_utils") @@ -81,20 +82,12 @@ def _internal_config_repo_impl(rctx): # An empty version signifies a development build, which is treated as # the latest version. if native.bazel_version: - version_parts = native.bazel_version.split(".") - bazel_major_version = int(version_parts[0]) - bazel_minor_version = int(version_parts[1]) + bazel_major_version = int(native.bazel_version.split(".")[0]) else: bazel_major_version = 99999 - bazel_minor_version = 99999 - supports_whl_extraction = False - extract_needs_chmod = bazel_major_version < 8 or (bazel_major_version == 8 and bazel_minor_version < 6) + features = extract_features() if bazel_major_version >= 8: - # Extracting .whl files requires Bazel 8.3.0 or later. - if bazel_major_version > 8 or bazel_minor_version >= 3: - supports_whl_extraction = True - builtin_py_info_symbol = "None" builtin_py_runtime_info_symbol = "None" builtin_py_cc_link_params_provider = "None" @@ -109,8 +102,8 @@ def _internal_config_repo_impl(rctx): enable_deprecation_warnings = _bool_from_environ(rctx, _ENABLE_DEPRECATION_WARNINGS_ENVVAR_NAME, _ENABLE_DEPRECATION_WARNINGS_DEFAULT), builtin_py_info_symbol = builtin_py_info_symbol, builtin_py_runtime_info_symbol = builtin_py_runtime_info_symbol, - supports_whl_extraction = str(supports_whl_extraction), - extract_needs_chmod = str(extract_needs_chmod), + supports_whl_extraction = str(features.supports_whl_extraction), + extract_needs_chmod = str(features.extract_needs_chmod), builtin_py_cc_link_params_provider = builtin_py_cc_link_params_provider, modules_using_explicit_initpy = str(explicit_init_py_modules), tool_deps_dev_only = str(rctx.attr.tool_deps_dev_only), diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index f94d24594f..e841b6893f 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -265,8 +265,8 @@ bzl_library( srcs = ["patch_whl.bzl"], deps = [ ":parse_whl_name", + "//python/private:extract_features", "//python/private:repo_utils", - "@rules_python_internal//:rules_python_config", ], ) @@ -475,8 +475,8 @@ bzl_library( srcs = ["whl_extract.bzl"], deps = [ ":whl_metadata", + "//python/private:extract_features", "//python/private:repo_utils", - "@rules_python_internal//:rules_python_config", ], ) diff --git a/python/private/pypi/patch_whl.bzl b/python/private/pypi/patch_whl.bzl index b257f2b4fe..fea1421150 100644 --- a/python/private/pypi/patch_whl.bzl +++ b/python/private/pypi/patch_whl.bzl @@ -19,7 +19,7 @@ repack patched wheels. Instead, after extracting and patching, we fix the RECORD file natively in Starlark and repack using system zip. """ -load("@rules_python_internal//:rules_python_config.bzl", rp_config = "config") +load("//python/private:extract_features.bzl", "extract_features") load("//python/private:repo_utils.bzl", "repo_utils") load(":parse_whl_name.bzl", "parse_whl_name") @@ -96,8 +96,8 @@ def patch_whl(rctx, *, whl_path, patches): repo_utils.extract( rctx, archive = whl_input, - supports_whl_extraction = rp_config.supports_whl_extraction, - extract_needs_chmod = rp_config.extract_needs_chmod, + supports_whl_extraction = extract_features().supports_whl_extraction, + extract_needs_chmod = extract_features().extract_needs_chmod, ) if not patches: diff --git a/python/private/pypi/whl_extract.bzl b/python/private/pypi/whl_extract.bzl index d7195fd681..a7a8d58dd5 100644 --- a/python/private/pypi/whl_extract.bzl +++ b/python/private/pypi/whl_extract.bzl @@ -1,6 +1,6 @@ """A simple whl extractor.""" -load("@rules_python_internal//:rules_python_config.bzl", rp_config = "config") +load("//python/private:extract_features.bzl", "extract_features") load("//python/private:repo_utils.bzl", "repo_utils") load(":whl_metadata.bzl", "find_whl_metadata") @@ -32,8 +32,8 @@ def whl_extract(rctx, *, whl_path, logger): rctx, archive = whl_path, output = install_dir_path, - supports_whl_extraction = rp_config.supports_whl_extraction, - extract_needs_chmod = rp_config.extract_needs_chmod, + supports_whl_extraction = extract_features().supports_whl_extraction, + extract_needs_chmod = extract_features().extract_needs_chmod, ) metadata_file = find_whl_metadata( diff --git a/tests/extract_features/BUILD.bazel b/tests/extract_features/BUILD.bazel new file mode 100644 index 0000000000..9b2fc599b3 --- /dev/null +++ b/tests/extract_features/BUILD.bazel @@ -0,0 +1,3 @@ +load(":extract_features_tests.bzl", "extract_features_test_suite") + +extract_features_test_suite(name = "extract_features_tests") diff --git a/tests/extract_features/extract_features_tests.bzl b/tests/extract_features/extract_features_tests.bzl new file mode 100644 index 0000000000..0a8c66cb75 --- /dev/null +++ b/tests/extract_features/extract_features_tests.bzl @@ -0,0 +1,35 @@ +"""Tests for the archive extraction features of the Bazel versions.""" + +load("@rules_testing//lib:test_suite.bzl", "test_suite") +load("//python/private:extract_features.bzl", "extract_features") # buildifier: disable=bzl-visibility + +_tests = [] + +def _test_extract_features(env): + for bazel_version, (supports_whl_extraction, extract_needs_chmod) in { + # A development build is treated as the latest version. + "": (True, False), + "7.4.1": (False, True), + "8.2.1": (False, True), + "8.3.0": (True, True), + "8.5.1": (True, True), + "8.6.0": (True, False), + "9.1.1": (True, False), + }.items(): + got = extract_features(bazel_version) + env.expect.where(bazel_version = bazel_version).that_bool( + got.supports_whl_extraction, + ).equals(supports_whl_extraction) + env.expect.where(bazel_version = bazel_version).that_bool( + got.extract_needs_chmod, + ).equals(extract_needs_chmod) + +_tests.append(_test_extract_features) + +def extract_features_test_suite(name): + """Create the test suite. + + Args: + name: the name of the test suite + """ + test_suite(name = name, basic_tests = _tests) From 4a55555032bee7308d94dfb3f97326025448617a Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Mon, 9 Nov 2026 23:24:55 +0900 Subject: [PATCH 2/4] refactor(pypi): do not load bazel_skylib from the whl_library load chain The `pypi_repo_utils.bzl` and `util.bzl` files only used `types.is_string` and `types.is_tuple` from `@bazel_skylib`, which are simple `type()` checks. Without them, `whl_library` can be loaded from the files that are loaded before the `WORKSPACE` defines `@bazel_skylib`, e.g. `python/repositories.bzl`. --- python/private/BUILD.bazel | 5 +---- python/private/pypi/BUILD.bazel | 1 - python/private/pypi/pypi_repo_utils.bzl | 3 +-- python/private/util.bzl | 3 +-- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index 7be464360b..f79c433074 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -908,10 +908,7 @@ bzl_library( bzl_library( name = "util", srcs = ["util.bzl"], - deps = [ - ":py_internal", - "@bazel_skylib//lib:types", - ], + deps = [":py_internal"], ) bzl_library( diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index e841b6893f..3a920c6bce 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -371,7 +371,6 @@ bzl_library( deps = [ "//python/private:repo_utils", "//python/private:util", - "@bazel_skylib//lib:types", ], ) diff --git a/python/private/pypi/pypi_repo_utils.bzl b/python/private/pypi/pypi_repo_utils.bzl index 8ec7bd1dbe..d9a074ca96 100644 --- a/python/private/pypi/pypi_repo_utils.bzl +++ b/python/private/pypi/pypi_repo_utils.bzl @@ -14,7 +14,6 @@ "" -load("@bazel_skylib//lib:types.bzl", "types") load("//python/private:repo_utils.bzl", "repo_utils") load("//python/private:util.bzl", "is_importable_name") @@ -113,7 +112,7 @@ def _execute_prep(mrctx, *, python, srcs, **kwargs): environment = kwargs.pop("environment", {}) pythonpath = environment.get("PYTHONPATH", "") - if pythonpath and not types.is_string(pythonpath): + if pythonpath and type(pythonpath) != "string": environment["PYTHONPATH"] = _construct_pypath(mrctx, entries = pythonpath) kwargs["environment"] = environment diff --git a/python/private/util.bzl b/python/private/util.bzl index 31f317fedf..575f27c1ae 100644 --- a/python/private/util.bzl +++ b/python/private/util.bzl @@ -14,7 +14,6 @@ """Functionality shared by multiple pieces of code.""" -load("@bazel_skylib//lib:types.bzl", "types") load("//python/private:py_internal.bzl", "py_internal") def copy_propagating_kwargs(from_kwargs, into_kwargs = None): @@ -62,7 +61,7 @@ def add_tag(attrs, tag): # Preserve the input type: this allows a test verifying the underlying # rule can accept the tuple for the tags argument. - if types.is_tuple(tags): + if type(tags) == "tuple": attrs["tags"] = tags + (tag,) else: # List concatenation is necessary because the original value From 98aa18483bad82a0534a96d957c5c0b4b372ae4b Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Mon, 9 Nov 2026 23:34:21 +0900 Subject: [PATCH 3/4] refactor: add bazel_features to //python:features.bzl Replace the private `extract_features` function with a public `bazel_features(bazel_version)` function in `//python:features.bzl`, which returns the features of a Bazel version, e.g. `bazel_features(native.bazel_version).supports_whl_extraction`. The Bazel version is only available when a repository rule or a module extension runs, so this is a function and not fields of the `features` struct. The values are no longer written to the `@rules_python_internal` config, as nothing reads them from there anymore. --- python/features.bzl | 39 +++++++++++++++++++ python/private/BUILD.bazel | 6 --- python/private/extract_features.bzl | 38 ------------------ python/private/internal_config_repo.bzl | 6 --- python/private/pypi/BUILD.bazel | 4 +- python/private/pypi/patch_whl.bzl | 6 +-- python/private/pypi/whl_extract.bzl | 6 +-- tests/bazel_features/BUILD.bazel | 3 ++ .../bazel_features_tests.bzl} | 12 +++--- tests/extract_features/BUILD.bazel | 3 -- 10 files changed, 56 insertions(+), 67 deletions(-) delete mode 100644 python/private/extract_features.bzl create mode 100644 tests/bazel_features/BUILD.bazel rename tests/{extract_features/extract_features_tests.bzl => bazel_features/bazel_features_tests.bzl} (72%) delete mode 100644 tests/extract_features/BUILD.bazel diff --git a/python/features.bzl b/python/features.bzl index 99050a7ca5..8e295ec747 100644 --- a/python/features.bzl +++ b/python/features.bzl @@ -148,6 +148,45 @@ _LOADABLE_SYMBOLS = { ], } +def _major_minor(bazel_version): + # An empty version signifies a development build, which is treated as + # the latest version. + if not bazel_version: + return 99999, 99999 + + parts = bazel_version.split(".") + return int(parts[0]), int(parts[1]) + +def bazel_features(bazel_version): + """Return the features of a Bazel version that `rules_python` uses. + + The Bazel version is only available when a repository rule or a module + extension runs, so this is a function instead of fields of {obj}`features`, + e.g. `bazel_features(native.bazel_version).supports_whl_extraction`. + + :::{versionadded} VERSION_NEXT_FEATURE + ::: + + Args: + bazel_version: {type}`str` the Bazel version, e.g. + `native.bazel_version`. An empty string is a development build, + which is treated as the latest version. + + Returns: + {type}`struct` with: + * `supports_whl_extraction`: {type}`bool` whether + `repository_ctx.extract` can extract `.whl` files, which requires + Bazel 8.3.0 or later. + * `extract_needs_chmod`: {type}`bool` whether the files extracted by + `repository_ctx.extract` need their permissions fixed, which is the + case before Bazel 8.6.0. + """ + major, minor = _major_minor(bazel_version) + return struct( + supports_whl_extraction = major > 8 or (major == 8 and minor >= 3), + extract_needs_chmod = major < 8 or (major == 8 and minor < 6), + ) + features = struct( TYPEDEF = _features_typedef, # keep sorted diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index f79c433074..1cdd28a847 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -410,7 +410,6 @@ bzl_library( name = "internal_config_repo", srcs = ["internal_config_repo.bzl"], deps = [ - ":extract_features", ":repo_utils", ":text_util", ], @@ -973,11 +972,6 @@ bzl_library( srcs = ["envsubst.bzl"], ) -bzl_library( - name = "extract_features", - srcs = ["extract_features.bzl"], -) - bzl_library( name = "full_version", srcs = ["full_version.bzl"], diff --git a/python/private/extract_features.bzl b/python/private/extract_features.bzl deleted file mode 100644 index 8e07c69ed3..0000000000 --- a/python/private/extract_features.bzl +++ /dev/null @@ -1,38 +0,0 @@ -"""The archive extraction features of the running Bazel version. - -This only uses `native.bazel_version`, so that the repository rules can use it -without loading the `@rules_python_internal` repository, which may not be -defined yet when the WORKSPACE macros are loaded. -""" - -def _major_minor(bazel_version): - # An empty version signifies a development build, which is treated as - # the latest version. - if not bazel_version: - return 99999, 99999 - - parts = bazel_version.split(".") - return int(parts[0]), int(parts[1]) - -def extract_features(bazel_version = None): - """Return the archive extraction features of the Bazel version. - - Args: - bazel_version: {type}`str | None` the Bazel version, defaults to - `native.bazel_version`. - - Returns: - {type}`struct` with: - * `supports_whl_extraction`: {type}`bool` whether `.whl` files can - be extracted, which requires Bazel 8.3.0 or later. - * `extract_needs_chmod`: {type}`bool` whether the extracted files need - their permissions fixed, which is the case before Bazel 8.6.0. - """ - if bazel_version == None: - bazel_version = native.bazel_version - - major, minor = _major_minor(bazel_version) - return struct( - supports_whl_extraction = major > 8 or (major == 8 and minor >= 3), - extract_needs_chmod = major < 8 or (major == 8 and minor < 6), - ) diff --git a/python/private/internal_config_repo.bzl b/python/private/internal_config_repo.bzl index 762160c839..620be5b4d1 100644 --- a/python/private/internal_config_repo.bzl +++ b/python/private/internal_config_repo.bzl @@ -18,7 +18,6 @@ such as globals available to Bazel versions, or propagating user environment settings for rules to later use. """ -load("//python/private:extract_features.bzl", "extract_features") load("//python/private:text_util.bzl", "render") load(":repo_utils.bzl", "repo_utils") @@ -28,10 +27,8 @@ _ENABLE_DEPRECATION_WARNINGS_DEFAULT = "0" _CONFIG_TEMPLATE = """ config = struct( build_python_zip_default = {build_python_zip_default}, - supports_whl_extraction = {supports_whl_extraction}, enable_pystar = True, enable_deprecation_warnings = {enable_deprecation_warnings}, - extract_needs_chmod = {extract_needs_chmod}, bazel_8_or_later = {bazel_8_or_later}, bazel_9_or_later = {bazel_9_or_later}, bazel_10_or_later = {bazel_10_or_later}, @@ -86,7 +83,6 @@ def _internal_config_repo_impl(rctx): else: bazel_major_version = 99999 - features = extract_features() if bazel_major_version >= 8: builtin_py_info_symbol = "None" builtin_py_runtime_info_symbol = "None" @@ -102,8 +98,6 @@ def _internal_config_repo_impl(rctx): enable_deprecation_warnings = _bool_from_environ(rctx, _ENABLE_DEPRECATION_WARNINGS_ENVVAR_NAME, _ENABLE_DEPRECATION_WARNINGS_DEFAULT), builtin_py_info_symbol = builtin_py_info_symbol, builtin_py_runtime_info_symbol = builtin_py_runtime_info_symbol, - supports_whl_extraction = str(features.supports_whl_extraction), - extract_needs_chmod = str(features.extract_needs_chmod), builtin_py_cc_link_params_provider = builtin_py_cc_link_params_provider, modules_using_explicit_initpy = str(explicit_init_py_modules), tool_deps_dev_only = str(rctx.attr.tool_deps_dev_only), diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index 3a920c6bce..eece782ef3 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -265,7 +265,7 @@ bzl_library( srcs = ["patch_whl.bzl"], deps = [ ":parse_whl_name", - "//python/private:extract_features", + "//python:features", "//python/private:repo_utils", ], ) @@ -474,7 +474,7 @@ bzl_library( srcs = ["whl_extract.bzl"], deps = [ ":whl_metadata", - "//python/private:extract_features", + "//python:features", "//python/private:repo_utils", ], ) diff --git a/python/private/pypi/patch_whl.bzl b/python/private/pypi/patch_whl.bzl index fea1421150..f8c01f94b7 100644 --- a/python/private/pypi/patch_whl.bzl +++ b/python/private/pypi/patch_whl.bzl @@ -19,7 +19,7 @@ repack patched wheels. Instead, after extracting and patching, we fix the RECORD file natively in Starlark and repack using system zip. """ -load("//python/private:extract_features.bzl", "extract_features") +load("//python:features.bzl", "bazel_features") load("//python/private:repo_utils.bzl", "repo_utils") load(":parse_whl_name.bzl", "parse_whl_name") @@ -96,8 +96,8 @@ def patch_whl(rctx, *, whl_path, patches): repo_utils.extract( rctx, archive = whl_input, - supports_whl_extraction = extract_features().supports_whl_extraction, - extract_needs_chmod = extract_features().extract_needs_chmod, + supports_whl_extraction = bazel_features(native.bazel_version).supports_whl_extraction, + extract_needs_chmod = bazel_features(native.bazel_version).extract_needs_chmod, ) if not patches: diff --git a/python/private/pypi/whl_extract.bzl b/python/private/pypi/whl_extract.bzl index a7a8d58dd5..c2b4a1a19b 100644 --- a/python/private/pypi/whl_extract.bzl +++ b/python/private/pypi/whl_extract.bzl @@ -1,6 +1,6 @@ """A simple whl extractor.""" -load("//python/private:extract_features.bzl", "extract_features") +load("//python:features.bzl", "bazel_features") load("//python/private:repo_utils.bzl", "repo_utils") load(":whl_metadata.bzl", "find_whl_metadata") @@ -32,8 +32,8 @@ def whl_extract(rctx, *, whl_path, logger): rctx, archive = whl_path, output = install_dir_path, - supports_whl_extraction = extract_features().supports_whl_extraction, - extract_needs_chmod = extract_features().extract_needs_chmod, + supports_whl_extraction = bazel_features(native.bazel_version).supports_whl_extraction, + extract_needs_chmod = bazel_features(native.bazel_version).extract_needs_chmod, ) metadata_file = find_whl_metadata( diff --git a/tests/bazel_features/BUILD.bazel b/tests/bazel_features/BUILD.bazel new file mode 100644 index 0000000000..2af882e20d --- /dev/null +++ b/tests/bazel_features/BUILD.bazel @@ -0,0 +1,3 @@ +load(":bazel_features_tests.bzl", "bazel_features_test_suite") + +bazel_features_test_suite(name = "bazel_features_tests") diff --git a/tests/extract_features/extract_features_tests.bzl b/tests/bazel_features/bazel_features_tests.bzl similarity index 72% rename from tests/extract_features/extract_features_tests.bzl rename to tests/bazel_features/bazel_features_tests.bzl index 0a8c66cb75..f452d65817 100644 --- a/tests/extract_features/extract_features_tests.bzl +++ b/tests/bazel_features/bazel_features_tests.bzl @@ -1,11 +1,11 @@ -"""Tests for the archive extraction features of the Bazel versions.""" +"""Tests for the features of the Bazel versions.""" load("@rules_testing//lib:test_suite.bzl", "test_suite") -load("//python/private:extract_features.bzl", "extract_features") # buildifier: disable=bzl-visibility +load("//python:features.bzl", "bazel_features") _tests = [] -def _test_extract_features(env): +def _test_bazel_features(env): for bazel_version, (supports_whl_extraction, extract_needs_chmod) in { # A development build is treated as the latest version. "": (True, False), @@ -16,7 +16,7 @@ def _test_extract_features(env): "8.6.0": (True, False), "9.1.1": (True, False), }.items(): - got = extract_features(bazel_version) + got = bazel_features(bazel_version) env.expect.where(bazel_version = bazel_version).that_bool( got.supports_whl_extraction, ).equals(supports_whl_extraction) @@ -24,9 +24,9 @@ def _test_extract_features(env): got.extract_needs_chmod, ).equals(extract_needs_chmod) -_tests.append(_test_extract_features) +_tests.append(_test_bazel_features) -def extract_features_test_suite(name): +def bazel_features_test_suite(name): """Create the test suite. Args: diff --git a/tests/extract_features/BUILD.bazel b/tests/extract_features/BUILD.bazel deleted file mode 100644 index 9b2fc599b3..0000000000 --- a/tests/extract_features/BUILD.bazel +++ /dev/null @@ -1,3 +0,0 @@ -load(":extract_features_tests.bzl", "extract_features_test_suite") - -extract_features_test_suite(name = "extract_features_tests") From 0bb36ad6805cdc6b0dec9366d20fdf97c66ccecd Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Mon, 9 Nov 2026 23:34:57 +0900 Subject: [PATCH 4/4] chore: explain why the skylib types helpers are not used --- python/private/pypi/pypi_repo_utils.bzl | 4 ++++ python/private/util.bzl | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/python/private/pypi/pypi_repo_utils.bzl b/python/private/pypi/pypi_repo_utils.bzl index d9a074ca96..d8ad340340 100644 --- a/python/private/pypi/pypi_repo_utils.bzl +++ b/python/private/pypi/pypi_repo_utils.bzl @@ -112,6 +112,10 @@ def _execute_prep(mrctx, *, python, srcs, **kwargs): environment = kwargs.pop("environment", {}) pythonpath = environment.get("PYTHONPATH", "") + + # NOTE: `types.is_string` from `@bazel_skylib` is not used, so that this + # file can be loaded before the `WORKSPACE` defines `@bazel_skylib`, e.g. + # via `whl_library` from `python/repositories.bzl`. if pythonpath and type(pythonpath) != "string": environment["PYTHONPATH"] = _construct_pypath(mrctx, entries = pythonpath) kwargs["environment"] = environment diff --git a/python/private/util.bzl b/python/private/util.bzl index 575f27c1ae..e96bd569e9 100644 --- a/python/private/util.bzl +++ b/python/private/util.bzl @@ -61,6 +61,10 @@ def add_tag(attrs, tag): # Preserve the input type: this allows a test verifying the underlying # rule can accept the tuple for the tags argument. + # NOTE: `types.is_tuple` from `@bazel_skylib` is not used, so that + # this file can be loaded before the `WORKSPACE` defines + # `@bazel_skylib`, e.g. via `whl_library` from + # `python/repositories.bzl`. if type(tags) == "tuple": attrs["tags"] = tags + (tag,) else: