Skip to content

Commit c355f6b

Browse files
author
Matt Mackay
authored
fix: add missing python version flag attr to pex (#399)
Adds the missing `_interpreter_version_flag` attr to the pex binary rule that allows it to resolve the correct Python toolchain in older versions of bazel. --- ### Changes are visible to end-users: yes - Searched for relevant documentation and updated as needed: yes - Breaking change (forces users to change their own code or config): no - Suggested release notes appear below: Ensure `py_pex_binary` can locate the Python version on the toolchain correctly on older bazel versions. ### Test plan - Manual testing; please provide instructions so we can reproduce: Run test suite with bazel 6.5.0
1 parent 28486e5 commit c355f6b

File tree

1 file changed

+27
-23
lines changed

1 file changed

+27
-23
lines changed

py/private/py_pex_binary.bzl

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ exclude_paths = [
1919
"aspect_rules_py~/py/tools/",
2020
# these will match in bzlmod setup with --incompatible_use_plus_in_repo_names flag flipped.
2121
"rules_python++python+",
22-
"aspect_rules_py+/py/tools/"
22+
"aspect_rules_py+/py/tools/",
2323
]
2424

2525
# determines if the given file is a `distinfo`, `dep` or a `source`
2626
# this required to allow PEX to put files into different places.
27-
#
27+
#
2828
# --dep: into `<PEX_UNPACK_ROOT>/.deps/<name_of_the_package>`
2929
# --distinfo: is only used for determining package metadata
3030
# --source: into `<PEX_UNPACK_ROOT>/<relative_path_to_workspace_root>/<file_name>`
@@ -37,23 +37,24 @@ def _map_srcs(f, workspace):
3737
return []
3838

3939
site_packages_i = f.path.find("site-packages")
40-
40+
4141
# if path contains `site-packages` and there is only two path segments
4242
# after it, it will be treated as third party dep.
4343
# Here are some examples of path we expect and use and ones we ignore.
44-
#
44+
#
4545
# Match: `external/rules_python~~pip~pypi_39_rtoml/site-packages/rtoml-0.11.0.dist-info/INSTALLER`
4646
# Reason: It has two `/` after first `site-packages` substring.
47-
#
47+
#
4848
# No Match: `external/rules_python~~pip~pypi_39_rtoml/site-packages/rtoml-0.11.0/src/mod/parse.py`
4949
# Reason: It has three `/` after first `site-packages` substring.
5050
if site_packages_i != -1 and f.path.count("/", site_packages_i) == 2:
5151
if f.path.find("dist-info", site_packages_i) != -1:
5252
return ["--distinfo={}".format(f.dirname)]
5353
return ["--dep={}".format(f.dirname)]
5454

55-
# If the path does not have a `site-packages` in it, then put it into
56-
# the standard runfiles tree.
55+
# If the path does not have a `site-packages` in it, then put it into
56+
# the standard runfiles tree.
57+
5758
elif site_packages_i == -1:
5859
return ["--source={}={}".format(f.path, dest_path)]
5960

@@ -74,22 +75,22 @@ def _py_python_pex_impl(ctx):
7475
workspace_name = str(ctx.workspace_name)
7576

7677
args.add_all(
77-
ctx.attr.inject_env.items(),
78+
ctx.attr.inject_env.items(),
7879
map_each = lambda e: "--inject-env={}={}".format(e[0], e[1]),
79-
# this is needed to allow passing a lambda to map_each
80+
# this is needed to allow passing a lambda to map_each
8081
allow_closure = True,
8182
)
8283

8384
args.add_all(
84-
binary[PyInfo].imports,
85-
format_each = "--sys-path=%s"
85+
binary[PyInfo].imports,
86+
format_each = "--sys-path=%s",
8687
)
8788

8889
args.add_all(
8990
runfiles.files,
9091
map_each = lambda f: _map_srcs(f, workspace_name),
9192
uniquify = True,
92-
# this is needed to allow passing a lambda (with workspace_name) to map_each
93+
# this is needed to allow passing a lambda (with workspace_name) to map_each
9394
allow_closure = True,
9495
)
9596
args.add(binary[DefaultInfo].files_to_run.executable, format = "--executable=%s")
@@ -99,10 +100,10 @@ def _py_python_pex_impl(ctx):
99100
py_version = py_toolchain.interpreter_version_info
100101
args.add_all(
101102
[
102-
constraint.format(major = py_version.major, minor = py_version.minor, patch = py_version.micro)
103+
constraint.format(major = py_version.major, minor = py_version.minor, patch = py_version.micro)
103104
for constraint in ctx.attr.python_interpreter_constraints
104-
],
105-
format_each = "--python-version-constraint=%s"
105+
],
106+
format_each = "--python-version-constraint=%s",
106107
)
107108
args.add(output, format = "--output-file=%s")
108109

@@ -116,10 +117,9 @@ def _py_python_pex_impl(ctx):
116117
)
117118

118119
return [
119-
DefaultInfo(files = depset([output]), executable = output)
120+
DefaultInfo(files = depset([output]), executable = output),
120121
]
121122

122-
123123
_attrs = dict({
124124
"binary": attr.label(executable = True, cfg = "target", mandatory = True, doc = "A py_binary target"),
125125
"inject_env": attr.string_dict(
@@ -128,7 +128,7 @@ _attrs = dict({
128128
),
129129
"python_shebang": attr.string(default = "#!/usr/bin/env python3"),
130130
"python_interpreter_constraints": attr.string_list(
131-
default = ["CPython=={major}.{minor}.*"],
131+
default = ["CPython=={major}.{minor}.*"],
132132
doc = """\
133133
Python interpreter versions this PEX binary is compatible with. A list of semver strings.
134134
The placeholder strings `{major}`, `{minor}`, `{patch}` can be used for gathering version
@@ -143,17 +143,21 @@ py_pex_binary
143143
]
144144
)
145145
```
146-
"""),
147-
"_pex": attr.label(executable = True, cfg = "exec", default = "//py/tools/pex")
146+
""",
147+
),
148+
# NB: this is read by _resolve_toolchain in py_semantics.
149+
"_interpreter_version_flag": attr.label(
150+
default = "//py:interpreter_version",
151+
),
152+
"_pex": attr.label(executable = True, cfg = "exec", default = "//py/tools/pex"),
148153
})
149154

150-
151155
py_pex_binary = rule(
152156
doc = "Build a pex executable from a py_binary",
153157
implementation = _py_python_pex_impl,
154158
attrs = _attrs,
155159
toolchains = [
156-
PY_TOOLCHAIN
160+
PY_TOOLCHAIN,
157161
],
158162
executable = True,
159-
)
163+
)

0 commit comments

Comments
 (0)