Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ A brief description of the categories of changes:
* **BREAKING** (wheel) The `incompatible_normalize_name` and
`incompatible_normalize_version` flags have been removed. They had been
flipped to `True` in 0.27.0 release.
* (bzlmod) The pip hub repository now uses the newly introduced config settings
using the `X.Y` python version notation. This improves cross module
interoperability and allows to share wheels built by interpreters using
different patch versions.

### Fixed

Expand Down
4 changes: 3 additions & 1 deletion examples/multi_python_versions/tests/my_lib_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,7 @@
if not my_lib.websockets_is_for_python_version(
workspace_version
) and not my_lib.websockets_is_for_python_version(bzlmod_version):
print("expected package for Python version is different than returned")
print("expected package for Python version is different than returned\n"
f"expected either {workspace_version} or {bzlmod_version}\n"
f"but got {my_lib.websockets.__file__}")
sys.exit(1)
11 changes: 7 additions & 4 deletions python/config_settings/config_settings.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def construct_config_settings(name, python_versions):

# Maps e.g. "3.8" -> ["3.8.1", "3.8.2", etc]
minor_to_micro_versions = {}

allowed_flag_values = []
for micro_version in python_versions:
minor, _, _ = micro_version.rpartition(".")
Expand All @@ -37,9 +38,12 @@ def construct_config_settings(name, python_versions):

string_flag(
name = "python_version",
# TODO: The default here should somehow match the MODULE config
build_setting_default = python_versions[0],
values = sorted(allowed_flag_values),
# TODO: The default here should somehow match the MODULE config. Until
# then, use the empty string to indicate an unknown version. This
# also prevents version-unaware targets from inadvertently matching
# a select condition when they shouldn't.
build_setting_default = "",
values = [""] + sorted(allowed_flag_values),
visibility = ["//visibility:public"],
)

Expand All @@ -53,7 +57,6 @@ def construct_config_settings(name, python_versions):
name = equals_minor_version_name,
flag_values = {":python_version": minor_version},
)

matches_minor_version_names = [equals_minor_version_name]

for micro_version in micro_versions:
Expand Down
23 changes: 20 additions & 3 deletions python/private/bzlmod/pip.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,29 @@ load(
"whl_library",
)
load("//python/pip_install:requirements_parser.bzl", parse_requirements = "parse")
load("//python/private:full_version.bzl", "full_version")
load("//python/private:normalize_name.bzl", "normalize_name")
load("//python/private:parse_whl_name.bzl", "parse_whl_name")
load("//python/private:version_label.bzl", "version_label")
load(":pip_repository.bzl", "pip_repository")

def _parse_version(version):
major, _, version = version.partition(".")
minor, _, version = version.partition(".")
patch, _, version = version.partition(".")
build, _, version = version.partition(".")

return struct(
# use semver vocabulary here
major = major,
minor = minor,
patch = patch, # this is called `micro` in the Python interpreter versioning scheme
build = build,
)

def _major_minor_version(version):
version = _parse_version(version)
return "{}.{}".format(version.major, version.minor)

def _whl_mods_impl(mctx):
"""Implementation of the pip.whl_mods tag class.

Expand Down Expand Up @@ -190,7 +207,7 @@ def _create_whl_repos(module_ctx, pip_attr, whl_map, whl_overrides):
if whl_name not in whl_map[hub_name]:
whl_map[hub_name][whl_name] = {}

whl_map[hub_name][whl_name][full_version(pip_attr.python_version)] = pip_name + "_"
whl_map[hub_name][whl_name][_major_minor_version(pip_attr.python_version)] = pip_name + "_"

def _pip_impl(module_ctx):
"""Implementation of a class tag that creates the pip hub and corresponding pip spoke whl repositories.
Expand Down Expand Up @@ -341,7 +358,7 @@ def _pip_impl(module_ctx):
name = hub_name,
repo_name = hub_name,
whl_map = whl_map,
default_version = full_version(DEFAULT_PYTHON_VERSION),
default_version = _major_minor_version(DEFAULT_PYTHON_VERSION),
)

def _pip_parse_ext_attrs():
Expand Down
2 changes: 1 addition & 1 deletion python/private/bzlmod/pip_repository.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pip_repository_attrs = {
"default_version": attr.string(
mandatory = True,
doc = """\
This is the default python version in the format of X.Y.Z. This should match
This is the default python version in the format of X.Y. This should match
what is setup by the 'python' extension using the 'is_default = True'
setting.""",
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ _tests.append(_test_all_legacy_aliases_are_created)

def _test_bzlmod_aliases(env):
actual = render_pkg_aliases(
default_version = "3.2.3",
default_version = "3.2",
repo_name = "pypi",
rules_python = "rules_python",
whl_map = {
"bar-baz": ["3.2.3"],
"bar-baz": ["3.2"],
},
)

Expand All @@ -94,7 +94,7 @@ alias(
name = "pkg",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:pkg",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:pkg",
"//conditions:default": "@pypi_32_bar_baz//:pkg",
},
),
Expand All @@ -104,7 +104,7 @@ alias(
name = "whl",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:whl",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:whl",
"//conditions:default": "@pypi_32_bar_baz//:whl",
},
),
Expand All @@ -114,7 +114,7 @@ alias(
name = "data",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:data",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:data",
"//conditions:default": "@pypi_32_bar_baz//:data",
},
),
Expand All @@ -124,7 +124,7 @@ alias(
name = "dist_info",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:dist_info",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:dist_info",
"//conditions:default": "@pypi_32_bar_baz//:dist_info",
},
),
Expand All @@ -141,7 +141,7 @@ def _test_bzlmod_aliases_with_no_default_version(env):
repo_name = "pypi",
rules_python = "rules_python",
whl_map = {
"bar-baz": ["3.2.3", "3.1.3"],
"bar-baz": ["3.2", "3.1"],
},
)

