build: Starlarkify python flags by mai93 · Pull Request #3334 · bazel-contrib/rules_python

thomasdesr added a commit to thomasdesr/rules_python that referenced this pull request

@thomasdesr

…y_binary

Problem:
In rules_python 1.7.0, PR bazel-contrib#3334 ("build: Starlarkify python flags") introduced
new template placeholders in the bootstrap scripts: %stage2_bootstrap% and
%interpreter_args%. These placeholders are expected to be substituted by
rules_python's Starlark code when building py_binary targets.

However, when external repositories (like gRPC's cython) define py_binary
using the native rule, these placeholders are NOT substituted. In Bazel 7+,
native py_binary is implemented by rules_python, but native py_binary doesn't
expose attributes like `interpreter_args` that the substitution logic expects.
The result is that literal placeholder text ends up in the generated bootstrap
scripts, causing Python SyntaxError or file-not-found errors at runtime:

    File ".../cython_binary", line 39
      %interpreter_args%
      ^
    SyntaxError: invalid syntax

Fix:
Use a sentinel detection pattern directly in the templates. The key insight is
that by splitting the sentinel string (e.g., "%stage2" + "_bootstrap%"), the
substitution logic won't replace it since it looks for the exact contiguous
string. At runtime, the concatenation produces the original placeholder text,
which we compare against to detect if substitution occurred.

For %stage2_bootstrap%, we fall back to %main% which IS substituted even for
native py_binary. For %interpreter_args%, we wrap it in triple-quotes so it's
always valid Python syntax, then detect the sentinel and default to an empty
list.

This is a template-side fix that is backwards compatible and doesn't require
changes to Bazel or the substitution logic.

Test:
Add an integration test that creates an external repository with a native
py_binary (exactly like gRPC and other external repos do) and verifies it
can be built and executed successfully in WORKSPACE mode.