mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 21:27:14 +01:00
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
181 lines
6.2 KiB
Python
181 lines
6.2 KiB
Python
"""The ~-layout gate: what it must catch, and what it must not.
|
|
|
|
The "must not" half carries the weight. A gate that fires on prose is a gate
|
|
that gets disabled: the first run of this checker returned 189 findings
|
|
across ~/src, and every single one outside `todo_desktop.dart` was either a
|
|
comment, a macOS branch, vendored third-party code, or a deliberate test
|
|
fixture. Each exclusion below is one of those, pinned so it cannot creep
|
|
back in.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from home_paths.check import ALLOW_MARKER, main, scan_file, scan_text
|
|
|
|
|
|
def _segments(text: str, name: str = "sample.py") -> list[str]:
|
|
return [f.segment for f in scan_text(Path(name), text)]
|
|
|
|
|
|
# --- the bug this gate exists for -------------------------------------------
|
|
|
|
|
|
def test_catches_the_todo_desktop_regression() -> None:
|
|
"""The exact line that served a stale backlog for a day."""
|
|
line = "backlogPath: _argValue(args, '--backlog-path') ?? p.join(home, 'todo', 'BACKLOG.md'),"
|
|
assert _segments(line, "todo_desktop.dart") == ["todo"]
|
|
|
|
|
|
def test_passes_the_fixed_form() -> None:
|
|
assert _segments("p.join(home, 'src', 'todo', 'BACKLOG.md')", "x.dart") == []
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("line", "segment"),
|
|
[
|
|
('Path.home() / "kuhylog"', "kuhylog"),
|
|
('Path.home().joinpath("kuhylog")', "kuhylog"),
|
|
("os.path.join(os.environ['HOME'], 'utils')", "utils"),
|
|
('expanduser("~/screen-locker")', "screen-locker"),
|
|
('filepath.Join(home, "octoforge")', "octoforge"),
|
|
("path.join(os.homedir(), 'signal-bot')", "signal-bot"),
|
|
('final dir = Directory("$home/todo");', "todo"),
|
|
('BACKUP="${HOME}/phone_backups"', "phone_backups"),
|
|
('f"{home}/scanlation-eval"', "scanlation-eval"),
|
|
],
|
|
)
|
|
def test_every_construction_spelling(line: str, segment: str) -> None:
|
|
"""The rewriter's blind spot was *how* the path was spelled, not which."""
|
|
assert _segments(line) == [segment]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"bucket", ["src", "vendor", "data", "sdk", "media", "Downloads", "Documents"]
|
|
)
|
|
def test_allowed_buckets_pass(bucket: str) -> None:
|
|
assert _segments(f'Path.home() / "{bucket}" / "thing"') == []
|
|
|
|
|
|
def test_dotfiles_are_not_our_business() -> None:
|
|
assert _segments('Path.home() / ".config" / "todo"') == []
|
|
assert _segments("p.join(home, '.local', 'share', 'todo')", "a.dart") == []
|
|
|
|
|
|
# --- the noise it must not make ---------------------------------------------
|
|
|
|
|
|
def test_comments_are_not_findings() -> None:
|
|
"""60% of the first run. `~/utils.` in English is a sentence."""
|
|
assert (
|
|
_segments("# Thin delegate to the shared gate in $HOME/utils, which owns it")
|
|
== []
|
|
)
|
|
assert _segments("// see ${HOME}/todo for the note format", "a.dart") == []
|
|
|
|
|
|
def test_placeholder_segments_are_not_findings() -> None:
|
|
"""Docstrings explaining the path grammar say ``$HOME/x``."""
|
|
assert (
|
|
_segments('"""One regex covers ``$HOME/x``, ``${HOME}/x`` and more."""') == []
|
|
)
|
|
|
|
|
|
def test_other_os_home_layouts_are_not_findings() -> None:
|
|
assert _segments('Path.home() / "Library" / "Logs"') == []
|
|
assert _segments('Path.home() / "AppData" / "Roaming"') == []
|
|
|
|
|
|
def test_third_party_and_test_trees_are_skipped(tmp_path: Path) -> None:
|
|
bad = "p.join(home, 'todo', 'x')"
|
|
for rel in (
|
|
"mcp-servers/a.py",
|
|
"vendor/b.py",
|
|
"repo/tests/c.py",
|
|
"repo/test_d.py",
|
|
"repo/e_test.py",
|
|
):
|
|
target = tmp_path / rel
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_text(bad)
|
|
assert scan_file(target) == [], rel
|
|
plain = tmp_path / "repo" / "real.py"
|
|
plain.write_text(bad)
|
|
assert [f.segment for f in scan_file(plain)] == ["todo"]
|
|
|
|
|
|
def test_allow_marker_is_an_escape_hatch() -> None:
|
|
assert _segments(f"x = home + '/todo' # {ALLOW_MARKER}: migration note") == []
|
|
|
|
|
|
def test_non_code_and_unreadable_files_yield_nothing(tmp_path: Path) -> None:
|
|
(tmp_path / "notes.md").write_text("p.join(home, 'todo')")
|
|
assert scan_file(tmp_path / "notes.md") == []
|
|
assert scan_file(tmp_path / "missing.py") == []
|
|
binary = tmp_path / "blob.py"
|
|
binary.write_bytes(b"\xff\xfe p.join(home, 'todo')")
|
|
assert scan_file(binary) == []
|
|
|
|
|
|
# --- CLI ---------------------------------------------------------------------
|
|
|
|
|
|
def test_cli_exit_codes(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None:
|
|
clean = tmp_path / "ok.py"
|
|
clean.write_text('Path.home() / "src" / "todo"')
|
|
dirty = tmp_path / "bad.py"
|
|
dirty.write_text('Path.home() / "todo"')
|
|
|
|
assert main([]) == 2
|
|
assert main([str(clean)]) == 0
|
|
assert main([str(dirty)]) == 1
|
|
out = capsys.readouterr().out
|
|
assert "builds ~/todo" in out and "Did you mean ~/src/todo?" in out
|
|
|
|
assert main(["--all", str(tmp_path)]) == 1
|
|
clean_dir = tmp_path / "clean"
|
|
clean_dir.mkdir()
|
|
(clean_dir / "f.py").write_text("x = 1")
|
|
assert main(["--all", str(clean_dir)]) == 0
|
|
|
|
|
|
def test_render_falls_back_to_absolute_path_outside_root(tmp_path: Path) -> None:
|
|
dirty = tmp_path / "bad.py"
|
|
dirty.write_text('Path.home() / "todo"')
|
|
(finding,) = scan_file(dirty)
|
|
assert finding.render(Path("/nowhere")).startswith(str(dirty))
|
|
assert finding.render(tmp_path).startswith("bad.py:")
|
|
|
|
|
|
def test_walk_prunes_caches_third_party_and_tests(tmp_path: Path) -> None:
|
|
"""`--all` must not descend into build output or vendored trees.
|
|
|
|
Without this the gate reports on code nobody here owns, which is how the
|
|
first run produced 18 findings about macOS `~/Library` inside a vendored
|
|
Unity MCP server.
|
|
"""
|
|
bad = 'Path.home() / "todo"'
|
|
for rel in (
|
|
"build/out.py",
|
|
"node_modules/pkg/index.js",
|
|
".venv/lib/thing.py",
|
|
"vendor/clone/x.py",
|
|
"pkg/tests/t.py",
|
|
"pkg/test_helper.py",
|
|
"pkg/thing_test.py",
|
|
"notes.md",
|
|
):
|
|
target = tmp_path / rel
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_text(bad)
|
|
real = tmp_path / "pkg" / "real.py"
|
|
real.write_text(bad)
|
|
|
|
assert main(["--all", str(tmp_path)]) == 1
|
|
from home_paths.check import walk
|
|
|
|
assert [p.name for p in walk(tmp_path)] == ["real.py"]
|