Ctrl K
ComunidadGuías…

scripts/p2f-batch16-harvest.py

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

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env python3
"""Fix low-error modules and append to P2-F strict gate until target count."""
from __future__ import annotations

import re
import subprocess
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
GATE = ROOT / "scripts/butler-mypy-strict-gate.sh"


def gate_modules() -> set[str]:
    text = GATE.read_text()
    return set(re.findall(r"butler/[^\s']+\.py", text))


def mypy_errors(path: Path) -> list[str]:
    r = subprocess.run(
        [sys.executable, "-m", "mypy", str(path), "--follow-imports=skip"],
        capture_output=True,
        text=True,
        cwd=ROOT,
    )
    return [ln for ln in (r.stdout + r.stderr).splitlines() if ": error:" in ln]


def apply_common_fixes(path: Path) -> bool:
    src = path.read_text()
    orig = src
    # bool env_truthy returns
    src = re.sub(
        r"return env_truthy\(",
        "return bool(env_truthy(",
        src,
    )
    # list[dict] without type args in annotations
    src = re.sub(r"\blist\[dict\]", "list[dict[str, Any]]", src)
    src = re.sub(r"\bdict\](?!\[)", "dict[str, Any]]", src)  # noqa - too broad, skip
  # Only fix list[dict] which is the common pattern
    if "from typing import" in src and "Any" not in src.split("from typing import", 1)[1].split("\n", 1)[0]:
        src = re.sub(
            r"from typing import ([^\n]+)",
            lambda m: (
                f"from typing import {m.group(1)}, Any"
                if "Any" not in m.group(1)
                else m.group(0)
            ),
            src,
            count=1,
        )
    if src != orig:
        path.write_text(src)
        return True
    return False


def main() -> int:
    target = int(sys.argv[1]) if len(sys.argv) > 1 else 180
    scan = subprocess.run(
        ["bash", str(ROOT / "scripts/p2f-low-error-scan.sh")],
        capture_output=True,
        text=True,
        cwd=ROOT,
    )
    candidates: list[tuple[int, Path]] = []
    for line in scan.stdout.splitlines():
        parts = line.strip().split(" ", 1)
        if len(parts) != 2:
            continue
        cnt, rel = int(parts[0]), parts[1]
        candidates.append((cnt, ROOT / rel))

    in_gate = gate_modules()
    added: list[str] = []
    for _cnt, path in candidates:
        if len(in_gate) + len(added) >= target:
            break
        rel = str(path.relative_to(ROOT))
        if rel in in_gate:
            continue
        apply_common_fixes(path)
        errs = mypy_errors(path)
        if errs:
            continue
        subprocess.run(
            [sys.executable, str(ROOT / "scripts/p2f-append-gate-modules.py"), rel],
            check=True,
            cwd=ROOT,
        )
        added.append(rel)
        in_gate.add(rel)

    print(f"Added {len(added)} modules; gate now ~{len(in_gate)}")
    for m in added:
        print(f"  + {m}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())