pbls/scripts/patch_build_7b.py
2026-09-22 22:03:22 +08:00

58 lines
2.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""一次性补丁脚本:在 apps/pbls/build.sh 第 7 步后插入「7b. 测试前置依赖(DISC.2)」。
为什么用脚本而不是 sed:build.sh 里含 `${...}` 与引号,shell 内嵌补丁容易吃掉转义。
本脚本幂等——已存在 7b 标记时直接退出,不重复插入。
"""
import io
import os
import sys
BUILD = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "build.sh")
ANCHOR = '# ---- 8. 本地安装 15 个 pbl_* 模块 + 复用模块(可编辑模式)----'
MARK = '# ---- 7b. 测试前置依赖(DISC.2)----'
BLOCK = '''# ---- 7b. 测试前置依赖(DISC.2)----
# 运行时依赖(requirements.txt)刻意不含 pytest;测试依赖单列 requirements-test.txt,
# 由本步装进同一个 venv,使
# source venv/bin/activate && python3 -m pytest tests/test_m5a_idempotency.py -v
# 在**不手工注入 PYTHONPATH** 的前提下可直接执行(此前靠 PYTHONPATH=<ws>/.pylibs
# 临时注入跑通,换机器/换角色即失效,test 角色会误判为环境不可用)。
# 只要运行时依赖的场景(如生产镜像)用 PBL_SKIP_TEST_DEPS=1 显式跳过。
REQ_TEST="${APP_DIR}/requirements-test.txt"
if [ "${PBL_SKIP_TEST_DEPS:-0}" = "1" ]; then
log "PBL_SKIP_TEST_DEPS=1:跳过测试前置依赖(venv 内将没有 pytest,测试角色需自行引导)"
elif [ ! -f "${REQ_TEST}" ]; then
die "缺测试依赖清单 ${REQ_TEST}(DISC.2 要求显式声明;确要跳过请设 PBL_SKIP_TEST_DEPS=1)"
else
log "安装测试前置依赖: ${REQ_TEST}"
"${PY}" -m pip install -r "${REQ_TEST}"
# 自证:装完必须真能 import + 跑 --version,否则本步等于没做(不让注释与事实矛盾)
"${PY}" -c 'import pytest' >/dev/null 2>&1 \\
|| die "安装后 venv 内仍无法 import pytest(${PY})"
log "7b 自证通过: $("${PY}" -m pytest --version 2>&1 | head -1) @ ${PY}"
fi
'''
def main():
build = os.path.abspath(BUILD)
with io.open(build, "r", encoding="utf-8") as f:
text = f.read()
if MARK in text:
print("SKIP: 7b 已存在,未重复插入")
return 0
if ANCHOR not in text:
print("FAIL: 找不到第 8 步锚点,拒绝盲目修改")
return 1
patched = text.replace(ANCHOR, BLOCK + ANCHOR, 1)
with io.open(build, "w", encoding="utf-8") as f:
f.write(patched)
print("OK: 已在 %s 第 8 步前插入 7b(+%d 字符)" % (build, len(patched) - len(text)))
return 0
if __name__ == "__main__":
sys.exit(main())