60 lines
2.8 KiB
GDScript
60 lines
2.8 KiB
GDScript
# python_host_check —— 在 app 进程里把内嵌解释器起来并跑 system.py(docs/PORT-PLAN.md 批次 2P step 4)。
|
||
#
|
||
# 和 ctest 的 `port.python_launcher` 跑的是同一条序列,区别只有一个:那边是独立可执行文件,这边在
|
||
# Godot 进程里,由 GDScript 发起 —— step 4 要验的就是这个差别。2V0 把 C++ 模块注册上之前,
|
||
# 在玩法模块补齐前,system.py 会停在下一个未注册的 native import。
|
||
#
|
||
# 真机上通常没有 40250 的 Client/pack(APK 里只有 python27.zip),所以分两段:解释器 + 标准库这一段
|
||
# 不需要 pack,任何平台都跑;system.py 这一段需要 pack,没有就跳过并说清楚。
|
||
#
|
||
# 桌面:python_host_test.gd(--script);真机:MT_TEST_MODE=python 从 client_main.gd 进来。
|
||
extends RefCounted
|
||
|
||
const EXPECTED_STOP := "No module named net"
|
||
|
||
var fail := 0
|
||
|
||
func _ck(ok: bool, message: String) -> void:
|
||
if not ok:
|
||
fail += 1
|
||
printerr("FAIL: " + message)
|
||
else:
|
||
print("ok: " + message)
|
||
|
||
# 返回失败数;0 表示落在预期的停止点上(或按上面的规则跳过)。
|
||
func run() -> int:
|
||
if not ClassDB.class_exists("Metin2PythonHost"):
|
||
printerr("FAIL: Metin2PythonHost extension is not registered")
|
||
return 1
|
||
if not FileAccess.file_exists("res://python27.zip"):
|
||
print("SKIP: python_host_check(没有 res://python27.zip,需要 -DMTGODOT_EMBED_PYTHON=ON 的构建)")
|
||
return 0
|
||
|
||
# 40250 Main() 先注册 pack,再造 CPythonLauncher —— system.py 是从 pack 里读出来的。
|
||
var has_pack := AssetRoot.pack_ready()
|
||
|
||
var start_error: String = Metin2PythonHost.start("")
|
||
_ck(start_error == "", "解释器在 app 进程里起来了:" + start_error)
|
||
if start_error != "":
|
||
return fail
|
||
_ck(Metin2PythonHost.is_running(), "is_running() 为真")
|
||
_ck(Metin2PythonHost.start("") == "", "重复 start() 是空操作")
|
||
|
||
# 标准库真的在 sys.path 上(真机是沙盒里那份 python27.zip),codec 注册表也重建过。
|
||
_ck(Metin2PythonHost.run_line("import os, string, types, codecs") == "", "标准库可 import")
|
||
_ck(Metin2PythonHost.run_line("assert u'\\xe4'.encode('cp1252') == '\\xe4'") == "", "codec 注册表可用")
|
||
_ck(Metin2PythonHost.run_line("import sys; assert sys.path") == "", "sys.path 非空")
|
||
|
||
if has_pack:
|
||
# RunMainScript:initpack() + __DEBUG__ + __COMMAND_LINE__ + RunFile("system.py")。
|
||
var err: String = Metin2PythonHost.run_main_script("")
|
||
print("system.py -> %s" % err)
|
||
_ck(err.contains(EXPECTED_STOP),
|
||
"system.py 停在预期的 '%s'(2V0 之后这里会往前走)" % EXPECTED_STOP)
|
||
else:
|
||
print("SKIP: system.py 这一段(没有 40250 Client/pack:%s)" % AssetRoot.client_path())
|
||
|
||
Metin2PythonHost.stop()
|
||
_ck(not Metin2PythonHost.is_running(), "stop() 之后 is_running() 为假")
|
||
return fail
|