@@ -104,11 +104,30 @@ def _construct_pypath(mrctx, *, entries):
104
104
])
105
105
return pypath
106
106
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
+
120
+ # -B is added to prevent the repo-phase invocation from creating timestamp
121
+ # based pyc files, which contributes to race conditions and non-determinism
122
+ kwargs ["arguments" ] = [python , "-B" ] + kwargs .get ("arguments" , [])
123
+ return kwargs
124
+
125
+ def _execute_checked (mrctx , * , python , srcs , ** kwargs ):
108
126
"""Helper function to run a python script and modify the PYTHONPATH to include external deps.
109
127
110
128
Args:
111
129
mrctx: Handle to the module_ctx or repository_ctx.
130
+ python: The python interpreter to use.
112
131
srcs: The src files that the script depends on. This is important to
113
132
ensure that the Bazel repository cache or the bzlmod lock file gets
114
133
invalidated when any one file changes. It is advisable to use
@@ -118,26 +137,34 @@ def _execute_checked(mrctx, *, srcs, **kwargs):
118
137
the `environment` has a value `PYTHONPATH` and it is a list, then
119
138
it will be passed to `construct_pythonpath` function.
120
139
"""
140
+ return repo_utils .execute_checked (
141
+ mrctx ,
142
+ ** _execute_prep (mrctx , python = python , srcs = srcs , ** kwargs )
143
+ )
121
144
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 )
145
+ def _execute_checked_stdout (mrctx , * , python , srcs , ** kwargs ):
146
+ """Helper function to run a python script and modify the PYTHONPATH to include external deps.
132
147
133
- return repo_utils .execute_checked (
148
+ Args:
149
+ mrctx: Handle to the module_ctx or repository_ctx.
150
+ python: The python interpreter to use.
151
+ srcs: The src files that the script depends on. This is important to
152
+ ensure that the Bazel repository cache or the bzlmod lock file gets
153
+ invalidated when any one file changes. It is advisable to use
154
+ `RECORD` files for external deps and the list of srcs from the
155
+ rules_python repo for any scripts.
156
+ **kwargs: Arguments forwarded to `repo_utils.execute_checked`. If
157
+ the `environment` has a value `PYTHONPATH` and it is a list, then
158
+ it will be passed to `construct_pythonpath` function.
159
+ """
160
+ return repo_utils .execute_checked_stdout (
134
161
mrctx ,
135
- environment = env ,
136
- ** kwargs
162
+ ** _execute_prep (mrctx , python = python , srcs = srcs , ** kwargs )
137
163
)
138
164
139
165
pypi_repo_utils = struct (
140
166
construct_pythonpath = _construct_pypath ,
141
167
execute_checked = _execute_checked ,
168
+ execute_checked_stdout = _execute_checked_stdout ,
142
169
resolve_python_interpreter = _resolve_python_interpreter ,
143
170
)
0 commit comments