From 2b758d07f62e372d81162740c36437974918449b Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Thu, 25 Sep 2025 11:48:12 +0000 Subject: [PATCH 1/9] WIP: add env override attrs Do minor version mapping --- python/private/python.bzl | 120 +++++++++++++++++++++++++++------- tests/python/python_tests.bzl | 6 -- 2 files changed, 95 insertions(+), 31 deletions(-) diff --git a/python/private/python.bzl b/python/private/python.bzl index 6eb8a3742e..a37955a0d5 100644 --- a/python/private/python.bzl +++ b/python/private/python.bzl @@ -15,7 +15,7 @@ "Python toolchain module extensions for use with bzlmod." load("@bazel_features//:features.bzl", "bazel_features") -load("//python:versions.bzl", "DEFAULT_RELEASE_BASE_URL", "PLATFORMS", "TOOL_VERSIONS") +load("//python:versions.bzl", "DEFAULT_RELEASE_BASE_URL", "MINOR_MAPPING", "PLATFORMS", "TOOL_VERSIONS") load(":auth.bzl", "AUTH_ATTRS") load(":full_version.bzl", "full_version") load(":platform_info.bzl", "platform_info") @@ -84,7 +84,7 @@ def parse_modules(*, module_ctx, logger, _fail = fail): if not module_ctx.modules[0].tags.toolchain: ignore_root_user_error = True - config = _get_toolchain_config(modules = module_ctx.modules, _fail = _fail) + config = _get_toolchain_config(module_ctx = module_ctx, _fail = _fail) default_python_version = None for mod in module_ctx.modules: @@ -598,7 +598,7 @@ def _validate_version(version_str, *, _fail = fail): return True -def _process_single_version_overrides(*, tag, _fail = fail, default): +def _process_single_version_overrides(*, tag, _fail = fail, default, module_ctx=None): if not _validate_version(tag.python_version, _fail = _fail): return @@ -648,31 +648,65 @@ def _process_single_version_overrides(*, tag, _fail = fail, default): if tag.distutils: kwargs.setdefault(tag.python_version, {})["distutils"] = tag.distutils -def _process_single_version_platform_overrides(*, tag, _fail = fail, default): - if not _validate_version(tag.python_version, _fail = _fail): +def _process_single_version_platform_overrides(*, tag, _fail = fail, default, module_ctx): + python_version = tag.python_version + python_version_env = getattr(tag, "python_version_env", None) + if python_version_env: + python_version = module_ctx.getenv(python_version_env, python_version) + + if not python_version: + _fail("Either `python_version` or `python_version_env` must be specified and non-empty for python.single_version_platform_override.") + return + + parsed_version = version.parse(python_version, _fail = _fail) + if not parsed_version: + _fail("Failed to parse PEP 440 version identifier '{}'. Parse error at '{}'".format(python_version, python_version)) + return + if len(parsed_version.release) < 3: + if python_version in MINOR_MAPPING: + python_version = MINOR_MAPPING[python_version] + + if not _validate_version(python_version, _fail = _fail): return available_versions = default["tool_versions"] - if tag.python_version not in available_versions: - if not tag.urls or not tag.sha256 or not tag.strip_prefix: - _fail("When introducing a new python_version '{}', 'sha256', 'strip_prefix' and 'urls' must be specified".format(tag.python_version)) + sha256 = getattr(tag, "sha256", None) + sha256_env = getattr(tag, "sha256_env", None) + if sha256_env: + sha256 = module_ctx.getenv(sha256_env, sha256) + + strip_prefix = tag.strip_prefix + strip_prefix_env = getattr(tag, "strip_prefix_env", None) + if strip_prefix_env: + strip_prefix = module_ctx.getenv(strip_prefix_env, strip_prefix) + + urls = getattr(tag, "urls", None) + url_env = getattr(tag, "url_env", None) + if url_env: + urls_from_env = module_ctx.getenv(url_env) + if urls_from_env: + urls = [url.strip() for url in urls_from_env.split(",")] + + if python_version not in available_versions: + if not urls or not sha256 or not strip_prefix: + _fail("When introducing a new python_version '{}', 'sha256', 'strip_prefix' and 'urls' must be specified".format(python_version)) return - available_versions[tag.python_version] = {} + available_versions[python_version] = {} if tag.coverage_tool: - available_versions[tag.python_version].setdefault("coverage_tool", {})[tag.platform] = tag.coverage_tool + available_versions[python_version].setdefault("coverage_tool", {})[tag.platform] = tag.coverage_tool if tag.patch_strip: - available_versions[tag.python_version].setdefault("patch_strip", {})[tag.platform] = tag.patch_strip + available_versions[python_version].setdefault("patch_strip", {})[tag.platform] = tag.patch_strip if tag.patches: - available_versions[tag.python_version].setdefault("patches", {})[tag.platform] = list(tag.patches) - if tag.sha256: - available_versions[tag.python_version].setdefault("sha256", {})[tag.platform] = tag.sha256 - if tag.strip_prefix: - available_versions[tag.python_version].setdefault("strip_prefix", {})[tag.platform] = tag.strip_prefix + available_versions[python_version].setdefault("patches", {})[tag.platform] = list(tag.patches) + if sha256: + available_versions[python_version].setdefault("sha256", {})[tag.platform] = sha256 + if strip_prefix: + available_versions[python_version].setdefault("strip_prefix", {})[tag.platform] = strip_prefix - if tag.urls: - available_versions[tag.python_version].setdefault("url", {})[tag.platform] = tag.urls + if urls: + available_versions[python_version].setdefault("url", {})[tag.platform] = urls # If platform is customized, or doesn't exist, (re)define one. if ((tag.target_compatible_with or tag.target_settings or tag.os_name or tag.arch) or @@ -720,7 +754,7 @@ def _process_single_version_platform_overrides(*, tag, _fail = fail, default): default["platforms"] = override_first -def _process_global_overrides(*, tag, default, _fail = fail): +def _process_global_overrides(*, tag, default, _fail = fail, module_ctx=None): if tag.available_python_versions: available_versions = default["tool_versions"] all_versions = dict(available_versions) @@ -755,8 +789,8 @@ def _process_global_overrides(*, tag, default, _fail = fail): if getattr(tag, key, None): default[key] = getattr(tag, key) -def _override_defaults(*overrides, modules, _fail = fail, default): - mod = modules[0] if modules else None +def _override_defaults(*overrides, module_ctx, _fail = fail, default): + mod = module_ctx.modules[0] if module_ctx.modules else None if not mod or not mod.is_root: return @@ -774,9 +808,9 @@ def _override_defaults(*overrides, modules, _fail = fail, default): _fail("Only a single 'python.{}' can be present".format(override.name)) return - override.fn(tag = tag, _fail = _fail, default = default) + override.fn(tag = tag, _fail = _fail, default = default, module_ctx = module_ctx) -def _get_toolchain_config(*, modules, _fail = fail): +def _get_toolchain_config(*, module_ctx, _fail = fail): """Computes the configs for toolchains. Args: @@ -848,7 +882,7 @@ def _get_toolchain_config(*, modules, _fail = fail): key = lambda t: None, fn = _process_global_overrides, ), - modules = modules, + module_ctx = module_ctx, default = default, _fail = _fail, ) @@ -1296,18 +1330,45 @@ Arbitrary platform strings allowed. ), ), "python_version": attr.string( - mandatory = True, + mandatory = False, doc = "The python version to override URLs for. Must be in `X.Y.Z` format.", ), + "python_version_env": attr.string( + mandatory = False, + doc = """\ +The environment variable for the python version. Overrides `python_version` if set. + +:::{{versionadded}} 1.6.0 +::: +""", + ), "sha256": attr.string( mandatory = False, doc = "The sha256 for the archive", ), + "sha256_env": attr.string( + mandatory = False, + doc = """\ +The environment variable for the sha256. Overrides `sha256` if set. + +:::{{versionadded}} 1.6.0 +::: +""", + ), "strip_prefix": attr.string( mandatory = False, doc = "The 'strip_prefix' for the archive, defaults to 'python'.", default = "python", ), + "strip_prefix_env": attr.string( + mandatory = False, + doc = """\ +The environment variable for the strip_prefix. Overrides `strip_prefix` if set. + +:::{{versionadded}} 1.6.0 +::: +""", + ), "target_compatible_with": attr.string_list( doc = """ The `target_compatible_with` values to use for the toolchain definition. @@ -1342,6 +1403,15 @@ Docs for [Registering custom runtimes] mandatory = False, doc = "The URL template to fetch releases for this Python version. If the URL template results in a relative fragment, default base URL is going to be used. Occurrences of `{python_version}`, `{platform}` and `{build}` will be interpolated based on the contents in the override and the known {attr}`platform` values.", ), + "url_env": attr.string( + mandatory = False, + doc = """\ +The environment variable for a comma-separated list of URLs. Overrides `urls` if set. + +:::{{versionadded}} 1.6.0 +::: +""", + ), }, ) diff --git a/tests/python/python_tests.bzl b/tests/python/python_tests.bzl index 9081a0e306..fd5a0bb0a5 100644 --- a/tests/python/python_tests.bzl +++ b/tests/python/python_tests.bzl @@ -795,12 +795,6 @@ def _test_single_version_platform_override_errors(env): ], want_error = "Only a single 'python.single_version_platform_override' can be present for '(\"3.12.4\", \"foo\")'", ), - struct( - overrides = [ - _single_version_platform_override(python_version = "3.12", platform = "foo"), - ], - want_error = "The 'python_version' attribute needs to specify the full version in at least 'X.Y.Z' format, got: '3.12'", - ), struct( overrides = [ _single_version_platform_override(python_version = "foo", platform = "foo"), From 77e65a32e51346a04873ec27f942981b68080738 Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Fri, 26 Sep 2025 10:38:24 +0000 Subject: [PATCH 2/9] Add test --- tests/python/python_tests.bzl | 92 +++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 3 deletions(-) diff --git a/tests/python/python_tests.bzl b/tests/python/python_tests.bzl index fd5a0bb0a5..13a0cdeab0 100644 --- a/tests/python/python_tests.bzl +++ b/tests/python/python_tests.bzl @@ -117,19 +117,27 @@ def _single_version_platform_override( patches = [], platform = "", python_version = "", + python_version_env = None, sha256 = "", + sha256_env = None, strip_prefix = "python", - urls = []): - if not platform or not python_version: - fail("missing mandatory args: platform ({}) and python_version ({})".format(platform, python_version)) + strip_prefix_env = None, + urls = [], + url_env = None): + if not platform: + fail("missing mandatory arg: platform") return struct( sha256 = sha256, + sha256_env = sha256_env, urls = urls, + url_env = url_env, strip_prefix = strip_prefix, + strip_prefix_env = strip_prefix_env, platform = platform, coverage_tool = coverage_tool, python_version = python_version, + python_version_env = python_version_env, patch_strip = patch_strip, patches = patches, target_compatible_with = [], @@ -818,6 +826,84 @@ def _test_single_version_platform_override_errors(env): _tests.append(_test_single_version_platform_override_errors) +def _test_single_version_platform_override_from_env(env): + py = parse_modules( + module_ctx = _mock_mctx( + _mod( + name = "my_module", + toolchain = [_toolchain("3.13")], + single_version_platform_override = [ + _single_version_platform_override( + platform = "aarch64-unknown-linux-gnu", + python_version_env = "PYTHON_VERSION_ENV", + sha256_env = "SHA256_ENV", + strip_prefix_env = "STRIP_PREFIX_ENV", + url_env = "URL_ENV", + ), + ], + override = [ + _override( + available_python_versions = ["3.13.6"], + ), + ], + ), + environ = { + "PYTHON_VERSION_ENV": "3.13", + "SHA256_ENV": "deadbeef", + "STRIP_PREFIX_ENV": "my-prefix", + "URL_ENV": "example.com,example.org", + }, + ), + logger = repo_utils.logger(verbosity_level = 0, name = "python"), + ) + + env.expect.that_dict(py.config.default["tool_versions"]["3.13.6"]).contains_exactly({ + "sha256": {"aarch64-unknown-linux-gnu": "deadbeef"}, + "strip_prefix": {"aarch64-unknown-linux-gnu": "my-prefix"}, + "url": {"aarch64-unknown-linux-gnu": ["example.com", "example.org"]}, + }) + +_tests.append(_test_single_version_platform_override_from_env) + +# def _test_single_version_platform_override_from_env_minor_version(env): +# py = parse_modules( +# module_ctx = _mock_mctx( +# _mod( +# name = "my_module", +# toolchain = [_toolchain("3.13")], +# single_version_platform_override = [ +# _single_version_platform_override( +# platform = "aarch64-unknown-linux-gnu", +# python_version_env = "PYTHON_VERSION_ENV", +# sha256_env = "SHA256_ENV", +# strip_prefix_env = "STRIP_PREFIX_ENV", +# url_env = "URL_ENV", +# ), +# ], +# override = [ +# _override( +# available_python_versions = ["3.13.6"], +# ), +# ], +# ), +# environ = { +# "PYTHON_VERSION_ENV": "3.13", +# "SHA256_ENV": "deadbeef", +# "STRIP_PREFIX_ENV": "my-prefix", +# "URL_ENV": "example.com,example.org", +# }, +# ), +# logger = repo_utils.logger(verbosity_level = 0, name = "python"), +# ) + +# env.expect.that_dict(py.config.default["tool_versions"]["3.13.6"]).contains_exactly({ +# "sha256": {"aarch64-unknown-linux-gnu": "deadbeef"}, +# "strip_prefix": {"aarch64-unknown-linux-gnu": "my-prefix"}, +# "url": {"aarch64-unknown-linux-gnu": ["example.com", "example.org"]}, +# }) + +# _tests.append(_test_single_version_platform_override_from_env_minor_version) + # TODO @aignas 2024-09-03: add failure tests: # * incorrect platform failure # * missing python_version failure From 209248789f8fc2e038d44dd60ddf74ff4ce383de Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Fri, 26 Sep 2025 10:38:45 +0000 Subject: [PATCH 3/9] Add test --- tests/python/python_tests.bzl | 80 +++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/tests/python/python_tests.bzl b/tests/python/python_tests.bzl index 13a0cdeab0..5c617769d3 100644 --- a/tests/python/python_tests.bzl +++ b/tests/python/python_tests.bzl @@ -827,6 +827,45 @@ def _test_single_version_platform_override_errors(env): _tests.append(_test_single_version_platform_override_errors) def _test_single_version_platform_override_from_env(env): + py = parse_modules( + module_ctx = _mock_mctx( + _mod( + name = "my_module", + toolchain = [_toolchain("3.13")], + single_version_platform_override = [ + _single_version_platform_override( + platform = "aarch64-unknown-linux-gnu", + python_version_env = "PYTHON_VERSION_ENV", + sha256_env = "SHA256_ENV", + strip_prefix_env = "STRIP_PREFIX_ENV", + url_env = "URL_ENV", + ), + ], + override = [ + _override( + available_python_versions = ["3.13.99"], + ), + ], + ), + environ = { + "PYTHON_VERSION_ENV": "3.13.99", + "SHA256_ENV": "deadbeef", + "STRIP_PREFIX_ENV": "my-prefix", + "URL_ENV": "example.com,example.org", + }, + ), + logger = repo_utils.logger(verbosity_level = 0, name = "python"), + ) + + env.expect.that_dict(py.config.default["tool_versions"]["3.13.99"]).contains_exactly({ + "sha256": {"aarch64-unknown-linux-gnu": "deadbeef"}, + "strip_prefix": {"aarch64-unknown-linux-gnu": "my-prefix"}, + "url": {"aarch64-unknown-linux-gnu": ["example.com", "example.org"]}, + }) + +_tests.append(_test_single_version_platform_override_from_env) + +def _test_single_version_platform_override_from_env_minor_version(env): py = parse_modules( module_ctx = _mock_mctx( _mod( @@ -863,46 +902,7 @@ def _test_single_version_platform_override_from_env(env): "url": {"aarch64-unknown-linux-gnu": ["example.com", "example.org"]}, }) -_tests.append(_test_single_version_platform_override_from_env) - -# def _test_single_version_platform_override_from_env_minor_version(env): -# py = parse_modules( -# module_ctx = _mock_mctx( -# _mod( -# name = "my_module", -# toolchain = [_toolchain("3.13")], -# single_version_platform_override = [ -# _single_version_platform_override( -# platform = "aarch64-unknown-linux-gnu", -# python_version_env = "PYTHON_VERSION_ENV", -# sha256_env = "SHA256_ENV", -# strip_prefix_env = "STRIP_PREFIX_ENV", -# url_env = "URL_ENV", -# ), -# ], -# override = [ -# _override( -# available_python_versions = ["3.13.6"], -# ), -# ], -# ), -# environ = { -# "PYTHON_VERSION_ENV": "3.13", -# "SHA256_ENV": "deadbeef", -# "STRIP_PREFIX_ENV": "my-prefix", -# "URL_ENV": "example.com,example.org", -# }, -# ), -# logger = repo_utils.logger(verbosity_level = 0, name = "python"), -# ) - -# env.expect.that_dict(py.config.default["tool_versions"]["3.13.6"]).contains_exactly({ -# "sha256": {"aarch64-unknown-linux-gnu": "deadbeef"}, -# "strip_prefix": {"aarch64-unknown-linux-gnu": "my-prefix"}, -# "url": {"aarch64-unknown-linux-gnu": ["example.com", "example.org"]}, -# }) - -# _tests.append(_test_single_version_platform_override_from_env_minor_version) +_tests.append(_test_single_version_platform_override_from_env_minor_version) # TODO @aignas 2024-09-03: add failure tests: # * incorrect platform failure From 31c386df700881a8afdd5dfbedeed4ac332e30f3 Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Fri, 26 Sep 2025 10:41:06 +0000 Subject: [PATCH 4/9] Add test --- tests/python/python_tests.bzl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/python/python_tests.bzl b/tests/python/python_tests.bzl index 5c617769d3..cdd3f7e0a6 100644 --- a/tests/python/python_tests.bzl +++ b/tests/python/python_tests.bzl @@ -896,11 +896,10 @@ def _test_single_version_platform_override_from_env_minor_version(env): logger = repo_utils.logger(verbosity_level = 0, name = "python"), ) - env.expect.that_dict(py.config.default["tool_versions"]["3.13.6"]).contains_exactly({ - "sha256": {"aarch64-unknown-linux-gnu": "deadbeef"}, - "strip_prefix": {"aarch64-unknown-linux-gnu": "my-prefix"}, - "url": {"aarch64-unknown-linux-gnu": ["example.com", "example.org"]}, - }) + tool_versions = py.config.default["tool_versions"]["3.13.6"] + env.expect.that_str(tool_versions["sha256"]["aarch64-unknown-linux-gnu"]).equals("deadbeef") + env.expect.that_str(tool_versions["strip_prefix"]["aarch64-unknown-linux-gnu"]).equals("my-prefix") + env.expect.that_collection(tool_versions["url"]["aarch64-unknown-linux-gnu"]).contains_exactly(["example.com", "example.org"]) _tests.append(_test_single_version_platform_override_from_env_minor_version) From 26b0ae2864987f81f33ec569ed5a4f926de24361 Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Fri, 26 Sep 2025 11:37:41 +0000 Subject: [PATCH 5/9] Fix version --- python/private/python.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/private/python.bzl b/python/private/python.bzl index a37955a0d5..a768655e0e 100644 --- a/python/private/python.bzl +++ b/python/private/python.bzl @@ -1338,7 +1338,7 @@ Arbitrary platform strings allowed. doc = """\ The environment variable for the python version. Overrides `python_version` if set. -:::{{versionadded}} 1.6.0 +:::{{versionadded}} 1.6.4 ::: """, ), @@ -1351,7 +1351,7 @@ The environment variable for the python version. Overrides `python_version` if s doc = """\ The environment variable for the sha256. Overrides `sha256` if set. -:::{{versionadded}} 1.6.0 +:::{{versionadded}} 1.6.4 ::: """, ), @@ -1365,7 +1365,7 @@ The environment variable for the sha256. Overrides `sha256` if set. doc = """\ The environment variable for the strip_prefix. Overrides `strip_prefix` if set. -:::{{versionadded}} 1.6.0 +:::{{versionadded}} 1.6.4 ::: """, ), @@ -1408,7 +1408,7 @@ Docs for [Registering custom runtimes] doc = """\ The environment variable for a comma-separated list of URLs. Overrides `urls` if set. -:::{{versionadded}} 1.6.0 +:::{{versionadded}} 1.6.4 ::: """, ), From e520823c6561c2ed6332a32dad9ef6eb88b8004a Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Fri, 26 Sep 2025 13:38:37 +0200 Subject: [PATCH 6/9] Update python/private/python.bzl Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- python/private/python.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/private/python.bzl b/python/private/python.bzl index a768655e0e..c945a992db 100644 --- a/python/private/python.bzl +++ b/python/private/python.bzl @@ -686,7 +686,7 @@ def _process_single_version_platform_overrides(*, tag, _fail = fail, default, mo if url_env: urls_from_env = module_ctx.getenv(url_env) if urls_from_env: - urls = [url.strip() for url in urls_from_env.split(",")] + urls = [url.strip() for url in urls_from_env.split(",") if url.strip()] if python_version not in available_versions: if not urls or not sha256 or not strip_prefix: From dbb6f11566add36834abd8e1d697aa7923f6daff Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Fri, 26 Sep 2025 11:41:30 +0000 Subject: [PATCH 7/9] Run buildifier --- python/private/python.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/private/python.bzl b/python/private/python.bzl index c945a992db..8faf8d0976 100644 --- a/python/private/python.bzl +++ b/python/private/python.bzl @@ -598,7 +598,7 @@ def _validate_version(version_str, *, _fail = fail): return True -def _process_single_version_overrides(*, tag, _fail = fail, default, module_ctx=None): +def _process_single_version_overrides(*, tag, _fail = fail, default, module_ctx = None): if not _validate_version(tag.python_version, _fail = _fail): return @@ -754,7 +754,7 @@ def _process_single_version_platform_overrides(*, tag, _fail = fail, default, mo default["platforms"] = override_first -def _process_global_overrides(*, tag, default, _fail = fail, module_ctx=None): +def _process_global_overrides(*, tag, default, _fail = fail, module_ctx = None): if tag.available_python_versions: available_versions = default["tool_versions"] all_versions = dict(available_versions) From 84063faca48812f28583dffbd966520f281dfb7c Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Fri, 26 Sep 2025 12:02:11 +0000 Subject: [PATCH 8/9] Make buildifier happy --- python/private/python.bzl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/python/private/python.bzl b/python/private/python.bzl index 8faf8d0976..c3a5df6f97 100644 --- a/python/private/python.bzl +++ b/python/private/python.bzl @@ -598,7 +598,7 @@ def _validate_version(version_str, *, _fail = fail): return True -def _process_single_version_overrides(*, tag, _fail = fail, default, module_ctx = None): +def _process_single_version_overrides(*, tag, _fail = fail, default, module_ctx = None): # buildifier: disable=unused-variable if not _validate_version(tag.python_version, _fail = _fail): return @@ -754,7 +754,7 @@ def _process_single_version_platform_overrides(*, tag, _fail = fail, default, mo default["platforms"] = override_first -def _process_global_overrides(*, tag, default, _fail = fail, module_ctx = None): +def _process_global_overrides(*, tag, default, _fail = fail, module_ctx = None): # buildifier: disable=unused-variable if tag.available_python_versions: available_versions = default["tool_versions"] all_versions = dict(available_versions) @@ -814,7 +814,7 @@ def _get_toolchain_config(*, module_ctx, _fail = fail): """Computes the configs for toolchains. Args: - modules: The modules from module_ctx + module_ctx: {type}`module_ctx` module context. _fail: Function to call for failing; only used for testing. Returns: @@ -1399,10 +1399,6 @@ Docs for [Registering custom runtimes] ::: """, ), - "urls": attr.string_list( - mandatory = False, - doc = "The URL template to fetch releases for this Python version. If the URL template results in a relative fragment, default base URL is going to be used. Occurrences of `{python_version}`, `{platform}` and `{build}` will be interpolated based on the contents in the override and the known {attr}`platform` values.", - ), "url_env": attr.string( mandatory = False, doc = """\ @@ -1412,6 +1408,10 @@ The environment variable for a comma-separated list of URLs. Overrides `urls` if ::: """, ), + "urls": attr.string_list( + mandatory = False, + doc = "The URL template to fetch releases for this Python version. If the URL template results in a relative fragment, default base URL is going to be used. Occurrences of `{python_version}`, `{platform}` and `{build}` will be interpolated based on the contents in the override and the known {attr}`platform` values.", + ), }, ) From efa4675f1c1fb10d625b9bdcb166b8d89f1b82c5 Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Fri, 26 Sep 2025 12:04:22 +0000 Subject: [PATCH 9/9] Update doc --- python/private/python.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/private/python.bzl b/python/private/python.bzl index c3a5df6f97..f9a3a20c76 100644 --- a/python/private/python.bzl +++ b/python/private/python.bzl @@ -1331,7 +1331,7 @@ Arbitrary platform strings allowed. ), "python_version": attr.string( mandatory = False, - doc = "The python version to override URLs for. Must be in `X.Y.Z` format.", + doc = "The python version to override URLs for. Must be in `X.Y.Z` or `X.Y` format.", ), "python_version_env": attr.string( mandatory = False,