diff --git a/python/private/pypi/generate_whl_library_build_bazel.bzl b/python/private/pypi/generate_whl_library_build_bazel.bzl index a9a29081f7..71eab26c0e 100644 --- a/python/private/pypi/generate_whl_library_build_bazel.bzl +++ b/python/private/pypi/generate_whl_library_build_bazel.bzl @@ -21,8 +21,6 @@ _RENDER = { "copy_files": render.dict, "data": render.list, "data_exclude": render.list, - "dependencies": render.list, - "dependencies_by_platform": lambda x: render.dict(x, value_repr = render.list), "entry_points": render.dict_dict, "extras": render.list, "group_deps": render.list, @@ -30,7 +28,6 @@ _RENDER = { "requires_dist": render.list, "srcs_exclude": render.list, "tags": render.list, - "target_platforms": render.list, } # NOTE @aignas 2024-10-25: We have to keep this so that files in @@ -55,15 +52,17 @@ package_metadata( def generate_whl_library_build_bazel( *, annotation = None, - default_python_version = None, + config_load, purl = None, + requires_dist = [], **kwargs): """Generate a BUILD file for an unzipped Wheel Args: annotation: The annotation for the build file. - default_python_version: The python version to use to parse the METADATA. + config_load: {type}`str` The location from where to load the config. purl: The purl. + requires_dist: {type}`list[str]` The list of dependencies from the METADATA file. **kwargs: Extra args serialized to be passed to the {obj}`whl_library_targets`. @@ -75,36 +74,14 @@ def generate_whl_library_build_bazel( """load("@package_metadata//rules:package_metadata.bzl", "package_metadata")""", ] - if kwargs.get("tags"): - fn = "whl_library_targets" - - # legacy path - unsupported_args = [ - "requires", - "metadata_name", - "metadata_version", - "packages", - "include", - ] + fn = "whl_library_targets_from_requires" + if not requires_dist: + # no deps, we can leave the extra loads out + pass else: - fn = "whl_library_targets_from_requires" - unsupported_args = [ - "dependencies", - "dependencies_by_platform", - "target_platforms", - "default_python_version", - ] - packages_load = kwargs.pop("config_load") - if not kwargs.get("requires_dist"): - # no deps, we can leave the extra loads out - pass - else: - loads.append("""load("{}", "{}")""".format(packages_load, "packages")) - kwargs["include"] = "packages" - - for arg in unsupported_args: - if kwargs.get(arg): - fail("BUG, unsupported arg: '{}'".format(arg)) + loads.append("""load("{}", "{}")""".format(config_load, "packages")) + kwargs["include"] = "packages" + kwargs["requires_dist"] = requires_dist loads.extend([ """load("@rules_python//python/private/pypi:whl_library_targets.bzl", "{}")""".format(fn), @@ -119,8 +96,6 @@ def generate_whl_library_build_bazel( kwargs["srcs_exclude"] = annotation.srcs_exclude_glob if annotation.additive_build_content: additional_content.append(annotation.additive_build_content) - if default_python_version: - kwargs["default_python_version"] = default_python_version contents = "\n".join( [ diff --git a/python/private/pypi/pkg_aliases.bzl b/python/private/pypi/pkg_aliases.bzl index 111a49d3c6..b1c29c95ee 100644 --- a/python/private/pypi/pkg_aliases.bzl +++ b/python/private/pypi/pkg_aliases.bzl @@ -201,6 +201,7 @@ def multiplatform_whl_aliases( ret[alias] = repo continue + # This is if we are using `whl_config_setting` struct config_settings = get_config_settings( target_platforms = alias.target_platforms, python_version = alias.version, diff --git a/python/private/pypi/whl_library_targets.bzl b/python/private/pypi/whl_library_targets.bzl index 01a89aadcc..933b529053 100644 --- a/python/private/pypi/whl_library_targets.bzl +++ b/python/private/pypi/whl_library_targets.bzl @@ -120,10 +120,8 @@ def whl_library_targets( tags = [], dependencies = [], filegroups = None, - dependencies_by_platform = {}, dependencies_with_markers = {}, entry_points = {}, - group_deps = [], group_name = "", data = [], copy_files = {}, @@ -151,8 +149,6 @@ def whl_library_targets( the filename of the sdist. tags: {type}`list[str]` The tags set on the `py_library`. dependencies: {type}`list[str]` A list of dependencies. - dependencies_by_platform: {type}`dict[str, list[str]]` A list of - dependencies by platform key. dependencies_with_markers: {type}`dict[str, str]` A marker to evaluate in order for the dep to be included. entry_points: {type}`list[dict]` A list of parsed entry point definitions. @@ -162,10 +158,6 @@ def whl_library_targets( contains this library. If set, this library will behave as a shim to group implementation rules which will provide simultaneously installed dependencies which would otherwise form a cycle. - group_deps: {type}`list[str]` names of fellow members of the group (if - any). These will be excluded from generated deps lists so as to avoid - direct cycles. These dependencies will be provided at runtime by the - group rules which wrap this library and its fellows together. copy_executables: {type}`dict[str, str]` The mapping between src and dest locations for the targets. copy_files: {type}`dict[str, str]` The mapping between src and @@ -183,10 +175,6 @@ def whl_library_targets( rules: {type}`struct` A struct with references to rules for creating targets. """ dependencies = sorted([normalize_name(d) for d in dependencies]) - dependencies_by_platform = { - platform: sorted([normalize_name(d) for d in deps]) - for platform, deps in dependencies_by_platform.items() - } tags = sorted(tags) data = [] + data @@ -267,9 +255,7 @@ def whl_library_targets( data.append(dest) _config_settings( - dependencies_by_platform = dependencies_by_platform.keys(), dependencies_with_markers = dependencies_with_markers, - native = native, rules = rules, visibility = ["//visibility:private"], ) @@ -278,25 +264,6 @@ def whl_library_targets( for d in dependencies_with_markers } - # Ensure this list is normalized - # Note: mapping used as set - group_deps = { - normalize_name(d): True - for d in group_deps - } - - dependencies = [ - d - for d in dependencies - if d not in group_deps - ] - dependencies_by_platform = { - p: deps - for p, deps in dependencies_by_platform.items() - for deps in [[d for d in deps if d not in group_deps]] - if deps - } - # If this library is a member of a group, its public label aliases need to # point to the group implementation rule not the implementation rules. We # also need to mark the implementation rules as visible to the group @@ -351,7 +318,6 @@ def whl_library_targets( srcs = [name], data = _deps( deps = dependencies, - deps_by_platform = dependencies_by_platform, deps_conditional = deps_conditional, tmpl = dep_template.format(name = "{}", target = WHEEL_FILE_PUBLIC_LABEL), ), @@ -418,7 +384,6 @@ def whl_library_targets( imports = ["site-packages"], deps = _deps( deps = dependencies, - deps_by_platform = dependencies_by_platform, deps_conditional = deps_conditional, tmpl = dep_template.format(name = "{}", target = PY_LIBRARY_PUBLIC_LABEL), ), @@ -428,22 +393,13 @@ def whl_library_targets( namespace_package_files = namespace_package_files, ) -def _config_settings(dependencies_by_platform, dependencies_with_markers, rules, native = native, **kwargs): +def _config_settings(dependencies_with_markers, rules, **kwargs): """Generate config settings for the targets. Args: - dependencies_by_platform: {type}`list[str]` platform keys, can be - one of the following formats: - * `//conditions:default` - * `@platforms//os:{value}` - * `@platforms//cpu:{value}` - * `@//python/config_settings:is_python_3.{minor_version}` - * `{os}_{cpu}` - * `cp3{minor_version}_{os}_{cpu}` dependencies_with_markers: {type}`dict[str, str]` The markers to evaluate by each dep. rules: used for testing - native: {type}`native` The native struct for overriding in tests. **kwargs: Extra kwargs to pass to the rule. """ for dep, expression in dependencies_with_markers.items(): @@ -453,46 +409,7 @@ def _config_settings(dependencies_by_platform, dependencies_with_markers, rules, **kwargs ) - for p in dependencies_by_platform: - if p.startswith("@") or p.endswith("default"): - continue - - # TODO @aignas 2025-04-20: add tests here - abi, _, tail = p.partition("_") - if not abi.startswith("cp"): - tail = p - abi = "" - os, _, arch = tail.partition("_") - - _kwargs = dict(kwargs) - _kwargs["constraint_values"] = [ - "@platforms//cpu:{}".format(arch), - "@platforms//os:{}".format(os), - ] - - if abi: - _kwargs["flag_values"] = { - Label("//python/config_settings:python_version"): "3.{}".format(abi[len("cp3"):]), - } - - native.config_setting( - name = "is_{name}".format( - name = p.replace("cp3", "python_3."), - ), - **_kwargs - ) - -def _plat_label(plat): - if plat.endswith("default"): - return plat - elif plat.startswith("@//"): - return Label(plat.strip("@")) - elif plat.startswith("@"): - return plat - else: - return ":is_" + plat.replace("cp3", "python_3.") - -def _deps(deps, deps_by_platform, deps_conditional, tmpl): +def _deps(deps, deps_conditional, tmpl): deps = [tmpl.format(d) for d in sorted(deps)] for dep, setting in deps_conditional.items(): @@ -501,22 +418,4 @@ def _deps(deps, deps_by_platform, deps_conditional, tmpl): "//conditions:default": [], }) - if not deps_by_platform: - return deps - - deps_by_platform = { - _plat_label(p): [ - tmpl.format(d) - for d in sorted(deps) - ] - for p, deps in sorted(deps_by_platform.items()) - } - - # Add the default, which means that we will be just using the dependencies in - # `deps` for platforms that are not handled in a special way by the packages - deps_by_platform.setdefault("//conditions:default", []) - - if not deps: - return select(deps_by_platform) - else: - return deps + select(deps_by_platform) + return deps 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 9586581cad..1fd99205b1 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 @@ -19,71 +19,6 @@ load("//python/private/pypi:generate_whl_library_build_bazel.bzl", "generate_whl _tests = [] -def _test_all_legacy(env): - want = """\ -load("@package_metadata//rules:package_metadata.bzl", "package_metadata") -load("@rules_python//python/private/pypi:whl_library_targets.bzl", "whl_library_targets") - -package(default_visibility = ["//visibility:public"]) - -package_metadata( - name = "package_metadata", - purl = None, - visibility = ["//:__subpackages__"], -) - -whl_library_targets( - copy_executables = { - "exec_src": "exec_dest", - }, - copy_files = { - "file_src": "file_dest", - }, - data = ["extra_target"], - data_exclude = [ - "exclude_via_attr", - "data_exclude_all", - ], - dep_template = "@pypi_{name}//:{target}", - dependencies = ["foo"], - dependencies_by_platform = { - "baz": ["bar"], - }, - group_deps = [ - "foo", - "fox", - "qux", - ], - group_name = "qux", - name = "foo.whl", - srcs_exclude = ["srcs_exclude_all"], - tags = ["tag1"], -) - -# SOMETHING SPECIAL AT THE END -""" - actual = generate_whl_library_build_bazel( - dep_template = "@pypi_{name}//:{target}", - name = "foo.whl", - dependencies = ["foo"], - dependencies_by_platform = {"baz": ["bar"]}, - data_exclude = ["exclude_via_attr"], - annotation = struct( - copy_files = {"file_src": "file_dest"}, - copy_executables = {"exec_src": "exec_dest"}, - data = ["extra_target"], - data_exclude_glob = ["data_exclude_all"], - srcs_exclude_glob = ["srcs_exclude_all"], - additive_build_content = """# SOMETHING SPECIAL AT THE END""", - ), - group_name = "qux", - group_deps = ["foo", "fox", "qux"], - tags = ["tag1"], - ) - env.expect.that_str(actual.replace("@@", "@")).equals(want) - -_tests.append(_test_all_legacy) - def _test_all_workspace(env): want = """\ load("@package_metadata//rules:package_metadata.bzl", "package_metadata") 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 91db15f296..5bd1d1f549 100644 --- a/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl +++ b/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl @@ -72,72 +72,12 @@ def _test_filegroups(env): _tests.append(_test_filegroups) -def _test_platforms(env): - calls = [] - - whl_library_targets( - name = "", - dep_template = None, - dependencies_by_platform = { - "@//python/config_settings:is_python_3.9": ["py39_dep"], - "@platforms//cpu:aarch64": ["arm_dep"], - "@platforms//os:windows": ["win_dep"], - "cp310.11_linux_ppc64le": ["full_version_dep"], - "cp310_linux_ppc64le": ["py310_linux_ppc64le_dep"], - "linux_x86_64": ["linux_intel_dep"], - }, - filegroups = {}, - native = struct( - config_setting = lambda **kwargs: calls.append(kwargs), - glob = lambda *args, **kwargs: [], - ), - rules = struct( - venv_rewrite_shebang = lambda **kwargs: None, - ), - ) - - env.expect.that_collection(calls).contains_exactly([ - { - "name": "is_python_3.10.11_linux_ppc64le", - "visibility": ["//visibility:private"], - "constraint_values": [ - "@platforms//cpu:ppc64le", - "@platforms//os:linux", - ], - "flag_values": { - Label("//python/config_settings:python_version"): "3.10.11", - }, - }, - { - "name": "is_python_3.10_linux_ppc64le", - "visibility": ["//visibility:private"], - "constraint_values": [ - "@platforms//cpu:ppc64le", - "@platforms//os:linux", - ], - "flag_values": { - Label("//python/config_settings:python_version"): "3.10", - }, - }, - { - "name": "is_linux_x86_64", - "visibility": ["//visibility:private"], - "constraint_values": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux", - ], - }, - ]) # buildifier: @unsorted-dict-items - -_tests.append(_test_platforms) - def _test_copy(env): calls = [] whl_library_targets( name = "", dep_template = None, - dependencies_by_platform = {}, filegroups = {}, copy_files = {"file_src": "file_dest"}, copy_executables = {"exec_src": "exec_dest"}, @@ -289,193 +229,6 @@ def _test_whl_and_library_deps_from_requires(env): _tests.append(_test_whl_and_library_deps_from_requires) -def _test_whl_and_library_deps(env): - filegroup_calls = [] - py_library_calls = [] - m_glob = mocks.glob() - m_glob.results.append([]) # bin - m_glob.results.append([]) # rewrite-bin - m_glob.results.append(["site-packages/foo/SRCS.py"]) - m_glob.results.append(["site-packages/foo/DATA.txt"]) - m_glob.results.append(["site-packages/foo/PYI.pyi"]) - - whl_library_targets( - name = "foo.whl", - dep_template = "@pypi_{name}//:{target}", - dependencies = ["foo", "bar-baz"], - dependencies_by_platform = { - "@//python/config_settings:is_python_3.9": ["py39_dep"], - "@platforms//cpu:aarch64": ["arm_dep"], - "@platforms//os:windows": ["win_dep"], - "cp310_linux_ppc64le": ["py310_linux_ppc64le_dep"], - "cp39_anyos_aarch64": ["py39_arm_dep"], - "cp39_linux_anyarch": ["py39_linux_dep"], - "linux_x86_64": ["linux_intel_dep"], - }, - data_exclude = [], - tags = ["tag1", "tag2"], - # Overrides for testing - filegroups = {}, - native = struct( - filegroup = lambda **kwargs: filegroup_calls.append(kwargs), - config_setting = lambda **_: None, - glob = m_glob.glob, - ), - rules = struct( - py_library = lambda **kwargs: py_library_calls.append(kwargs), - create_inits = lambda **kwargs: ["_create_inits_target"], - venv_rewrite_shebang = lambda **kwargs: None, - ), - ) - - env.expect.that_collection(filegroup_calls).contains_exactly([ - { - "name": "whl", - "srcs": ["foo.whl"], - "data": [ - "@pypi_bar_baz//:whl", - "@pypi_foo//:whl", - ] + select( - { - Label("//python/config_settings:is_python_3.9"): ["@pypi_py39_dep//:whl"], - "@platforms//cpu:aarch64": ["@pypi_arm_dep//:whl"], - "@platforms//os:windows": ["@pypi_win_dep//:whl"], - ":is_python_3.10_linux_ppc64le": ["@pypi_py310_linux_ppc64le_dep//:whl"], - ":is_python_3.9_anyos_aarch64": ["@pypi_py39_arm_dep//:whl"], - ":is_python_3.9_linux_anyarch": ["@pypi_py39_linux_dep//:whl"], - ":is_linux_x86_64": ["@pypi_linux_intel_dep//:whl"], - "//conditions:default": [], - }, - ), - "visibility": ["//visibility:public"], - }, - ]) # buildifier: @unsorted-dict-items - - env.expect.that_collection(py_library_calls).has_size(1) - if len(py_library_calls) != 1: - return - env.expect.that_dict(py_library_calls[0]).contains_exactly({ - "name": "pkg", - "srcs": ["site-packages/foo/SRCS.py"] + select({ - Label("//python/config_settings:_is_venvs_site_packages_yes"): [], - "//conditions:default": ["_create_inits_target"], - }), - "pyi_srcs": ["site-packages/foo/PYI.pyi"], - "data": ["site-packages/foo/DATA.txt", "data"], - "imports": ["site-packages"], - "deps": [ - "@pypi_bar_baz//:pkg", - "@pypi_foo//:pkg", - ] + select( - { - Label("//python/config_settings:is_python_3.9"): ["@pypi_py39_dep//:pkg"], - "@platforms//cpu:aarch64": ["@pypi_arm_dep//:pkg"], - "@platforms//os:windows": ["@pypi_win_dep//:pkg"], - ":is_python_3.10_linux_ppc64le": ["@pypi_py310_linux_ppc64le_dep//:pkg"], - ":is_python_3.9_anyos_aarch64": ["@pypi_py39_arm_dep//:pkg"], - ":is_python_3.9_linux_anyarch": ["@pypi_py39_linux_dep//:pkg"], - ":is_linux_x86_64": ["@pypi_linux_intel_dep//:pkg"], - "//conditions:default": [], - }, - ), - "tags": ["tag1", "tag2"], - "visibility": ["//visibility:public"], - "experimental_venvs_site_packages": Label("//python/config_settings:venvs_site_packages"), - "namespace_package_files": [] + select({ - Label("//python/config_settings:_is_venvs_site_packages_yes"): [], - "//conditions:default": ["_create_inits_target"], - }), - }) # buildifier: @unsorted-dict-items - -_tests.append(_test_whl_and_library_deps) - -def _test_group(env): - alias_calls = [] - py_library_calls = [] - - m_glob = mocks.glob() - m_glob.results.append([]) # bin - m_glob.results.append([]) # rewrite-bin - m_glob.results.append(["site-packages/foo/srcs.py"]) - m_glob.results.append(["site-packages/foo/data.txt"]) - m_glob.results.append(["site-packages/foo/pyi.pyi"]) - - whl_library_targets( - name = "foo.whl", - dep_template = "@pypi_{name}//:{target}", - dependencies = ["foo", "bar-baz", "qux"], - dependencies_by_platform = { - "linux_x86_64": ["box", "box-amd64"], - "windows_x86_64": ["fox"], - "@platforms//os:linux": ["box"], # buildifier: disable=unsorted-dict-items to check that we sort inside the test - }, - tags = [], - data_exclude = [], - group_name = "qux", - group_deps = ["foo", "fox", "qux"], - # Overrides for testing - filegroups = {}, - native = struct( - config_setting = lambda **_: None, - glob = m_glob.glob, - alias = lambda **kwargs: alias_calls.append(kwargs), - ), - rules = struct( - py_library = lambda **kwargs: py_library_calls.append(kwargs), - create_inits = lambda **kwargs: ["_create_inits_target"], - venv_rewrite_shebang = lambda **kwargs: None, - ), - ) - - env.expect.that_collection(alias_calls).contains_exactly([ - {"name": "pkg", "actual": "@pypi__config//_groups:qux_pkg", "visibility": ["//visibility:public"]}, - {"name": "whl", "actual": "@pypi__config//_groups:qux_whl", "visibility": ["//visibility:public"]}, - ]) # buildifier: @unsorted-dict-items - - env.expect.that_collection(py_library_calls).has_size(1) - if len(py_library_calls) != 1: - return - - py_library_call = py_library_calls[0] - env.expect.where(case = "verify py library call").that_dict( - py_library_call, - ).contains_exactly({ - "name": "_pkg", - "srcs": ["site-packages/foo/srcs.py"] + select({ - Label("//python/config_settings:_is_venvs_site_packages_yes"): [], - "//conditions:default": ["_create_inits_target"], - }), - "pyi_srcs": ["site-packages/foo/pyi.pyi"], - "data": ["site-packages/foo/data.txt", "data"], - "imports": ["site-packages"], - "deps": ["@pypi_bar_baz//:pkg"] + select({ - "@platforms//os:linux": ["@pypi_box//:pkg"], - ":is_linux_x86_64": ["@pypi_box//:pkg", "@pypi_box_amd64//:pkg"], - "//conditions:default": [], - }), - "tags": [], - "visibility": ["@pypi__config//_groups:__pkg__"], - "experimental_venvs_site_packages": Label("//python/config_settings:venvs_site_packages"), - "namespace_package_files": [] + select({ - Label("//python/config_settings:_is_venvs_site_packages_yes"): [], - "//conditions:default": ["_create_inits_target"], - }), - }) # buildifier: @unsorted-dict-items - - env.expect.that_collection(m_glob.calls, expr = "glob calls").contains_exactly([ - mocks.glob_call(["bin/*"], allow_empty = True), - mocks.glob_call(["rewrite-bin/*"], allow_empty = True), - mocks.glob_call(["site-packages/**/*.py"], exclude = [], allow_empty = True), - mocks.glob_call(["site-packages/**/*"], exclude = [ - "**/*.py", - "**/*.pyc", - "**/*.pyc.*", - ], allow_empty = True), - mocks.glob_call(["site-packages/**/*.pyi"], allow_empty = True), - ]) - -_tests.append(_test_group) - def _test_sdist_excludes_record(env): py_library_calls = [] m_glob = mocks.glob()