- Makefile:新增 验收数据库(生成→检查→库层全量,前置校验隔离库连接串)、数据库分片、浏览器测试三个入口; 格式写入 末尾就地重新生成;数据库测试 与 验收数据库 统一排除 浏览器/网络;快检 不再静默跳过类型门; 前端旅程 预检补齐四个必需变量;pytest 目标改用仓内解释器(uv run 在嵌套检出会解析到外层环境)。 - 工具/验证锁.py:验证会话持共享锁,写入口用 --执行 在独占锁内落盘,生成/格式写入/索引生成走同一闸门。 - 工具/并行数据库测试.py:按文件分片并行,缺连接串在采集前拒绝。 - 工具/构建编排.py、环境预检.py、构建资源包.py、维护索引.py 与上述口径对齐。 - .gitignore / CI / README / AGENTS:忽略构建产物、CI 与 Makefile 单一口径、README 按实际实现陈述、AGENTS 补日常入口与验证纪律。
132 lines
5.3 KiB
Python
132 lines
5.3 KiB
Python
"""从实际业务入口递归提取本仓 Python 导入闭包,用于效果资质投影。
|
|
|
|
入口是能力合同,不是待维护的文件白名单。未知动态导入拒绝封闭;类型专用导入
|
|
不参与运行闭包。资源由构建器按生成阶段传入,不按文件名猜测是否影响效果。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import ast
|
|
import hashlib
|
|
from pathlib import Path
|
|
|
|
能力入口 = {
|
|
"writer_generation": ["muse.编排.生成正文", "muse.编排.执行评测"],
|
|
"literary_judging": [
|
|
"muse.编排.执行评测",
|
|
"muse.效果评测.文学评分",
|
|
"muse.效果评测.启用判据",
|
|
],
|
|
"semantic_detection": [
|
|
"muse.编排.审校修订",
|
|
"muse.编排.执行评测",
|
|
"muse.效果评测.语义检测",
|
|
],
|
|
}
|
|
|
|
|
|
def _运行节点(树: ast.AST):
|
|
"""保留函数内部实际导入;跳过静态类型检查分支。"""
|
|
yield 树
|
|
for 子 in ast.iter_child_nodes(树):
|
|
if isinstance(子, ast.If) and (
|
|
isinstance(子.test, ast.Name)
|
|
and 子.test.id == "TYPE_CHECKING"
|
|
or isinstance(子.test, ast.Attribute)
|
|
and 子.test.attr == "TYPE_CHECKING"
|
|
):
|
|
for 节点 in 子.orelse:
|
|
yield from _运行节点(节点)
|
|
else:
|
|
yield from _运行节点(子)
|
|
|
|
|
|
def _闭包(源码根: Path, 入口: list[str]) -> tuple[dict[str, str], list[str]]:
|
|
模块文件 = {}
|
|
for 文件 in 源码根.rglob("*.py"):
|
|
if "__pycache__" in 文件.parts:
|
|
continue
|
|
片段 = list(文件.relative_to(源码根).with_suffix("").parts)
|
|
if 片段[-1] == "__init__":
|
|
片段.pop()
|
|
模块文件[".".join(片段)] = 文件
|
|
结果: dict[str, str] = {}
|
|
未封闭: set[str] = set()
|
|
待查 = list(入口)
|
|
while 待查:
|
|
名 = 待查.pop()
|
|
if 名 in 结果:
|
|
continue
|
|
文件 = 模块文件.get(名)
|
|
if 文件 is None:
|
|
未封闭.add(f"缺本仓模块:{名}")
|
|
continue
|
|
树 = ast.parse(文件.read_text(encoding="utf-8"))
|
|
结果[名] = hashlib.sha256(ast.dump(树, include_attributes=False).encode()).hexdigest()
|
|
依赖: set[str] = set()
|
|
节点们 = list(_运行节点(树))
|
|
动态名称 = {"__import__"}
|
|
for 节点 in 节点们:
|
|
if isinstance(节点, ast.ImportFrom) and 节点.module == "importlib":
|
|
动态名称.update(v.asname or v.name for v in 节点.names if v.name == "import_module")
|
|
for 节点 in 节点们:
|
|
if isinstance(节点, ast.Import):
|
|
依赖.update(v.name for v in 节点.names)
|
|
elif isinstance(节点, ast.ImportFrom):
|
|
基 = 节点.module or ""
|
|
if 节点.level:
|
|
包 = 名.split(".") if 文件.name == "__init__.py" else 名.split(".")[:-1]
|
|
基 = ".".join(包[: len(包) - 节点.level + 1] + ([基] if 基 else []))
|
|
依赖.add(基)
|
|
依赖.update(f"{基}.{v.name}" for v in 节点.names if f"{基}.{v.name}" in 模块文件)
|
|
elif isinstance(节点, ast.Call):
|
|
函数 = 节点.func
|
|
动态 = isinstance(函数, ast.Name) and 函数.id in 动态名称
|
|
动态 = (
|
|
动态
|
|
or isinstance(函数, ast.Attribute)
|
|
and 函数.attr in {"import_module", "__import__"}
|
|
)
|
|
if 动态:
|
|
if (
|
|
节点.args
|
|
and isinstance(节点.args[0], ast.Constant)
|
|
and isinstance(节点.args[0].value, str)
|
|
and not 节点.args[0].value.startswith(".")
|
|
):
|
|
依赖.add(节点.args[0].value)
|
|
else:
|
|
未封闭.add(f"动态导入:{名}:{节点.lineno}")
|
|
if isinstance(函数, ast.Name) and 函数.id in {"exec", "eval"}:
|
|
未封闭.add(f"动态代码:{名}:{节点.lineno}")
|
|
# 导入子模块也会执行各级包的 __init__。
|
|
依赖.update(".".join(名.split(".")[:i]) for i in range(1, len(名.split("."))))
|
|
for 目标 in sorted(依赖):
|
|
if 目标 == "muse" or 目标.startswith("muse."):
|
|
if 目标 in 模块文件:
|
|
if 目标 not in 结果:
|
|
待查.append(目标)
|
|
else:
|
|
未封闭.add(f"缺本仓模块:{目标}")
|
|
return dict(sorted(结果.items())), sorted(未封闭)
|
|
|
|
|
|
def 构建效果依赖(根: Path, 资源: dict[str, str], 分组: dict[str, list[str]]) -> dict:
|
|
能力 = {}
|
|
for 名, 根模块 in 能力入口.items():
|
|
入口 = sorted(set(根模块 + ["muse.编排.运行装配"]))
|
|
代码, 未封闭 = _闭包(根 / "src", 入口)
|
|
能力[名] = {
|
|
"roots": 入口,
|
|
"code": 代码,
|
|
"resources": dict(sorted(资源.items())),
|
|
"resource_groups": 分组,
|
|
"closed": not 未封闭,
|
|
"unresolved": 未封闭,
|
|
}
|
|
return {
|
|
"version": "effect-dependencies-v1",
|
|
"dependency_lock_sha256": hashlib.sha256((根 / "uv.lock").read_bytes()).hexdigest(),
|
|
"capabilities": 能力,
|
|
}
|