# -*- coding: utf-8 -*- """用 pyflakes 静态检查所有 Python 源码。 为什么必须加这一层: 我加 check_code_available() 时用了 DEFAULT_RELAY_URL, 但那个常量定义在 server.py、run_agent.py 里没导入。 结果:安装到最后一步直接弹 NameError 崩溃。 自带的回归全绿、编码审计也过 —— 因为这是**运行到那行才炸**的问题。 pyflakes 是静态分析,扫一眼就能发现"用了没定义的名字"。 本机自带 pyflakes 4.0.2。没有的话就跳过(不阻塞)。 """ from __future__ import annotations import subprocess import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent TARGETS = ( list((ROOT / "windows").glob("*.py")) + list((ROOT / "windows" / "lanremote").glob("*.py")) + list((ROOT / "relay").glob("*.py")) + list((ROOT / "_build").glob("*.py")) + list((ROOT / "_tests").glob("*.py")) ) def main() -> int: try: import pyflakes # noqa: F401 except ImportError: print(" (本机没有 pyflakes,跳过)") return 0 files = [str(p) for p in TARGETS if p.is_file()] print(f" 检查 {len(files)} 个 Python 文件…") # ⚠ 不能一次把 450 多个文件全塞进命令行 —— # Windows 的 CreateProcess 有命令行长度上限(约 32767 字符), # 超了直接 FileNotFoundError: [WinError 206] 文件名或扩展名太长, # 而且报错看起来像"文件找不到",很容易误判。 # 所以分批调用,每批的总长度控制住。 all_lines = [] batch, batch_len = [], 0 LIMIT = 6000 # 单批命令行里文件路径的总字符数预算(留足余量) batches = [] for path in files: if batch and batch_len + len(path) + 1 > LIMIT: batches.append(batch) batch, batch_len = [], 0 batch.append(path) batch_len += len(path) + 1 if batch: batches.append(batch) for chunk in batches: proc = subprocess.run([sys.executable, "-m", "pyflakes"] + chunk, capture_output=True, text=True, encoding="utf-8", errors="replace") all_lines.extend( line for line in (proc.stdout or "").splitlines() if line.strip()) lines = all_lines if not lines: print(" ✓ 没有未定义名 / 未使用导入等问题") return 0 # 分类:undefined name 是致命的,未使用导入是无害的 fatal = [line for line in lines if "undefined name" in line] minor = [line for line in lines if line not in fatal] if minor: print(f" {len(minor)} 条小问题(未使用的导入/变量,不影响运行):") for line in minor[:8]: print(f" {line}") if fatal: print() print(f" ✗ {len(fatal)} 条**未定义名**(运行到这行会 NameError):") for line in fatal: print(f" {line}") return 1 print(" ✓ 没有会导致崩溃的问题") return 0 if __name__ == "__main__": sys.exit(main())