Skip to content

Commit 2b758d0

Browse files
committed
WIP: add env override attrs
Do minor version mapping
1 parent 05735c8 commit 2b758d0

2 files changed

Lines changed: 95 additions & 31 deletions

File tree

python/private/python.bzl

Lines changed: 95 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"Python toolchain module extensions for use with bzlmod."
1616

1717
load("@bazel_features//:features.bzl", "bazel_features")
18-
load("//python:versions.bzl", "DEFAULT_RELEASE_BASE_URL", "PLATFORMS", "TOOL_VERSIONS")
18+
load("//python:versions.bzl", "DEFAULT_RELEASE_BASE_URL", "MINOR_MAPPING", "PLATFORMS", "TOOL_VERSIONS")
1919
load(":auth.bzl", "AUTH_ATTRS")
2020
load(":full_version.bzl", "full_version")
2121
load(":platform_info.bzl", "platform_info")
@@ -84,7 +84,7 @@ def parse_modules(*, module_ctx, logger, _fail = fail):
8484
if not module_ctx.modules[0].tags.toolchain:
8585
ignore_root_user_error = True
8686

87-
config = _get_toolchain_config(modules = module_ctx.modules, _fail = _fail)
87+
config = _get_toolchain_config(module_ctx = module_ctx, _fail = _fail)
8888

8989
default_python_version = None
9090
for mod in module_ctx.modules:
@@ -598,7 +598,7 @@ def _validate_version(version_str, *, _fail = fail):
598598

599599
return True
600600

601-
def _process_single_version_overrides(*, tag, _fail = fail, default):
601+
def _process_single_version_overrides(*, tag, _fail = fail, default, module_ctx=None):
602602
if not _validate_version(tag.python_version, _fail = _fail):
603603
return
604604

@@ -648,31 +648,65 @@ def _process_single_version_overrides(*, tag, _fail = fail, default):
648648
if tag.distutils:
649649
kwargs.setdefault(tag.python_version, {})["distutils"] = tag.distutils
650650

651-
def _process_single_version_platform_overrides(*, tag, _fail = fail, default):
652-
if not _validate_version(tag.python_version, _fail = _fail):
651+
def _process_single_version_platform_overrides(*, tag, _fail = fail, default, module_ctx):
652+
python_version = tag.python_version
653+
python_version_env = getattr(tag, "python_version_env", None)
654+
if python_version_env:
655+
python_version = module_ctx.getenv(python_version_env, python_version)
656+
657+
if not python_version:
658+
_fail("Either `python_version` or `python_version_env` must be specified and non-empty for python.single_version_platform_override.")
659+
return
660+
661+
parsed_version = version.parse(python_version, _fail = _fail)
662+
if not parsed_version:
663+
_fail("Failed to parse PEP 440 version identifier '{}'. Parse error at '{}'".format(python_version, python_version))
664+
return
665+
if len(parsed_version.release) < 3:
666+
if python_version in MINOR_MAPPING:
667+
python_version = MINOR_MAPPING[python_version]
668+
669+
if not _validate_version(python_version, _fail = _fail):
653670
return
654671

655672
available_versions = default["tool_versions"]
656673

657-
if tag.python_version not in available_versions:
658-
if not tag.urls or not tag.sha256 or not tag.strip_prefix:
659-
_fail("When introducing a new python_version '{}', 'sha256', 'strip_prefix' and 'urls' must be specified".format(tag.python_version))
674+
sha256 = getattr(tag, "sha256", None)
675+
sha256_env = getattr(tag, "sha256_env", None)
676+
if sha256_env:
677+
sha256 = module_ctx.getenv(sha256_env, sha256)
678+
679+
strip_prefix = tag.strip_prefix
680+
strip_prefix_env = getattr(tag, "strip_prefix_env", None)
681+
if strip_prefix_env:
682+
strip_prefix = module_ctx.getenv(strip_prefix_env, strip_prefix)
683+
684+
urls = getattr(tag, "urls", None)
685+
url_env = getattr(tag, "url_env", None)
686+
if url_env:
687+
urls_from_env = module_ctx.getenv(url_env)
688+
if urls_from_env:
689+
urls = [url.strip() for url in urls_from_env.split(",")]
690+
691+
if python_version not in available_versions:
692+
if not urls or not sha256 or not strip_prefix:
693+
_fail("When introducing a new python_version '{}', 'sha256', 'strip_prefix' and 'urls' must be specified".format(python_version))
660694
return
661-
available_versions[tag.python_version] = {}
695+
available_versions[python_version] = {}
662696

663697
if tag.coverage_tool:
664-
available_versions[tag.python_version].setdefault("coverage_tool", {})[tag.platform] = tag.coverage_tool
698+
available_versions[python_version].setdefault("coverage_tool", {})[tag.platform] = tag.coverage_tool
665699
if tag.patch_strip:
666-
available_versions[tag.python_version].setdefault("patch_strip", {})[tag.platform] = tag.patch_strip
700+
available_versions[python_version].setdefault("patch_strip", {})[tag.platform] = tag.patch_strip
667701
if tag.patches:
668-
available_versions[tag.python_version].setdefault("patches", {})[tag.platform] = list(tag.patches)
669-
if tag.sha256:
670-
available_versions[tag.python_version].setdefault("sha256", {})[tag.platform] = tag.sha256
671-
if tag.strip_prefix:
672-
available_versions[tag.python_version].setdefault("strip_prefix", {})[tag.platform] = tag.strip_prefix
702+
available_versions[python_version].setdefault("patches", {})[tag.platform] = list(tag.patches)
703+
if sha256:
704+
available_versions[python_version].setdefault("sha256", {})[tag.platform] = sha256
705+
if strip_prefix:
706+
available_versions[python_version].setdefault("strip_prefix", {})[tag.platform] = strip_prefix
673707

