From 827658beab0343fdf32a2f8468ad52dfaaade44f Mon Sep 17 00:00:00 2001 From: Nanaloveyuki Date: Mon, 28 Jul 2025 16:09:33 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E4=BA=86`config`=E8=AF=BB=E5=8F=96=E5=86=99=E5=85=A5=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E7=9A=84=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- config.json => logger_config.json | 0 src/logiliteal/utils/configs.py | 191 ++++++++++++++++-------------- 3 files changed, 105 insertions(+), 88 deletions(-) rename config.json => logger_config.json (100%) diff --git a/.gitignore b/.gitignore index a7858f2..f322a7f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Custom -*.backup.json +*_backup.json # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/config.json b/logger_config.json similarity index 100% rename from config.json rename to logger_config.json diff --git a/src/logiliteal/utils/configs.py b/src/logiliteal/utils/configs.py index e2d266e..a6977ca 100644 --- a/src/logiliteal/utils/configs.py +++ b/src/logiliteal/utils/configs.py @@ -6,7 +6,15 @@ py-logiliteal's config settings, used to set py-logiliteal's global config # encoding = utf-8 # python 3.13.5 -DEFAULT_CONFIG_PATH = "config.json" +import json +from os import remove +import shutil +import time +from pathlib import Path +from typing import Union, Optional, Tuple +from logging import error + +DEFAULT_CONFIG_PATH = "logger_config.json" DEFAULT_CONFIG = { "file_level": "DEBUG", "file_name": "latest.log", @@ -25,9 +33,47 @@ DEFAULT_CONFIG = { "level_color": {"DEBUG": "#c1d5ff", "INFO": "#c1ffff", "WARN": "#fff600", "ERRO": "#ffa000", "CRIT": "#ff8181"}, } -from typing import Union, Optional -from logging import error, info -import json +g_config_cache = None +g_config_mtime = 0 + +def create_backup(config_path: Path) -> Tuple[bool, str]: + """ + 创建配置文件备份 + :param config_path: 配置文件路径 + :param backup_prefix: 备份文件前缀 + :return: (是否成功, 备份路径或错误信息) + """ + try: + if not config_path.exists(): + return False, f"配置文件不存在: {config_path}" + backup_path = config_path.parent / f"logger_config_backup.json" + + if backup_path.exists(): + remove(backup_path) + shutil.copy2(config_path, backup_path) + return True, str(backup_path) + except PermissionError: + return False, f"权限不足,无法创建备份: {config_path}" + except Exception as e: + return False, f"备份失败: {str(e)}" + +def handle_config_exceptions(func): + """ + 配置操作异常处理装饰器 + """ + def wrapper(*args, **kwargs): + try: + return func(*args, **kwargs) + except json.JSONDecodeError as e: + error(f"配置文件格式错误: {e}") + return False, f"配置文件格式错误: {str(e)}" + except PermissionError: + error(f"没有权限操作配置文件: {DEFAULT_CONFIG_PATH}") + return False, "没有权限操作配置文件" + except Exception as e: + error(f"配置操作失败: {e}") + return False, f"配置操作失败: {str(e)}" + return wrapper def get_config(select: str = None) -> Union[dict, str, bool, int, None]: """ @@ -35,27 +81,24 @@ def get_config(select: str = None) -> Union[dict, str, bool, int, None]: :param select: 配置项名称 Config item name :return: 配置项值 Config item value """ - try: - with open(DEFAULT_CONFIG_PATH, "r", encoding="utf-8") as f: - config = json.load(f) - if select: - return config[select] - return config - except (FileNotFoundError, json.JSONDecodeError): - with open(DEFAULT_CONFIG_PATH, "w", encoding="utf-8") as f: - json.dump(DEFAULT_CONFIG, f, indent=4) - if select: - return DEFAULT_CONFIG[select] - return DEFAULT_CONFIG - except KeyError as e: - error(f"配置项 '{select}' 不存在") - return None - except Exception as e: - error(f"读取配置文件失败: {e}") - return None + global g_config_cache, g_config_mtime + config_path = Path(DEFAULT_CONFIG_PATH) -import shutil -from pathlib import Path + if config_path.exists(): + current_mtime = config_path.stat().st_mtime + if current_mtime != g_config_mtime or g_config_cache is None: + with open(config_path, "r", encoding="utf-8") as f: + g_config_cache = json.load(f) + g_config_mtime = current_mtime + else: + with open(config_path, "w", encoding="utf-8") as f: + json.dump(DEFAULT_CONFIG, f, indent=4) + g_config_cache = DEFAULT_CONFIG + g_config_mtime = config_path.stat().st_mtime + + if select: + return g_config_cache.get(select) + return g_config_cache def set_config(select: str, value: Union[dict, str, bool, int, None]) -> tuple[bool, Optional[str]]: """ @@ -64,75 +107,49 @@ def set_config(select: str, value: Union[dict, str, bool, int, None]) -> tuple[b :param value: 配置项值 Config item value :return: (设置是否成功, 消息) (Set success or not, message) """ - try: - config_path = Path(DEFAULT_CONFIG_PATH) - backup_path = Path(__file__).parent / "configs.backup.json" - - if not config_path.exists(): - with open(config_path, "w", encoding="utf-8") as f: - json.dump(DEFAULT_CONFIG, f, indent=4) - - shutil.copy2(config_path, backup_path) - - with open(DEFAULT_CONFIG_PATH, "r+", encoding="utf-8") as f: - config = json.load(f) - config[select] = value - f.seek(0) - json.dump(config, f, indent=4) - f.truncate() - - with open(DEFAULT_CONFIG_PATH, "r", encoding="utf-8") as f: - verify_config = json.load(f) - if verify_config.get(select) != value: - error(f"配置项 '{select}' 设置失败,值为 {value}") - shutil.move(backup_path, DEFAULT_CONFIG_PATH) - return False, f"配置项 '{select}' 设置失败,已恢复备份" - - Path(backup_path).unlink(missing_ok=True) - return True, f"配置项 '{select}' 设置成功" + config_path = Path(DEFAULT_CONFIG_PATH) - except json.JSONDecodeError as e: - error(f"配置文件格式错误: {e}") - return False, f"配置文件格式错误: {str(e)}" - except PermissionError: - error(f"没有权限操作配置文件: {DEFAULT_CONFIG_PATH}") - return False, "没有权限操作配置文件" - except Exception as e: - error(f"设置配置文件失败: {e}") + if not config_path.exists(): + with open(config_path, "w", encoding="utf-8") as f: + json.dump(DEFAULT_CONFIG, f, indent=4) - if Path(backup_path).exists(): - shutil.move(backup_path, DEFAULT_CONFIG_PATH) - return False, f"设置失败,已恢复备份: {str(e)}" - return False, f"设置配置文件失败: {str(e)}" + backup_success, backup_info = create_backup(config_path) + if not backup_success: + return False, f"备份失败: {backup_info}" -@staticmethod + with open(config_path, "r+", encoding="utf-8") as f: + config = json.load(f) + config[select] = value + f.seek(0) + json.dump(config, f, indent=4) + f.truncate() + + with open(config_path, "r", encoding="utf-8") as f: + verify_config = json.load(f) + if verify_config.get(select) != value: + shutil.move(backup_info, config_path) + return False, f"配置项 '{select}' 设置失败,已恢复备份" + + global g_config_cache + g_config_cache = None + return True, f"配置项 '{select}' 设置成功" + +@handle_config_exceptions def reset_config() -> tuple[bool, Optional[str]]: """ 重置配置信息 Reset config info :return: (重置是否成功, 消息) (Reset success or not, message) """ - try: - config_path = Path(DEFAULT_CONFIG_PATH) - - if not config_path.exists(): - with open(config_path, "w", encoding="utf-8") as f: - json.dump(DEFAULT_CONFIG, f, indent=4) - return True, "配置文件不存在,已创建默认配置" + config_path = Path(DEFAULT_CONFIG_PATH) - from .time import get_asctime - timestamp = get_asctime() - backup_path = f"{DEFAULT_CONFIG_PATH}_{timestamp}.backup.json" - backup_path = backup_path.replace(":", "-") - shutil.copy2(DEFAULT_CONFIG_PATH, backup_path) - with open(DEFAULT_CONFIG_PATH, "w", encoding="utf-8") as f: - json.dump(DEFAULT_CONFIG, f, indent=4) - return True - except PermissionError: - error(f"权限不足,无法操作配置文件: {DEFAULT_CONFIG_PATH}") - return False, "权限不足,无法重置配置" - except json.JSONDecodeError: - error("配置文件格式错误,无法解析") - return False, "配置文件格式错误,无法重置" - except Exception as e: - error(f"重置配置文件失败: {e}") - return False, f"重置配置失败: {str(e)}" + if config_path.exists(): + backup_success, backup_info = create_backup(config_path) + if not backup_success: + return False, f"备份失败: {backup_info}" + + with open(config_path, "w", encoding="utf-8") as f: + json.dump(DEFAULT_CONFIG, f, indent=4) + + global g_config_cache + g_config_cache = None + return True, "配置已重置为默认值"