from __future__ import annotations import ast import sys import re def gut_file(file_path: str) -> None: """Removes delegation wrappers and fixes all calls in the file.""" with open(file_path, "r", encoding="utf-8") as f: lines = f.read().splitlines() content = "\n".join(lines) tree = ast.parse(content) app_class = next((n for n in tree.body if isinstance(n, ast.ClassDef) and n.name == "App"), None) if not app_class: return # 1. Identify all _render_xxx methods that have module-level counterparts render_methods = [ m for m in app_class.body if isinstance(m, ast.FunctionDef) and m.name.startswith("_render_") and m.name != "_render_window_if_open" ] render_names = {m.name for m in render_methods} # Process methods in reverse to keep line numbers valid render_methods.sort(key=lambda x: x.lineno, reverse=True) for m in render_methods: s_idx = m.lineno - 1 e_idx = m.end_lineno if m.decorator_list: s_idx = m.decorator_list[0].lineno - 1 del lines[s_idx:e_idx] # 2. Fix all calls in the remaining lines for i in range(len(lines)): for m_name in render_names: t_func = m_name.lstrip("_") # Replace self._render_xxx( with render_xxx(self, lines[i] = lines[i].replace(f"self.{m_name}(", f"{t_func}(self, ") lines[i] = lines[i].replace(f"app.{m_name}(", f"{t_func}(app, ") # Clean up (self, ) or (app, ) lines[i] = lines[i].replace("(self, )", "(self)") lines[i] = lines[i].replace("(app, )", "(app)") final_content = "\n".join(lines) + "\n" with open(file_path, "w", encoding="utf-8") as f: f.write(final_content) print(f"Successfully GUTTED {file_path}") if __name__ == "__main__": gut_file(sys.argv[1])