101 lines
3.7 KiB
Python
101 lines
3.7 KiB
Python
import os
|
||
import json5
|
||
import app.env as env
|
||
|
||
class Config:
|
||
"""
|
||
配置类,用于加载和管理应用配置。
|
||
|
||
该类通过读取配置文件并将内容映射到实例属性中,使得配置项可以像访问普通属性一样被访问。
|
||
它支持递归加载字典类型的配置项,以及直接加载列表和基本数据类型的配置项。
|
||
"""
|
||
base_config = {
|
||
"theme": "dark",
|
||
"init": False
|
||
}
|
||
def __init__(self):
|
||
"""
|
||
初始化Config实例,从配置文件中加载配置并更新实例属性。
|
||
"""
|
||
# 加载配置文件并指定编码为utf-8,确保中文字符正确解析
|
||
self._conf_Dict = json5.load(open(os.path.join(env.dirs.user_config_path, "config.json"), encoding="utf-8"))
|
||
self._conf_Dict = self.merge_dicts(self.base_config, self._conf_Dict)
|
||
# 设置实例的名称,用于标识配置类型
|
||
self.__name__ = "<Standard Dictionary>"
|
||
# 更新实例属性,将配置项映射为可直接访问的属性
|
||
self.update()
|
||
|
||
def __getattr__(self, name):
|
||
"""
|
||
当访问不存在的属性时,尝试从配置字典中获取相应的值。
|
||
|
||
参数:
|
||
name (str): 试图访问的属性名。
|
||
|
||
返回:
|
||
配置字典中的对应值。
|
||
|
||
异常:
|
||
如果配置字典中也没有该属性名,则抛出AttributeError。
|
||
"""
|
||
# 检查配置字典中是否存在该属性名
|
||
if name in self._conf_Dict:
|
||
return self._conf_Dict[name]
|
||
else:
|
||
raise AttributeError(
|
||
f"'{self.__class__.__name__}' object has no attribute '{name}'"
|
||
)
|
||
def merge_dicts(self, *dict_args):
|
||
"""
|
||
递归合并多个字典。
|
||
|
||
参数:
|
||
*dict_args: 多个字典参数,按优先级从低到高传递。
|
||
default (any, 可选): 默认值,当找不到键时返回此值,默认为 None。
|
||
|
||
返回:
|
||
合并后的字典。
|
||
"""
|
||
result = {}
|
||
for dictionary in dict_args:
|
||
for key, value in dictionary.items():
|
||
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
|
||
# 如果当前键对应的值都是字典,则递归合并
|
||
result[key] = self.merge_dicts(result[key], value)
|
||
else:
|
||
# 否则直接覆盖或设置值
|
||
result[key] = value
|
||
return result
|
||
def update(self):
|
||
"""
|
||
更新实例属性,将配置字典中的内容映射到实例属性中。
|
||
|
||
该方法主要处理三种类型的配置项:
|
||
1. 字典类型:递归创建Config实例并设置属性。
|
||
2. 列表类型:遍历列表,对字典项创建Config实例,其他项保持不变。
|
||
3. 基本数据类型:直接设置实例属性。
|
||
"""
|
||
# 遍历配置字典中的所有项
|
||
for k, v in self._conf_Dict.items():
|
||
# 如果值是字典类型,递归创建Config实例
|
||
if isinstance(v, dict):
|
||
setattr(self, k, Config(v))
|
||
# 如果值是列表类型,对列表中的字典项创建Config实例
|
||
elif isinstance(v, list):
|
||
setattr(
|
||
self,
|
||
k,
|
||
[Config(item) if isinstance(item, dict) else item for item in v],
|
||
)
|
||
# 如果值是基本数据类型,直接设置实例属性
|
||
else:
|
||
setattr(self, k, v)
|
||
|
||
def __str__(self):
|
||
"""
|
||
返回配置字典的字符串表示形式。
|
||
|
||
返回:
|
||
配置字典的字符串形式。
|
||
"""
|
||
return str(self._conf_Dict) |