#!/usr/bin/env python3 """verify_i18n_fix.py — W1 修复后的文件完整性验证 .ui: 纯 JSON → json.loads;含 Jinja {{}} → 渲染 stub 后 json.loads;再不行 → 剥离 {{...}} 后 loads .dspy: python 语法 → 包一层 async def + 编译(tab 缩进),或直接 py_compile 源文件级检查 """ import json, re, sys, subprocess files = sorted(set(v['file'] for v in json.load(open(sys.argv[1]))['violations'] if v['code'] == 'W1' and not v['git_ignored'])) bad = [] for fp in files: raw = open(fp, encoding='utf-8').read() if fp.endswith('.ui'): # 剥离 Jinja:引号内的 {{...}} 换成不带引号的占位符;裸 {{...}} 换成字符串 stripped = re.sub(r'"([^"]*?)\{\{.*?\}\}([^"]*?)"', r'"\1__JINJA__\2"', raw, flags=re.S) stripped = re.sub(r'\{\{.*?\}\}', '"__JINJA__"', stripped, flags=re.S) stripped = re.sub(r'\{%.*?%\}', '', stripped, flags=re.S) try: json.loads(stripped) except Exception as e: bad.append((fp, f'JSON: {e}')) elif fp.endswith('.dspy'): # dspy 是 exec 片段,包 async def 验证语法 wrapped = 'async def __dspy_check(request, **ns):\n' + \ ''.join('\t' + l + '\n' if l.strip() else l + '\n' for l in raw.split('\n')) try: compile(wrapped, fp, 'exec') except SyntaxError as e: bad.append((fp, f'SyntaxError: {e.lineno}: {e.msg}')) print(f'checked={len(files)} bad={len(bad)}') for b in bad[:30]: print(' BAD', b[0].replace('/home/ymq/work/repos/', ''), '|', b[1][:100]) sys.exit(1 if bad else 0)