Skip to content

Commit f9992f7

Browse files
shayanhoshyariShayan Hoshyaririckeylev
authored
fix (venv_site_packages): Fix wrong runfiles.symlinks when py_binary is not in root module (#3505)
When: 1) venv_site_packages is on 2) we have a py_binary in a non-root module (e.g. a tool used in rules), and it uses python deps that result in usage of runfiles.symlinks, the `ctx.runfile` based symlinks end up going in the wrong folder (`_main`), while the `ctx.actions.symlink(...)` files go in the right place. This results in an invalid `venv` and import errors. The reason is that `actions.symlinks` always go to the `_main` module, as [Bazel docs explain](https://bazel.build/extending/rules#runfiles_symlinks). To send symlinks to other modules, one needs to use root_symlinks and prefix them with the right module name. Fixes: #3503 --------- Co-authored-by: Shayan Hoshyari <[email protected]> Co-authored-by: Richard Levasseur <[email protected]>
1 parent 22f3de0 commit f9992f7

File tree

6 files changed

+61
-2
lines changed

6 files changed

+61
-2
lines changed

python/private/py_executable.bzl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,10 @@ def _create_venv(ctx, output_prefix, imports, runtime_details, add_runfiles_root
629629
),
630630
# venv files for user library dependencies (files that are specific
631631
# to the executable bootstrap and python runtime aren't here).
632+
# `root_symlinks` should be used, otherwise, with symlinks files always go
633+
# to `_main` prefix, and binaries from non-root module become broken.
632634
lib_runfiles = ctx.runfiles(
633-
symlinks = venv_app_files.runfiles_symlinks,
635+
root_symlinks = venv_app_files.runfiles_symlinks,
634636
),
635637
)
636638

python/private/venv_runfiles.bzl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ def create_venv_app_files(ctx, deps, venv_dir_map):
6565
bin_venv_path = paths.join(base, venv_path)
6666
if is_file(link_to):
6767
# use paths.join to handle ctx.label.package = ""
68-
symlink_from = paths.join(ctx.label.package, bin_venv_path)
68+
# runfile_prefix should be prepended as we use runfiles.root_symlinks
69+
runfile_prefix = ctx.label.repo_name or ctx.workspace_name
70+
symlink_from = paths.join(runfile_prefix, ctx.label.package, bin_venv_path)
71+
6972
runfiles_symlinks[symlink_from] = link_to
7073
else:
7174
venv_link = ctx.actions.declare_symlink(bin_venv_path)

tests/modules/other/BUILD.bazel

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
load("@rules_python//python:py_binary.bzl", "py_binary")
12
load("@rules_python//tests/support:py_reconfig.bzl", "py_reconfig_binary")
23

34
package(
@@ -12,3 +13,18 @@ py_reconfig_binary(
1213
bootstrap_impl = "system_python",
1314
main = "external_main.py",
1415
)
16+
17+
py_binary(
18+
name = "venv_bin",
19+
srcs = ["venv_bin.py"],
20+
config_settings = {
21+
"@rules_python//python/config_settings:bootstrap_impl": "script",
22+
"@rules_python//python/config_settings:venvs_site_packages": "yes",
23+
},
24+
deps = [
25+
# Add two packages that install into the same directory. This is
26+
# to test that namespace packages install correctly and are importable.
27+
"//nspkg_delta",
28+
"//nspkg_gamma",
29+
],
30+
)

tests/modules/other/venv_bin.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import nspkg
2+
3+
print(nspkg)
4+
5+
import nspkg.subnspkg
6+
7+
print(nspkg.subnspkg)
8+
9+
import nspkg.subnspkg.delta
10+
11+
print(nspkg.subnspkg.delta)
12+
13+
import nspkg.subnspkg.gamma
14+
15+
print(nspkg.subnspkg.gamma)
16+
17+
print("@other//:venv_bin ran successfully.")

tests/venv_site_packages_libs/BUILD.bazel

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
load("@rules_shell//shell:sh_test.bzl", "sh_test")
12
load("//python:py_library.bzl", "py_library")
23
load("//tests/support:py_reconfig.bzl", "py_reconfig_test")
34
load(
@@ -19,6 +20,20 @@ py_library(
1920
],
2021
)
2122

23+
sh_test(
24+
name = "py_binary_other_module_test",
25+
srcs = [
26+
"py_binary_other_module_test.sh",
27+
],
28+
data = [
29+
"@other//:venv_bin",
30+
],
31+
env = {
32+
"VENV_BIN": "$(rootpath @other//:venv_bin)",
33+
},
34+
target_compatible_with = NOT_WINDOWS,
35+
)
36+
2237
py_reconfig_test(
2338
name = "venvs_site_packages_libs_test",
2439
srcs = ["bin.py"],
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Test that for a py_binary from a dependency module, we place links created via
2+
# runfiles(...) in the right place. This tests the fix made for issues/3503
3+
4+
set -eu
5+
echo "[*] Testing running the binary"
6+
"$VENV_BIN"

0 commit comments

Comments
 (0)