Ctrl K
ComunidadGuías…

scripts/butler-complexity-report.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env bash
# Complexity / size report for Butler Python sources (ENG-1).
#
# Usage:
#   bash scripts/butler-complexity-report.sh
#   bash scripts/butler-complexity-report.sh --json
#
set -uo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"

JSON=0
for arg in "$@"; do
  case "$arg" in
    --json) JSON=1 ;;
    -h|--help)
      sed -n '1,8p' "$0"
      exit 0
      ;;
  esac
done

python3 - "$ROOT" "$JSON" <<'PY'
import ast
import json
import sys
from pathlib import Path

root = Path(sys.argv[1])
as_json = sys.argv[2] == "1"
min_fn = 80
min_file = 600

py_files = sorted(
    p for p in root.joinpath("butler").rglob("*.py")
    if "__pycache__" not in p.parts
)

large_files: list[dict] = []
long_funcs: list[dict] = []

for path in py_files:
    rel = path.relative_to(root).as_posix()
    text = path.read_text(encoding="utf-8", errors="replace")
    lines = text.count("\n") + (1 if text else 0)
    if lines >= min_file:
        large_files.append({"path": rel, "lines": lines})
    try:
        tree = ast.parse(text)
    except SyntaxError:
        continue
    for node in ast.walk(tree):
        if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
            continue
        if node.end_lineno is None:
            continue
        span = node.end_lineno - node.lineno + 1
        if span >= min_fn:
            long_funcs.append(
                {
                    "path": rel,
                    "name": node.name,
                    "lines": span,
                    "start": node.lineno,
                }
            )

large_files.sort(key=lambda x: -x["lines"])
long_funcs.sort(key=lambda x: (-x["lines"], x["path"], x["name"]))

from butler.ops.lazy_import_budget import (
    LAZY_IMPORT_BUDGET,
    count_lazy_butler_imports,
    count_module_level_butler_imports,
)

lazy_imports = count_lazy_butler_imports()

report = {
    "python_files": len(py_files),
    "files_ge_600_lines": len(large_files),
    "functions_ge_80_lines": len(long_funcs),
    "lazy_from_butler_imports": lazy_imports,
    "large_files": large_files[:25],
    "long_functions": long_funcs[:40],
}

if as_json:
    print(json.dumps(report, ensure_ascii=False, indent=2))
    sys.exit(0)

print("=== Butler complexity report (ENG-1) ===")
print(f"python_files={report['python_files']}")
print(f"files>={min_file}L={report['files_ge_600_lines']}")
print(f"functions>={min_fn}L={report['functions_ge_80_lines']}")
print(f"lazy_from_butler_imports={report['lazy_from_butler_imports']} (function-scoped)")
print(f"module_level_from_butler={count_module_level_butler_imports()}")
if report["lazy_from_butler_imports"] > LAZY_IMPORT_BUDGET:
    print(f"WARN: lazy imports exceed budget {LAZY_IMPORT_BUDGET}")
print("")
print(f"Top files (>={min_file} lines):")
for row in large_files[:15]:
    print(f"  {row['lines']:5d}  {row['path']}")
print("")
print(f"Top functions (>={min_fn} lines):")
for row in long_funcs[:20]:
    print(
        f"  {row['lines']:4d} L{row['start']:4d}  "
        f"{row['path']}::{row['name']}"
    )
PY