Skip to content

Commit 4a1b068

Browse files
committed
feat(venv): Make the venv strategy configurable
1 parent 96c6774 commit 4a1b068

File tree

9 files changed

+154
-44
lines changed

9 files changed

+154
-44
lines changed

py/BUILD.bazel

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
11
load("@aspect_bazel_lib//:bzl_library.bzl", "bzl_library")
22
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
33

4-
# For Bazel 6.x compatibility, since
5-
# PyRuntimeInfo shipped only with Bazel 7
6-
# Users can set, e.g. --@aspect_rules_py//py:interpreter_version=3.9.18
74
alias(
85
name = "interpreter_version",
9-
actual = "@rules_python//python/config_settings:python_version",
10-
visibility = ["//visibility:public"],
11-
)
12-
13-
string_flag(
14-
name = "venv_strategy",
15-
build_setting_default = "dynamic",
16-
values = [
17-
"dynamic",
18-
"static",
19-
],
6+
actual = "//py/settings:interpreter_version",
207
visibility = ["//visibility:public"],
8+
deprecation = "Please prefer py/settings:interpreter_version",
219
)
2210

2311
bzl_library(
@@ -46,12 +34,14 @@ bzl_library(
4634
"//py/private:py_wheel",
4735
"//py/private:virtual",
4836
"//py/private/py_venv",
37+
"//py/private/link",
4938
"@aspect_bazel_lib//lib:utils",
5039
],
5140
)
5241

5342
# This needs to dep on @aspect_tools_telemetry_report but we don't have that in WORKSPACE
5443
# gazelle:exclude extensions.bzl
44+
#
5545
# bzl_library(
5646
# name = "extensions",
5747
# srcs = [

py/defs.bzl

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,48 @@ load("//py/private:py_pex_binary.bzl", _py_pex_binary = "py_pex_binary")
4242
load("//py/private:py_pytest_main.bzl", _py_pytest_main = "py_pytest_main")
4343
load("//py/private:py_unpacked_wheel.bzl", _py_unpacked_wheel = "py_unpacked_wheel")
4444
load("//py/private:virtual.bzl", _resolutions = "resolutions")
45-
load("//py/private/py_venv:defs.bzl", _py_venv_link = "py_venv_link")
45+
load("//py/private/py_venv:defs.bzl", _py_venv_binary = "py_venv_binary")
46+
load("//py/private/link:defs.bzl", _py_link_venv = "py_link_venv")
4647

4748
py_pex_binary = _py_pex_binary
4849
py_pytest_main = _py_pytest_main
4950

5051
# FIXME: Badly chosen name; will be replaced/migrated
51-
py_venv = _py_venv_link
52-
py_venv_link = _py_venv_link
52+
def py_venv(name, srcs = [], data = [], deps = [], imports = None, testonly = False, **kwargs):
53+
native.alias(
54+
name = name,
55+
actual = select({
56+
Label("//py/private/link:dynamic_venvs"): ":{}_dynamic".format(name),
57+
Label("//py/private/link:static_venvs"): ":{}_static".format(name),
58+
}),
59+
tags = ["manual"],
60+
)
61+
62+
_py_link_venv(
63+
_py_binary,
64+
name = "{}_dynamic".format(name),
65+
srcs = srcs,
66+
data = data,
67+
deps = deps,
68+
imports = kwargs.get("imports"),
69+
tags = ["manual"],
70+
testonly = kwargs.get("testonly", False),
71+
target_compatible_with = kwargs.get("target_compatible_with", []),
72+
)
73+
74+
_py_link_venv(
75+
_py_venv_binary,
76+
name = "{}_static".format(name),
77+
srcs = srcs,
78+
data = data,
79+
deps = deps,
80+
imports = kwargs.get("imports"),
81+
tags = ["manual"],
82+
testonly = kwargs.get("testonly", False),
83+
target_compatible_with = kwargs.get("target_compatible_with", []),
84+
)
85+
86+
py_venv_link = py_venv
5387

5488
py_binary_rule = _py_binary
5589
py_test_rule = _py_test
@@ -70,15 +104,12 @@ def _py_binary_or_test(name, rule, srcs, main, data = [], deps = [], **kwargs):
70104
**kwargs
71105
)
72106

