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__ = "" # 更新实例属性,将配置项映射为可直接访问的属性 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)