From 1fe9dc8786406e7ea9343d3572065ac4f1a99f82 Mon Sep 17 00:00:00 2001 From: DrSmoothl <1787882683@qq.com> Date: Mon, 27 Apr 2026 13:17:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=20ConfigManager=20?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=EF=BC=8C=E6=94=AF=E6=8C=81=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E8=87=AA=E5=8A=A8=E5=8D=87=E7=BA=A7=E5=B9=B6=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E7=9B=B8=E5=BA=94=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test_config_manager_hot_reload.py | 6 ++-- .../test_config_manager_startup_upgrade.py | 33 +++++++++++++++++++ src/config/config.py | 11 +++++-- 3 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 pytests/config_test/test_config_manager_startup_upgrade.py diff --git a/pytests/config_test/test_config_manager_hot_reload.py b/pytests/config_test/test_config_manager_hot_reload.py index ab2dd898..a42a4133 100644 --- a/pytests/config_test/test_config_manager_hot_reload.py +++ b/pytests/config_test/test_config_manager_hot_reload.py @@ -16,7 +16,7 @@ async def test_handle_file_changes_throttles_reload(): called = 0 - async def reload_stub() -> bool: + async def reload_stub(changed_scopes=None) -> bool: nonlocal called called += 1 return True @@ -36,7 +36,7 @@ async def test_handle_file_changes_timeout_logged(caplog): manager._hot_reload_min_interval_s = 0.0 manager._hot_reload_timeout_s = 0.01 - async def reload_stub() -> bool: + async def reload_stub(changed_scopes=None) -> bool: await asyncio.sleep(0.05) return True @@ -55,7 +55,7 @@ async def test_handle_file_changes_empty_skips_reload(): called = 0 - async def reload_stub() -> bool: + async def reload_stub(changed_scopes=None) -> bool: nonlocal called called += 1 return True diff --git a/pytests/config_test/test_config_manager_startup_upgrade.py b/pytests/config_test/test_config_manager_startup_upgrade.py new file mode 100644 index 00000000..96d1f08e --- /dev/null +++ b/pytests/config_test/test_config_manager_startup_upgrade.py @@ -0,0 +1,33 @@ +from typing import Any + +import pytest + +from src.config import config as config_module +from src.config.config import Config, ConfigManager, ModelConfig + + +class _StartupUpgradeExit(Exception): + pass + + +def test_initialize_upgrades_bot_and_model_config_before_exit(monkeypatch): + manager = ConfigManager() + loaded_config_classes: list[type[Any]] = [] + exit_codes: list[int | None] = [] + + def fake_load_config_from_file(config_class, config_path, new_ver, override_repr=False): + loaded_config_classes.append(config_class) + return object(), True + + def fake_exit(code: int | None = None): + exit_codes.append(code) + raise _StartupUpgradeExit + + monkeypatch.setattr(config_module, "load_config_from_file", fake_load_config_from_file) + monkeypatch.setattr(config_module.sys, "exit", fake_exit) + + with pytest.raises(_StartupUpgradeExit): + manager.initialize() + + assert loaded_config_classes == [Config, ModelConfig] + assert exit_codes == [0] diff --git a/src/config/config.py b/src/config/config.py index 7a9a6d3a..36eac1a9 100644 --- a/src/config/config.py +++ b/src/config/config.py @@ -196,8 +196,15 @@ class ConfigManager: def initialize(self): logger.info(t("config.current_version", version=MMC_VERSION)) logger.info(t("config.loading")) - self.global_config = self.load_global_config() - self.model_config = self.load_model_config() + self.global_config, global_updated = load_config_from_file(Config, self.bot_config_path, CONFIG_VERSION) + self.model_config, model_updated = load_config_from_file( + ModelConfig, + self.model_config_path, + MODEL_CONFIG_VERSION, + True, + ) + if global_updated or model_updated: + sys.exit(0) # 配置已自动升级,退出一次让用户确认新配置后再启动 logger.info(t("config.loaded")) def load_global_config(self) -> Config: