Files
ZiPingEightChar/tests/test_runtime_guard.py
T
moxiaonian 433c9b4a41 v3.6.0 同步发版
- 交互契约改对话式询问(禁点选工具、一次1~2问、先铺垫再问),规则库 3.6
- 盘面图默认生成+chart_shot 截图;品牌区、大运/流年小卡信息补全、交流群二维码卡
- day_boundary 子正换日;memory_save --update-chart 换盘留痕;share_export 事件简介+城市级地域
- share_push 失败诊断+代理引导;_runtime_guard;修 STAR_ORDER 三奇贵人 KeyError
- README 规则计数 541→542;manifest 重建(1275 文件);测试 142 项全绿
2026-10-10 13:13:41 +08:00

75 lines
2.9 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.
"""运行环境守卫(scripts/_runtime_guard.py):版本判定文案、import 时拦截、入口脚本接线。
import 时拦截用子进程模拟:伪造 sys.version_info = (3, 9, 6) 后再 import,
守卫应打印中文报错并以退出码 3 结束进程。
"""
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SCRIPTS = ROOT / "scripts"
sys.path.insert(0, str(SCRIPTS))
import _runtime_guard as guard
ENTRY_SCRIPTS = ("cast_chart.py", "chart_shot.py", "memory_lookup.py",
"memory_save.py", "query_shensha.py", "self_update.py",
"share_export.py", "share_push.py")
def run_with_fake_py39(code: str) -> subprocess.CompletedProcess:
"""在子进程中把 sys.version_info 伪造成 3.9.6 后执行 code。"""
prefix = "import sys, runpy; sys.version_info = (3, 9, 6); "
return subprocess.run([sys.executable, "-c", prefix + code],
capture_output=True, text=True, timeout=60)
class TestVersionError:
def test_current_interpreter_passes(self):
assert guard.version_error() is None
def test_py39_denied_with_chinese_message(self):
msg = guard.version_error((3, 9, 6))
assert msg is not None
assert "Python 3.10" in msg
assert "3.9.6" in msg
assert sys.executable in msg
def test_boundary_versions(self):
assert guard.version_error((3, 10, 0)) is None
assert guard.version_error((4, 0, 0)) is None
assert guard.version_error((3, 8, 10)) is not None
assert guard.version_error((2, 7, 18)) is not None
class TestImportTimeGuard:
def test_import_denied_exits_3(self):
cp = run_with_fake_py39(
f"sys.path.insert(0, {str(SCRIPTS)!r}); import _runtime_guard")
assert cp.returncode == 3
assert "Python 3.10" in cp.stderr
def test_import_allowed_is_silent(self):
cp = subprocess.run(
[sys.executable, "-c",
f"import sys; sys.path.insert(0, {str(SCRIPTS)!r}); import _runtime_guard"],
capture_output=True, text=True, timeout=60)
assert cp.returncode == 0
assert cp.stderr == ""
def test_entry_script_intercepts_before_deep_error(self):
"""chart_shot.py 在 3.9 下原本 def 期即 TypeError;接线后守卫先拦截,报错清晰。"""
cp = run_with_fake_py39(
f"sys.argv = ['chart_shot.py', 'x.html']; "
f"runpy.run_path({str(SCRIPTS / 'chart_shot.py')!r}, run_name='__main__')")
assert cp.returncode == 3
assert "Python 3.10" in cp.stderr
assert "TypeError" not in cp.stderr
class TestEntryScriptsWired:
def test_every_entry_script_imports_guard(self):
for name in ENTRY_SCRIPTS:
src = (SCRIPTS / name).read_text(encoding="utf-8")
assert "import _runtime_guard" in src, f"{name} 未接入 _runtime_guard"