hermes-agent / tests /scripts /test_check_public_surface.py
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
18d3630 verified
Raw History Blame Contribute Delete
4.3 kB
"""scripts/ci/check_public_surface.py detects silently dropped public names, methods and test defs.
Replayed against the Sep 2026 refactor PR at open it reports 1,703 public names dropped in 341 modules
(the figure reviewers had to find ~30 of by hand); here the contract is pinned on a throwaway repo.
"""
import importlib.util
import subprocess
import textwrap
from pathlib import Path
SCRIPT = Path(__file__).resolve().parents[2] / "scripts" / "ci" / "check_public_surface.py"
def _load():
spec = importlib.util.spec_from_file_location("check_public_surface", SCRIPT)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
def _git(repo, *args):
subprocess.run(["git", "-C", str(repo), *args], check=True, capture_output=True,
env={"GIT_AUTHOR_NAME": "t", "GIT_AUTHOR_EMAIL": "t@t", "GIT_COMMITTER_NAME": "t",
"GIT_COMMITTER_EMAIL": "t@t", "PATH": "/usr/bin:/bin:/usr/local/bin"})
def test_dropped_public_names_methods_and_test_defs_are_reported_and_moves_are_not(tmp_path, monkeypatch):
repo = tmp_path
(repo / "agent").mkdir(); (repo / "tests").mkdir(); (repo / "docs").mkdir()
(repo / "agent" / "mod.py").write_text(textwrap.dedent('''
import os
from json import loads as parse
LIMIT = 3
def keep(): ...
def gone(): ...
def _private(): ...
class K:
def pub(self): ...
def __len__(self): return 0
def _hidden(self): ...
class Big:
def stays(self): ...
def extracted(self): ...
'''), encoding="utf-8")
(repo / "agent" / "moved.py").write_text("def relocated(): ...\n", encoding="utf-8")
(repo / "tests" / "test_x.py").write_text("def test_a(): ...\ndef test_b(): ...\nasync def test_c(): ...\n", encoding="utf-8")
(repo / "docs" / "notes.py").write_text("def doc_helper(): ...\n", encoding="utf-8")
_git(repo, "init", "-q", "-b", "main"); _git(repo, "add", "."); _git(repo, "commit", "-qm", "base")
# HEAD: drop `gone`, `parse`, `K.pub`, `K.__len__`; drop `_private`/`K._hidden` (private: fine);
# move `relocated` into mod with a re-export left behind (fine); lose one test def; change a
# non-source module (ignored).
(repo / "agent" / "mod.py").write_text(textwrap.dedent('''
import os
from agent.moved import relocated # re-export
LIMIT = 3
def keep(): ...
class K: ...
class _BigMixin:
def extracted(self): ... # moved into an in-module base: still reachable on Big
class Big(_BigMixin):
def stays(self): ...
'''), encoding="utf-8")
(repo / "agent" / "moved.py").write_text("def relocated(): ...\ndef relocated2(): ...\n", encoding="utf-8")
(repo / "tests" / "test_x.py").write_text("def test_a(): ...\nasync def test_c(): ...\n", encoding="utf-8")
(repo / "docs" / "notes.py").write_text("def other(): ...\n", encoding="utf-8")
_git(repo, "add", "."); _git(repo, "commit", "-qm", "head")
monkeypatch.chdir(repo)
mod = _load()
report = mod.diff_surface("HEAD~1", "HEAD")
assert report["dropped_names"] == {"agent/mod.py": ["gone", "parse"]}
assert report["dropped_methods"] == {"agent/mod.py": ["K.__len__", "K.pub"]}
assert report["test_drops"] == {"tests/test_x.py": (3, 2)}
assert mod.main(["--base", "HEAD~1", "--head", "HEAD"]) == 0 # advisory
assert mod.main(["--base", "HEAD~1", "--head", "HEAD", "--strict"]) == 1
assert mod.main(["--base", "HEAD", "--head", "HEAD", "--strict"]) == 0 # nothing dropped
def test_unresolvable_refs_are_an_error_not_a_clean_report(tmp_path, monkeypatch):
"""Independent-review witness: a nonexistent base ref under --strict reported zero drops and exited 0,
which would make a mis-fetched CI job look clean."""
repo = tmp_path
(repo / "a.py").write_text("x = 1\n", encoding="utf-8")
_git(repo, "init", "-q", "-b", "main"); _git(repo, "add", "."); _git(repo, "commit", "-qm", "base")
monkeypatch.chdir(repo)
mod = _load()
assert mod.main(["--base", "origin/does-not-exist", "--head", "HEAD", "--strict"]) == 2
assert mod.main(["--base", "origin/does-not-exist", "--head", "HEAD"]) == 2