Files
NyaHome/src/nyahome/config/manager.py
T

147 lines
4.4 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.
import json
import logging
from pathlib import Path
from typing import Any, TypeVar
import aiofiles
from .config import Config
logger = logging.getLogger(__name__)
CONFIG_PATH = Path.cwd() / ".nyahome" / "config.json"
T = TypeVar("T", str, int, bool, list)
class ConfigManager:
"""
ConfigManager 携带一个初始化的 Config 实例。在 Config 初始化时,所有的默认设置键的值就都已经加载。
因此,如果不 load_configConfigManager 也将持有一套默认设置。
"""
def __init__(self) -> None:
CONFIG_PATH.parent.mkdir(exist_ok=True)
self._config = Config()
def _parse(self, config: dict) -> None:
"""
解析给定的字典作为配置。
Args:
config: 配置字典
"""
for key, value in config.items():
setattr(self._config, key, value)
def _dumps(self) -> str:
"""
将配置项序列化为 json 字符串,包含格式化缩进。
Returns:
json 字符串。
"""
config = {}
for attr in dir(self._config):
if not attr.startswith("_"):
value = getattr(self._config, attr)
config[attr] = value
return json.dumps(config, ensure_ascii=False, indent=2)
async def async_load_config(self) -> None:
async with aiofiles.open(CONFIG_PATH, "r", encoding="utf-8") as f:
self._parse(json.loads(await f.read()))
logger.info("异步从 config.json 读取设置完成。")
def sync_load_config(self) -> None:
with open(CONFIG_PATH, "r", encoding="utf-8") as f:
self._parse(json.load(f))
logger.info("同步从 config.json 读取设置完成。")
async def async_save_config(self) -> None:
async with aiofiles.open(CONFIG_PATH, "w", encoding="utf-8") as f:
await f.write(self._dumps())
logger.info("异步保存设置到 config.json 完成。")
def sync_save_config(self) -> None:
with open(CONFIG_PATH, "w", encoding="utf-8") as f:
f.write(self._dumps())
logger.info("同步保存设置到 config.json 完成。")
def get(self, key: str, default: T | None = None) -> T:
"""
获取配置项
Args:
key: 配置键
default: 默认值,如果不提供则会在获取配置项失败时报错
Returns:
返回配置值,返回类型根据提供的默认值进行推断。
"""
return getattr(self._config, key, default) # type: ignore[return-value]
def set(self, key: str, value: T) -> None:
"""
设置配置项。
Args:
key: 配置键名
value: 配置键的新值,可以是(且仅支持)字符串、整型以及列表。
Raises:
AttributeError: 配置键名错误
TypeError: 配置键值类型错误
"""
try:
old_value = self.get(key)
except AttributeError as e:
raise e
match old_value:
case str():
new_value = str(value)
case int():
new_value = int(value)
case bool():
new_value = bool(value)
case list():
new_value = list(value)
case _:
raise TypeError(f"不支持 {type(old_value).__name__} 类型的设置项。({key}")
setattr(self._config, key, new_value)
def reset(self, key: str) -> None:
"""
将配置项恢复至默认值。
Args:
key: 配置键名
Raises:
AttributeError: 配置键名错误
"""
ci = Config()
try:
default_value = getattr(ci, key)
except AttributeError as e:
raise e
setattr(self._config, key, default_value)
def get_config(self) -> dict[str, Any]:
config = {}
for attr in dir(self._config):
if not attr.startswith("_"):
value = getattr(self._config, attr)
config[attr] = value
return config
def set_config(self, config: dict[str, Any]) -> dict[str, Any]:
for attr in dir(self._config):
if not attr.startswith("_"):
setattr(self._config, attr, config[attr])
return self.get_config()
config_manager = ConfigManager()