73-
_py_venv_link(
74-
name = "{}.venv".format(name),
107+
py_venv(
108+
name = name + ".venv",
75109
srcs = srcs,
76110
data = data,
77111
deps = deps,
78-
imports = kwargs.get("imports"),
79-
tags = ["manual"],
80-
testonly = kwargs.get("testonly", False),
81-
target_compatible_with = kwargs.get("target_compatible_with", []),
112+
**kwargs,
82113
)
83114

84115
def py_binary(name, srcs = [], main = None, **kwargs):

py/private/link/BUILD.bazel

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
load("@bazel_lib//:bzl_library.bzl", "bzl_library")
2+
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
3+
4+
package(default_visibility = ["//visibility:public"])
5+
6+
exports_files(["link.py"])
7+
8+
bzl_library(
9+
name = "link",
10+
srcs = [
11+
"defs.bzl"
12+
],
13+
deps = [
14+
"@bazel_skylib//lib:sets",
15+
]
16+
)
17+
18+
string_flag(
19+
name = "venv_strategy",
20+
build_setting_default = "dynamic",
21+
values = [
22+
"dynamic",
23+
"static",
24+
],
25+
visibility = ["//visibility:public"],
26+
)
27+
28+
29+
config_setting(
30+
name = "static_venvs",
31+
flag_values = {
32+
":venv_strategy": "static",
33+
}
34+
)
35+
36+
config_setting(
37+
name = "dynamic_venvs",
38+
flag_values = {
39+
":venv_strategy": "dynamic",
40+
}
41+
)

py/private/link/defs.bzl

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
load("@bazel_skylib//lib:sets.bzl", "sets")
2+
3+
def py_link_venv(
4+
binary_rule,
5+
name,
6+
srcs,
7+
args = [],
8+
venv_name = None,
9+
venv_dest = None,
10+
**kwargs):
11+
"""
12+
Build a Python virtual environment and produce a script to link it into the
13+
user's directory of choice.
14+
15+
Args:
16+
binary_rule (rule): A py_binary-alike rule to employ. Must build a "venv".
17+
18+
venv_name (str): A name to use for venv's link.
19+
20+
venv_dest (str): A path (relative to the repo
21+
root/$BUILD_WORKING_DIRECTORY) where the link will be created.
22+
23+
srcs (list): srcs for the underlying binary.
24+
25+
args (list): args for the underlying binary.
26+
27+
**kwargs (dict): Delegate args for the underlying binary rule.
28+
29+
"""
30+
31+
# Note that the binary is already wrapped with debug
32+
link_script = str(Label("//py/private/link:link.py"))
33+
34+
if venv_name != None:
35+
args = ["--name=" + venv_name] + args
36+
37+
if venv_dest != None:
38+
args = ["--dest=" + venv_dest] + args
39+
40+
binary_rule(
41+
name = name,
42+
args = args,
43+
main = link_script,
44+
srcs = sets.to_list(sets.make(srcs + [link_script])),
45+
**kwargs
46+
)

py/private/py_venv/link.py renamed to py/private/link/link.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ def munge_venv_name(target_package, virtualenv_name):
2121
if __name__ == "__main__":
2222
virtualenv_home = os.path.normpath(os.environ["VIRTUAL_ENV"])
2323
virtualenv_name = os.path.basename(virtualenv_home)
24-
runfiles_dir = os.path.normpath(os.environ["RUNFILES_DIR"])
2524
builddir = os.path.normpath(os.environ["BUILD_WORKING_DIRECTORY"])
2625
target_package, target_name = os.environ["BAZEL_TARGET"].split("//", 1)[1].split(":")
2726

py/private/py_venv/defs.bzl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
"""Implementation for the py_binary and py_test rules."""
22

3-
load(":py_venv.bzl", _py_venv = "py_venv", _py_venv_binary = "py_venv_binary", _py_venv_link = "py_venv_link", _py_venv_test = "py_venv_test")
3+
load(":py_venv.bzl", _py_venv = "py_venv", _py_venv_binary = "py_venv_binary", _py_venv_test = "py_venv_test")
44

55
py_venv = _py_venv
6-
py_venv_link = _py_venv_link
76
py_venv_binary = _py_venv_binary
87
py_venv_test = _py_venv_test

py/private/py_venv/py_venv.bzl

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -430,19 +430,3 @@ _py_venv_test = rule(
430430
py_venv = _wrap_with_debug(_py_venv)
431431
py_venv_binary = _wrap_with_debug(_py_venv_binary)
432432
py_venv_test = _wrap_with_debug(_py_venv_test)
433-
434-
def py_venv_link(venv_name = None, srcs = [], **kwargs):
435-
"""Build a Python virtual environment and produce a script to link it into the build directory."""
436-
437-
# Note that the binary is already wrapped with debug
438-
link_script = str(Label("//py/private/py_venv:link.py"))
439-
kwargs["debug"] = select({
440-
Label(":debug_venv_setting"): True,
441-
"//conditions:default": False,
442-
})
443-
py_venv_binary(
444-
args = [] + (["--name=" + venv_name] if venv_name else []),
445-
main = link_script,
446-
srcs = srcs + [link_script],
447-
**kwargs
448-
)

py/settings/BUILD.bazel

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
load("@aspect_bazel_lib//:bzl_library.bzl", "bzl_library")
2+
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
3+
4+
# For Bazel 6.x compatibility, since
5+
# PyRuntimeInfo shipped only with Bazel 7
6+
# Users can set, e.g. --@aspect_rules_py//py:interpreter_version=3.9.18
7+
alias(
8+
name = "interpreter_version",
9+
actual = "@rules_python//python/config_settings:python_version",
10+
visibility = ["//visibility:public"],
11+
)
12+
13+
string_flag(
14+
name = "venv_strategy",
15+
build_setting_default = "dynamic",
16+
values = [
17+
"dynamic",
18+
"static",
19+
],
20+
visibility = ["//visibility:public"],
21+
)

py/unstable/defs.bzl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ Unstable rules and preview machinery.
55
No promises are made about compatibility across releases.
66
"""
77

8-
load("//py/private/py_venv:defs.bzl", _bin = "py_venv_binary", _link = "py_venv_link", _test = "py_venv_test", _venv = "py_venv")
8+
load("//py/private/py_venv:defs.bzl", _bin = "py_venv_binary", _test = "py_venv_test", _venv = "py_venv")
99

1010
py_venv = _venv
11-
py_venv_link = _link
1211
py_venv_binary = _bin
1312
py_venv_test = _test

0 commit comments

Comments
 (0)