bazelbuild / rules_python

Bazel Python Rules
https://rules-python.readthedocs.io
Apache License 2.0
529 stars 539 forks source link

Stage-2 bootstrap script incorrectly removes inherited PYTHONPATH entries on Python 3.11 and above #2318

Open chowder opened 3 hours ago

chowder commented 3 hours ago

🐞 bug report

Affected Rule

The issue is caused by the rule: py_binary / py_test

Is this a regression?

Yes.

Description

The stage-1 bootstrap script runs python with PYTHONSAFEPATH=1, which means that no unsafe paths are preprended to the runtime environment of stage-2.

However, the stage-2 script unconditionally deletes sys.path[0]. This is harmless most of the time, since the search path that is deleted is /usr/lib/python311.zip (or similar).

But if the target caller attempts to propagate PYTHONPATH to the application, the first entry in PYTHONPATH is incorrectly removed.

🔬 Minimal Reproduction

script.py:

import sys
print("\n".join(sys.path))

BUILD.bazel:

py_binary(
    name = "script",
    srcs = [":script.py"],
)

Build and run the target with PYTHONPATH=foo:bar, observe that foo is missing from sys.path.

🌍 Your Environment

Operating System:

Linux AMD64 - CentOS 7, and Debian 11

Output of bazel version:

Bazel 7.2.1

Rules_python version:

0.36.0 (but present in 0.37.0 too)

chowder commented 2 hours ago

I suppose something is to be said about the smell that is attempting to set PYTHONPATH for a Bazel target.

Where I run into this problem is with VSCode/PyCharm debuggers which run their own bootstrap code via PYTHONPATH propagation, before running your actual target.

In any case, a simple fix for this is to replace this line, with:

if not getattr(sys.flags, "safe_path", False):
    del sys.path[0]

Happy to raise a PR if agreed.