# -*- coding: utf-8 -*- r'''对比 git 版本,找出 swap_admin_page.py 误删的所有东西。 事故: 那个脚本把 relay.py 从 "_admin_page" 那行一直截到文件末尾, 以为 _admin_page 是最后一个东西。实际它后面还有: - 一大堆模块级函数/常量(ADMIN_PATH、Server、Handler...) - main() 入口 结果 relay 起不来,systemd 重启 14 次。 这个脚本用 AST 对比两边的**顶层名字**,把丢了的一次性列清楚。 ''' from __future__ import annotations import ast import subprocess import sys from pathlib import Path ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") RELAY = ROOT / "relay" / "relay.py" GIT = r"C:\Program Files\Git\bin\git.exe" def top_names(source: str) -> list: """列出模块顶层的定义名(按出现顺序)。""" tree = ast.parse(source) out = [] for node in tree.body: if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): out.append(("def", node.name, node.lineno)) elif isinstance(node, ast.ClassDef): out.append(("class", node.name, node.lineno)) elif isinstance(node, ast.Assign): for target in node.targets: if isinstance(target, ast.Name): out.append(("var", target.id, node.lineno)) elif isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): out.append(("var", node.target.id, node.lineno)) return out def main() -> int: old = subprocess.run([GIT, "show", "HEAD:relay/relay.py"], cwd=str(ROOT), capture_output=True, text=True, encoding="utf-8", errors="replace").stdout new = RELAY.read_text(encoding="utf-8") if not old: print(" [失败] 取不到 git 版本") return 1 old_names = top_names(old) new_names = top_names(new) new_set = {n[1] for n in new_names} missing = [item for item in old_names if item[1] not in new_set] print(" git 版本顶层定义 %d 个,当前 %d 个" % (len(old_names), len(new_names))) print() if not missing: print(" 没有缺失 ✓") return 0 print(" 缺失 %d 个:" % len(missing)) for kind, name, lineno in missing: print(" %-6s %-28s (git 第 %d 行)" % (kind, name, lineno)) # 把缺失的部分从 git 里摘出来 old_lines = old.splitlines() print() print(" 缺失部分在 git 里的行范围:") # 找最小的起止行 starts = [item[2] for item in missing] print(" 从第 %d 行到文件末尾(共 %d 行)" % (min(starts), len(old_lines) - min(starts) + 1)) print() print(" 这些行的开头(确认是什么内容):") for i in range(min(starts) - 1, min(len(old_lines), min(starts) + 30)): line = old_lines[i] if line.strip(): print(" %5d: %s" % (i + 1, line[:84])) # 存一份给恢复脚本用 out = ROOT / "_build" / "_missing_tail.py" out.write_text("\n".join(old_lines[min(starts) - 1:]) + "\n", encoding="utf-8") print() print(" 缺失的整段已存到 _build/_missing_tail.py") return 0 if __name__ == "__main__": sys.exit(main())