Files
SDR-Rover/tools/quick_gate.py
LittleSam129 c486039053 Split experiments from tests
The tests/ directory held 50 laboratory programs and no tests. They model
channels, run hundreds of repetitions and write CSV, PNG and reports;
calling that a test suite blocked introducing a real one, because any
pytest run would have collected the labs and re-executed every
experiment.

- move all 50 lab programs to experiments/ with git mv, preserving history
- rewrite the 38 cross-imports between labs from tests.labNNN to
  experiments.labNNN
- leave tests/ empty for actual fast checks of protocol/
- point quick_gate and the hook at the new layout and add experiments/ to
  the syntax sweep
- update the paths quoted in the Lab042 specification and the verifier
  agent definition

This also defuses the import-time work finding without touching 41 files:
the labs still create directories and write files on import, but nothing
imports them now except the gate, which does so deliberately.

Gate passes: syntax clean, protocol imports, 15 lab modules import, 2
functional suites run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 14:34:58 +03:00

146 lines
4.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Быстрый шлюз проверки SDR Rover Link.
Проверяет за одну-две секунды то, что ломается чаще всего:
1. Синтаксис всех файлов в protocol, tests и tools.
2. Импорт каждого модуля protocol.
3. Функциональные проверки тех лаб, которым не нужны данные эксперимента.
Полный прогон лабы шлюз не заменяет.
Он отвечает на один вопрос: не сломана ли кодовая база прямо сейчас.
Запуск:
python tools/quick_gate.py
"""
from __future__ import annotations
import ast
import importlib
import inspect
from pathlib import Path
import sys
import traceback
PROJECT_ROOT = Path(__file__).resolve().parent.parent
CHECKED_DIRECTORIES = ("protocol", "tests", "experiments", "tools")
def check_syntax() -> list[str]:
"""Разобрать все файлы Python и вернуть список сообщений об ошибках."""
failures: list[str] = []
for directory in CHECKED_DIRECTORIES:
for path in sorted((PROJECT_ROOT / directory).glob("*.py")):
try:
ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
except SyntaxError as error:
relative = path.relative_to(PROJECT_ROOT)
failures.append(f"{relative}:{error.lineno}: синтаксис: {error.msg}")
return failures
def check_protocol_imports() -> list[str]:
"""Импортировать каждый модуль protocol и вернуть список сообщений об ошибках."""
failures: list[str] = []
for path in sorted((PROJECT_ROOT / "protocol").glob("*.py")):
if path.name == "__init__.py":
continue
module_name = f"protocol.{path.stem}"
try:
importlib.import_module(module_name)
except Exception:
failures.append(f"{module_name}: импорт: {traceback.format_exc(limit=3).strip()}")
return failures
def check_functional_tests() -> tuple[list[str], int, int]:
"""
Выполнить функциональные проверки лаб, не требующие данных эксперимента.
Возвращает:
failures:
Список сообщений об ошибках.
executed:
Количество выполненных лаб.
skipped:
Количество пропущенных лаб.
"""
failures: list[str] = []
executed = 0
skipped = 0
for path in sorted((PROJECT_ROOT / "experiments").glob("lab*.py")):
source = path.read_text(encoding="utf-8")
if "def run_functional_tests" not in source:
continue
module_name = f"experiments.{path.stem}"
try:
module = importlib.import_module(module_name)
except Exception:
failures.append(f"{module_name}: импорт: {traceback.format_exc(limit=3).strip()}")
continue
run_functional_tests = module.run_functional_tests
parameters = inspect.signature(run_functional_tests).parameters
required = [name for name, parameter in parameters.items() if parameter.default is parameter.empty]
if required:
skipped += 1
continue
try:
run_functional_tests()
except Exception:
failures.append(f"{module_name}: проверки: {traceback.format_exc(limit=3).strip()}")
continue
executed += 1
return failures, executed, skipped
def main() -> int:
"""Выполнить шлюз и вернуть код возврата процесса."""
sys.path.insert(0, str(PROJECT_ROOT))
syntax_failures = check_syntax()
if syntax_failures:
print("Шлюз не пройден: ошибки синтаксиса")
for failure in syntax_failures:
print(f" {failure}")
return 1
import_failures = check_protocol_imports()
test_failures, executed, skipped = check_functional_tests()
failures = import_failures + test_failures
if failures:
print("Шлюз не пройден")
for failure in failures:
print(f" {failure}")
return 1
print(f"Шлюз пройден: синтаксис в порядке, protocol импортируется, функциональных проверок выполнено {executed}, пропущено {skipped}")
return 0
if __name__ == "__main__":
raise SystemExit(main())