You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Cover all override directives in the apple_support CI guard - #424
Added all four remaining Bazel module override directives to the alternation, plus a test for each. Confirmed each new test fails against the pre-fix pattern (standalone repro) before adding the fix.
Test plan
bazelisk test //python:ci_macos_asan_test — passes with the fixed helper; each new test confirmed red against the old pattern first
_has_apple_support_override() only matched single_version_override --
archive_override, git_override, local_path_override, and
multiple_version_override all silently returned False. Same gap flagged
by review on the equivalent toolchains_llvm guard in #423. Added the
remaining four directives to the alternation and a test for each;
confirmed each new test fails against the pre-fix pattern (standalone
repro) before adding the fix.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same gap review caught on the toolchains_llvm guard in #423: the inline
regex only matched "name" immediately followed by "version", so reordered
or multiline bazel_dep(...) arguments would fail the guard even with the
dependency correctly pinned. Extracted _apple_support_bazel_dep_version(),
parsing the whole call body and finding both fields independently, matching
_rules_cc_bazel_dep_version() in ci_windows_cppopts_test.py. Confirmed the
new reordered-args test fails against the old inline pattern (standalone
repro) before the fix.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Proactively applied the same fix review caught on #423's analogous version parser: the inline `bazel_dep` regex here only matched `name` immediately followed by `version`, so reordered/multiline args would fail the guard despite the dependency being correctly pinned. Extracted `_apple_support_bazel_dep_version()` parsing the whole call body, matching `_rules_cc_bazel_dep_version()` in `ci_windows_cppopts_test.py`. Confirmed red against the old pattern before the fix (2c95756).
Same bug review found on the toolchains_llvm guard in #423: [^)]*)\)
stops at the first ")" even inside a string, comment, or nested call, so
a leading comment like "# fixes Xcode 27 crosstool warnings (see docs)"
before the real args would truncate the match. _iter_call_bodies()
replaces both regexes with a character scanner tracking string/comment
state and paren depth. Added a test with a ")" in a leading comment for
each helper; confirmed both fail against the old regex (standalone repro)
before the fix.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Proactively applied the same fix review caught on #423's analogous helpers: `[^)]*)\)` truncates at the first `)`, including one inside a leading comment, which would spuriously fail/bypass this guard. Replaced both regexes with `_iter_call_bodies()`, a character scanner tracking string/comment state and paren depth. Added a test with a `)` in a leading comment for each helper; confirmed red against the old regex before the fix (d9589ac).
…tring.
- git_override was the one new directive in the #421 follow-up without its
own dedicated test, even though the alternation already matched it
correctly -- added test_has_apple_support_override_detects_git_override
so a future regression in that branch would be caught.
- _has_apple_support_override()'s docstring said it detects a pin "to a
specific commit/version set," which doesn't describe local_path_override
(selects a local directory, not a commit or version). Reworded to
describe the actual predicate: any of the five override directives
targeting apple_support.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed in a8ffd41 — these two weren't covered by the earlier proactive mirroring from #423 (they're specific to this PR's own diff):
Added `test_has_apple_support_override_detects_git_override`, the one directive left without a dedicated test.
Reworded `_has_apple_support_override()`'s docstring, which described the predicate as detecting a pin "to a specific commit/version set" — inaccurate for `local_path_override`, which selects a local directory, not a commit or version.
Ignore commented-out directives when detecting version overrides
python/tests/ci_macos_asan_test.py:35
pattern.finditer() locates call-looking text before any lexical state is tracked, so commented-out directives are treated as active overrides. For example, # single_version_override(module_name = "apple_support", version = "1.24.2") makes _has_apple_support_override() return True even though MODULE.bazel contains no override. Please identify call starts while scanning code state (excluding comments and strings), and add a regression test for a commented-out override.
Same bug fixed on the toolchains_llvm guard in #423: _iter_call_bodies()
located each call with a plain regex search for "name(", which matches
that text inside a "#" comment too -- a commented-out "bazel_dep(...
version = \"9.9.9\")" before the real dependency made the version guard
read the dead value, and a commented-out override made
_has_apple_support_override return a false positive. Rewritten as a
single linear scan that tracks string/comment state continuously.
Confirmed both failure modes against the old scanner (standalone repro)
before the fix, and added a dedicated commented-out-call test for each
helper.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Mirrored the fix from #423: `_iter_call_bodies()` located each call via a plain regex search for `name(`, which matches that text inside a `#` comment too — confirmed with a standalone repro that a commented-out `bazel_dep(... version = "9.9.9")` before the real dependency made the version guard read the dead value, and a commented-out override made `_has_apple_support_override` return a false positive.
Rewrote it as a single linear scan tracking string/comment state continuously, and added a dedicated commented-out-call test for each helper (8c8e2b0).
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Parser edge cases can cause the CI guard to miss overrides or accept commented-out version values.
0 open findings
Previously missed (2)
In code that hasn't changed since last review
Allow whitespace between directive name and opening parenthesis
python/tests/ci_macos_asan_test.py:76
This requires ( to immediately follow the directive name, although whitespace before the call parenthesis is valid. An override written as archive_override ( is therefore skipped and the CI guard can pass despite the prohibited override. Skip horizontal whitespace after a matched name before checking and consuming (.
Ignore commented-out assignments when matching directives
python/tests/ci_macos_asan_test.py:98
The scanner tracks comment state while balancing parentheses, but returns the original slice with comments intact. Both downstream regexes therefore treat commented-out assignments as live: for example, an active version = "1.0.0" preceded by # version = "9.9.9" makes the minimum-version guard pass, and a comment containing module_name = "apple_support" makes an override for another module look like an apple_support override. Return a body with comment text masked/removed (while preserving strings), or parse active argument tokens before matching.
Two gaps in _iter_call_bodies(), confirmed with standalone adversarial
inputs before fixing:
- "archive_override (module_name = ...)" (space before the parenthesis,
valid Starlark) matched zero calls, so the guard missed it entirely —
a false negative.
- The body text it returned still contained comment characters verbatim,
so a commented-out "module_name = \"apple_support\"" inside a different
module's override made it look like an apple_support override (false
positive), and a commented-out stale version before the real one could
win the regex search (version guard reads the wrong value).
The name/paren scan now skips whitespace between the call name and "(",
and the body-building loop drops "#" comment characters from the output
(string contents are still kept verbatim) instead of just tracking comment
state to avoid breaking paren balance. Added a regression test for each.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Whitespace before "(": `archive_override (module_name = ...)` (valid Starlark, space before the paren) previously matched zero calls — a false negative. Fixed by skipping whitespace between the call name and "(" before requiring it.
Commented-out assignments inside a call body: the returned body text kept comment characters verbatim, so a commented-out `module_name = "apple_support"` inside a different module's override made it look like an apple_support override, and a commented-out stale version before the real one could win the version-guard's regex search. Fixed by dropping "#" comment characters from the body text the function returns (string contents are kept verbatim).
Confirmed both with standalone adversarial-input repros before fixing, and added a dedicated regression test for each.
Mirrors the fix just applied to the identical apple_support guard in #424,
confirmed here with the same standalone adversarial-input repros before
fixing:
- "archive_override (module_name = ...)" (space before the parenthesis,
valid Starlark) matched zero calls -- a false negative.
- The returned body text kept comment characters verbatim, so a
commented-out "module_name = \"toolchains_llvm\"" inside a different
module's override made it look like a toolchains_llvm override, and a
commented-out stale version before the real one could win the
version-guard's regex search.
The name/paren scan now skips whitespace between the call name and "(",
and the body-building loop drops "#" comment characters from the output
(string contents are kept verbatim). Added a regression test for each.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Starlark accepts both quote styles, but this matcher only recognizes double quotes. A valid override such as archive_override(module_name = 'apple_support', ...) therefore makes the guard return False, allowing exactly the override this test is meant to reject. Match and back-reference either quote delimiter (and add a single-quoted regression case).
…y text.
Mirrors the fix just applied to the identical toolchains_llvm guard in
#423: masking "#" comments out of the returned body still left a gap --
a regex search over that body text also matches an unrelated argument's
string value that happens to contain assignment-shaped text, e.g. a
bazel_dep for rules_cc with
patch_cmds = ['historically name = "apple_support", version = "9.9.9"']
would be misread as the apple_support dependency, and the same shape of
string value fools the override check.
_iter_call_bodies() is replaced by _iter_call_kwargs(), which parses actual
"identifier = value" pairs at the call's top-level parenthesis depth only,
with the identifier-matcher never offered a character while scanning
inside a string or comment. _apple_support_bazel_dep_version() and
_has_apple_support_override() now check dict lookups instead of regexes.
Added a dedicated test for the string-value case on each helper.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Mirrors the same fix on #423: a top-level list or dict expression
opening the first positional argument (e.g. ["apple_support"][0]) was
descended into without ever recording _POSITIONAL_KEY, so module_name
read as absent and _has_apple_support_override() missed the override.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Proactively mirrored a fix from #423's identical `_iter_call_kwargs()`: a top-level list or dict expression opening the first positional argument — e.g. `archive_override(["apple_support"][0], ...)` — was descended into without ever recording `_POSITIONAL_KEY`, so `module_name` read as absent and `_has_apple_support_override()` missed the override.
Applied the same "mark unresolved before descending" guard to the `[` and `{` branches, plus two mirrored regression tests — list and dict (614a2f4).
The RHS lookahead after "ident =" only skipped whitespace, so a
comment on its own line between "=" and the literal (valid Starlark
formatting) made the RHS look non-literal: module_name = # note\n
"rules_cc" was marked _UNRESOLVED and falsely tripped
_has_apple_support_override() for an unrelated module's override, and
the same shape on bazel_dep's version returned the sentinel instead of
the actual version string.
Factored the comment-skipping loop already in _is_complete_literal()
out into _skip_ws_and_comments(), and used it for the RHS lookahead too.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed the latest Copilot finding: comments between "=" and the RHS.
The RHS lookahead after `ident =` only skipped whitespace via `_skip_ws()`, so a comment on its own line between `=` and the literal — valid Starlark formatting — made the RHS look non-literal. Reproduced both cases from the finding:
`module_name =\n # pin past Xcode 27 fixes\n "rules_cc"` was marked `_UNRESOLVED`, falsely tripping `_has_apple_support_override()` for an unrelated module's override (returned `True`, should be `False`).
The same shape on `bazel_dep`'s `version =` returned the sentinel instead of the actual version string.
Factored the comment-skipping loop already in `_is_complete_literal()` out into a shared `_skip_ws_and_comments()`, and used it for the RHS lookahead too (7d162ae). Both reproductions now resolve correctly, confirmed directly, plus two regression tests (one per function) and confirmed the apple_support-with-a-comment case still correctly returns `True` (not over-corrected into never matching).
Mirrors the same fix on #424: the RHS lookahead after "ident =" only
skipped whitespace, so a comment on its own line between "=" and the
literal (valid Starlark formatting) made the RHS look non-literal:
module_name = # note\n "rules_cc" was marked _UNRESOLVED and falsely
tripped _has_toolchains_llvm_override() for an unrelated module's
override, and the same shape on bazel_dep's version returned the
sentinel instead of the actual version string.
Factored the comment-skipping loop already in _is_complete_literal()
out into _skip_ws_and_comments(), and used it for the RHS lookahead too.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The outer call-name scan only recognized a bare "name(" call, so a
valid Starlark call through a parenthesized callable reference --
"(archive_override)(module_name = \"apple_support\", ...)", equivalent
to the direct form since grouping parens around any expression are
legal and the result can be called immediately -- didn't match
textually and let the override bypass _has_apple_support_override().
Added _match_parenthesized_call() to recognize "(" name ")(" as an
alternate way to find the same call, wired into the outer scan
alongside the existing direct-call match.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed the latest Copilot finding: parenthesized-callable indirection.
Reproduced the example directly: `(archive_override)(module_name = "apple_support", urls = ["x"])` — valid Starlark, since grouping parens around any expression are legal and the result can be called immediately — returned `False` from `_has_apple_support_override()` before the fix (should be `True`).
Took the second option the finding offered (fail closed for this specific callable-indirection form, rather than a full Starlark-aware parser/evaluator, which would be a much larger change than this guard warrants): added `_match_parenthesized_call()`, which recognizes `"(" name ")("` as an alternate way to find the same call, wired into the outer scan alongside the existing direct `name(` match (43f561d).
Verified: the indirection form is now detected, a longer identifier like `(archive_override_foo)(...)` is correctly rejected (not a false match), an indirected override on an unrelated module doesn't false-trigger, and the direct `archive_override(...)` form is unaffected. Two regression tests added.
Mirrors the same fix on #424: the outer call-name scan only recognized
a bare "name(" call, so a valid Starlark call through a parenthesized
callable reference -- "(archive_override)(module_name =
\"toolchains_llvm\", ...)", equivalent to the direct form since
grouping parens around any expression are legal and the result can be
called immediately -- didn't match textually and let the override
bypass _has_toolchains_llvm_override().
Added _match_parenthesized_call() to recognize "(" name ")(" as an
alternate way to find the same call, wired into the outer scan
alongside the existing direct-call match.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Mirrors the same fix on #423: _decode_escape() had no case for a
backslash immediately followed by an actual LF/CRLF line break in the
source (as opposed to the two-character "\n" escape for a newline
value), so it fell through to the default "leave as literal backslash
+ next character" branch. A module_name literal split across two
source lines by a trailing backslash -- valid Starlark, which drops
the continuation entirely -- kept both the backslash and the newline
character, producing a value that never equals the real module name
and letting the override bypass the fail-closed guard.
Added LF and CRLF line-continuation decoding (both collapse to "").
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Proactively mirrored a fix from #423's identical `_decode_escape()`: a backslash immediately followed by an actual LF/CRLF line break in the source (as opposed to the two-character `\n` escape for a newline value) fell through to the default "leave as literal backslash + next character" branch. A `module_name` literal split across two source lines by a trailing backslash — valid Starlark, which drops the continuation entirely — kept both characters, producing a value that never equals the real module name and letting the override bypass the fail-closed guard.
Added the same LF/CRLF line-continuation decoding (both collapse to `""`), plus two mirrored regression tests (0e22b4f).
Raw string literals are misclassified as unresolved names
python/tests/ci_macos_asan_test.py:360
This treats only a quote as a string-literal RHS, but Starlark also supports raw literals such as r"rules_cc". For archive_override(module_name = r"rules_cc", ...), the parser marks module_name unresolved and _has_apple_support_override incorrectly returns true, blocking a valid unrelated override. Recognize the raw-string prefix throughout tokenization and skip escape decoding for its contents.
module_name = r"rules_cc" (a raw string, valid Starlark) was read as a
bare identifier "r" followed by a separate, unrelated quoted string:
the keyword-RHS and positional-capture checks only recognized a quote
character directly, so the "r"/"R" prefix fell through to the
bare-identifier-is-unresolved path added earlier, and the guard
incorrectly failed closed (returned True) for an override on a
completely unrelated module -- a false-positive CI failure, not a
guard bypass, but still wrong.
Added _is_raw_string_start()/_skip_raw_string()/_skip_any_string():
raw strings only give "\<quote>" special meaning (a literal quote,
string continues) while every other backslash, including one before a
newline, is kept completely literal -- unlike an ordinary string's
_decode_escape(). Wired _skip_any_string() into the two places that
decide whether a token is the argument's literal value (keyword RHS,
first-positional capture); left the outer call-name scan and bracket-
interior skipping on plain _skip_string(), since those only need to
correctly skip past a string's content (never read its value) and
already do so correctly for every raw string actually seen in
MODULE.bazel.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed the latest Copilot finding: raw string literals.
`module_name = r"rules_cc"` — valid Starlark, a raw string literal — was read as a bare identifier `r` followed by a separate quoted string, falling through to the bare-identifier "unresolved" path, which made the guard incorrectly return `True` (fail closed) for an override on a completely unrelated module. Not a guard bypass, but a false-positive CI failure, as the finding's headline says.
Added `_is_raw_string_start()`/`_skip_raw_string()`/`_skip_any_string()`: per the Starlark spec, a raw string only gives `<quote>` special meaning (a literal quote, the string continues) — every other backslash, including one before a newline, is kept completely literal rather than decoded. Wired `_skip_any_string()` into the two places that decide whether a token is the argument's literal value (keyword RHS, first-positional capture) (4468a31).
Verified: the unrelated-module case no longer false-triggers, an `apple_support` raw literal is still detected (both keyword and positional forms, confirmed `r`/`R` prefixes and single/double quotes), a raw literal with an escaped quote (`r"apple_"support"`, a different string from "apple_support") correctly resolves to its true value rather than matching, and the plain-literal and real-bare-identifier cases are unaffected. Four regression tests added.
Two fixes:
1. _match_parenthesized_call() used _skip_ws() around the grouped
callable name's tokens, so a comment inside the grouping -- e.g.
"(archive_override # note\n)(module_name = \"toolchains_llvm\",
...)", which Starlark ignores the comment in and treats identically
to the plain "(name)(" form -- made this scanner miss the call and
let the override bypass the guard. Switched to
_skip_ws_and_comments().
2. Mirrored from #424: module_name = r"rules_cc" (a raw string literal,
valid Starlark) was read as a bare identifier "r" followed by a
separate quoted string, falling through to the bare-identifier
"unresolved" path, so the guard incorrectly returned True (failed
closed) for an override on a completely unrelated module -- a
false-positive CI failure, not a guard bypass, but still wrong.
Added _is_raw_string_start()/_skip_raw_string()/_skip_any_string()
(raw strings only give "\<quote>" special meaning; every other
backslash, including one before a newline, is kept completely
literal) and wired _skip_any_string() into the keyword-RHS and
first-positional checks.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Mirrors the same fix on #423: _match_parenthesized_call() used
_skip_ws() around the grouped callable name's tokens, so a comment
inside the grouping -- e.g. "(archive_override # note\n)(module_name
= \"apple_support\", ...)", which Starlark ignores the comment in and
treats identically to the plain "(name)(" form -- made this scanner
miss the call and let the override bypass the guard. Switched to
_skip_ws_and_comments().
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Proactively mirrored a fix from #423's identical `_match_parenthesized_call()`: it used `_skip_ws()` around the grouped callable name's tokens, so a comment inside the grouping — `(archive_override # note\n)(module_name = "apple_support", ...)`, which Starlark ignores identically to the plain `(name)(` form — made this scanner miss the call and let the override bypass the guard.
Switched to `_skip_ws_and_comments()` (already used elsewhere in this file for the same reason), plus a mirrored regression test (0a416ab).
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The scanner mishandles valid raw triple-quoted strings and misses multiply grouped override calls.
0 open findings
Previously missed (1)
In code that hasn't changed since last review
Triple-quoted raw strings trigger false override detection
python/tests/ci_macos_asan_test.py:171
Raw triple-quoted literals are valid Starlark, but this deliberately parses only one-character raw-string delimiters. For archive_override(module_name = r"""rules_cc""", ...), _skip_raw_string stops at the first quote and marks the value unresolved; the fail-closed check then incorrectly reports an apple_support override, so an unrelated valid override breaks this CI guard. Handle triple delimiters as _skip_string does and add an unrelated-module regression case.
_skip_raw_string() only handled a single-character delimiter, so
module_name = r"""rules_cc""" stopped at the first lone quote inside
the triple-quote run, leaving the value unresolved. The fail-closed
guard then incorrectly returned True for an override on a completely
unrelated module -- a false-positive CI failure, same class of bug as
the earlier single-quote raw-string fix.
Extended _skip_raw_string() to match a triple-quote delimiter as the
3-character sequence, the same way _skip_string() already does for
ordinary strings, while keeping the raw "\<quote>" escape rule (a
backslash before a single quote character is still a literal quote
that doesn't end the string, even inside a triple-quoted raw literal).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed the latest Copilot finding: raw triple-quoted strings.
`_skip_raw_string()` only handled a single-character delimiter, so `module_name = r"""rules_cc"""` stopped at the first lone quote inside the triple-quote run, leaving the value unresolved and making the fail-closed guard incorrectly return `True` for an override on a completely unrelated module. Reproduced directly against the Copilot-supplied example (returned `True`, should be `False`).
Extended `_skip_raw_string()` to match a triple-quote delimiter as the 3-character sequence, the same way `_skip_string()` already does for ordinary strings, keeping the raw `<quote>` escape rule (a backslash before a single quote character is still a literal quote that doesn't end the string) (91b57ff). Added both regression cases the finding asked for — an unrelated override and the `bazel_dep` name — plus one confirming `apple_support` via a raw triple-quote still matches, and confirmed the plain and ordinary-raw-string cases are unaffected.
Mirrors the same fix on #424: _skip_raw_string() only handled a
single-character delimiter, so module_name = r"""apple_support"""
stopped at the first lone quote inside the triple-quote run, leaving
the value unresolved. The fail-closed guard then incorrectly returned
True for an override on a completely unrelated module -- a
false-positive CI failure, same class of bug as the earlier
single-quote raw-string fix.
Extended _skip_raw_string() to match a triple-quote delimiter as the
3-character sequence, the same way _skip_string() already does for
ordinary strings, while keeping the raw "\<quote>" escape rule.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The scanner misses or mishandles several valid Starlark call and string forms.
0 open findings
Previously missed (2)
In code that hasn't changed since last review
Handle backslash parity when parsing raw-string closing quotes
python/tests/ci_macos_asan_test.py:184
Raw-string quote handling must account for the parity of the preceding backslash run. With a valid raw literal ending in two backslashes, such as strip_prefix = r"foo\\\\", the second backslash is currently treated as escaping the closing quote; parsing then consumes later arguments and marks an unrelated override unresolved, so the apple_support guard fails spuriously. Count consecutive backslashes and treat the quote as escaped only after an odd run (while preserving raw backslashes in the value).
Capture bazel_dep version from the second positional argument
python/tests/ci_macos_asan_test.py:468
bazel_dep also permits version as its second positional argument, but the scanner records only the first positional value. Consequently the valid declaration bazel_dep("apple_support", "2.10.1") makes this helper raise instead of verifying the pin. Capture positional arguments by index, or otherwise handle the second positional value here.
🧠 Review effort: Balanced
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Test plan
bazelisk test //python:ci_macos_asan_test— passes with the fixed helper; each new test confirmed red against the old pattern firstbazelisk test //python/...— 24/24 pass🤖 Generated with Claude Code