#!/usr/bin/env python3 """Подсчёт строк кода WESP (см. docs/README.full.md).""" from __future__ import annotations from pathlib import Path ROOT = Path(__file__).resolve().parents[1] EXCLUDE_DIRS = { ".venv", "vendor", "data", ".git", "legacy", "__pycache__", "node_modules", ".pytest_cache", "htmlcov", "dist", "backups", ".cursor", "test", # Windows venv test/Lib/site-packages } EXTS = { ".py": "Python", ".js": "JavaScript", ".css": "CSS", ".html": "HTML", ".sh": "Shell", } def should_skip(path: Path) -> bool: try: rel = path.relative_to(ROOT) except ValueError: return True return any(part in EXCLUDE_DIRS for part in rel.parts) def count_file(path: Path) -> tuple[int, int]: text = path.read_text(encoding="utf-8", errors="ignore") code = blank = 0 for line in text.splitlines(): if line.strip(): code += 1 else: blank += 1 return code, blank def main() -> None: stats: dict[str, dict[str, int]] = { ext: {"files": 0, "code": 0, "blank": 0} for ext in EXTS } for path in sorted(ROOT.rglob("*")): if not path.is_file() or should_skip(path): continue ext = path.suffix.lower() if ext not in EXTS: continue code, blank = count_file(path) stats[ext]["files"] += 1 stats[ext]["code"] += code stats[ext]["blank"] += blank print(f"WESP LOC — {ROOT}") print(f"{'Language':<12} {'files':>6} {'code':>8} {'blank':>8}") print("-" * 38) total = {"files": 0, "code": 0, "blank": 0} for ext in sorted(EXTS, key=lambda e: -stats[e]["code"]): s = stats[ext] if not s["files"]: continue print( f"{EXTS[ext]:<12} {s['files']:>6} {s['code']:>8} {s['blank']:>8}" ) for k in total: total[k] += s[k] print("-" * 38) print(f"{'SUM':<12} {total['files']:>6} {total['code']:>8} {total['blank']:>8}") py_by_dir: dict[str, int] = {} for path in sorted(ROOT.rglob("*.py")): if should_skip(path): continue rel = path.relative_to(ROOT) top = rel.parts[0] if len(rel.parts) > 1 else "." code, _ = count_file(path) py_by_dir[top] = py_by_dir.get(top, 0) + code print("\nPython by top-level dir:") for name, lines in sorted(py_by_dir.items(), key=lambda x: -x[1]): print(f" {name:20} {lines:>6}") if __name__ == "__main__": main()