Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 70 additions & 4 deletions tests/test_watermark_route_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"""
from __future__ import annotations

import io
import re
import tokenize
from pathlib import Path

import pytest
Expand Down Expand Up @@ -75,6 +77,46 @@
]


def _code_only(src: str) -> str:
"""``src`` with comments and string literals blanked to spaces.

ee35d238 made a module a "producer" by *mentioning* ``backend.generate()``
in a comment β€” prose can't synthesize audio. Only real call sites may
match ``_SYNTH_CALL``, so blank every COMMENT/STRING token span (spaces,
not deletion, to keep the layout the regexes were written against).
Unparseable source falls back to the raw text β€” fail closed, a module we
can't tokenize still gets scanned.

f-strings stay conservative (Greptile P1 on #1564): on Python ≀3.11 the
whole f-string β€” replacement expressions included β€” is ONE STRING token,
so blanking it would let ``f"{backend.generate(t)}"`` evade the guard.
f-prefixed strings are therefore kept raw there (a literal f-string
*mentioning* a primitive false-positives toward the allowlist β€” fail
closed). On 3.12+ (PEP 701) replacement code arrives as ordinary tokens
and only the literal FSTRING_MIDDLE text is blanked.
"""
fstring_middle = getattr(tokenize, "FSTRING_MIDDLE", None)
lines = src.splitlines(keepends=True)
try:
tokens = list(tokenize.generate_tokens(io.StringIO(src).readline))
except (tokenize.TokenError, IndentationError, SyntaxError):
return src
for tok in tokens:
Comment thread
greptile-apps[bot] marked this conversation as resolved.
if tok.type == tokenize.STRING:
prefix = tok.string.split(tok.string[-1], 1)[0].rstrip("\"'")
if "f" in prefix.lower():
continue # pre-3.12 f-string: may contain executable code
elif tok.type not in (tokenize.COMMENT, fstring_middle):
continue
Comment thread
coderabbitai[bot] marked this conversation as resolved.
(srow, scol), (erow, ecol) = tok.start, tok.end
for row in range(srow - 1, erow):
line = lines[row]
lo = scol if row == srow - 1 else 0
hi = ecol if row == erow - 1 else len(line.rstrip("\r\n"))
lines[row] = line[:lo] + " " * (hi - lo) + line[hi:]
return "".join(lines)


def _py_files():
for sub in ("api", "services", "worker"):
for p in sorted((_BACKEND / sub).rglob("*.py")):
Expand All @@ -84,9 +126,11 @@ def _py_files():
def test_every_synthesis_module_routes_through_mark_synthetic():
offenders = []
for rel, src in _py_files():
if not _SYNTH_CALL.search(src):
if not _SYNTH_CALL.search(_code_only(src)):
Comment thread
coderabbitai[bot] marked this conversation as resolved.
continue
if rel in _ALLOWED or "mark_synthetic" in src:
# The satisfying reference must be code too β€” a comment saying
# "mark_synthetic" must not certify a module (CodeRabbit, #1564).
if rel in _ALLOWED or "mark_synthetic" in _code_only(src):
continue
offenders.append(rel)
assert not offenders, (
Expand All @@ -100,7 +144,7 @@ def test_every_synthesis_module_routes_through_mark_synthetic():
@pytest.mark.parametrize("rel", _PRODUCERS)
def test_known_producer_still_marks(rel):
src = (_BACKEND / rel).read_text(encoding="utf-8")
assert "mark_synthetic" in src, (
assert "mark_synthetic" in _code_only(src), (
f"{rel} lost its mark_synthetic call β€” its synthetic audio would ship "
"without the Art. 50(2) provenance mark (#1169)."
)
Expand All @@ -127,12 +171,34 @@ def test_allowlist_is_not_stale():
p = _BACKEND / rel
assert p.is_file(), f"watermark-coverage list names a missing file: {rel}"
for rel in _ALLOWED:
assert _SYNTH_CALL.search((_BACKEND / rel).read_text(encoding="utf-8")), (
assert _SYNTH_CALL.search(_code_only((_BACKEND / rel).read_text(encoding="utf-8"))), (
f"{rel} no longer matches a synthesis primitive β€” remove it from "
"tests/test_watermark_route_coverage.py so the guard stays sharp."
)


def test_prose_mentions_are_not_producers():
"""The ee35d238 regression: a comment (or log string / docstring) naming a
synthesis primitive must not make a module a producer β€” only a call can."""
prose = (
"# A generic backend.generate() call accepts the same wire shape\n"
'MSG = "route through generate_with_cached_ref(model) instead"\n'
"def f():\n"
' """Docs may mention _run_inference( freely."""\n'
" return 1\n"
)
assert not _SYNTH_CALL.search(_code_only(prose))
real = "def f(backend):\n return backend.generate(text='hi')\n"
assert _SYNTH_CALL.search(_code_only(real))
# Greptile P1: a call inside an f-string replacement field is code and
# must still be caught, on every supported Python (≀3.11 tokenizes the
# whole f-string as one STRING; 3.12+ splits out the expression tokens).
fstring_call = 'def f(backend):\n return f"{backend.generate(text=\'hi\')}"\n'
assert _SYNTH_CALL.search(_code_only(fstring_call))
# ...and a comment claiming mark_synthetic must not certify a producer.
assert "mark_synthetic" not in _code_only("# routes via mark_synthetic\nx = 1\n")


# ── mark_synthetic unit contract (delegation, not new policy) ────────────────


Expand Down
Loading