Skip to content

Commit f0b36ae

Browse files
committed
compute relative path from venv bin dir to actual interpreter path
1 parent ca1d310 commit f0b36ae

File tree

1 file changed

+25
-9
lines changed

1 file changed

+25
-9
lines changed

python/private/py_executable_bazel.bzl

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ def _create_executable(
191191
hasattr(runtime_details.effective_runtime, "stage2_bootstrap_template")):
192192
venv = _create_venv(
193193
ctx,
194-
executable = executable,
195194
output_prefix = base_executable_name,
196195
imports = imports,
197196
runtime_details = runtime_details,
@@ -345,13 +344,34 @@ def _create_zip_main(ctx, *, stage2_bootstrap, runtime_details, venv):
345344
)
346345
return output
347346

347+
348+
# Return a relative path from one path to another, where both paths are each
349+
# relative paths from a common root.
350+
def _relative_path(from_, to):
351+
from_parts = from_.split("/")
352+
to_parts = to.split("/")
353+
354+
# Strip common "../" parts from both paths
355+
# (no while loops in starlark :( )
356+
n = max(len(from_parts), len(to_parts))
357+
for _ in range(n):
358+
if from_parts[0] == ".." and to_parts[0] == "..":
359+
from_parts.pop(0)
360+
to_parts.pop(0)
361+
else:
362+
break
363+
364+
parent = "/".join([".."] * len(from_parts))
365+
return "/".join([parent] + to_parts)
366+
367+
348368
# Create a venv the executable can use.
349369
# For venv details and the venv startup process, see:
350370
# * https://docs.python.org/3/library/venv.html
351371
# * https://snarky.ca/how-virtual-environments-work/
352372
# * https://github.com/python/cpython/blob/main/Modules/getpath.py
353373
# * https://github.com/python/cpython/blob/main/Lib/site.py
354-
def _create_venv(ctx, executable, output_prefix, imports, runtime_details):
374+
def _create_venv(ctx, output_prefix, imports, runtime_details):
355375
venv = "_{}.venv".format(output_prefix.lstrip("_"))
356376

357377
# The pyvenv.cfg file must be present to trigger the venv site hooks.
@@ -369,13 +389,9 @@ def _create_venv(ctx, executable, output_prefix, imports, runtime_details):
369389
# in runfiles is always a symlink. An RBE implementation, for example,
370390
# may choose to write what symlink() points to instead.
371391
interpreter = ctx.actions.declare_symlink("{}/bin/{}".format(venv, py_exe_basename))
372-
interpreter_actual_path = runtime.interpreter.short_path # Always relative to .runfiles/${workspace}
373-
374-
escapes = 2 # To escape out of ${target}.venv/bin
375-
escapes += executable.short_path.count("/") # To escape into .runfiles/${workspace}
376-
377-
parent = "/".join([".."] * escapes)
378-
rel_path = parent + "/" + interpreter_actual_path
392+
interpreter_actual_path = runtime.interpreter.short_path
393+
venv_bin_dir = paths.dirname(interpreter.short_path)
394+
rel_path = _relative_path(from_=venv_bin_dir, to=interpreter_actual_path)
379395
ctx.actions.symlink(output = interpreter, target_path = rel_path)
380396
else:
381397
py_exe_basename = paths.basename(runtime.interpreter_path)

0 commit comments

Comments
 (0)