# -*- coding: utf-8 -*- """M1b 补丁脚本 2/2:init.py 的 env 注册(三处同步第三环)。 (patch_m1b.py 已完成 m1b_init.py 与 __init__.py;本脚本只改 init.py,可重复执行—— 已打过补丁时检测到锚点缺失即跳过并报告,不重复插入。) 执行:python3 tools/patch_m1b_init.py """ import io import os REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) P = os.path.join(REPO, "pbl_blueprint", "init.py") def read(p): with io.open(p, "r", encoding="utf-8") as f: return f.read() def write(p, s): with io.open(p, "w", encoding="utf-8") as f: f.write(s) print("WROTE %s (%d chars)" % (os.path.relpath(p, REPO), len(s))) t = read(P) if "M1B_TABLE_NAMES" in t: print("SKIP: init.py 已含 M1b 注册(幂等,不重复打补丁)") raise SystemExit(0) # ---- 1) import + 表清单 old = ('MODULE_NAME = "pbl_blueprint"\n' 'TABLE_NAMES = list(_tables.TABLES.keys()) # 11 表\n' 'SUBOBJECT_TYPES = _tables.SUBOBJECT_TYPES # 7 类\n') new = ('from . import m1b_init as _m1b_init\n' 'from .m1b_api import M1B_ROUTES, register_m1b_routes\n' 'from .m1b_init import (M1B_CRUD_FILES, M1B_DDL, M1B_MODEL_FILES, M1B_TABLES,\n' ' ensure_m1b_tables, init_m1b, load_m1b_crud_defs,\n' ' load_m1b_models, seed_platform_data)\n' '\n' 'MODULE_NAME = "pbl_blueprint"\n' 'TABLE_NAMES = list(_tables.TABLES.keys()) # M1a 11 表\n' 'SUBOBJECT_TYPES = _tables.SUBOBJECT_TYPES # 7 类\n' 'M1B_TABLE_NAMES = list(M1B_TABLES) # M1b 4 表\n' 'ALL_TABLE_NAMES = TABLE_NAMES + [x for x in M1B_TABLE_NAMES\n' ' if x not in TABLE_NAMES]\n') assert t.count(old) == 1, "anchor1 not unique: %d" % t.count(old) t = t.replace(old, new) # ---- 2) __all__ old = ('__all__ = [\n' ' "load_pbl_blueprint", "ensure_tables", "MODULE_NAME", "TABLE_NAMES",\n' ' "SUBOBJECT_TYPES", "BUILTIN_SCHEMA",') new = ('__all__ = [\n' ' "load_pbl_blueprint", "ensure_tables", "MODULE_NAME", "TABLE_NAMES",\n' ' "SUBOBJECT_TYPES", "BUILTIN_SCHEMA",\n' ' # ---- M1b 三处同步之「init.py env 注册」环节\n' ' "M1B_TABLES", "M1B_TABLE_NAMES", "ALL_TABLE_NAMES", "M1B_MODEL_FILES",\n' ' "M1B_CRUD_FILES", "M1B_DDL", "M1B_ROUTES",\n' ' "init_m1b", "ensure_m1b_tables", "register_m1b_routes",\n' ' "load_m1b_models", "load_m1b_crud_defs", "seed_platform_data",') assert t.count(old) == 1, "anchor2 not unique: %d" % t.count(old) t = t.replace(old, new) # ---- 3) load_pbl_blueprint:M1b 挂载 + env 注册 old = ('def load_pbl_blueprint(app=None, sor=None, ensure=False, **kw):\n' ' dbname = get_module_dbname(_MODULE_NAME) # noqa: F841 库名由应用注入\n' ' if ensure:\n' ' ensure_tables(sor)\n' ' if app is not None:\n' ' try:\n' ' app.register_module(MODULE_NAME, {\n' ' "tables": TABLE_NAMES,') new = ('def _m1b_register_callback(app):\n' ' """解析应用层路由注册回调:register_route / register / route / add_route 四选一。"""\n' ' if app is None:\n' ' return None\n' ' for name in ("register_route", "register", "route", "add_route"):\n' ' fn = getattr(app, name, None)\n' ' if callable(fn):\n' ' return fn\n' ' return None\n' '\n' '\n' 'def load_pbl_blueprint(app=None, sor=None, ensure=False, **kw):\n' ' dbname = get_module_dbname(_MODULE_NAME) # noqa: F841 库名由应用注入\n' ' if ensure:\n' ' ensure_tables(sor)\n' '\n' ' # -------------------------------------------------------- M1b 挂载\n' ' # 三处同步:m1b_api.register_m1b_routes(定义)+ __init__.py(导出)+ 此处(env 注册)\n' ' # Q-OPEN-3:init_m1b 只建 M1b 自有 4 表,绝不触碰 world/scene/entity/script 基表。\n' ' m1b_result = {"ok": False, "skipped": True}\n' ' if kw.get("m1b", True):\n' ' try:\n' ' m1b_result = init_m1b(\n' ' db=kw.get("m1b_db"),\n' ' env=kw.get("env"),\n' ' register=_m1b_register_callback(app),\n' ' executor=kw.get("m1b_executor"),\n' ' seed=bool(kw.get("m1b_seed", ensure)),\n' ' )\n' ' except Exception as e: # M1b 失败不拖垮 M1a 挂载\n' ' m1b_result = {"ok": False,\n' ' "error": "%s: %s" % (type(e).__name__, e)}\n' '\n' ' if app is not None:\n' ' try:\n' ' app.register_module(MODULE_NAME, {\n' ' "tables": ALL_TABLE_NAMES,\n' ' "m1b": {\n' ' "tables": M1B_TABLE_NAMES,\n' ' "model_files": M1B_MODEL_FILES,\n' ' "crud_files": M1B_CRUD_FILES,\n' ' "ddl": M1B_DDL,\n' ' "routes": [(m, p) for m, p, _ in M1B_ROUTES],\n' ' "init": m1b_result,\n' ' },') assert t.count(old) == 1, "anchor3 not unique: %d" % t.count(old) t = t.replace(old, new) # ---- 4) 返回值 old = (' return {"module": MODULE_NAME, "tables": TABLE_NAMES,\n' ' "subobject_types": list(SUBOBJECT_TYPES), "loaded": True}') new = (' return {"module": MODULE_NAME, "tables": TABLE_NAMES,\n' ' "m1b_tables": M1B_TABLE_NAMES, "m1b": m1b_result,\n' ' "subobject_types": list(SUBOBJECT_TYPES), "loaded": True}') assert t.count(old) == 1, "anchor4 not unique: %d" % t.count(old) t = t.replace(old, new) write(P, t) print("PATCH init.py OK")