diff --git a/examples/bzlmod/MODULE.bazel.lock b/examples/bzlmod/MODULE.bazel.lock index d747ed35d..e4bc1e3e2 100644 --- a/examples/bzlmod/MODULE.bazel.lock +++ b/examples/bzlmod/MODULE.bazel.lock @@ -1231,7 +1231,7 @@ }, "@@rules_python~//python/extensions:pip.bzl%pip": { "general": { - "bzlTransitiveDigest": "vzdh1M3LRVqyF10AVUO1+FOE7CZwlZaFT+7RgQ4OKXg=", + "bzlTransitiveDigest": "X5mAzRTQVEblHlQ3C6fQ5P2dKhhI1botl80drDbpYd8=", "usagesDigest": "MChlcSw99EuW3K7OOoMcXQIdcJnEh6YmfyjJm+9mxIg=", "recordedFileInputs": { "@@other_module~//requirements_lock_3_11.txt": "a7d0061366569043d5efcf80e34a32c732679367cb3c831c4cdc606adc36d314", @@ -6140,7 +6140,7 @@ }, "@@rules_python~//python/private/pypi:pip.bzl%pip_internal": { "general": { - "bzlTransitiveDigest": "TgRegkReKbGzK4VxYz9up697gcf5Q8NFuZYnZHryck8=", + "bzlTransitiveDigest": "izcO4fumi7/gLahZx0w1QGqPMKtNdbFpL+ixwYJtnLk=", "usagesDigest": "Y8ihY+R57BAFhalrVLVdJFrpwlbsiKz9JPJ99ljF7HA=", "recordedFileInputs": { "@@rules_python~//tools/publish/requirements.txt": "031e35d03dde03ae6305fe4b3d1f58ad7bdad857379752deede0f93649991b8a", diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index 7b913df2b..3d2361442 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -114,7 +114,6 @@ bzl_library( bzl_library( name = "full_version_bzl", srcs = ["full_version.bzl"], - deps = ["//python:versions_bzl"], ) bzl_library( @@ -132,6 +131,7 @@ bzl_library( name = "python_bzl", srcs = ["python.bzl"], deps = [ + ":full_version_bzl", ":pythons_hub_bzl", ":repo_utils_bzl", ":toolchains_repo_bzl", @@ -164,7 +164,6 @@ bzl_library( deps = [ ":full_version_bzl", ":py_toolchain_suite_bzl", - "//python:versions_bzl", ], ) diff --git a/python/private/config_settings.bzl b/python/private/config_settings.bzl index 99b8b94ad..301a97b25 100644 --- a/python/private/config_settings.bzl +++ b/python/private/config_settings.bzl @@ -27,14 +27,15 @@ def _ver_key(s): micro, _, s = s.partition(".") return (int(major), int(minor), int(micro)) -def _flag_values(python_versions): +def _flag_values(*, python_versions, minor_mapping): """Construct a map of python_version to a list of toolchain values. This mapping maps the concept of a config setting to a list of compatible toolchain versions. For using this in the code, the VERSION_FLAG_VALUES should be used instead. Args: - python_versions: list of strings; all X.Y.Z python versions + python_versions: {type}`list[str]` X.Y.Z` python versions. + minor_mapping: {type}`dict[str, str]` `X.Y` to `X.Y.Z` mapping. Returns: A `map[str, list[str]]`. Each key is a python_version flag value. Each value @@ -61,13 +62,13 @@ def _flag_values(python_versions): ret.setdefault(minor_version, [minor_version]).append(micro_version) # Ensure that is_python_3.9.8 is matched if python_version is set - # to 3.9 if MINOR_MAPPING points to 3.9.8 - default_micro_version = MINOR_MAPPING[minor_version] + # to 3.9 if minor_mapping points to 3.9.8 + default_micro_version = minor_mapping[minor_version] ret[micro_version] = [micro_version, minor_version] if default_micro_version == micro_version else [micro_version] return ret -VERSION_FLAG_VALUES = _flag_values(TOOL_VERSIONS.keys()) +VERSION_FLAG_VALUES = _flag_values(python_versions = TOOL_VERSIONS.keys(), minor_mapping = MINOR_MAPPING) def is_python_config_setting(name, *, python_version, reuse_conditions = None, **kwargs): """Create a config setting for matching 'python_version' configuration flag. diff --git a/python/private/full_version.bzl b/python/private/full_version.bzl index 98eeee59a..0292d6c77 100644 --- a/python/private/full_version.bzl +++ b/python/private/full_version.bzl @@ -14,20 +14,19 @@ """A small helper to ensure that we are working with full versions.""" -load("//python:versions.bzl", "MINOR_MAPPING") - -def full_version(version): +def full_version(*, version, minor_mapping): """Return a full version. Args: - version: the version in `X.Y` or `X.Y.Z` format. + version: {type}`str` the version in `X.Y` or `X.Y.Z` format. + minor_mapping: {type}`dict[str, str]` mapping between `X.Y` to `X.Y.Z` format. Returns: a full version given the version string. If the string is already a major version then we return it as is. """ - if version in MINOR_MAPPING: - return MINOR_MAPPING[version] + if version in minor_mapping: + return minor_mapping[version] parts = version.split(".") if len(parts) == 3: @@ -36,7 +35,7 @@ def full_version(version): fail( "Unknown Python version '{}', available values are: {}".format( version, - ",".join(MINOR_MAPPING.keys()), + ",".join(minor_mapping.keys()), ), ) else: diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index 3b11dbe7f..eda66b120 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -287,6 +287,7 @@ bzl_library( srcs = ["whl_library_alias.bzl"], deps = [ ":render_pkg_aliases_bzl", + "//python:versions_bzl", "//python/private:full_version_bzl", ], ) diff --git a/python/private/pypi/whl_library_alias.bzl b/python/private/pypi/whl_library_alias.bzl index 263d7ec0e..5bcf89204 100644 --- a/python/private/pypi/whl_library_alias.bzl +++ b/python/private/pypi/whl_library_alias.bzl @@ -14,6 +14,7 @@ """whl_library aliases for multi_pip_parse.""" +load("//python:versions.bzl", "MINOR_MAPPING") load("//python/private:full_version.bzl", "full_version") load(":render_pkg_aliases.bzl", "NO_MATCH_ERROR_MESSAGE_TEMPLATE") @@ -29,6 +30,7 @@ def _whl_library_alias_impl(rctx): build_content.append(_whl_library_render_alias_target( alias_name = alias_name, default_repo_prefix = default_repo_prefix, + minor_mapping = rctx.minor_mapping, rules_python = rules_python, version_map = version_map, wheel_name = rctx.attr.wheel_name, @@ -36,8 +38,10 @@ def _whl_library_alias_impl(rctx): rctx.file("BUILD.bazel", "\n".join(build_content)) def _whl_library_render_alias_target( + *, alias_name, default_repo_prefix, + minor_mapping, rules_python, version_map, wheel_name): @@ -48,7 +52,7 @@ alias( for [python_version, repo_prefix] in version_map: alias.append("""\ "@{rules_python}//python/config_settings:is_python_{full_python_version}": "{actual}",""".format( - full_python_version = full_version(python_version), + full_python_version = full_version(version = python_version, minor_mapping = minor_mapping), actual = "@{repo_prefix}{wheel_name}//:{alias_name}".format( repo_prefix = repo_prefix, wheel_name = wheel_name, @@ -92,6 +96,7 @@ whl_library_alias = repository_rule( "not specified, then the default rules won't be able to " + "resolve a wheel and an error will occur.", ), + "minor_mapping": attr.string_dict(mandatory = True, default = MINOR_MAPPING), "version_map": attr.string_dict(mandatory = True), "wheel_name": attr.string(mandatory = True), "_rules_python_workspace": attr.label(default = Label("//:WORKSPACE")), diff --git a/python/private/python.bzl b/python/private/python.bzl index e1d13b9f1..9a9a240cb 100644 --- a/python/private/python.bzl +++ b/python/private/python.bzl @@ -16,9 +16,10 @@ load("@bazel_features//:features.bzl", "bazel_features") load("//python:repositories.bzl", "python_register_toolchains") -load("//python:versions.bzl", "TOOL_VERSIONS") -load("//python/private:repo_utils.bzl", "repo_utils") +load("//python:versions.bzl", "MINOR_MAPPING", "TOOL_VERSIONS") +load(":full_version.bzl", "full_version") load(":pythons_hub.bzl", "hub_repo") +load(":repo_utils.bzl", "repo_utils") load(":text_util.bzl", "render") load(":toolchains_repo.bzl", "multi_toolchain_aliases") load(":util.bzl", "IS_BAZEL_6_4_OR_HIGHER") @@ -184,6 +185,11 @@ def parse_modules(module_ctx): fail("more than {} python versions are not supported".format(_MAX_NUM_TOOLCHAINS)) return struct( + debug_info = debug_info, + default_python_version = toolchains[-1].python_version, + defaults = { + "ignore_root_user_error": ignore_root_user_error, + }, toolchains = [ struct( python_version = t.python_version, @@ -192,11 +198,6 @@ def parse_modules(module_ctx): ) for t in toolchains ], - debug_info = debug_info, - default_python_version = toolchains[-1].python_version, - defaults = { - "ignore_root_user_error": ignore_root_user_error, - }, ) def _python_impl(module_ctx): @@ -207,6 +208,7 @@ def _python_impl(module_ctx): name = toolchain_info.name, python_version = toolchain_info.python_version, register_coverage_tool = toolchain_info.register_coverage_tool, + minor_mapping = MINOR_MAPPING, **py.defaults ) @@ -220,7 +222,10 @@ def _python_impl(module_ctx): render.toolchain_prefix(index, toolchain.name, _TOOLCHAIN_INDEX_PAD_LENGTH) for index, toolchain in enumerate(py.toolchains) ], - toolchain_python_versions = [t.python_version for t in py.toolchains], + toolchain_python_versions = [ + full_version(version = t.python_version, minor_mapping = MINOR_MAPPING) + for t in py.toolchains + ], # The last toolchain is the default; it can't have version constraints # Despite the implication of the arg name, the values are strs, not bools toolchain_set_python_version_constraints = [ diff --git a/python/private/python_repositories.bzl b/python/private/python_repositories.bzl index b65127b96..4aff57d05 100644 --- a/python/private/python_repositories.bzl +++ b/python/private/python_repositories.bzl @@ -22,6 +22,7 @@ load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") load( "//python:versions.bzl", "DEFAULT_RELEASE_BASE_URL", + "MINOR_MAPPING", "PLATFORMS", "TOOL_VERSIONS", "get_release_info", @@ -583,6 +584,7 @@ def python_register_toolchains( register_coverage_tool = False, set_python_version_constraint = False, tool_versions = None, + minor_mapping = None, **kwargs): """Convenience macro for users which does typical setup. @@ -607,6 +609,8 @@ def python_register_toolchains( tool_versions: {type}`dict` contains a mapping of version with SHASUM and platform info. If not supplied, the defaults in python/versions.bzl will be used. + minor_mapping: {type}`dict[str, str]` contains a mapping from `X.Y` to `X.Y.Z` + version. **kwargs: passed to each {obj}`python_repository` call. """ @@ -616,8 +620,9 @@ def python_register_toolchains( base_url = kwargs.pop("base_url", DEFAULT_RELEASE_BASE_URL) tool_versions = tool_versions or TOOL_VERSIONS + minor_mapping = minor_mapping or MINOR_MAPPING - python_version = full_version(python_version) + python_version = full_version(version = python_version, minor_mapping = minor_mapping) toolchain_repo_name = "{name}_toolchains".format(name = name) diff --git a/python/private/pythons_hub.bzl b/python/private/pythons_hub.bzl index 7a8c874ed..da6c80d07 100644 --- a/python/private/pythons_hub.bzl +++ b/python/private/pythons_hub.bzl @@ -14,7 +14,6 @@ "Repo rule used by bzlmod extension to create a repo that has a map of Python interpreters and their labels" -load("//python/private:full_version.bzl", "full_version") load( "//python/private:toolchains_repo.bzl", "python_toolchain_build_file_content", @@ -59,7 +58,7 @@ def _hub_build_file_content( [ python_toolchain_build_file_content( prefix = prefixes[i], - python_version = full_version(python_versions[i]), + python_version = python_versions[i], set_python_version_constraint = set_python_version_constraints[i], user_repository_name = user_repository_names[i], ) @@ -123,7 +122,7 @@ This rule also writes out the various toolchains for the different Python versio implementation = _hub_repo_impl, attrs = { "default_python_version": attr.string( - doc = "Default Python version for the build.", + doc = "Default Python version for the build in `X.Y` or `X.Y.Z` format.", mandatory = True, ), "toolchain_prefixes": attr.string_list( @@ -131,7 +130,7 @@ This rule also writes out the various toolchains for the different Python versio mandatory = True, ), "toolchain_python_versions": attr.string_list( - doc = "List of Python versions for the toolchains", + doc = "List of Python versions for the toolchains. In `X.Y.Z` format.", mandatory = True, ), "toolchain_set_python_version_constraints": attr.string_list(