atlasbot/scripts/check_file_sizes.py

71 lines
1.8 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
"""Fail when production Python files exceed the configured line budget.
The gate is intentionally narrow:
- it only checks the `atlasbot/` package tree;
- it treats each file independently;
- it keeps the threshold explicit so CI can ratchet without guesswork.
"""
from __future__ import annotations
import argparse
from pathlib import Path
def _count_lines(path: Path) -> int:
"""Return the physical line count for `path`.
Input:
- `path`: a readable Python source file.
Output:
- The number of newline-delimited lines in the file.
"""
return len(path.read_text(encoding="utf-8").splitlines())
def _iter_python_files(root: Path) -> list[Path]:
"""List production Python files under `root`.
Input:
- `root`: repository package root to scan.
Output:
- Sorted Python file paths, excluding bytecode and hidden caches.
"""
return sorted(
path
for path in root.rglob("*.py")
if path.is_file() and "__pycache__" not in path.parts and ".venv" not in path.parts
)
def main() -> int:
"""Run the size gate and return a process exit code."""
parser = argparse.ArgumentParser()
parser.add_argument("--root", default="atlasbot")
parser.add_argument("--max-lines", type=int, default=500)
args = parser.parse_args()
root = Path(args.root)
violations: list[tuple[int, Path]] = []
for path in _iter_python_files(root):
lines = _count_lines(path)
if lines > args.max_lines:
violations.append((lines, path))
if violations:
for lines, path in sorted(violations, reverse=True):
print(f"{path}: {lines} lines (limit {args.max_lines})")
return 1
return 0
if __name__ == "__main__":
raise SystemExit(main())