0827b2399c
引导器 UEFI.boot.py (纯 stdlib, 内核的管家) 体检 6 项 (解释器/venv/包/驱动目录/PG) / venv 重建 / 包台账 / 内核进程启停记账 / 参数原样透传 内核日志 / 引导器日志 / 内核 stdio 三条道的查看入口都归它 内核 内核/ (常驻调度 = 甲) 命令消费 (PG commands + LISTEN/NOTIFY) / 驱动调用仲裁六条 (越权·成环·无人提供·按需拉起·同锁排队·超时收权) 依赖链巡检 10s / 心跳 300s / 独一份调度锁 (pg_try_advisory_lock 0x65666901) 扫描: 9 条校验 + 契约匹配 + 拓扑排序; 状态: 快照原子写 + 断电收尸判定 db.py 是唯一碰 SQL 的文件 (drivers/driver_state/events/scans/commands/calls/kernel_env/kernel_runs) 日志系统 (2026-09-16 完整化, 设计/04-日志系统.md) 三条道一个文件一种内容: 内核.log (结构化行) / 内核.out.log (命令输出 + 崩溃原文) / 引导器.log (引导器动作) 驱动日志每轮启动前插分隔头; 门槛 log_level / 轮转 log_max_mb + log_keep / -n · -f · --级别 · -g · --json · --全部 实现 内核/日志.py (内核与引导器共用一份); 修掉"命令输出混进日志文件" (实证存档 归档/20260916-日志系统重做前/) 驱动样板 (也是写驱动的示范): Json解码 (oneshot) / 样板常驻 (provides 样板:心跳) / 样例消费器 (needs 只发契约名) 代码标点统一为 ASCII (保留界面用的框线 ─│◄▶ 与表格占位符 —); 已用 AST 等价对比证明逻辑零改动 自测 (真机, 不 mock): 进程 (真起进程真收子树) / 内核 58 项 / 配置 / db 182 项 / 日志 86 项 验收: 试跑引导器.py PASS 11 / FAIL 0 / 残留无; uvx pyright 与 uvx basedpyright 均 0 errors 0 warnings
100 lines
3.7 KiB
Python
100 lines
3.7 KiB
Python
"""引导器的配置解析自测: 脏配置不许把引导器搞崩.
|
|
|
|
用法: python3 内核/自测配置.py
|
|
|
|
覆盖:
|
|
* 读包要求 / db段 / _解析包表 对脏数据 (字符串当数组, 数字当对象, 缺键, 坏 json) 的容错
|
|
* 取对象 / 取清单 两个 json 取值助手
|
|
* 版本比较的边界 (相等, 短版本补零, 空要求)
|
|
跑完 0 退出, 有 FAIL 退出 1.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import sys
|
|
from pathlib import Path
|
|
from types import ModuleType
|
|
from typing import Any
|
|
|
|
项目根 = Path(__file__).resolve().parent.parent
|
|
if not (项目根 / "UEFI.boot.py").exists():
|
|
项目根 = Path(__file__).resolve().parent
|
|
|
|
失败数 = 0
|
|
|
|
|
|
def 载入引导器() -> Any:
|
|
"""动态加载 UEFI.boot.py (文件名带点, 没法当模块名 import).
|
|
|
|
坑: exec_module 之前必须把模块塞进 sys.modules, 否则 py3.14 的 dataclass 找不到
|
|
cls.__module__ 对应的模块, 直接 AttributeError ('NoneType' has no attribute '__dict__').
|
|
返回类型写 Any: 动态加载出来的模块成员对类型检查器是未知的, 当成 Any 用最省事.
|
|
"""
|
|
spec = importlib.util.spec_from_file_location("uefi_boot", str(项目根 / "UEFI.boot.py"))
|
|
if spec is None or spec.loader is None:
|
|
print("[FAIL] 加载 UEFI.boot.py 失败")
|
|
sys.exit(1)
|
|
模块: ModuleType = importlib.util.module_from_spec(spec)
|
|
sys.modules["uefi_boot"] = 模块
|
|
spec.loader.exec_module(模块)
|
|
return 模块
|
|
|
|
|
|
def 核对(名称: str, 实际: object, 期望: object) -> None:
|
|
global 失败数
|
|
好 = 实际 == 期望
|
|
if not 好:
|
|
失败数 += 1
|
|
print(f"[{'OK ' if 好 else 'FAIL'}] {名称}: {实际!r}" + ("" if 好 else f" (期望 {期望!r})"))
|
|
|
|
|
|
引导 = 载入引导器()
|
|
|
|
脏包 = {
|
|
"packages": [
|
|
{"name": "a", "version": ">=1", "required": True},
|
|
"脏项",
|
|
3,
|
|
{"name": ""},
|
|
{"name": "b"},
|
|
]
|
|
}
|
|
核对(
|
|
"读包要求: 脏项混合只留两条有名字的",
|
|
[(条.名, 条.要求, 条.必需) for 条 in 引导.读包要求(脏包)],
|
|
[("a", ">=1", True), ("b", "", False)],
|
|
)
|
|
核对("读包要求: packages 是字符串", 引导.读包要求({"packages": "不是数组"}), [])
|
|
核对("读包要求: 没有 packages 键", 引导.读包要求({}), [])
|
|
核对("读包要求: 项是数字", 引导.读包要求({"packages": [7]}), [])
|
|
|
|
核对("db段: 正常", 引导.db段({"db": {"name": "x"}}), {"name": "x"})
|
|
核对("db段: 缺键", 引导.db段({}), {})
|
|
核对("db段: 是数字", 引导.db段({"db": 5}), {})
|
|
核对("db段: 是 None", 引导.db段({"db": None}), {})
|
|
|
|
核对("_解析包表: 空数组", 引导._解析包表("[]"), {})
|
|
核对("_解析包表: 坏 json", 引导._解析包表("坏 json"), None)
|
|
核对(
|
|
"_解析包表: 包名要归一化 (PEP 503)",
|
|
引导._解析包表('[{"name": "P_Sql.Thing", "version": "1.2"}]'),
|
|
{"p-sql-thing": "1.2"},
|
|
)
|
|
|
|
核对("取对象: None", 引导.取对象(None), {})
|
|
核对("取对象: 数组", 引导.取对象([1]), {})
|
|
核对("取清单: 字符串", 引导.取清单("x"), [])
|
|
核对("取清单: 数组", 引导.取清单([1, 2]), [1, 2])
|
|
|
|
核对("缺 db 段时库名兜底", 引导.db.从配置(引导.db段({})).name, "efi_kernel")
|
|
核对("版本比较: 相等算满足", 引导.满足要求("2.9.9", ">=2.9.9"), True)
|
|
核对("版本比较: 短版本补零", 引导.满足要求("2.9", ">=2.9.0"), True)
|
|
核对("版本比较: 差一位不算满足", 引导.满足要求("2.9.8", ">=2.9.9"), False)
|
|
核对("版本比较: 空要求 = 不校验", 引导.满足要求("", ""), True)
|
|
核对("版本比较: 没装就是没装", 引导.满足要求("", ">=1.0"), False)
|
|
|
|
print()
|
|
print(f"结论: {'全过' if 失败数 == 0 else f'{失败数} 项没过'}")
|
|
sys.exit(0 if 失败数 == 0 else 1)
|