fix: use the python micro version to parse whl metadata in bzlmod (#2793) Add `<micro>` version to the target platform. Instead of `cpxy_os_cpu` the target platform string format becomes `cpxy.z_os_cpu`. This is a temporary measure until we get a better API for defining target platforms. Summary: - [x] test `select_whls` function needs to be tested to ensure that the whl selection is not impacted when we have the full version in the target platform. - [ ] `download_only` legacy whl code path in `bzlmod` needs further testing. - [x] test `whl_config_setting` handling and config setting creation. The config settings in the hub repo should not use the full version, because from the outside, the whl is compatible with all `micro` versions of a given `3.<minor_version>` of the Python interpreter. This means that the already documented config setting do not need to be changed. - [x] `pep508_deps` tests for handling the `full_python_version` correctly. - [x] `pep508_deps` tests for ensuring the `default_abi` is being handled correctly. Fixes #2319 (cherry picked from commit 1e21dbdbba45a3fa7a3bcb2495d72f89eae1fb98)
diff --git a/CHANGELOG.md b/CHANGELOG.md index f078acf..c8602f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md
@@ -111,6 +111,9 @@ * (packaging) An empty `requires_file` is treated as if it were omitted, resulting in a valid `METADATA` file. * (rules) py_wheel and sphinxdocs rules now propagate `target_compatible_with` to all targets they create. [PR #2788](https://github.com/bazel-contrib/rules_python/pull/2788). +* (pypi) Correctly handle `METADATA` entries when `python_full_version` is used in + the environment marker. + Fixes [#2319](https://github.com/bazel-contrib/rules_python/issues/2319). {#1-4-0-added} ### Added
diff --git a/examples/bzlmod/entry_points/BUILD.bazel b/examples/bzlmod/entry_points/BUILD.bazel index a0939cb..4ca5b53 100644 --- a/examples/bzlmod/entry_points/BUILD.bazel +++ b/examples/bzlmod/entry_points/BUILD.bazel
@@ -1,4 +1,3 @@ -load("@python_versions//3.9:defs.bzl", py_console_script_binary_3_9 = "py_console_script_binary") load("@rules_python//python/entry_points:py_console_script_binary.bzl", "py_console_script_binary") # This is how you can define a `pylint` entrypoint which uses the default python version. @@ -24,10 +23,11 @@ ], ) -# A specific Python version can be forced by using the generated version-aware -# wrappers, e.g. to force Python 3.9: -py_console_script_binary_3_9( +# A specific Python version can be forced by passing `python_version` +# attribute, e.g. to force Python 3.9: +py_console_script_binary( name = "yamllint", pkg = "@pip//yamllint:pkg", + python_version = "3.9", visibility = ["//entry_points:__subpackages__"], )
diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index a758b3f..bfb0be2 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel
@@ -103,6 +103,7 @@ "//python/private:version_label_bzl", "@bazel_features//:features", "@pythons_hub//:interpreters_bzl", + "@pythons_hub//:versions_bzl", ], ) @@ -220,7 +221,9 @@ ":pep508_evaluate_bzl", ":pep508_platform_bzl", ":pep508_requirement_bzl", + "//python/private:full_version_bzl", "//python/private:normalize_name_bzl", + "@pythons_hub//:versions_bzl", ], )
diff --git a/python/private/pypi/config_settings.bzl b/python/private/pypi/config_settings.bzl index 1045ffe..d1b85d1 100644 --- a/python/private/pypi/config_settings.bzl +++ b/python/private/pypi/config_settings.bzl
@@ -42,6 +42,8 @@ * `:is_cp3<minor_version>_abi3_<platform_suffix>` * `:is_cp3<minor_version>_cp3<minor_version>_<platform_suffix>` and `:is_cp3<minor_version>_cp3<minor_version>t_<platform_suffix>` +Optionally instead of `<minor_version>` there sometimes may be `<minor_version>.<micro_version>` used in order to fully specify the versions + The specialization of free-threaded vs non-free-threaded wheels is the same as they are just variants of each other. The same goes for the specialization of `musllinux` vs `manylinux`.
diff --git a/python/private/pypi/extension.bzl b/python/private/pypi/extension.bzl index d1895ca..e9eba68 100644 --- a/python/private/pypi/extension.bzl +++ b/python/private/pypi/extension.bzl
@@ -16,7 +16,9 @@ load("@bazel_features//:features.bzl", "bazel_features") load("@pythons_hub//:interpreters.bzl", "INTERPRETER_LABELS") +load("@pythons_hub//:versions.bzl", "MINOR_MAPPING") load("//python/private:auth.bzl", "AUTH_ATTRS") +load("//python/private:full_version.bzl", "full_version") load("//python/private:normalize_name.bzl", "normalize_name") load("//python/private:repo_utils.bzl", "repo_utils") load("//python/private:semver.bzl", "semver") @@ -68,6 +70,7 @@ pip_attr, whl_overrides, available_interpreters = INTERPRETER_LABELS, + minor_mapping = MINOR_MAPPING, get_index_urls = None): """create all of the whl repositories @@ -80,6 +83,8 @@ interpreters that have been registered using the `python` bzlmod extension. The keys are in the form `python_{snake_case_version}_host`. This is to be used during the `repository_rule` and must be always compatible with the host. + minor_mapping: {type}`dict[str, str]` The dictionary needed to resolve the full + python version used to parse package METADATA files. Returns a {type}`struct` with the following attributes: whl_map: {type}`dict[str, list[struct]]` the output is keyed by the @@ -159,8 +164,10 @@ requirements_osx = pip_attr.requirements_darwin, requirements_windows = pip_attr.requirements_windows, extra_pip_args = pip_attr.extra_pip_args, - # TODO @aignas 2025-04-15: pass the full version into here - python_version = major_minor, + python_version = full_version( + version = pip_attr.python_version, + minor_mapping = minor_mapping, + ), logger = logger, ), extra_pip_args = pip_attr.extra_pip_args, @@ -304,9 +311,6 @@ if requirement.extra_pip_args: args["extra_pip_args"] = requirement.extra_pip_args - if download_only: - args.setdefault("experimental_target_platforms", requirement.target_platforms) - target_platforms = requirement.target_platforms if multiple_requirements_for_whl else [] repo_name = pypi_repo_name( normalize_name(requirement.distribution),
diff --git a/python/private/pypi/pep508_deps.bzl b/python/private/pypi/pep508_deps.bzl index 115bbd7..bcc4845 100644 --- a/python/private/pypi/pep508_deps.bzl +++ b/python/private/pypi/pep508_deps.bzl
@@ -15,14 +15,23 @@ """This module is for implementing PEP508 compliant METADATA deps parsing. """ -load("@pythons_hub//:versions.bzl", "DEFAULT_PYTHON_VERSION") +load("@pythons_hub//:versions.bzl", "DEFAULT_PYTHON_VERSION", "MINOR_MAPPING") +load("//python/private:full_version.bzl", "full_version") load("//python/private:normalize_name.bzl", "normalize_name") load(":pep508_env.bzl", "env") load(":pep508_evaluate.bzl", "evaluate") load(":pep508_platform.bzl", "platform", "platform_from_str") load(":pep508_requirement.bzl", "requirement") -def deps(name, *, requires_dist, platforms = [], extras = [], excludes = [], default_python_version = None): +def deps( + name, + *, + requires_dist, + platforms = [], + extras = [], + excludes = [], + default_python_version = None, + minor_mapping = MINOR_MAPPING): """Parse the RequiresDist from wheel METADATA Args: @@ -33,6 +42,9 @@ extras: {type}`list[str]` the requested extras to generate targets for. platforms: {type}`list[str]` the list of target platform strings. default_python_version: {type}`str` the host python version. + minor_mapping: {type}`type[str, str]` the minor mapping to use when + resolving to the full python version as DEFAULT_PYTHON_VERSION can by + of format `3.x`. Returns: A struct with attributes: @@ -53,6 +65,12 @@ excludes = [name] + [normalize_name(x) for x in excludes] default_python_version = default_python_version or DEFAULT_PYTHON_VERSION + if default_python_version: + # if it is not bzlmod, then DEFAULT_PYTHON_VERSION may be unset + default_python_version = full_version( + version = default_python_version, + minor_mapping = minor_mapping, + ) platforms = [ platform_from_str(p, python_version = default_python_version) for p in platforms @@ -60,9 +78,8 @@ abis = sorted({p.abi: True for p in platforms if p.abi}) if default_python_version and len(abis) > 1: - _, _, minor_version = default_python_version.partition(".") - minor_version, _, _ = minor_version.partition(".") - default_abi = "cp3" + minor_version + _, _, tail = default_python_version.partition(".") + default_abi = "cp3" + tail elif len(abis) > 1: fail( "all python versions need to be specified explicitly, got: {}".format(platforms),
diff --git a/python/private/pypi/pkg_aliases.bzl b/python/private/pypi/pkg_aliases.bzl index a9eee7b..28d70ff 100644 --- a/python/private/pypi/pkg_aliases.bzl +++ b/python/private/pypi/pkg_aliases.bzl
@@ -371,6 +371,9 @@ abi = parsed.abi_tag + # TODO @aignas 2025-04-20: test + abi, _, _ = abi.partition(".") + if parsed.platform_tag == "any": prefixes = ["{}{}_any".format(py, abi)] else:
diff --git a/python/private/pypi/render_pkg_aliases.bzl b/python/private/pypi/render_pkg_aliases.bzl index 863d250..28f32ed 100644 --- a/python/private/pypi/render_pkg_aliases.bzl +++ b/python/private/pypi/render_pkg_aliases.bzl
@@ -143,6 +143,18 @@ files["_groups/BUILD.bazel"] = generate_group_library_build_bazel("", requirement_cycles) return files +def _major_minor(python_version): + major, _, tail = python_version.partition(".") + minor, _, _ = tail.partition(".") + return "{}.{}".format(major, minor) + +def _major_minor_versions(python_versions): + if not python_versions: + return [] + + # Use a dict as a simple set + return sorted({_major_minor(v): None for v in python_versions}) + def render_multiplatform_pkg_aliases(*, aliases, **kwargs): """Render the multi-platform pkg aliases. @@ -174,7 +186,7 @@ glibc_versions = flag_versions.get("glibc_versions", []), muslc_versions = flag_versions.get("muslc_versions", []), osx_versions = flag_versions.get("osx_versions", []), - python_versions = flag_versions.get("python_versions", []), + python_versions = _major_minor_versions(flag_versions.get("python_versions", [])), target_platforms = flag_versions.get("target_platforms", []), visibility = ["//:__subpackages__"], )
diff --git a/python/private/pypi/requirements_files_by_platform.bzl b/python/private/pypi/requirements_files_by_platform.bzl index e3aafc0..9165c05 100644 --- a/python/private/pypi/requirements_files_by_platform.bzl +++ b/python/private/pypi/requirements_files_by_platform.bzl
@@ -91,13 +91,12 @@ return list(platforms.keys()) def _platform(platform_string, python_version = None): - if not python_version or platform_string.startswith("cp3"): + if not python_version or platform_string.startswith("cp"): return platform_string - _, _, tail = python_version.partition(".") - minor, _, _ = tail.partition(".") + major, _, tail = python_version.partition(".") - return "cp3{}_{}".format(minor, platform_string) + return "cp{}{}_{}".format(major, tail, platform_string) def requirements_files_by_platform( *,
diff --git a/python/private/pypi/whl_config_setting.bzl b/python/private/pypi/whl_config_setting.bzl index d966206..6e10eb4 100644 --- a/python/private/pypi/whl_config_setting.bzl +++ b/python/private/pypi/whl_config_setting.bzl
@@ -35,10 +35,20 @@ a struct with the validated and parsed values. """ if target_platforms: - for p in target_platforms: + target_platforms_input = target_platforms + target_platforms = [] + for p in target_platforms_input: if not p.startswith("cp"): fail("target_platform should start with 'cp' denoting the python version, got: " + p) + abi, _, tail = p.partition("_") + + # drop the micro version here, currently there is no usecase to use + # multiple python interpreters with the same minor version but + # different micro version. + abi, _, _ = abi.partition(".") + target_platforms.append("{}_{}".format(abi, tail)) + return struct( config_setting = config_setting, filename = filename,
diff --git a/python/private/pypi/whl_library_targets.bzl b/python/private/pypi/whl_library_targets.bzl index cf3df13..21e4a54 100644 --- a/python/private/pypi/whl_library_targets.bzl +++ b/python/private/pypi/whl_library_targets.bzl
@@ -369,26 +369,22 @@ 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("_") - os = "" if os == "anyos" else os - arch = "" if arch == "anyarch" else arch _kwargs = dict(kwargs) - if arch: - _kwargs.setdefault("constraint_values", []).append("@platforms//cpu:{}".format(arch)) - if os: - _kwargs.setdefault("constraint_values", []).append("@platforms//os:{}".format(os)) + _kwargs["constraint_values"] = [ + "@platforms//cpu:{}".format(arch), + "@platforms//os:{}".format(os), + ] if abi: _kwargs["flag_values"] = { - "@rules_python//python/config_settings:python_version_major_minor": "3.{minor_version}".format( - minor_version = abi[len("cp3"):], - ), + Label("//python/config_settings:python_version"): "3.{}".format(abi[len("cp3"):]), } native.config_setting(
diff --git a/python/private/pypi/whl_target_platforms.bzl b/python/private/pypi/whl_target_platforms.bzl index 9f47e62..6ea3f12 100644 --- a/python/private/pypi/whl_target_platforms.bzl +++ b/python/private/pypi/whl_target_platforms.bzl
@@ -75,8 +75,11 @@ fail("expected all platforms to start with ABI, but got: {}".format(p)) abi, _, os_cpu = p.partition("_") + abi, _, _ = abi.partition(".") _want_platforms[os_cpu] = None - _want_platforms[p] = None + + # TODO @aignas 2025-04-20: add a test + _want_platforms["{}_{}".format(abi, os_cpu)] = None version_limit_candidate = int(abi[3:]) if not version_limit:
diff --git a/tests/pypi/extension/extension_tests.bzl b/tests/pypi/extension/extension_tests.bzl index ce5474e..5de3bb5 100644 --- a/tests/pypi/extension/extension_tests.bzl +++ b/tests/pypi/extension/extension_tests.bzl
@@ -157,6 +157,7 @@ available_interpreters = { "python_3_15_host": "unit_test_interpreter_target", }, + minor_mapping = {"3.15": "3.15.19"}, ) pypi.exposed_packages().contains_exactly({"pypi": ["simple"]}) @@ -204,6 +205,7 @@ available_interpreters = { "python_3_15_host": "unit_test_interpreter_target", }, + minor_mapping = {"3.15": "3.15.19"}, ) pypi.exposed_packages().contains_exactly({"pypi": ["simple"]}) @@ -270,6 +272,7 @@ available_interpreters = { "python_3_15_host": "unit_test_interpreter_target", }, + minor_mapping = {"3.15": "3.15.19"}, ) pypi.exposed_packages().contains_exactly({"pypi": ["torch"]}) @@ -392,6 +395,7 @@ available_interpreters = { "python_3_12_host": "unit_test_interpreter_target", }, + minor_mapping = {"3.12": "3.12.19"}, simpleapi_download = mocksimpleapi_download, ) @@ -515,6 +519,7 @@ available_interpreters = { "python_3_15_host": "unit_test_interpreter_target", }, + minor_mapping = {"3.15": "3.15.19"}, ) pypi.exposed_packages().contains_exactly({"pypi": ["simple"]}) @@ -544,7 +549,8 @@ "pypi_315_extra": { "dep_template": "@pypi//{name}:{target}", "download_only": True, - "experimental_target_platforms": ["cp315_linux_x86_64"], + # TODO @aignas 2025-04-20: ensure that this is in the hub repo + # "experimental_target_platforms": ["cp315_linux_x86_64"], "extra_pip_args": ["--platform=manylinux_2_17_x86_64", "--python-version=315", "--implementation=cp", "--abi=cp315"], "python_interpreter_target": "unit_test_interpreter_target", "requirement": "extra==0.0.1 --hash=sha256:deadb00f", @@ -552,7 +558,6 @@ "pypi_315_simple_linux_x86_64": { "dep_template": "@pypi//{name}:{target}", "download_only": True, - "experimental_target_platforms": ["cp315_linux_x86_64"], "extra_pip_args": ["--platform=manylinux_2_17_x86_64", "--python-version=315", "--implementation=cp", "--abi=cp315"], "python_interpreter_target": "unit_test_interpreter_target", "requirement": "simple==0.0.1 --hash=sha256:deadbeef", @@ -560,7 +565,6 @@ "pypi_315_simple_osx_aarch64": { "dep_template": "@pypi//{name}:{target}", "download_only": True, - "experimental_target_platforms": ["cp315_osx_aarch64"], "extra_pip_args": ["--platform=macosx_10_9_arm64", "--python-version=315", "--implementation=cp", "--abi=cp315"], "python_interpreter_target": "unit_test_interpreter_target", "requirement": "simple==0.0.3 --hash=sha256:deadbaaf", @@ -648,6 +652,7 @@ available_interpreters = { "python_3_15_host": "unit_test_interpreter_target", }, + minor_mapping = {"3.15": "3.15.19"}, simpleapi_download = mocksimpleapi_download, ) @@ -850,6 +855,7 @@ available_interpreters = { "python_3_15_host": "unit_test_interpreter_target", }, + minor_mapping = {"3.15": "3.15.19"}, ) pypi.exposed_packages().contains_exactly({"pypi": []})
diff --git a/tests/pypi/pep508/deps_tests.bzl b/tests/pypi/pep508/deps_tests.bzl index d362925..118cd50 100644 --- a/tests/pypi/pep508/deps_tests.bzl +++ b/tests/pypi/pep508/deps_tests.bzl
@@ -48,6 +48,15 @@ ], python_version = "", ), + struct( + platforms = [ + "cp33.1_linux_x86_64", + "cp33.1_osx_x86_64", + "cp33.1_osx_aarch64", + "cp33.1_windows_x86_64", + ], + python_version = "", + ), ]: got = deps( "foo", @@ -154,7 +163,7 @@ def _test_can_get_deps_based_on_specific_python_version(env): requires_dist = [ "bar", - "baz; python_version < '3.8'", + "baz; python_full_version < '3.7.3'", "posix_dep; os_name=='posix' and python_version >= '3.8'", ] @@ -163,6 +172,11 @@ requires_dist = requires_dist, platforms = ["cp38_linux_x86_64"], ) + py373 = deps( + "foo", + requires_dist = requires_dist, + platforms = ["cp37.3_linux_x86_64"], + ) py37 = deps( "foo", requires_dist = requires_dist, @@ -174,6 +188,8 @@ env.expect.that_dict(py37.deps_select).contains_exactly({}) env.expect.that_collection(py38.deps).contains_exactly(["bar", "posix_dep"]) env.expect.that_dict(py38.deps_select).contains_exactly({}) + env.expect.that_collection(py373.deps).contains_exactly(["bar"]) + env.expect.that_dict(py373.deps_select).contains_exactly({}) _tests.append(_test_can_get_deps_based_on_specific_python_version) @@ -210,27 +226,29 @@ "posix_dep_with_version; os_name=='posix' and python_version >= '3.8'", "arch_dep; platform_machine=='x86_64' and python_version < '3.8'", ] - default_python_version = "3.7.4" got = deps( "foo", requires_dist = requires_dist, platforms = [ "cp3{}_{}_x86_64".format(minor, os) - for minor in [7, 8, 9] + for minor in ["7.4", "8.8", "9.8"] for os in ["linux", "windows"] ], - default_python_version = default_python_version, + default_python_version = "3.7", + minor_mapping = { + "3.7": "3.7.4", + }, ) env.expect.that_collection(got.deps).contains_exactly(["bar"]) env.expect.that_dict(got.deps_select).contains_exactly({ - "cp37_linux_x86_64": ["arch_dep", "baz", "posix_dep"], - "cp37_windows_x86_64": ["arch_dep", "baz"], - "cp38_linux_x86_64": ["baz_new", "posix_dep", "posix_dep_with_version"], - "cp38_windows_x86_64": ["baz_new"], - "cp39_linux_x86_64": ["baz_new", "posix_dep", "posix_dep_with_version"], - "cp39_windows_x86_64": ["baz_new"], + "cp37.4_linux_x86_64": ["arch_dep", "baz", "posix_dep"], + "cp37.4_windows_x86_64": ["arch_dep", "baz"], + "cp38.8_linux_x86_64": ["baz_new", "posix_dep", "posix_dep_with_version"], + "cp38.8_windows_x86_64": ["baz_new"], + "cp39.8_linux_x86_64": ["baz_new", "posix_dep", "posix_dep_with_version"], + "cp39.8_windows_x86_64": ["baz_new"], "linux_x86_64": ["arch_dep", "baz", "posix_dep"], "windows_x86_64": ["arch_dep", "baz"], }) @@ -294,8 +312,6 @@ _tests.append(_test_deps_are_not_duplicated) def _test_deps_are_not_duplicated_when_encountering_platform_dep_first(env): - default_python_version = "3.7.1" - # Note, that we are sorting the incoming `requires_dist` and we need to ensure that we are not getting any # issues even if the platform-specific line comes first. requires_dist = [ @@ -307,19 +323,20 @@ "foo", requires_dist = requires_dist, platforms = [ - "cp37_linux_aarch64", - "cp37_linux_x86_64", + "cp37.1_linux_aarch64", + "cp37.1_linux_x86_64", "cp310_linux_aarch64", "cp310_linux_x86_64", ], - default_python_version = default_python_version, + default_python_version = "3.7.1", + minor_mapping = {}, ) env.expect.that_collection(got.deps).contains_exactly([]) env.expect.that_dict(got.deps_select).contains_exactly({ "cp310_linux_aarch64": ["bar"], "cp310_linux_x86_64": ["bar"], - "cp37_linux_aarch64": ["bar"], + "cp37.1_linux_aarch64": ["bar"], "linux_aarch64": ["bar"], })
diff --git a/tests/pypi/render_pkg_aliases/render_pkg_aliases_test.bzl b/tests/pypi/render_pkg_aliases/render_pkg_aliases_test.bzl index c60761b..416d50b 100644 --- a/tests/pypi/render_pkg_aliases/render_pkg_aliases_test.bzl +++ b/tests/pypi/render_pkg_aliases/render_pkg_aliases_test.bzl
@@ -68,7 +68,8 @@ aliases = { "bar-baz": { whl_config_setting( - version = "3.2", + # Add one with micro version to mimic construction in the extension + version = "3.2.2", config_setting = "//:my_config_setting", ): "pypi_32_bar_baz", whl_config_setting( @@ -83,10 +84,10 @@ filename = "foo-0.0.0-py3-none-any.whl", ): "filename_repo", whl_config_setting( - version = "3.2", + version = "3.2.2", filename = "foo-0.0.0-py3-none-any.whl", target_platforms = [ - "cp32_linux_x86_64", + "cp32.2_linux_x86_64", ], ): "filename_repo_linux_x86_64", }, @@ -117,7 +118,7 @@ whl_config_setting( filename = "foo-0.0.0-py3-none-any.whl", target_platforms = ("cp32_linux_x86_64",), - version = "3.2", + version = "3.2.2", ): "filename_repo_linux_x86_64", }, extra_aliases = ["foo"],
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 61e5441..432cdbf 100644 --- a/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl +++ b/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl
@@ -68,9 +68,8 @@ "@//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"], - "cp39_anyos_aarch64": ["py39_arm_dep"], - "cp39_linux_anyarch": ["py39_linux_dep"], "linux_x86_64": ["linux_intel_dep"], }, filegroups = {}, @@ -82,39 +81,34 @@ env.expect.that_collection(calls).contains_exactly([ { - "name": "is_python_3.10_linux_ppc64le", - "flag_values": { - "@rules_python//python/config_settings:python_version_major_minor": "3.10", - }, + "name": "is_python_3.10.11_linux_ppc64le", + "visibility": ["//visibility:private"], "constraint_values": [ "@platforms//cpu:ppc64le", "@platforms//os:linux", ], - "visibility": ["//visibility:private"], + "flag_values": { + Label("//python/config_settings:python_version"): "3.10.11", + }, }, { - "name": "is_python_3.9_anyos_aarch64", - "flag_values": { - "@rules_python//python/config_settings:python_version_major_minor": "3.9", - }, - "constraint_values": ["@platforms//cpu:aarch64"], + "name": "is_python_3.10_linux_ppc64le", "visibility": ["//visibility:private"], - }, - { - "name": "is_python_3.9_linux_anyarch", + "constraint_values": [ + "@platforms//cpu:ppc64le", + "@platforms//os:linux", + ], "flag_values": { - "@rules_python//python/config_settings:python_version_major_minor": "3.9", + Label("//python/config_settings:python_version"): "3.10", }, - "constraint_values": ["@platforms//os:linux"], - "visibility": ["//visibility:private"], }, { "name": "is_linux_x86_64", + "visibility": ["//visibility:private"], "constraint_values": [ "@platforms//cpu:x86_64", "@platforms//os:linux", ], - "visibility": ["//visibility:private"], }, ]) # buildifier: @unsorted-dict-items
diff --git a/tests/pypi/whl_target_platforms/select_whl_tests.bzl b/tests/pypi/whl_target_platforms/select_whl_tests.bzl index 8ab2413..1674ac5 100644 --- a/tests/pypi/whl_target_platforms/select_whl_tests.bzl +++ b/tests/pypi/whl_target_platforms/select_whl_tests.bzl
@@ -289,6 +289,22 @@ _tests.append(_test_freethreaded_wheels) +def _test_micro_version_freethreaded(env): + # Check we prefer platform specific wheels + got = _select_whls(whls = WHL_LIST, want_platforms = ["cp313.3_linux_x86_64"]) + _match( + env, + got, + "pkg-0.0.1-cp313-cp313t-musllinux_1_1_x86_64.whl", + "pkg-0.0.1-cp313-cp313-musllinux_1_1_x86_64.whl", + "pkg-0.0.1-cp313-abi3-musllinux_1_1_x86_64.whl", + "pkg-0.0.1-cp313-none-musllinux_1_1_x86_64.whl", + "pkg-0.0.1-cp39-abi3-any.whl", + "pkg-0.0.1-py3-none-any.whl", + ) + +_tests.append(_test_micro_version_freethreaded) + def select_whl_test_suite(name): """Create the test suite.