Expand All @@ -154,7 +154,7 @@ No matching wheel for current configuration's Python version.

The current build configuration's Python version doesn't match any of the Python
versions available for this wheel. This wheel supports the following Python versions:
3.1.3, 3.2.3
3.1, 3.2

As matched by the `@rules_python//python/config_settings:is_python_<version>`
configuration settings.
Expand All @@ -177,8 +177,8 @@ alias(
name = "pkg",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.1.3": "@pypi_31_bar_baz//:pkg",
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:pkg",
"@@rules_python//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:pkg",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:pkg",
},
no_match_error = _NO_MATCH_ERROR,
),
Expand All @@ -188,8 +188,8 @@ alias(
name = "whl",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.1.3": "@pypi_31_bar_baz//:whl",
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:whl",
"@@rules_python//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:whl",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:whl",
},
no_match_error = _NO_MATCH_ERROR,
),
Expand All @@ -199,8 +199,8 @@ alias(
name = "data",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.1.3": "@pypi_31_bar_baz//:data",
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:data",
"@@rules_python//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:data",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:data",
},
no_match_error = _NO_MATCH_ERROR,
),
Expand All @@ -210,8 +210,8 @@ alias(
name = "dist_info",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.1.3": "@pypi_31_bar_baz//:dist_info",
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:dist_info",
"@@rules_python//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:dist_info",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:dist_info",
},
no_match_error = _NO_MATCH_ERROR,
),
Expand All @@ -224,11 +224,18 @@ _tests.append(_test_bzlmod_aliases_with_no_default_version)

def _test_bzlmod_aliases_for_non_root_modules(env):
actual = render_pkg_aliases(
default_version = "3.2.4",
# NOTE @aignas 2024-01-17: if the default X.Y version coincides with the
# versions that are used in the root module, then this would be the same as
# as _test_bzlmod_aliases.
#
# However, if the root module uses a different default version than the
# non-root module, then we will have a no-match-error because the default_version
# is not in the list of the versions in the whl_map.
default_version = "3.3",
repo_name = "pypi",
rules_python = "rules_python",
whl_map = {
"bar-baz": ["3.2.3", "3.1.3"],
"bar-baz": ["3.2", "3.1"],
},
)

Expand All @@ -241,7 +248,7 @@ No matching wheel for current configuration's Python version.

The current build configuration's Python version doesn't match any of the Python
versions available for this wheel. This wheel supports the following Python versions:
3.1.3, 3.2.3
3.1, 3.2

As matched by the `@rules_python//python/config_settings:is_python_<version>`
configuration settings.
Expand All @@ -264,8 +271,8 @@ alias(
name = "pkg",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.1.3": "@pypi_31_bar_baz//:pkg",
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:pkg",
"@@rules_python//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:pkg",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:pkg",
},
no_match_error = _NO_MATCH_ERROR,
),
Expand All @@ -275,8 +282,8 @@ alias(
name = "whl",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.1.3": "@pypi_31_bar_baz//:whl",
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:whl",
"@@rules_python//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:whl",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:whl",
},
no_match_error = _NO_MATCH_ERROR,
),
Expand All @@ -286,8 +293,8 @@ alias(
name = "data",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.1.3": "@pypi_31_bar_baz//:data",
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:data",
"@@rules_python//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:data",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:data",
},
no_match_error = _NO_MATCH_ERROR,
),
Expand All @@ -297,8 +304,8 @@ alias(
name = "dist_info",
actual = select(
{
"@@rules_python//python/config_settings:is_python_3.1.3": "@pypi_31_bar_baz//:dist_info",
"@@rules_python//python/config_settings:is_python_3.2.3": "@pypi_32_bar_baz//:dist_info",
"@@rules_python//python/config_settings:is_python_3.1": "@pypi_31_bar_baz//:dist_info",
"@@rules_python//python/config_settings:is_python_3.2": "@pypi_32_bar_baz//:dist_info",
},
no_match_error = _NO_MATCH_ERROR,
),
Expand All @@ -311,12 +318,12 @@ _tests.append(_test_bzlmod_aliases_for_non_root_modules)

def _test_bzlmod_aliases_are_created_for_all_wheels(env):
actual = render_pkg_aliases(
default_version = "3.2.3",
default_version = "3.2",
repo_name = "pypi",
rules_python = "rules_python",
whl_map = {
"bar": ["3.1.2", "3.2.3"],
"foo": ["3.1.2", "3.2.3"],
"bar": ["3.1", "3.2"],
"foo": ["3.1", "3.2"],
},
)

Expand Down