Skip to content

Commit dea6493

Browse files
committed
fix(pypi): use python -B for all invocations
Before this change we would just invoke the Python interpreter. This means that in the `rules_python` directory there would be `__pycache__` folders created in the source tree and the same `__pycache__` folders would be created in the python interpreter repository rules if the directories were writable. This change ensures that we are executing `python` with `-B` in those contexts and reduces any likelihood of us doing the wrong thing. Work towards #1169.
1 parent bb6249b commit dea6493

File tree

5 files changed

+58
-25
lines changed

5 files changed

+58
-25
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ Unreleased changes template.
109109
{obj}`--venvs_use_declare_symlink=no` to have it not create symlinks at
110110
build time (they will be created at runtime instead).
111111
(Fixes [#2489](https://github.com/bazelbuild/rules_python/issues/2489))
112+
* (pypi) From now on `python` invocations in repository and module extension
113+
evaluation contexts will invoke Python interpreter with `-B` to avoid
114+
creating `.pyc` files.
112115

113116
{#v1-2-0-added}
114117
### Added

python/private/pypi/evaluate_markers.bzl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ def evaluate_markers(mrctx, *, requirements, python_interpreter, python_interpre
5555
pypi_repo_utils.execute_checked(
5656
mrctx,
5757
op = "ResolveRequirementEnvMarkers({})".format(in_file),
58+
python = pypi_repo_utils.resolve_python_interpreter(
59+
mrctx,
60+
python_interpreter = python_interpreter,
61+
python_interpreter_target = python_interpreter_target,
62+
),
5863
arguments = [
59-
pypi_repo_utils.resolve_python_interpreter(
60-
mrctx,
61-
python_interpreter = python_interpreter,
62-
python_interpreter_target = python_interpreter_target,
63-
),
6464
"-m",
6565
"python.private.pypi.requirements_parser.resolve_target_platforms",
6666
in_file,

python/private/pypi/patch_whl.bzl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ other patches ensures that the users have overview on exactly what has changed
2727
within the wheel.
2828
"""
2929

30-
load("//python/private:repo_utils.bzl", "repo_utils")
3130
load(":parse_whl_name.bzl", "parse_whl_name")
31+
load(":pypi_repo_utils.bzl", "pypi_repo_utils")
3232

3333
_rules_python_root = Label("//:BUILD.bazel")
3434

@@ -102,10 +102,14 @@ def patch_whl(rctx, *, python_interpreter, whl_path, patches, **kwargs):
102102
record_patch = rctx.path("RECORD.patch")
103103
whl_patched = patched_whl_name(whl_input.basename)
104104

105-
repo_utils.execute_checked(
105+
pypi_repo_utils.execute_checked(
106106
rctx,
107+
python = python_interpreter,
108+
srcs = [
109+
"//python/private/pypi:repack_whl.py",
110+
"//tools:wheelmaker.py",
111+
],
107112
arguments = [
108-
python_interpreter,
109113
"-m",
110114
"python.private.pypi.repack_whl",
111115
"--record-patch",

python/private/pypi/pypi_repo_utils.bzl

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,27 @@ def _construct_pypath(mrctx, *, entries):
104104
])
105105
return pypath
106106

107-
def _execute_checked(mrctx, *, srcs, **kwargs):
107+
def _execute_prep(mrctx, *, python, srcs, **kwargs):
108+
for src in srcs:
109+
# This will ensure that we will re-evaluate the bzlmod extension or
110+
# refetch the repository_rule when the srcs change. This should work on
111+
# Bazel versions without `mrctx.watch` as well.
112+
repo_utils.watch(mrctx, mrctx.path(src))
113+
114+
environment = kwargs.pop("environment", {})
115+
pythonpath = environment.get("PYTHONPATH", "")
116+
if pythonpath and not types.is_string(pythonpath):
117+
environment["PYTHONPATH"] = _construct_pypath(mrctx, entries = pythonpath)
118+
kwargs["environment"] = environment
119+
kwargs["arguments"] = [python, "-B"] + kwargs.get("arguments", [])
120+
return kwargs
121+
122+
def _execute_checked(mrctx, *, python, srcs, **kwargs):
108123
"""Helper function to run a python script and modify the PYTHONPATH to include external deps.
109124
110125
Args:
111126
mrctx: Handle to the module_ctx or repository_ctx.
127+
python: The python interpreter to use.
112128
srcs: The src files that the script depends on. This is important to
113129
ensure that the Bazel repository cache or the bzlmod lock file gets
114130
invalidated when any one file changes. It is advisable to use
@@ -118,26 +134,34 @@ def _execute_checked(mrctx, *, srcs, **kwargs):
118134
the `environment` has a value `PYTHONPATH` and it is a list, then
119135
it will be passed to `construct_pythonpath` function.
120136
"""
137+
return repo_utils.execute_checked(
138+
mrctx,
139+
**_execute_prep(mrctx, python = python, srcs = srcs, **kwargs)
140+
)
121141

122-
for src in srcs:
123-
# This will ensure that we will re-evaluate the bzlmod extension or
124-
# refetch the repository_rule when the srcs change. This should work on
125-
# Bazel versions without `mrctx.watch` as well.
126-
repo_utils.watch(mrctx, mrctx.path(src))
127-
128-
env = kwargs.pop("environment", {})
129-
pythonpath = env.get("PYTHONPATH", "")
130-
if pythonpath and not types.is_string(pythonpath):
131-
env["PYTHONPATH"] = _construct_pypath(mrctx, entries = pythonpath)
142+
def _execute_checked_stdout(mrctx, *, python, srcs, **kwargs):
143+
"""Helper function to run a python script and modify the PYTHONPATH to include external deps.
132144
133-
return repo_utils.execute_checked(
145+
Args:
146+
mrctx: Handle to the module_ctx or repository_ctx.
147+
python: The python interpreter to use.
148+
srcs: The src files that the script depends on. This is important to
149+
ensure that the Bazel repository cache or the bzlmod lock file gets
150+
invalidated when any one file changes. It is advisable to use
151+
`RECORD` files for external deps and the list of srcs from the
152+
rules_python repo for any scripts.
153+
**kwargs: Arguments forwarded to `repo_utils.execute_checked`. If
154+
the `environment` has a value `PYTHONPATH` and it is a list, then
155+
it will be passed to `construct_pythonpath` function.
156+
"""
157+
return repo_utils.execute_checked_stdout(
134158
mrctx,
135-
environment = env,
136-
**kwargs
159+
**_execute_prep(mrctx, python = python, srcs = srcs, **kwargs)
137160
)
138161

139162
pypi_repo_utils = struct(
140163
construct_pythonpath = _construct_pypath,
141164
execute_checked = _execute_checked,
165+
execute_checked_stdout = _execute_checked_stdout,
142166
resolve_python_interpreter = _resolve_python_interpreter,
143167
)

python/private/pypi/whl_library.bzl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,15 @@ def _get_toolchain_unix_cflags(rctx, python_interpreter, logger = None):
7575
if not is_standalone_interpreter(rctx, python_interpreter, logger = logger):
7676
return []
7777

78-
stdout = repo_utils.execute_checked_stdout(
78+
stdout = pypi_repo_utils.execute_checked_stdout(
7979
rctx,
8080
op = "GetPythonVersionForUnixCflags",
81+
python = python_interpreter,
8182
arguments = [
82-
python_interpreter,
8383
"-c",
8484
"import sys; print(f'{sys.version_info[0]}.{sys.version_info[1]}', end='')",
8585
],
86+
srcs = [],
8687
)
8788
_python_version = stdout
8889
include_path = "{}/include/python{}".format(
@@ -181,7 +182,6 @@ def _whl_library_impl(rctx):
181182
python_interpreter_target = rctx.attr.python_interpreter_target,
182183
)
183184
args = [
184-
python_interpreter,
185185
"-m",
186186
"python.private.pypi.whl_installer.wheel_installer",
187187
"--requirement",
@@ -247,6 +247,7 @@ def _whl_library_impl(rctx):
247247
# truncate the requirement value when logging it / reporting
248248
# progress since it may contain several ' --hash=sha256:...
249249
# --hash=sha256:...' substrings that fill up the console
250+
python = python_interpreter,
250251
op = op_tmpl.format(name = rctx.attr.name, requirement = rctx.attr.requirement.split(" ", 1)[0]),
251252
arguments = args,
252253
environment = environment,
@@ -295,6 +296,7 @@ def _whl_library_impl(rctx):
295296
pypi_repo_utils.execute_checked(
296297
rctx,
297298
op = "whl_library.ExtractWheel({}, {})".format(rctx.attr.name, whl_path),
299+
python = python_interpreter,
298300
arguments = args + [
299301
"--whl-file",
300302
whl_path,

0 commit comments

Comments
 (0)