chronaxis.user_guide
源码基线:8904c2f744951857659abd40aaa3535d57faf53c
1"""定位可以直接阅读的AI指南,按显式请求另存独立ZIP。23只处理公开使用说明、配置规范和合成样例,不读取用户业务输入。4默认只检查入口并返回路径,不构建、解压或复制。源码使用Docs/AI,5安装使用包内guide目录;显式导出才读取整套资料并写用户指定的新文件。6"""7from io import BytesIO8import json9from pathlib import Path10from runpy import run_path11from zipfile import ZIP_DEFLATED, ZipFile, ZipInfo121314def guide_path(language="zh"):15 """定位中英文README,不写文件。1617 参数: language为zh或en,默认中文。返回: README的绝对Path。18 异常: 未知语言ValueError;指南缺失FileNotFoundError。只支持普通目录安装。19 """20 if language not in ("zh", "en"):21 raise ValueError("指南语言应为zh或en")22 package = Path(__file__).resolve().parent23 installed = package / "guide"24 # 已有安装目录时不借源码补齐损坏资源;可编辑/源码布局直接使用人工入口。25 if installed.is_dir():26 root = installed27 else:28 root = package.parent.parent / "Docs/AI"29 if not (root / "inputs.lock.json").is_file():30 raise FileNotFoundError("安装包缺少用户指南,请重新安装同版本的完整wheel")31 entry = root / ("en/README.md" if language == "en" else "README.md")32 if not entry.is_file():33 raise FileNotFoundError("用户指南入口缺失:" + str(entry))34 return entry.resolve()353637def _installed_archive(root):38 """按发行清单打包,忽略阅读后产生的缓存或结果。3940 参数: root为包内guide目录。返回: 确定性ZIP字节。异常: 清单/资源缺失或越界。41 """42 manifest = json.loads((root / "manifest.json").read_bytes())43 output = BytesIO()44 with ZipFile(output, "w", compression=ZIP_DEFLATED) as archive:45 for name in sorted({"manifest.json", *manifest["sha256"]}):46 path = (root / name).resolve()47 if not path.is_relative_to(root.resolve()):48 raise ValueError("指南成员路径超出资料目录")49 info = ZipInfo(name, date_time=(1980, 1, 1, 0, 0, 0))50 info.create_system = 351 info.external_attr = 0o100644 << 1652 archive.writestr(info, path.read_bytes(), compress_type=ZIP_DEFLATED)53 return output.getvalue()545556def export_guide(output):57 """参数: output为父目录已存在的新ZIP路径。返回: 导出路径。异常: 已有目标、缺资料或I/O失败。"""58 # 仅显式导出读取整套资源;安装目录不维护第二份ZIP副本。59 resource = Path(__file__).resolve().parent / "guide"60 if resource.is_dir():61 data = _installed_archive(resource)62 else:63 builder = Path(__file__).resolve().parents[2] / "tools/build_ai_guide.py"64 if not builder.is_file() or not (builder.parent.parent / "Docs/AI/inputs.lock.json").is_file():65 raise FileNotFoundError("安装包缺少用户指南,请重新安装同版本的完整wheel")66 data = run_path(str(builder))["build"]()67 target = Path(output)68 # 独占创建避免覆盖用户资料;只有自己成功创建且写入失败时才移除残件。69 stream = target.open("xb")70 try:71 with stream:72 stream.write(data)73 except BaseException as error:74 try:75 target.unlink()76 except OSError as cleanup:77 error.add_note("未能清理本次未完成的资料文件:" + str(cleanup))78 raise79 return target80