重大重构:引擎模块拆分 + P0插件实现 + 55个Bug修复

核心变更:
- engine.py(1781行)拆分为8个独立模块: lifecycle/security/deps/
  datastore/pl_injector/watcher/signature/manager
- 新增plugin-bridge: 事件总线 + 服务注册 + RPC通信
- 新增i18n: 国际化/多语言翻译支持
- 新增plugin-storage: 插件键值/文件存储
- 新增ws-api: WebSocket实时通信(pub/sub + 自定义处理器)
- nodejs-adapter统一为Plugin ABC模式

Bug修复:
- 修复load_all()中store_dir未定义崩溃
- 修复DependencyResolver入度计算(拓扑排序)
- 修复PermissionError隐藏内置异常
- 修复CORS中间件头部未附加到响应
- 修复IntegrityChecker跳过__pycache__目录
- 修复版本号不一致(v2.0.0→v1.2.0)
- 修复测试文件的Logger导入/路径/私有方法调用
- 修复context.py缺少typing导入
- 修复config.py STORE_DIR默认路径(./mods→./store)

测试覆盖: 14→91个测试, 全部通过
This commit is contained in:
Falck
2026-05-12 11:40:06 +08:00
parent 3a096f59a9
commit bce27db4ac
57 changed files with 3669 additions and 2367 deletions

83
oss/tests/test_i18n.py Normal file
View File

@@ -0,0 +1,83 @@
"""Tests for i18n plugin"""
import os
import sys
import tempfile
import json
import pytest
from pathlib import Path
PLUGIN_DIR = Path(__file__).parent.parent / "store" / "NebulaShell" / "i18n"
sys.path.insert(0, str(PLUGIN_DIR))
import importlib.util
spec = importlib.util.spec_from_file_location("i18n_main", str(PLUGIN_DIR / "main.py"))
main_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(main_module)
I18n = main_module.I18n
class TestI18n:
def test_default_language(self):
i18n = I18n()
assert i18n.get_language() == "zh-CN"
def test_set_language_valid(self):
i18n = I18n()
assert i18n.set_language("en-US") == True
assert i18n.get_language() == "en-US"
def test_set_language_invalid(self):
i18n = I18n()
assert i18n.set_language("fr-FR") == False
assert i18n.get_language() == "zh-CN"
def test_supported_languages(self):
i18n = I18n()
langs = i18n.get_supported_languages()
assert "zh-CN" in langs
assert "en-US" in langs
assert "ja-JP" in langs
def test_translate_fallback_to_key(self):
i18n = I18n()
result = i18n.translate("nonexistent.key")
assert result == "nonexistent.key"
def test_register_and_translate(self):
i18n = I18n()
i18n.register_translations("zh-CN", "test", {"greeting": "你好"})
assert i18n.translate("greeting", "test") == "你好"
def test_translate_with_format(self):
i18n = I18n()
i18n.register_translations("zh-CN", "test", {"welcome": "欢迎 {name}"})
result = i18n.translate("welcome", "test", name="张三")
assert result == "欢迎 张三"
def test_load_domain(self):
i18n = I18n()
i18n.load_domain("custom", {"key": "val"})
assert i18n.translate("key", "custom") == "val"
def test_t_alias(self):
i18n = I18n()
assert i18n.t("missing") == "missing"
def test_get_info(self):
i18n = I18n()
info = i18n.get_info()
assert "language" in info
assert "supported" in info
assert "domains" in info
def test_lifecycle(self):
i18n = I18n()
i18n.init()
i18n.start()
i18n.stop()
assert i18n.get_language() == "zh-CN"
if __name__ == '__main__':
pytest.main([__file__, '-v'])