scripts/p5_wave2_fix_core_ops.py
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env python3
"""P5 wave2b: minimal mypy strict fixes for butler/core/*_ops.py."""
from __future__ import annotations
import re
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def ensure_import(src: str, name: str) -> str:
if re.search(rf"\b{name}\b", src.split("def ", 1)[0]) is None and name not in src:
return src
if name == "cast" and "cast(" in src:
if re.search(r"from typing import[^\n]*\bcast\b", src):
return src
if "from typing import" in src:
return re.sub(
r"(from typing import [^\n]+)",
lambda m: m.group(1) + (", cast" if "cast" not in m.group(1) else ""),
src,
count=1,
)
return "from typing import cast\n" + src
if name == "Any":
if re.search(r"from typing import[^\n]*\bAny\b", src):
return src
if "from typing import" in src:
return re.sub(
r"(from typing import [^\n]+)",
lambda m: m.group(1) + (", Any" if "Any" not in m.group(1) else ""),
src,
count=1,
)
return "from typing import Any\n" + src
return src
def fix_file(path: Path) -> bool:
src = path.read_text(encoding="utf-8")
orig = src
src = re.sub(r": dict\)(?!])", ": dict[str, Any])", src)
src = re.sub(r": dict \|", ": dict[str, Any] |", src)
src = re.sub(r": dict,", ": dict[str, Any],", src)
src = re.sub(r": dict$", ": dict[str, Any]", src, flags=re.MULTILINE)
src = re.sub(r"list\[dict\]", "list[dict[str, Any]]", src)
src = re.sub(r": list\)(?!])", ": list[Any])", src)
src = re.sub(r"-> list:", "-> list[Any]:", src)
src = re.sub(r"\bdict\[\]", "dict[str, Any]", src)
src = re.sub(r"\blist\[\]", "list[Any]", src)
# remove stale unused ignores on imports (strict may not need them)
src = re.sub(
r" # type: ignore\[import-untyped\]\n",
"\n",
src,
)
if "dict[str, Any]" in src or ": dict[str, Any]" in src:
src = ensure_import(src, "Any")
if "list[Any]" in src:
src = ensure_import(src, "Any")
if src != orig:
path.write_text(src, encoding="utf-8")
return True
return False
def main() -> int:
changed = 0
for p in sorted((ROOT / "butler/core").glob("*_ops.py")):
if fix_file(p):
changed += 1
print("auto", p.relative_to(ROOT))
return 0
if __name__ == "__main__":
raise SystemExit(main())