Skip to content

Commit 46537cf

Browse files
authored
feat(bzlmod)!: Move each bzlmod extension into its own file (#1226)
This commit refactors the files that contain the bzlmod extensions. - All extensions are moved under the new extensions folder - Private extensions are moved under extensions/private - All extension files are renamed to remove the _extension suffix - pip and internal_deps extensions are moved to their own file This commit organizes the extensions better and also follows the best practice of having a single extension per file. Having each extension in its own file allows them to use some additional features while helping avoid backwards incompatible changes. ## BREAKING CHANGES This splits `//python:extensions.bzl`, which previously held the `python` and `pip` extensions, into separate files (`python.bzl` and `pip.bzl`, respectively). Unfortunately, moving the location of the extensions is a breaking change due to how bzlmod extension identity works (see https://bazel.build/external/extension#extension_identity). Fortunately, by moving to one extension per file, we shouldn't have to ever do this again. Users must update the file path in their `use_repo()` statements as follows: * `use_extension("@rules_python//python:extensions.bzl", "python")` -> `use_extension("@rules_python//python/extensions:python.bzl", "python")` * `use_extension("@rules_python//python:extensions.bzl", "pip")` -> `use_extension("@rules_python//python/extensions:pip.bzl", "pip")` The following `sed` commands should approximate the necessary changes: ``` sed 'sXuse_extension("@rules_python//python:extensions.bzl", "python")Xuse_extension("@rules_python//python/extensions:python.bzl", "python")X'` sed 'sXuse_extension("@rules_python//python:extensions.bzl", "pip")Xuse_extension("@rules_python//python/extensions:pip.bzl", "pip")X'` ``` See `examples/bzlmod_build_file_generation/MODULE.bazel` for an example of the new paths.
1 parent ccea92a commit 46537cf

File tree

11 files changed

+148
-70
lines changed

11 files changed

+148
-70
lines changed

MODULE.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ bazel_dep(name = "bazel_skylib", version = "1.3.0")
1111
bazel_dep(name = "rules_proto", version = "5.3.0-21.7")
1212
bazel_dep(name = "protobuf", version = "21.7", repo_name = "com_google_protobuf")
1313

14-
internal_deps = use_extension("@rules_python//python:extensions.bzl", "internal_deps")
14+
internal_deps = use_extension("@rules_python//python/extensions/private:internal_deps.bzl", "internal_deps")
1515
internal_deps.install()
1616
use_repo(
1717
internal_deps,
@@ -47,5 +47,5 @@ use_repo(
4747
"pypi__coverage_cp39_x86_64-unknown-linux-gnu",
4848
)
4949

50-
python = use_extension("@rules_python//python:extensions.bzl", "python")
50+
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
5151
use_repo(python, "pythons_hub")

examples/bzlmod/MODULE.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ local_path_override(
1010
path = "../..",
1111
)
1212

13-
python = use_extension("@rules_python//python:extensions.bzl", "python")
13+
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
1414
python.toolchain(
1515
name = "python3_9",
1616
configure_coverage_tool = True,
@@ -23,7 +23,7 @@ register_toolchains(
2323
"@python3_9_toolchains//:all",
2424
)
2525

26-
pip = use_extension("@rules_python//python:extensions.bzl", "pip")
26+
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
2727
pip.parse(
2828
name = "pip",
2929
requirements_lock = "//:requirements_lock.txt",

examples/bzlmod_build_file_generation/MODULE.bazel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ bazel_dep(name = "gazelle", version = "0.30.0", repo_name = "bazel_gazelle")
4242

4343
# The following stanze returns a proxy object representing a module extension;
4444
# its methods can be invoked to create module extension tags.
45-
python = use_extension("@rules_python//python:extensions.bzl", "python")
45+
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
4646

4747
# This name is passed into python.toolchain and it's use_repo statement.
4848
# We also use the same name for python.host_python_interpreter.
@@ -74,7 +74,7 @@ register_toolchains(
7474
# The interpreter extension discovers the platform specific Python binary.
7575
# It creates a symlink to the binary, and we pass the label to the following
7676
# pip.parse call.
77-
interpreter = use_extension("@rules_python//python:interpreter_extension.bzl", "interpreter")
77+
interpreter = use_extension("@rules_python//python/extensions:interpreter.bzl", "interpreter")
7878
interpreter.install(
7979
name = "interpreter_python3",
8080
python_name = PYTHON_NAME,
@@ -88,7 +88,7 @@ use_repo(interpreter, "interpreter_python3")
8888
# You can instead check this `requirements.bzl` file into your repo.
8989
# Because this project has different requirements for windows vs other
9090
# operating systems, we have requirements for each.
91-
pip = use_extension("@rules_python//python:extensions.bzl", "pip")
91+
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
9292
pip.parse(
9393
name = "pip",
9494
# When using gazelle you must use set the following flag

examples/py_proto_library/MODULE.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ local_path_override(
1212
path = "../..",
1313
)
1414

15-
python = use_extension("@rules_python//python:extensions.bzl", "python")
15+
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
1616
python.toolchain(
1717
name = "python3_9",
1818
configure_coverage_tool = True,

python/extensions/BUILD.bazel

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright 2017 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
package(default_visibility = ["//visibility:public"])
16+
17+
licenses(["notice"])
18+
19+
filegroup(
20+
name = "distribution",
21+
srcs = glob(["**"]),
22+
visibility = ["//extensions:__pkg__"],
23+
)
File renamed without changes.

python/extensions.bzl renamed to python/extensions/pip.bzl

Lines changed: 5 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,71 +12,10 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
"Module extensions for use with bzlmod"
15+
"pip module extension for use with bzlmod"
1616

17-
load("@rules_python//python:repositories.bzl", "python_register_toolchains")
1817
load("@rules_python//python/pip_install:pip_repository.bzl", "locked_requirements_label", "pip_repository_attrs", "pip_repository_bzlmod", "use_isolated", "whl_library")
19-
load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies")
2018
load("@rules_python//python/pip_install:requirements_parser.bzl", parse_requirements = "parse")
21-
load("@rules_python//python/private:coverage_deps.bzl", "install_coverage_deps")
22-
load("@rules_python//python/private:interpreter_hub.bzl", "hub_repo")
23-
24-
def _python_impl(module_ctx):
25-
toolchains = []
26-
for mod in module_ctx.modules:
27-
for toolchain_attr in mod.tags.toolchain:
28-
python_register_toolchains(
29-
name = toolchain_attr.name,
30-
python_version = toolchain_attr.python_version,
31-
bzlmod = True,
32-
# Toolchain registration in bzlmod is done in MODULE file
33-
register_toolchains = False,
34-
register_coverage_tool = toolchain_attr.configure_coverage_tool,
35-
ignore_root_user_error = toolchain_attr.ignore_root_user_error,
36-
)
37-
38-
# We collect all of the toolchain names to create
39-
# the INTERPRETER_LABELS map. This is used
40-
# by interpreter_extensions.bzl
41-
toolchains.append(toolchain_attr.name)
42-
43-
hub_repo(
44-
name = "pythons_hub",
45-
toolchains = toolchains,
46-
)
47-
48-
python = module_extension(
49-
implementation = _python_impl,
50-
tag_classes = {
51-
"toolchain": tag_class(
52-
attrs = {
53-
"configure_coverage_tool": attr.bool(
54-
mandatory = False,
55-
doc = "Whether or not to configure the default coverage tool for the toolchains.",
56-
),
57-
"ignore_root_user_error": attr.bool(
58-
default = False,
59-
doc = "Whether the check for root should be ignored or not. This causes cache misses with .pyc files.",
60-
mandatory = False,
61-
),
62-
"name": attr.string(mandatory = True),
63-
"python_version": attr.string(mandatory = True),
64-
},
65-
),
66-
},
67-
)
68-
69-
# buildifier: disable=unused-variable
70-
def _internal_deps_impl(module_ctx):
71-
pip_install_dependencies()
72-
install_coverage_deps()
73-
74-
internal_deps = module_extension(
75-
implementation = _internal_deps_impl,
76-
tag_classes = {
77-
"install": tag_class(attrs = dict()),
78-
},
79-
)
8019

8120
def _pip_impl(module_ctx):
8221
for mod in module_ctx.modules:
@@ -134,6 +73,10 @@ def _pip_parse_ext_attrs():
13473
return attrs
13574

13675
pip = module_extension(
76+
doc = """\
77+
This extension is used to create a pip respository and create the various wheel libaries if
78+
provided in a requirements file.
79+
""",
13780
implementation = _pip_impl,
13881
tag_classes = {
13982
"parse": tag_class(attrs = _pip_parse_ext_attrs()),

python/extensions/private/BUILD.bazel

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright 2022 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
package(default_visibility = ["//visibility:private"])
16+
17+
licenses(["notice"])
18+
19+
filegroup(
20+
name = "distribution",
21+
srcs = glob(["**"]),
22+
visibility = ["//python/extensions/private:__pkg__"],
23+
)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# http://www.apache.org/licenses/LICENSE-2.0
2+
#
3+
# Unless required by applicable law or agreed to in writing, software
4+
# distributed under the License is distributed on an "AS IS" BASIS,
5+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6+
# See the License for the specific language governing permissions and
7+
# limitations under the License.
8+
9+
"Python toolchain module extension for internal rule use"
10+
11+
load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies")
12+
load("@rules_python//python/private:coverage_deps.bzl", "install_coverage_deps")
13+
14+
# buildifier: disable=unused-variable
15+
def _internal_deps_impl(module_ctx):
16+
pip_install_dependencies()
17+
install_coverage_deps()
18+
19+
internal_deps = module_extension(
20+
doc = "This extension to register internal rules_python dependecies.",
21+
implementation = _internal_deps_impl,
22+
tag_classes = {
23+
"install": tag_class(attrs = dict()),
24+
},
25+
)

python/extensions/python.bzl

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Copyright 2023 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"Python toolchain module extensions for use with bzlmod"
16+
17+
load("@rules_python//python:repositories.bzl", "python_register_toolchains")
18+
load("@rules_python//python/extensions/private:interpreter_hub.bzl", "hub_repo")
19+
20+
def _python_impl(module_ctx):
21+
toolchains = []
22+
for mod in module_ctx.modules:
23+
for toolchain_attr in mod.tags.toolchain:
24+
python_register_toolchains(
25+
name = toolchain_attr.name,
26+
python_version = toolchain_attr.python_version,
27+
bzlmod = True,
28+
# Toolchain registration in bzlmod is done in MODULE file
29+
register_toolchains = False,
30+
register_coverage_tool = toolchain_attr.configure_coverage_tool,
31+
ignore_root_user_error = toolchain_attr.ignore_root_user_error,
32+
)
33+
34+
# We collect all of the toolchain names to create
35+
# the INTERPRETER_LABELS map. This is used
36+
# by interpreter_extensions.bzl
37+
toolchains.append(toolchain_attr.name)
38+
39+
hub_repo(
40+
name = "pythons_hub",
41+
toolchains = toolchains,
42+
)
43+
44+
python = module_extension(
45+
doc = "Bzlmod extension that is used to register a Python toolchain.",
46+
implementation = _python_impl,
47+
tag_classes = {
48+
"toolchain": tag_class(
49+
attrs = {
50+
"configure_coverage_tool": attr.bool(
51+
mandatory = False,
52+
doc = "Whether or not to configure the default coverage tool for the toolchains.",
53+
),
54+
"ignore_root_user_error": attr.bool(
55+
default = False,
56+
doc = "Whether the check for root should be ignored or not. This causes cache misses with .pyc files.",
57+
mandatory = False,
58+
),
59+
"name": attr.string(mandatory = True),
60+
"python_version": attr.string(mandatory = True),
61+
},
62+
),
63+
},
64+
)

0 commit comments

Comments
 (0)