674-
if tag.urls:
675-
available_versions[tag.python_version].setdefault("url", {})[tag.platform] = tag.urls
708+
if urls:
709+
available_versions[python_version].setdefault("url", {})[tag.platform] = urls
676710

677711
# If platform is customized, or doesn't exist, (re)define one.
678712
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):
720754

721755
default["platforms"] = override_first
722756

723-
def _process_global_overrides(*, tag, default, _fail = fail):
757+
def _process_global_overrides(*, tag, default, _fail = fail, module_ctx=None):
724758
if tag.available_python_versions:
725759
available_versions = default["tool_versions"]
726760
all_versions = dict(available_versions)
@@ -755,8 +789,8 @@ def _process_global_overrides(*, tag, default, _fail = fail):
755789
if getattr(tag, key, None):
756790
default[key] = getattr(tag, key)
757791

758-
def _override_defaults(*overrides, modules, _fail = fail, default):
759-
mod = modules[0] if modules else None
792+
def _override_defaults(*overrides, module_ctx, _fail = fail, default):
793+
mod = module_ctx.modules[0] if module_ctx.modules else None
760794
if not mod or not mod.is_root:
761795
return
762796

@@ -774,9 +808,9 @@ def _override_defaults(*overrides, modules, _fail = fail, default):
774808
_fail("Only a single 'python.{}' can be present".format(override.name))
775809
return
776810

777-
override.fn(tag = tag, _fail = _fail, default = default)
811+
override.fn(tag = tag, _fail = _fail, default = default, module_ctx = module_ctx)
778812

779-
def _get_toolchain_config(*, modules, _fail = fail):
813+
def _get_toolchain_config(*, module_ctx, _fail = fail):
780814
"""Computes the configs for toolchains.
781815
782816
Args:
@@ -848,7 +882,7 @@ def _get_toolchain_config(*, modules, _fail = fail):
848882
key = lambda t: None,
849883
fn = _process_global_overrides,
850884
),
851-
modules = modules,
885+
module_ctx = module_ctx,
852886
default = default,
853887
_fail = _fail,
854888
)
@@ -1296,18 +1330,45 @@ Arbitrary platform strings allowed.
12961330
),
12971331
),
12981332
"python_version": attr.string(
1299-
mandatory = True,
1333+
mandatory = False,
13001334
doc = "The python version to override URLs for. Must be in `X.Y.Z` format.",
13011335
),
1336+
"python_version_env": attr.string(
1337+
mandatory = False,
1338+
doc = """\
1339+
The environment variable for the python version. Overrides `python_version` if set.
1340+
1341+
:::{{versionadded}} 1.6.0
1342+
:::
1343+
""",
1344+
),
13021345
"sha256": attr.string(
13031346
mandatory = False,
13041347
doc = "The sha256 for the archive",
13051348
),
1349+
"sha256_env": attr.string(
1350+
mandatory = False,
1351+
doc = """\
1352+
The environment variable for the sha256. Overrides `sha256` if set.
1353+
1354+
:::{{versionadded}} 1.6.0
1355+
:::
1356+
""",
1357+
),
13061358
"strip_prefix": attr.string(
13071359
mandatory = False,
13081360
doc = "The 'strip_prefix' for the archive, defaults to 'python'.",
13091361
default = "python",
13101362
),
1363+
"strip_prefix_env": attr.string(
1364+
mandatory = False,
1365+
doc = """\
1366+
The environment variable for the strip_prefix. Overrides `strip_prefix` if set.
1367+
1368+
:::{{versionadded}} 1.6.0
1369+
:::
1370+
""",
1371+
),
13111372
"target_compatible_with": attr.string_list(
13121373
doc = """
13131374
The `target_compatible_with` values to use for the toolchain definition.
@@ -1342,6 +1403,15 @@ Docs for [Registering custom runtimes]
13421403
mandatory = False,
13431404
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.",
13441405
),
1406+
"url_env": attr.string(
1407+
mandatory = False,
1408+
doc = """\
1409+
The environment variable for a comma-separated list of URLs. Overrides `urls` if set.
1410+
1411+
:::{{versionadded}} 1.6.0
1412+
:::
1413+
""",
1414+
),
13451415
},
13461416
)
13471417

tests/python/python_tests.bzl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -795,12 +795,6 @@ def _test_single_version_platform_override_errors(env):
795795
],
796796
want_error = "Only a single 'python.single_version_platform_override' can be present for '(\"3.12.4\", \"foo\")'",
797797
),
798-
struct(
799-
overrides = [
800-
_single_version_platform_override(python_version = "3.12", platform = "foo"),
801-
],
802-
want_error = "The 'python_version' attribute needs to specify the full version in at least 'X.Y.Z' format, got: '3.12'",
803-
),
804798
struct(
805799
overrides = [
806800
_single_version_platform_override(python_version = "foo", platform = "foo"),

0 commit comments

Comments
 (0)