Compare commits

...

2 Commits

Author SHA1 Message Date
abmantis d9cfc0ce6c Add scripts 2026-05-22 15:11:58 +01:00
abmantis 167e6d2bd8 Enable mypy explicit-override check 2026-05-22 15:08:45 +01:00
4 changed files with 66 additions and 1 deletions
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env python3
"""Add @override decorator to methods listed in explicit_override_errors.txt."""
from __future__ import annotations
import re
import subprocess
from collections import defaultdict
from pathlib import Path
INPUT = Path("explicit_override_errors.txt")
ERROR_RE = re.compile(r"^(.+?):(\d+): error:.*\[explicit-override\]")
def decorator_stack_top(lines: list[str], def_idx: int) -> int:
"""Return the index of the topmost decorator above the def at def_idx."""
i = def_idx - 1
while i >= 0 and lines[i].lstrip().startswith("@"):
i -= 1
return i + 1
by_file: dict[Path, set[int]] = defaultdict(set)
for line in INPUT.read_text().splitlines():
if m := ERROR_RE.match(line):
by_file[Path(m.group(1))].add(int(m.group(2)))
for path, line_nums in by_file.items():
lines = path.read_text().splitlines(keepends=True)
for lineno in sorted(line_nums, reverse=True):
insert_idx = decorator_stack_top(lines, lineno - 1)
target = lines[insert_idx]
indent = target[: len(target) - len(target.lstrip())]
lines.insert(insert_idx, f"{indent}@override\n")
first_import = next(
i for i, ln in enumerate(lines) if ln.startswith(("import ", "from "))
)
lines.insert(first_import, "from typing import override\n")
path.write_text("".join(lines))
print(f"Updated {path} ({len(line_nums)} methods)")
if by_file:
subprocess.run(["ruff", "check", "--fix", *map(str, by_file)], check=False)
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/env python3
"""Run mypy on a directory and write `[explicit-override]` errors to a file."""
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
OUTPUT = Path("explicit_override_errors.txt")
target = sys.argv[1]
result = subprocess.run(
["mypy", "--enable-error-code=explicit-override", target],
capture_output=True,
text=True,
check=False,
)
matches = [line for line in result.stdout.splitlines() if "[explicit-override]" in line]
OUTPUT.write_text("\n".join(matches) + ("\n" if matches else ""))
print(f"Wrote {len(matches)} errors to {OUTPUT}")
Generated
+1 -1
View File
@@ -17,7 +17,7 @@ no_implicit_optional = true
warn_incomplete_stub = true
warn_redundant_casts = true
warn_unused_ignores = true
enable_error_code = deprecated, ignore-without-code, redundant-self, truthy-iterable
enable_error_code = deprecated, explicit-override, ignore-without-code, redundant-self, truthy-iterable
disable_error_code = annotation-unchecked, import-not-found, import-untyped
extra_checks = false
check_untyped_defs = true
+1
View File
@@ -54,6 +54,7 @@ GENERAL_SETTINGS: Final[dict[str, str]] = {
"enable_error_code": ", ".join( # noqa: FLY002
[
"deprecated",
"explicit-override",
"ignore-without-code",
"redundant-self",
"truthy-iterable",