From 65e3c977dc7b0e1117c27485a5e91a9169ec6a7f Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Fri, 24 Apr 2026 23:54:16 +0900 Subject: [PATCH] chore(entry_point): remove all repository_rule entry_point code and docs Fixes #3642 --- examples/pip_parse/BUILD.bazel | 3 - .../pypi/generate_whl_library_build_bazel.bzl | 13 --- python/private/pypi/labels.bzl | 1 - python/private/pypi/pip_repository.bzl | 24 ------ python/private/pypi/whl_library.bzl | 79 ------------------- python/private/pypi/whl_library_targets.bzl | 18 ----- python/private/pypi/whl_metadata.bzl | 58 +------------- ...generate_whl_library_build_bazel_tests.bzl | 44 ----------- .../whl_library_targets_tests.bzl | 30 ------- .../pypi/whl_metadata/whl_metadata_tests.bzl | 49 ------------ 10 files changed, 2 insertions(+), 317 deletions(-) diff --git a/examples/pip_parse/BUILD.bazel b/examples/pip_parse/BUILD.bazel index 37a25fe873..2dc9d61127 100644 --- a/examples/pip_parse/BUILD.bazel +++ b/examples/pip_parse/BUILD.bazel @@ -45,9 +45,6 @@ py_test( deps = [":main"], ) -# For pip dependencies which have entry points, the `entry_point` macro can be -# used from the generated `pip_parse` repository to access a runnable binary. - py_console_script_binary( name = "yamllint", pkg = "@pypi//yamllint", diff --git a/python/private/pypi/generate_whl_library_build_bazel.bzl b/python/private/pypi/generate_whl_library_build_bazel.bzl index fbabe2ede3..5811ed1574 100644 --- a/python/private/pypi/generate_whl_library_build_bazel.bzl +++ b/python/private/pypi/generate_whl_library_build_bazel.bzl @@ -23,7 +23,6 @@ _RENDER = { "data_exclude": render.list, "dependencies": render.list, "dependencies_by_platform": lambda x: render.dict(x, value_repr = render.list), - "entry_points": render.dict, "extras": render.list, "group_deps": render.list, "include": str, @@ -100,18 +99,6 @@ def generate_whl_library_build_bazel( ]) additional_content = [] - entry_points = kwargs.get("entry_points") - if entry_points: - entry_point_files = sorted({ - entry_point_script.replace("\\", "/"): True - for entry_point_script in entry_points.values() - }.keys()) - additional_content.append( - "exports_files(\n" + - " srcs = {},\n".format(render.list(entry_point_files)) + - " visibility = [\"//visibility:public\"],\n" + - ")\n", - ) if annotation: kwargs["data"] = annotation.data kwargs["copy_files"] = annotation.copy_files diff --git a/python/private/pypi/labels.bzl b/python/private/pypi/labels.bzl index 22161b1496..8f91a03b4c 100644 --- a/python/private/pypi/labels.bzl +++ b/python/private/pypi/labels.bzl @@ -21,5 +21,4 @@ PY_LIBRARY_PUBLIC_LABEL = "pkg" PY_LIBRARY_IMPL_LABEL = "_pkg" DATA_LABEL = "data" DIST_INFO_LABEL = "dist_info" -WHEEL_ENTRY_POINT_PREFIX = "rules_python_wheel_entry_point" NODEPS_LABEL = "no_deps" diff --git a/python/private/pypi/pip_repository.bzl b/python/private/pypi/pip_repository.bzl index 6d38334cc6..4560bd7eef 100644 --- a/python/private/pypi/pip_repository.bzl +++ b/python/private/pypi/pip_repository.bzl @@ -348,30 +348,6 @@ functionality for exposing [entry points][whl_ep] as `py_binary` targets as well [whl_ep]: https://packaging.python.org/specifications/entry-points/ -```starlark -load("@pypi//:requirements.bzl", "entry_point") - -alias( - name = "pip-compile", - actual = entry_point( - pkg = "pip-tools", - script = "pip-compile", - ), -) -``` - -Note that for packages whose name and script are the same, only the name of the package -is needed when calling the `entry_point` macro. - -```starlark -load("@pip//:requirements.bzl", "entry_point") - -alias( - name = "flake8", - actual = entry_point("flake8"), -) -``` - :::{rubric} Vendoring the requirements.bzl file :heading-level: 3 ::: diff --git a/python/private/pypi/whl_library.bzl b/python/private/pypi/whl_library.bzl index 3586494dc2..bd76741fa3 100644 --- a/python/private/pypi/whl_library.bzl +++ b/python/private/pypi/whl_library.bzl @@ -33,7 +33,6 @@ load(":whl_target_platforms.bzl", "whl_target_platforms") _CPPFLAGS = "CPPFLAGS" _COMMAND_LINE_TOOLS_PATH_SLUG = "commandlinetools" -_WHEEL_ENTRY_POINT_PREFIX = "rules_python_wheel_entry_point" def _get_xcode_location_cflags(rctx, logger = None): """Query the xcode sdk location to update cflags @@ -443,30 +442,6 @@ def _whl_library_impl(rctx): ) namespace_package_files = pypi_repo_utils.find_namespace_package_files(rctx, install_dir_path) - # NOTE @aignas 2024-06-22: this has to live on until we stop supporting - # passing `twine` as a `:pkg` library via the `WORKSPACE` builds. - # - # See ../../packaging.bzl line 190 - entry_points = {} - for item in metadata.entry_points: - name = item.name - module = item.module - attribute = item.attribute - - # There is an extreme edge-case with entry_points that end with `.py` - # See: https://github.com/bazelbuild/bazel/blob/09c621e4cf5b968f4c6cdf905ab142d5961f9ddc/src/test/java/com/google/devtools/build/lib/rules/python/PyBinaryConfiguredTargetTest.java#L174 - entry_point_without_py = name[:-3] + "_py" if name.endswith(".py") else name - entry_point_target_name = ( - _WHEEL_ENTRY_POINT_PREFIX + "_" + entry_point_without_py - ) - entry_point_script_name = entry_point_target_name + ".py" - - rctx.file( - entry_point_script_name, - _generate_entry_point_contents(module, attribute), - ) - entry_points[entry_point_without_py] = entry_point_script_name - build_file_contents = generate_whl_library_build_bazel( name = whl_path.basename, sdist_filename = sdist_filename, @@ -474,7 +449,6 @@ def _whl_library_impl(rctx): rctx.attr.repo_prefix, ), config_load = rctx.attr.config_load, - entry_points = entry_points, metadata_name = metadata.name, metadata_version = metadata.version, requires_dist = metadata.requires_dist, @@ -492,37 +466,12 @@ def _whl_library_impl(rctx): metadata = json.decode(rctx.read("metadata.json")) rctx.delete("metadata.json") - # NOTE @aignas 2024-06-22: this has to live on until we stop supporting - # passing `twine` as a `:pkg` library via the `WORKSPACE` builds. - # - # See ../../packaging.bzl line 190 - entry_points = {} - for item in metadata["entry_points"]: - name = item["name"] - module = item["module"] - attribute = item["attribute"] - - # There is an extreme edge-case with entry_points that end with `.py` - # See: https://github.com/bazelbuild/bazel/blob/09c621e4cf5b968f4c6cdf905ab142d5961f9ddc/src/test/java/com/google/devtools/build/lib/rules/python/PyBinaryConfiguredTargetTest.java#L174 - entry_point_without_py = name[:-3] + "_py" if name.endswith(".py") else name - entry_point_target_name = ( - _WHEEL_ENTRY_POINT_PREFIX + "_" + entry_point_without_py - ) - entry_point_script_name = entry_point_target_name + ".py" - - rctx.file( - entry_point_script_name, - _generate_entry_point_contents(module, attribute), - ) - entry_points[entry_point_without_py] = entry_point_script_name - namespace_package_files = pypi_repo_utils.find_namespace_package_files(rctx, rctx.path("site-packages")) build_file_contents = generate_whl_library_build_bazel( name = whl_path.basename, sdist_filename = sdist_filename, dep_template = rctx.attr.dep_template or "@{}{{name}}//:{{target}}".format(rctx.attr.repo_prefix), - entry_points = entry_points, # TODO @aignas 2025-05-17: maybe have a build flag for this instead enable_implicit_namespace_pkgs = rctx.attr.enable_implicit_namespace_pkgs, # TODO @aignas 2025-04-14: load through the hub: @@ -568,34 +517,6 @@ def _remove_files(rctx, *basenames): elif path.is_dir: paths.extend(path.readdir()) -def _generate_entry_point_contents( - module, - attribute, - shebang = "#!/usr/bin/env python3"): - """Generate the contents of an entry point script. - - Args: - module (str): The name of the module to use. - attribute (str): The name of the attribute to call. - shebang (str, optional): The shebang to use for the entry point python - file. - - Returns: - str: A string of python code. - """ - contents = """\ -{shebang} -import sys -from {module} import {attribute} -if __name__ == "__main__": - sys.exit({attribute}()) -""".format( - shebang = shebang, - module = module, - attribute = attribute, - ) - return contents - # NOTE @aignas 2024-03-21: The usage of dict({}, **common) ensures that all args to `dict` are unique whl_library_attrs = dict({ "annotation": attr.label( diff --git a/python/private/pypi/whl_library_targets.bzl b/python/private/pypi/whl_library_targets.bzl index dc99aab532..dde5f815eb 100644 --- a/python/private/pypi/whl_library_targets.bzl +++ b/python/private/pypi/whl_library_targets.bzl @@ -26,7 +26,6 @@ load( "EXTRACTED_WHEEL_FILES", "PY_LIBRARY_IMPL_LABEL", "PY_LIBRARY_PUBLIC_LABEL", - "WHEEL_ENTRY_POINT_PREFIX", "WHEEL_FILE_IMPL_LABEL", "WHEEL_FILE_PUBLIC_LABEL", ) @@ -120,7 +119,6 @@ def whl_library_targets( data = [], copy_files = {}, copy_executables = {}, - entry_points = {}, native = native, enable_implicit_namespace_pkgs = False, namespace_package_files = [], @@ -165,8 +163,6 @@ def whl_library_targets( srcs_exclude: {type}`list[str]` The globs for srcs attribute exclusion in `py_library`. data: {type}`list[str]` A list of labels to include as part of the `data` attribute in `py_library`. - entry_points: {type}`dict[str, str]` The mapping between the script - name and the python file to use. DEPRECATED. enable_implicit_namespace_pkgs: {type}`boolean` generate __init__.py files for namespace pkgs. native: {type}`native` The native struct for overriding in tests. @@ -237,20 +233,6 @@ def whl_library_targets( for d in dependencies_with_markers } - # TODO @aignas 2024-10-25: remove the entry_point generation once - # `py_console_script_binary` is the only way to use entry points. - for entry_point, entry_point_script_name in entry_points.items(): - rules.py_binary( - name = "{}_{}".format(WHEEL_ENTRY_POINT_PREFIX, entry_point), - # Ensure that this works on Windows as well - script may have Windows path separators. - srcs = [entry_point_script_name.replace("\\", "/")], - # This makes this directory a top-level in the python import - # search path for anything that depends on this. - imports = ["."], - deps = [":" + PY_LIBRARY_PUBLIC_LABEL], - visibility = ["//visibility:public"], - ) - # Ensure this list is normalized # Note: mapping used as set group_deps = { diff --git a/python/private/pypi/whl_metadata.bzl b/python/private/pypi/whl_metadata.bzl index 0d3a14ab54..002e5773cc 100644 --- a/python/private/pypi/whl_metadata.bzl +++ b/python/private/pypi/whl_metadata.bzl @@ -4,7 +4,6 @@ _NAME = "Name: " _PROVIDES_EXTRA = "Provides-Extra: " _REQUIRES_DIST = "Requires-Dist: " _VERSION = "Version: " -_CONSOLE_SCRIPTS = "[console_scripts]" def whl_metadata(*, install_dir, read_fn, logger): """Find and parse the METADATA file in the extracted whl contents dir. @@ -24,13 +23,8 @@ def whl_metadata(*, install_dir, read_fn, logger): """ metadata_file = find_whl_metadata(install_dir = install_dir, logger = logger) contents = read_fn(metadata_file) - entry_points_file = metadata_file.dirname.get_child("entry_points.txt") - if entry_points_file.exists: - entry_points_contents = read_fn(entry_points_file) - else: - entry_points_contents = "" - result = parse_whl_metadata(contents, entry_points_contents) + result = parse_whl_metadata(contents) if not (result.name and result.version): logger.fail("Failed to parse the wheel METADATA file:\n{}\n{}\n{}".format( @@ -42,12 +36,11 @@ def whl_metadata(*, install_dir, read_fn, logger): return result -def parse_whl_metadata(contents, entry_points_contents = ""): +def parse_whl_metadata(contents): """Parse .whl METADATA file Args: contents: {type}`str` the contents of the file. - entry_points_contents: {type}`str` the contents of the `entry_points.txt` file if it exists. Returns: A struct with parsed values: @@ -56,8 +49,6 @@ def parse_whl_metadata(contents, entry_points_contents = ""): * `requires_dist`: {type}`list[str]` the list of requirements. * `provides_extra`: {type}`list[str]` the list of extras that this package provides. - * `entry_points`: {type}`list[struct]` the list of - entry_point metadata. """ parsed = { "name": "", @@ -89,7 +80,6 @@ def parse_whl_metadata(contents, entry_points_contents = ""): provides_extra = parsed["provides_extra"], requires_dist = parsed["requires_dist"], version = parsed["version"], - entry_points = _parse_entry_points(entry_points_contents), ) def find_whl_metadata(*, install_dir, logger): @@ -121,47 +111,3 @@ def find_whl_metadata(*, install_dir, logger): else: logger.fail("The '*.dist-info' directory could not be found in '{}'".format(install_dir.basename)) return None - -def _parse_entry_points(contents): - """parse the entry_points.txt file. - - Args: - contents: {type}`str` The contents of the file - - Returns: - A list of console_script entry point metadata. - """ - start = False - ret = [] - for line in contents.split("\n"): - line = line.rstrip() - - if line == _CONSOLE_SCRIPTS: - start = True - continue - - if not start: - continue - - if start and line.startswith("["): - break - - line, _, _comment = line.partition("#") - line = line.strip() - if not line: - continue - - name, _, tail = line.partition("=") - - # importable.module:object.attr - py_import, _, extras = tail.strip().partition(" ") - module, _, attribute = py_import.partition(":") - - ret.append(struct( - name = name.strip(), - module = module.strip(), - attribute = attribute.strip(), - extras = extras.replace(" ", ""), - )) - - return ret diff --git a/tests/pypi/generate_whl_library_build_bazel/generate_whl_library_build_bazel_tests.bzl b/tests/pypi/generate_whl_library_build_bazel/generate_whl_library_build_bazel_tests.bzl index 85e96be579..2f421f35d4 100644 --- a/tests/pypi/generate_whl_library_build_bazel/generate_whl_library_build_bazel_tests.bzl +++ b/tests/pypi/generate_whl_library_build_bazel/generate_whl_library_build_bazel_tests.bzl @@ -42,9 +42,6 @@ whl_library_targets( dependencies_by_platform = { "baz": ["bar"], }, - entry_points = { - "foo": "bar.py", - }, group_deps = [ "foo", "fox", @@ -56,11 +53,6 @@ whl_library_targets( tags = ["tag1"], ) -exports_files( - srcs = ["bar.py"], - visibility = ["//visibility:public"], -) - # SOMETHING SPECIAL AT THE END """ actual = generate_whl_library_build_bazel( @@ -68,9 +60,6 @@ exports_files( name = "foo.whl", dependencies = ["foo"], dependencies_by_platform = {"baz": ["bar"]}, - entry_points = { - "foo": "bar.py", - }, data_exclude = ["exclude_via_attr"], annotation = struct( copy_files = {"file_src": "file_dest"}, @@ -108,9 +97,6 @@ whl_library_targets_from_requires( "data_exclude_all", ], dep_template = "@pypi//{name}:{target}", - entry_points = { - "foo": "bar.py", - }, group_deps = [ "foo", "fox", @@ -127,20 +113,12 @@ whl_library_targets_from_requires( srcs_exclude = ["srcs_exclude_all"], ) -exports_files( - srcs = ["bar.py"], - visibility = ["//visibility:public"], -) - # SOMETHING SPECIAL AT THE END """ actual = generate_whl_library_build_bazel( dep_template = "@pypi//{name}:{target}", name = "foo.whl", requires_dist = ["foo", "bar-baz", "qux"], - entry_points = { - "foo": "bar.py", - }, data_exclude = ["exclude_via_attr"], annotation = struct( copy_files = {"file_src": "file_dest"}, @@ -178,9 +156,6 @@ whl_library_targets_from_requires( "data_exclude_all", ], dep_template = "@pypi//{name}:{target}", - entry_points = { - "foo": "bar.py", - }, group_deps = [ "foo", "fox", @@ -197,20 +172,12 @@ whl_library_targets_from_requires( srcs_exclude = ["srcs_exclude_all"], ) -exports_files( - srcs = ["bar.py"], - visibility = ["//visibility:public"], -) - # SOMETHING SPECIAL AT THE END """ actual = generate_whl_library_build_bazel( dep_template = "@pypi//{name}:{target}", name = "foo.whl", requires_dist = ["foo", "bar-baz", "qux"], - entry_points = { - "foo": "bar.py", - }, data_exclude = ["exclude_via_attr"], annotation = struct( copy_files = {"file_src": "file_dest"}, @@ -248,9 +215,6 @@ whl_library_targets_from_requires( "data_exclude_all", ], dep_template = "@pypi//{name}:{target}", - entry_points = { - "foo": "bar.py", - }, group_deps = [ "foo", "fox", @@ -267,20 +231,12 @@ whl_library_targets_from_requires( srcs_exclude = ["srcs_exclude_all"], ) -exports_files( - srcs = ["bar.py"], - visibility = ["//visibility:public"], -) - # SOMETHING SPECIAL AT THE END """ actual = generate_whl_library_build_bazel( dep_template = "@pypi//{name}:{target}", name = "foo.whl", requires_dist = ["foo", "bar-baz", "qux"], - entry_points = { - "foo": "bar.py", - }, data_exclude = ["exclude_via_attr"], annotation = struct( copy_files = {"file_src": "file_dest"}, diff --git a/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl b/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl index 08715fbf77..28765770f4 100644 --- a/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl +++ b/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl @@ -158,35 +158,6 @@ def _test_copy(env): _tests.append(_test_copy) -def _test_entrypoints(env): - calls = [] - - whl_library_targets( - name = "", - dep_template = None, - dependencies_by_platform = {}, - filegroups = {}, - entry_points = { - "fizz": "buzz.py", - }, - native = struct(), - rules = struct( - py_binary = lambda **kwargs: calls.append(kwargs), - ), - ) - - env.expect.that_collection(calls).contains_exactly([ - { - "name": "rules_python_wheel_entry_point_fizz", - "srcs": ["buzz.py"], - "deps": [":pkg"], - "imports": ["."], - "visibility": ["//visibility:public"], - }, - ]) # buildifier: @unsorted-dict-items - -_tests.append(_test_entrypoints) - def _test_whl_and_library_deps_from_requires(env): filegroup_calls = [] py_library_calls = [] @@ -412,7 +383,6 @@ def _test_group(env): "@platforms//os:linux": ["box"], # buildifier: disable=unsorted-dict-items to check that we sort inside the test }, tags = [], - entry_points = {}, data_exclude = [], group_name = "qux", group_deps = ["foo", "fox", "qux"], diff --git a/tests/pypi/whl_metadata/whl_metadata_tests.bzl b/tests/pypi/whl_metadata/whl_metadata_tests.bzl index 1d78611901..329423a26c 100644 --- a/tests/pypi/whl_metadata/whl_metadata_tests.bzl +++ b/tests/pypi/whl_metadata/whl_metadata_tests.bzl @@ -81,14 +81,12 @@ def _parse_whl_metadata(env, **kwargs): version = result.version, requires_dist = result.requires_dist, provides_extra = result.provides_extra, - entry_points = result.entry_points, ), attrs = dict( name = subjects.str, version = subjects.str, requires_dist = subjects.collection, provides_extra = subjects.collection, - entry_points = subjects.collection, ), ) @@ -173,53 +171,6 @@ Requires-Dist: this will be ignored _tests.append(_test_parse_metadata_multiline_license) -def _test_parse_entry_points_txt(env): - got = _parse_whl_metadata( - env, - contents = """\ -Name: foo -Version: 0.0.1 -""", - entry_points_contents = """\ -[something] -interesting # with comments - -[console_scripts] -foo = foomod:main -# One which depends on extras: -foobar = importable.foomod:main_bar [bar, baz] - - # With a comment at the end -foobarbaz = foomod:main.attr # comment - -[something else] -not very much interesting - -""", - ) - got.entry_points().contains_exactly([ - struct( - attribute = "main", - extras = "", - module = "foomod", - name = "foo", - ), - struct( - attribute = "main_bar", - extras = "[bar,baz]", - module = "importable.foomod", - name = "foobar", - ), - struct( - attribute = "main.attr", - extras = "", - module = "foomod", - name = "foobarbaz", - ), - ]) - -_tests.append(_test_parse_entry_points_txt) - def whl_metadata_test_suite(name): # buildifier: disable=function-docstring test_suite( name = name,