51 lines
1.8 KiB
Python
51 lines
1.8 KiB
Python
"""File-size and naming validation for the managed testing surface."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from collections.abc import Iterable
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
|
|
def _expand_globs(root: Path, patterns: Iterable[str]) -> list[Path]:
|
|
matched: set[Path] = set()
|
|
for pattern in patterns:
|
|
matched.update(path for path in root.glob(pattern) if path.is_file())
|
|
return sorted(matched)
|
|
|
|
|
|
def run_check(contract: dict[str, Any], root: Path) -> list[str]:
|
|
"""Return human-readable issues for naming and file-size rules."""
|
|
config = contract.get("hygiene", {})
|
|
max_lines = int(config.get("max_lines", 500))
|
|
issues: list[str] = []
|
|
|
|
for path in _expand_globs(root, config.get("line_limit_globs", [])):
|
|
line_count = sum(1 for _ in path.open("r", encoding="utf-8"))
|
|
if line_count > max_lines:
|
|
issues.append(f"file exceeds {max_lines} LOC: {path.relative_to(root)} ({line_count})")
|
|
|
|
for rule in config.get("naming_rules", []):
|
|
pattern = re.compile(rule["pattern"])
|
|
for path in _expand_globs(root, [rule["glob"]]):
|
|
if not pattern.match(path.name):
|
|
issues.append(
|
|
f"naming rule failed ({rule['description']}): {path.relative_to(root)}"
|
|
)
|
|
|
|
return issues
|
|
|
|
|
|
def count_files_over_line_limit(contract: dict[str, Any], root: Path) -> int:
|
|
"""Return the number of managed files that exceed the configured LOC cap."""
|
|
|
|
config = contract.get("hygiene", {})
|
|
max_lines = int(config.get("max_lines", 500))
|
|
count = 0
|
|
for path in _expand_globs(root, config.get("line_limit_globs", [])):
|
|
line_count = sum(1 for _ in path.open("r", encoding="utf-8"))
|
|
if line_count > max_lines:
|
|
count += 1
|
|
return count
|