mirror of
https://github.com/Nanaloveyuki/py-logiliteal.git
synced 2025-09-01 00:56:23 +00:00
💩 ♻️ 重构了fmt
和config
的代码
This commit is contained in:
178
log.txt
Normal file
178
log.txt
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
这是一条调试信息这是**粗体**这是*斜体*这是__下划线__这是~~删除线~~这是**粗斜体**这是__粗下划线__这是~~删除线~~这是<#ff0000>红色</>这是<#00ff00>绿色</>这是<#0000ff>蓝色</>这是<#ff0000>嵌<#00ff00>套</></>这是<#ff0000>不完全闭合这是<#ff0000>样式<c>清理这是<b>粗体</b>这是<i>斜体</i>这是<u>下划线</u>这是<s>删除线</s>这是<b><i>粗斜体</i></b>这是<b><u>粗下划线</u></b>这是<b><s>粗删除线</s></b><#ff0000>111<#ff0000>111这是前缀这是后缀</></>这是一条调试信息
|
||||||
|
这是**粗体**
|
||||||
|
这是*斜体*
|
||||||
|
这是__下划线__
|
||||||
|
这是~~删除线~~
|
||||||
|
这是**粗斜体**
|
||||||
|
这是__粗下划线__
|
||||||
|
这是~~删除线~~
|
||||||
|
这是<#ff0000>红色</>
|
||||||
|
这是<#00ff00>绿色</>
|
||||||
|
这是<#0000ff>蓝色</>
|
||||||
|
这是<#ff0000>嵌<#00ff00>套</></>
|
||||||
|
这是<#ff0000>不完全闭合
|
||||||
|
这是<#ff0000>样式<c>清理
|
||||||
|
这是<b>粗体</b>
|
||||||
|
这是<i>斜体</i>
|
||||||
|
这是<u>下划线</u>
|
||||||
|
这是<s>删除线</s>
|
||||||
|
这是<b><i>粗斜体</i></b>
|
||||||
|
这是<b><u>粗下划线</u></b>
|
||||||
|
这是<b><s>粗删除线</s></b>
|
||||||
|
<#ff0000>111<#ff0000>111这是前缀
|
||||||
|
这是后缀</></>
|
||||||
|
这是一条调试信息
|
||||||
|
这是**粗体**
|
||||||
|
这是*斜体*
|
||||||
|
这是__下划线__
|
||||||
|
这是~~删除线~~
|
||||||
|
这是**粗斜体**
|
||||||
|
这是__粗下划线__
|
||||||
|
这是~~删除线~~
|
||||||
|
这是<#ff0000>红色</>
|
||||||
|
这是<#00ff00>绿色</>
|
||||||
|
这是<#0000ff>蓝色</>
|
||||||
|
这是<#ff0000>嵌<#00ff00>套</></>
|
||||||
|
这是<#ff0000>不完全闭合
|
||||||
|
这是<#ff0000>样式<c>清理
|
||||||
|
这是<b>粗体</b>
|
||||||
|
这是<i>斜体</i>
|
||||||
|
这是<u>下划线</u>
|
||||||
|
这是<s>删除线</s>
|
||||||
|
这是<b><i>粗斜体</i></b>
|
||||||
|
这是<b><u>粗下划线</u></b>
|
||||||
|
这是<b><s>粗删除线</s></b>
|
||||||
|
这是一条调试信息
|
||||||
|
|
||||||
|
这是**粗体**
|
||||||
|
|
||||||
|
这是*斜体*
|
||||||
|
|
||||||
|
这是__下划线__
|
||||||
|
|
||||||
|
这是~~删除线~~
|
||||||
|
|
||||||
|
这是**粗斜体**
|
||||||
|
|
||||||
|
这是__粗下划线__
|
||||||
|
|
||||||
|
这是~~删除线~~
|
||||||
|
|
||||||
|
这是<#ff0000>红色</>
|
||||||
|
|
||||||
|
这是<#00ff00>绿色</>
|
||||||
|
|
||||||
|
这是<#0000ff>蓝色</>
|
||||||
|
|
||||||
|
这是<#ff0000>嵌<#00ff00>套</></>
|
||||||
|
|
||||||
|
这是<#ff0000>不完全闭合
|
||||||
|
|
||||||
|
这是<#ff0000>样式<c>清理
|
||||||
|
|
||||||
|
这是<b>粗体</b>
|
||||||
|
|
||||||
|
这是<i>斜体</i>
|
||||||
|
|
||||||
|
这是<u>下划线</u>
|
||||||
|
|
||||||
|
这是<s>删除线</s>
|
||||||
|
|
||||||
|
这是<b><i>粗斜体</i></b>
|
||||||
|
|
||||||
|
这是<b><u>粗下划线</u></b>
|
||||||
|
|
||||||
|
这是<b><s>粗删除线</s></b>
|
||||||
|
|
||||||
|
这是一条调试信息
|
||||||
|
|
||||||
|
这是**粗体**
|
||||||
|
|
||||||
|
这是*斜体*
|
||||||
|
|
||||||
|
这是__下划线__
|
||||||
|
|
||||||
|
这是~~删除线~~
|
||||||
|
|
||||||
|
这是**粗斜体**
|
||||||
|
|
||||||
|
这是__粗下划线__
|
||||||
|
|
||||||
|
这是~~删除线~~
|
||||||
|
|
||||||
|
这是<#ff0000>红色</>
|
||||||
|
|
||||||
|
这是<#00ff00>绿色</>
|
||||||
|
|
||||||
|
这是<#0000ff>蓝色</>
|
||||||
|
|
||||||
|
这是<#ff0000>嵌<#00ff00>套</></>
|
||||||
|
|
||||||
|
这是<#ff0000>不完全闭合
|
||||||
|
|
||||||
|
这是<#ff0000>样式<c>清理
|
||||||
|
|
||||||
|
这是<b>粗体</b>
|
||||||
|
|
||||||
|
这是<i>斜体</i>
|
||||||
|
|
||||||
|
这是<u>下划线</u>
|
||||||
|
|
||||||
|
这是<s>删除线</s>
|
||||||
|
|
||||||
|
这是<b><i>粗斜体</i></b>
|
||||||
|
|
||||||
|
这是<b><u>粗下划线</u></b>
|
||||||
|
|
||||||
|
这是<b><s>粗删除线</s></b>
|
||||||
|
|
||||||
|
<#ff0000>111<#ff0000>111这是前缀
|
||||||
|
|
||||||
|
这是后缀</>
|
||||||
|
</>
|
||||||
|
这是一条调试信息
|
||||||
|
|
||||||
|
这是**粗体**
|
||||||
|
|
||||||
|
这是*斜体*
|
||||||
|
|
||||||
|
这是__下划线__
|
||||||
|
|
||||||
|
这是~~删除线~~
|
||||||
|
|
||||||
|
这是**粗斜体**
|
||||||
|
|
||||||
|
这是__粗下划线__
|
||||||
|
|
||||||
|
这是~~删除线~~
|
||||||
|
|
||||||
|
这是<#ff0000>红色</>
|
||||||
|
|
||||||
|
这是<#00ff00>绿色</>
|
||||||
|
|
||||||
|
这是<#0000ff>蓝色</>
|
||||||
|
|
||||||
|
这是<#ff0000>嵌<#00ff00>套</></>
|
||||||
|
|
||||||
|
这是<#ff0000>不完全闭合
|
||||||
|
|
||||||
|
这是<#ff0000>样式<c>清理
|
||||||
|
|
||||||
|
这是<b>粗体</b>
|
||||||
|
|
||||||
|
这是<i>斜体</i>
|
||||||
|
|
||||||
|
这是<u>下划线</u>
|
||||||
|
|
||||||
|
这是<s>删除线</s>
|
||||||
|
|
||||||
|
这是<b><i>粗斜体</i></b>
|
||||||
|
|
||||||
|
这是<b><u>粗下划线</u></b>
|
||||||
|
|
||||||
|
这是<b><s>粗删除线</s></b>
|
||||||
|
|
||||||
|
<#ff0000>111<#ff0000>111这是前缀
|
||||||
|
|
||||||
|
这是后缀</>
|
||||||
|
</>
|
@ -2,20 +2,19 @@
|
|||||||
"file_level": "DEBUG",
|
"file_level": "DEBUG",
|
||||||
"file_name": "latest.log",
|
"file_name": "latest.log",
|
||||||
"file_path": "./logs",
|
"file_path": "./logs",
|
||||||
"file_format": "{asctime} {levelname} | {prefix}{message}",
|
"file_format": "{asctime} {levelname} | {prefix}{message}{suffix}",
|
||||||
"file_encoding": "utf-8",
|
"file_encoding": "utf-8",
|
||||||
"enable_console": true,
|
"enable_console": true,
|
||||||
"enable_file": true,
|
"enable_file": true,
|
||||||
"console_color": true,
|
"console_color": true,
|
||||||
"console_level": "DEBUG",
|
"console_level": "DEBUG",
|
||||||
"console_format": "{time} {levelname} | {prefix}{message}",
|
"console_format": "{time} {levelname} | {prefix}{message}{suffix}",
|
||||||
"console_prefix": "Auto",
|
|
||||||
"console_encoding": "utf-8",
|
"console_encoding": "utf-8",
|
||||||
"asctime_format": "%Y-%m-%d %H:%M:%S",
|
"asctime_format": "%Y-%m-%d %H:%M:%S",
|
||||||
"time_format": "%H:%M:%S",
|
"time_format": "%H:%M:%S",
|
||||||
"date_format": "%Y-%m-%d",
|
"date_format": "%Y-%m-%d",
|
||||||
"weekday_format": "%A",
|
"weekday_format": "%A",
|
||||||
"level_name": {
|
"level_nickname": {
|
||||||
"DEBUG": "DEBUG",
|
"DEBUG": "DEBUG",
|
||||||
"INFO": "INFO",
|
"INFO": "INFO",
|
||||||
"WARN": "WARN",
|
"WARN": "WARN",
|
||||||
|
@ -5,9 +5,9 @@ py-logiliteal's config settings, used to set py-logiliteal's global config
|
|||||||
# encoding = utf-8
|
# encoding = utf-8
|
||||||
# python 3.13.5
|
# python 3.13.5
|
||||||
|
|
||||||
from .utils import get_config, set_config, reset_config, create_backup
|
from .utils import get_config, set_config, reset_config, backup_config, restore_config, init_config
|
||||||
from .utils import get_asctime, get_date, get_time, get_weekday
|
from .utils import get_asctime, get_date, get_time, get_weekday, _get_time
|
||||||
from .utils import fmt_console, fmt_placeholder, fmt_message, fmt_level_name
|
from .utils import fmt_console, fmt_content, fmt_file, fmt_level_list, fmt_level_name_to_number, fmt_level_number_to_name, fmt_placeholder, fmt_regex, add_placeholder, remove_placeholder, get_placeholder
|
||||||
from .utils import set_style, set_color, set_bg_color
|
from .utils import set_style, set_color, set_bg_color
|
||||||
from .levels import Logger
|
from .levels import Logger
|
||||||
|
|
||||||
@ -17,18 +17,31 @@ __all__ = [
|
|||||||
"get_config",
|
"get_config",
|
||||||
"set_config",
|
"set_config",
|
||||||
"reset_config",
|
"reset_config",
|
||||||
|
"backup_config",
|
||||||
|
"restore_config",
|
||||||
|
"init_config",
|
||||||
"get_asctime",
|
"get_asctime",
|
||||||
"get_date",
|
"get_date",
|
||||||
"get_time",
|
"get_time",
|
||||||
"get_weekday",
|
"get_weekday",
|
||||||
|
"_get_time",
|
||||||
"fmt_console",
|
"fmt_console",
|
||||||
|
"fmt_content",
|
||||||
|
"fmt_file",
|
||||||
|
"fmt_level_list",
|
||||||
|
"fmt_level_name_to_number",
|
||||||
|
"fmt_level_number_to_name",
|
||||||
"fmt_placeholder",
|
"fmt_placeholder",
|
||||||
"fmt_message",
|
"fmt_regex",
|
||||||
"fmt_level_name",
|
"add_placeholder",
|
||||||
"set_style",
|
"remove_placeholder",
|
||||||
|
"get_placeholder",
|
||||||
"set_color",
|
"set_color",
|
||||||
"set_bg_color",
|
"set_bg_color",
|
||||||
"create_backup",
|
"set_style",
|
||||||
"Logger", # 日志记录器非实例化
|
"_placeholder",
|
||||||
"logger" # 日志记录器实例化
|
"_level_name_map",
|
||||||
|
"DEFAULT_CONFIG",
|
||||||
|
"logger",
|
||||||
|
"Logger",
|
||||||
]
|
]
|
139
src/logiliteal/levels.py
Normal file
139
src/logiliteal/levels.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
"""
|
||||||
|
日志级别模块
|
||||||
|
Log level module
|
||||||
|
|
||||||
|
"""
|
||||||
|
# encoding: utf-8
|
||||||
|
# python 3.13.5
|
||||||
|
|
||||||
|
from .utils import fmt_console, fmt_file, fmt_content
|
||||||
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
class Logger:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _log(
|
||||||
|
self,
|
||||||
|
message: Any,
|
||||||
|
prefix: str = "",
|
||||||
|
suffix: str = "",
|
||||||
|
level_number: int = 0,
|
||||||
|
no_console: bool = False,
|
||||||
|
no_file: bool = False,
|
||||||
|
no_placeholder: bool = False,
|
||||||
|
no_regex: bool = False,
|
||||||
|
no_color: bool = False,
|
||||||
|
no_html: bool = False,
|
||||||
|
no_link: bool = False,
|
||||||
|
no_markdown: bool = False,
|
||||||
|
no_special_tags: bool = False,
|
||||||
|
) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
同步日志方法
|
||||||
|
Synchronous logging method
|
||||||
|
Args:
|
||||||
|
message (Any): 日志消息 Log message
|
||||||
|
level_number (int, optional): 日志级别编号. Defaults to 0.
|
||||||
|
no_console (bool, optional): 是否禁用控制台输出. Defaults to False.
|
||||||
|
no_file (bool, optional): 是否禁用文件输出. Defaults to False.
|
||||||
|
no_placeholder (bool, optional): 是否禁用占位符替换. Defaults to False.
|
||||||
|
no_regex (bool, optional): 是否禁用正则表达式替换. Defaults to False.
|
||||||
|
no_color (bool, optional): 是否禁用颜色输出. Defaults to False.
|
||||||
|
no_html (bool, optional): 是否禁用HTML标签输出. Defaults to False.
|
||||||
|
no_link (bool, optional): 是否禁用链接输出. Defaults to False.
|
||||||
|
no_markdown (bool, optional): 是否禁用Markdown格式输出. Defaults to False.
|
||||||
|
no_special_tags (bool, optional): 是否禁用特殊标签输出. Defaults to False.
|
||||||
|
**kwargs: 其他参数同fmt_console和fmt_file
|
||||||
|
Returns:
|
||||||
|
Optional[Union[str, bool]]: 格式化后的日志消息或False
|
||||||
|
"""
|
||||||
|
if not no_console:
|
||||||
|
print(fmt_console(
|
||||||
|
message=message,
|
||||||
|
level_number=level_number,
|
||||||
|
prefix=prefix,
|
||||||
|
suffix=suffix,
|
||||||
|
no_placeholder=no_placeholder,
|
||||||
|
no_regex=no_regex,
|
||||||
|
no_color=no_color,
|
||||||
|
no_special_tags=no_special_tags,
|
||||||
|
))
|
||||||
|
if not no_file:
|
||||||
|
with open("log.txt", "a", encoding="utf-8") as f:
|
||||||
|
f.write(fmt_file(
|
||||||
|
message=message,
|
||||||
|
prefix=prefix,
|
||||||
|
suffix=suffix,
|
||||||
|
level_number=level_number,
|
||||||
|
no_placeholder=no_placeholder,
|
||||||
|
no_regex=no_regex,
|
||||||
|
no_color=no_color,
|
||||||
|
no_html=no_html,
|
||||||
|
no_link=no_link,
|
||||||
|
no_markdown=no_markdown,
|
||||||
|
no_special_tags=no_special_tags,
|
||||||
|
))
|
||||||
|
return fmt_content(
|
||||||
|
message=message,
|
||||||
|
prefix=prefix,
|
||||||
|
suffix=suffix,
|
||||||
|
level_number=level_number,
|
||||||
|
no_placeholder=no_placeholder,
|
||||||
|
no_regex=no_regex,
|
||||||
|
no_color=no_color,
|
||||||
|
no_html=no_html,
|
||||||
|
no_link=no_link,
|
||||||
|
no_markdown=no_markdown,
|
||||||
|
no_special_tags=no_special_tags,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def debug(
|
||||||
|
self,
|
||||||
|
message: Any,
|
||||||
|
prefix: str = "",
|
||||||
|
suffix: str = "",
|
||||||
|
level_number: int = 0,
|
||||||
|
no_console: bool = False,
|
||||||
|
no_file: bool = False,
|
||||||
|
no_placeholder: bool = False,
|
||||||
|
no_regex: bool = False,
|
||||||
|
no_color: bool = False,
|
||||||
|
no_html: bool = False,
|
||||||
|
no_link: bool = False,
|
||||||
|
no_markdown: bool = False,
|
||||||
|
no_special_tags: bool = False,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
同步debug日志方法
|
||||||
|
Synchronous debug logging method
|
||||||
|
Args:
|
||||||
|
message (Any): 日志消息 Log message
|
||||||
|
level_number (int, optional): 日志级别编号. Defaults to 0.
|
||||||
|
no_console (bool, optional): 是否禁用控制台输出. Defaults to False.
|
||||||
|
no_file (bool, optional): 是否禁用文件输出. Defaults to False.
|
||||||
|
no_placeholder (bool, optional): 是否禁用占位符替换. Defaults to False.
|
||||||
|
no_regex (bool, optional): 是否禁用正则表达式替换. Defaults to False.
|
||||||
|
no_color (bool, optional): 是否禁用颜色输出. Defaults to False.
|
||||||
|
no_html (bool, optional): 是否禁用HTML标签输出. Defaults to False.
|
||||||
|
no_link (bool, optional): 是否禁用链接输出. Defaults to False.
|
||||||
|
no_markdown (bool, optional): 是否禁用Markdown格式输出. Defaults to False.
|
||||||
|
no_special_tags (bool, optional): 是否禁用特殊标签输出. Defaults to False.
|
||||||
|
其他参数同fmt_console和fmt_file
|
||||||
|
"""
|
||||||
|
self._log(
|
||||||
|
message=message,
|
||||||
|
prefix=prefix,
|
||||||
|
suffix=suffix,
|
||||||
|
level_number=level_number,
|
||||||
|
no_console=no_console,
|
||||||
|
no_file=no_file,
|
||||||
|
no_placeholder=no_placeholder,
|
||||||
|
no_regex=no_regex,
|
||||||
|
no_color=no_color,
|
||||||
|
no_html=no_html,
|
||||||
|
no_link=no_link,
|
||||||
|
no_markdown=no_markdown,
|
||||||
|
no_special_tags=no_special_tags,
|
||||||
|
)
|
@ -1,11 +0,0 @@
|
|||||||
"""
|
|
||||||
日志级别模块
|
|
||||||
Log level module
|
|
||||||
|
|
||||||
"""
|
|
||||||
# encoding: utf-8
|
|
||||||
# python 3.13.5
|
|
||||||
|
|
||||||
from .levels import Logger
|
|
||||||
|
|
||||||
__all__ = ["Logger"]
|
|
@ -1,150 +0,0 @@
|
|||||||
"""
|
|
||||||
日志级别模块
|
|
||||||
Log level module
|
|
||||||
|
|
||||||
"""
|
|
||||||
# encoding: utf-8
|
|
||||||
# python 3.13.5
|
|
||||||
|
|
||||||
from typing import Optional, Any
|
|
||||||
from ..utils.fmt import fmt_file, fmt_message, fmt_console
|
|
||||||
from ..utils.configs import get_config, set_config
|
|
||||||
from ..utils.time import get_asctime
|
|
||||||
import pathlib
|
|
||||||
from pathlib import Path
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
def _get_full_path(file_path, file_name):
|
|
||||||
file_path.mkdir(parents=True, exist_ok=True)
|
|
||||||
return file_path / file_name
|
|
||||||
|
|
||||||
class Logger:
|
|
||||||
def __init__(self):
|
|
||||||
# 检测虚拟环境并确定项目根目录
|
|
||||||
python_path = sys.executable
|
|
||||||
project_root = Path.cwd()
|
|
||||||
|
|
||||||
# 如果在虚拟环境中,向上查找项目根目录
|
|
||||||
if 'venv' in python_path.lower():
|
|
||||||
# 分割路径并查找venv目录
|
|
||||||
path_parts = os.path.normpath(python_path).split(os.sep)
|
|
||||||
if 'venv' in path_parts:
|
|
||||||
venv_index = path_parts.index('venv')
|
|
||||||
project_root = Path(os.sep.join(path_parts[:venv_index]))
|
|
||||||
|
|
||||||
file_path = project_root / get_config("file_path")
|
|
||||||
file_path.mkdir(parents=True, exist_ok=True)
|
|
||||||
if file_path.exists():
|
|
||||||
if not file_path.is_dir():
|
|
||||||
self.warn("日志文件路径不是目录,已自动使用默认目录")
|
|
||||||
set_config("file_path", "./logs")
|
|
||||||
pathlib.Path("./logs").mkdir(parents=True, exist_ok=True)
|
|
||||||
current_file = _get_full_path(file_path, get_config("file_name"))
|
|
||||||
if current_file.exists():
|
|
||||||
from os import rename
|
|
||||||
rename(current_file, _get_full_path(file_path, f"{get_asctime().replace(':', '-')}.log"))
|
|
||||||
self.debug("日志文件已存在,已自动重命名")
|
|
||||||
|
|
||||||
def _log(self, msg, pf, lvn, no_file: bool = False, no_console: bool = False):
|
|
||||||
# 检测虚拟环境并确定项目根目录
|
|
||||||
python_path = sys.executable
|
|
||||||
project_root = Path.cwd()
|
|
||||||
|
|
||||||
# 如果在虚拟环境中,向上查找项目根目录
|
|
||||||
if 'venv' in python_path.lower():
|
|
||||||
# 分割路径并查找venv目录
|
|
||||||
path_parts = os.path.normpath(python_path).split(os.sep)
|
|
||||||
if 'venv' in path_parts:
|
|
||||||
venv_index = path_parts.index('venv')
|
|
||||||
project_root = Path(os.sep.join(path_parts[:venv_index]))
|
|
||||||
|
|
||||||
file_path = project_root / get_config("file_path")
|
|
||||||
file_path.mkdir(parents=True, exist_ok=True)
|
|
||||||
file_name = get_config("file_name")
|
|
||||||
file_encoding = get_config("file_encoding")
|
|
||||||
is_enable_file = get_config("enable_file")
|
|
||||||
is_enable_console = get_config("enable_console")
|
|
||||||
if not no_file and is_enable_file:
|
|
||||||
try:
|
|
||||||
with open(_get_full_path(file_path, file_name), "a", encoding=file_encoding) as f:
|
|
||||||
f.write(fmt_file(lvn, fmt_message(msg, no_placeholder=True, no_process=True), pf))
|
|
||||||
except Exception as e:
|
|
||||||
self.error(f"日志写入失败: {str(e)}", no_file=True)
|
|
||||||
if not no_console and is_enable_console:
|
|
||||||
console_output = fmt_console(lvn, fmt_message(msg, no_placeholder=True), pf)
|
|
||||||
if console_output is not None:
|
|
||||||
print(console_output)
|
|
||||||
return fmt_console(lvn, fmt_message(msg, no_placeholder=True), pf)
|
|
||||||
|
|
||||||
def debug(self, message: Any, prefix: str | None = None, level: int = 0, no_file: bool = False, no_console: bool = False) -> Optional[str]:
|
|
||||||
"""
|
|
||||||
调试日志
|
|
||||||
Debug log
|
|
||||||
:param message: 消息内容 Message content
|
|
||||||
:param prefix: 前缀 Prefix
|
|
||||||
:param level: 日志级别 Log level(0~9)
|
|
||||||
:param no_file: 不写入文件 Do not write to file
|
|
||||||
:param no_console: 不输出到控制台 Do not output to console
|
|
||||||
"""
|
|
||||||
return self._log(message, prefix, level, no_file, no_console)
|
|
||||||
|
|
||||||
def info(self, message: Any, prefix: str | None = None, level: int = 10, no_file: bool = False, no_console: bool = False) -> Optional[str]:
|
|
||||||
"""
|
|
||||||
信息日志
|
|
||||||
Info log
|
|
||||||
:param message: 消息内容 Message content
|
|
||||||
:param prefix: 前缀 Prefix
|
|
||||||
:param level: 日志级别 Log level(10~19)
|
|
||||||
:param no_file: 不写入文件 Do not write to file
|
|
||||||
:param no_console: 不输出到控制台 Do not output to console
|
|
||||||
"""
|
|
||||||
return self._log(message, prefix, level, no_file, no_console)
|
|
||||||
|
|
||||||
def warn(self, message: Any, prefix: str | None = None, level: int = 20, no_file: bool = False, no_console: bool = False) -> Optional[str]:
|
|
||||||
"""
|
|
||||||
警告日志
|
|
||||||
Warn log
|
|
||||||
:param message: 消息内容 Message content
|
|
||||||
:param prefix: 前缀 Prefix
|
|
||||||
:param level: 日志级别 Log level(20~29)
|
|
||||||
:param no_file: 不写入文件 Do not write to file
|
|
||||||
:param no_console: 不输出到控制台 Do not output to console
|
|
||||||
"""
|
|
||||||
return self._log(message, prefix, level, no_file, no_console)
|
|
||||||
|
|
||||||
def error(self, message: Any, prefix: str | None = None, level: int = 30, no_file: bool = False, no_console: bool = False) -> Optional[str]:
|
|
||||||
"""
|
|
||||||
错误日志
|
|
||||||
Error log
|
|
||||||
:param message: 消息内容 Message content
|
|
||||||
:param prefix: 前缀 Prefix
|
|
||||||
:param level: 日志级别 Log level(30~39)
|
|
||||||
:param no_file: 不写入文件 Do not write to file
|
|
||||||
:param no_console: 不输出到控制台 Do not output to console
|
|
||||||
"""
|
|
||||||
return self._log(message, prefix, level, no_file, no_console)
|
|
||||||
|
|
||||||
def critical(self, message: Any, prefix: str | None = None, level: int = 40, no_file: bool = False, no_console: bool = False) -> Optional[str]:
|
|
||||||
"""
|
|
||||||
严重错误日志
|
|
||||||
Critical error log
|
|
||||||
:param message: 消息内容 Message content
|
|
||||||
:param prefix: 前缀 Prefix
|
|
||||||
:param level: 日志级别 Log level(40~49)
|
|
||||||
:param no_file: 不写入文件 Do not write to file
|
|
||||||
:param no_console: 不输出到控制台 Do not output to console
|
|
||||||
"""
|
|
||||||
return self._log(message, prefix, level, no_file, no_console)
|
|
||||||
|
|
||||||
def log(self, message: Any, prefix: str | None = None, level: int = 50, no_file: bool = False, no_console: bool = False) -> Optional[str]:
|
|
||||||
"""
|
|
||||||
自定义日志
|
|
||||||
Custom log
|
|
||||||
:param message: 消息内容 Message content
|
|
||||||
:param prefix: 前缀 Prefix
|
|
||||||
:param level: 日志级别 Log level(50~59...)
|
|
||||||
:param no_file: 不写入文件 Do not write to file
|
|
||||||
:param no_console: 不输出到控制台 Do not output to console
|
|
||||||
"""
|
|
||||||
return self._log(message, prefix, level, no_file, no_console)
|
|
@ -5,7 +5,7 @@ Utility functions
|
|||||||
# encoding = utf-8
|
# encoding = utf-8
|
||||||
# python 3.13.5
|
# python 3.13.5
|
||||||
|
|
||||||
from .configs import get_config, set_config, reset_config, create_backup
|
from .configs import get_config, set_config, reset_config, backup_config, restore_config, init_config
|
||||||
from .time import get_asctime, get_date, get_time, get_weekday, _get_time
|
from .time import get_asctime, get_date, get_time, get_weekday, _get_time
|
||||||
from .formats import fmt_console, fmt_content, fmt_file, fmt_level_list, fmt_level_name_to_number, fmt_level_number_to_name, fmt_placeholder, fmt_regex, add_placeholder, remove_placeholder, get_placeholder
|
from .formats import fmt_console, fmt_content, fmt_file, fmt_level_list, fmt_level_name_to_number, fmt_level_number_to_name, fmt_placeholder, fmt_regex, add_placeholder, remove_placeholder, get_placeholder
|
||||||
from .styles import set_color, set_bg_color, set_style
|
from .styles import set_color, set_bg_color, set_style
|
||||||
@ -15,7 +15,9 @@ __all__ = [
|
|||||||
"get_config",
|
"get_config",
|
||||||
"set_config",
|
"set_config",
|
||||||
"reset_config",
|
"reset_config",
|
||||||
"create_backup",
|
"backup_config",
|
||||||
|
"restore_config",
|
||||||
|
"init_config",
|
||||||
"get_asctime",
|
"get_asctime",
|
||||||
"get_date",
|
"get_date",
|
||||||
"get_time",
|
"get_time",
|
||||||
|
@ -7,166 +7,107 @@ py-logiliteal's config settings, used to set py-logiliteal's global config
|
|||||||
# python 3.13.5
|
# python 3.13.5
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from os import remove
|
from .env import DEFAULT_CONFIG, get_config_path
|
||||||
import shutil
|
import pathlib
|
||||||
import os
|
from typing import Any
|
||||||
from pathlib import Path
|
def init_config(config: dict = DEFAULT_CONFIG, config_path: str = None) -> bool:
|
||||||
from typing import Union, Optional, Tuple
|
|
||||||
from logging import error
|
|
||||||
|
|
||||||
def get_config_path():
|
|
||||||
# 检查环境变量
|
|
||||||
env_config = os.getenv('LOGILITEAL_CONFIG')
|
|
||||||
if env_config and os.path.exists(env_config):
|
|
||||||
return env_config
|
|
||||||
|
|
||||||
# 检查当前工作目录
|
|
||||||
cwd_config = os.path.join(os.getcwd(), 'logger_config.json')
|
|
||||||
if os.path.exists(cwd_config):
|
|
||||||
return cwd_config
|
|
||||||
|
|
||||||
# 检查XDG配置目录
|
|
||||||
xdg_config_dir = os.getenv('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config'))
|
|
||||||
xdg_config_path = os.path.join(xdg_config_dir, 'logiliteal', 'logger_config.json')
|
|
||||||
|
|
||||||
# 创建目录(如果不存在)
|
|
||||||
if not os.path.exists(os.path.dirname(xdg_config_path)):
|
|
||||||
try:
|
|
||||||
os.makedirs(os.path.dirname(xdg_config_path), exist_ok=True)
|
|
||||||
except Exception as e:
|
|
||||||
error(f"创建配置目录失败: {e}")
|
|
||||||
# 回退到项目根目录的配置文件
|
|
||||||
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
|
||||||
fallback_config = os.path.join(project_root, 'logger_config.json')
|
|
||||||
if os.path.exists(fallback_config):
|
|
||||||
return fallback_config
|
|
||||||
else:
|
|
||||||
return xdg_config_path
|
|
||||||
|
|
||||||
return xdg_config_path
|
|
||||||
|
|
||||||
DEFAULT_CONFIG_PATH = get_config_path()
|
|
||||||
|
|
||||||
|
|
||||||
g_config_cache = None
|
|
||||||
g_config_mtime = 0
|
|
||||||
|
|
||||||
def create_backup(config_path: Path) -> Tuple[bool, str]:
|
|
||||||
"""
|
"""
|
||||||
创建配置文件备份
|
初始化配置
|
||||||
:param config_path: 配置文件路径
|
Init config
|
||||||
:param backup_prefix: 备份文件前缀
|
Args:
|
||||||
:return: (是否成功, 备份路径或错误信息)
|
config (dict, optional): 配置字典. Defaults to DEFAULT_CONFIG.
|
||||||
|
config_path (str, optional): 配置文件路径. Defaults to None.
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功初始化配置
|
||||||
"""
|
"""
|
||||||
try:
|
if config_path is None:
|
||||||
if not config_path.exists():
|
config_path = str(get_config_path())
|
||||||
return False, f"配置文件不存在: {config_path}"
|
dump_config = json.dumps(config, indent=4)
|
||||||
backup_path = config_path.parent / f"logger_config_backup.json"
|
with open(config_path, "w") as f:
|
||||||
|
f.write(dump_config)
|
||||||
|
return True
|
||||||
|
|
||||||
if backup_path.exists():
|
def get_config(key: str | None = None) -> Any:
|
||||||
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):
|
|
||||||
"""
|
"""
|
||||||
配置操作异常处理装饰器
|
获取配置
|
||||||
|
Get config
|
||||||
|
Args:
|
||||||
|
key (str | None, optional): 配置键. Defaults to None.
|
||||||
|
Returns:
|
||||||
|
Any: 配置值
|
||||||
"""
|
"""
|
||||||
def wrapper(*args, **kwargs):
|
if not pathlib.Path(str(get_config_path())).exists():
|
||||||
try:
|
init_config()
|
||||||
return func(*args, **kwargs)
|
with open(str(get_config_path()), "r") as f:
|
||||||
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]:
|
|
||||||
"""
|
|
||||||
获取配置信息 Get config info
|
|
||||||
:param select: 配置项名称 Config item name
|
|
||||||
:return: 配置项值 Config item value
|
|
||||||
"""
|
|
||||||
global g_config_cache, g_config_mtime
|
|
||||||
config_path = Path(DEFAULT_CONFIG_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:
|
|
||||||
# 确保目录存在
|
|
||||||
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
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]]:
|
|
||||||
"""
|
|
||||||
设置配置信息 Set config info
|
|
||||||
:param select: 配置项名称 Config item name
|
|
||||||
:param value: 配置项值 Config item value
|
|
||||||
:return: (设置是否成功, 消息) (Set success or not, message)
|
|
||||||
"""
|
|
||||||
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)
|
|
||||||
|
|
||||||
backup_success, backup_info = create_backup(config_path)
|
|
||||||
if not backup_success:
|
|
||||||
return False, f"备份失败: {backup_info}"
|
|
||||||
|
|
||||||
with open(config_path, "r+", encoding="utf-8") as f:
|
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
config[select] = value
|
if key is None:
|
||||||
f.seek(0)
|
return config
|
||||||
|
return config.get(key, None)
|
||||||
|
|
||||||
|
def set_config(key: str, value: Any) -> bool:
|
||||||
|
"""
|
||||||
|
设置配置
|
||||||
|
Set config
|
||||||
|
Args:
|
||||||
|
key (str): 配置键
|
||||||
|
value (Any): 配置值
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功设置配置
|
||||||
|
"""
|
||||||
|
if not pathlib.Path(str(get_config_path())).exists():
|
||||||
|
init_config()
|
||||||
|
with open(str(get_config_path()), "r") as f:
|
||||||
|
config = json.load(f)
|
||||||
|
config[key] = value
|
||||||
|
with open(str(get_config_path()), "w") as f:
|
||||||
json.dump(config, f, indent=4)
|
json.dump(config, f, indent=4)
|
||||||
f.truncate()
|
return config.get(key, None) == value
|
||||||
|
|
||||||
with open(config_path, "r", encoding="utf-8") as f:
|
def backup_config(backup_path: str = None) -> bool:
|
||||||
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)
|
Backup config
|
||||||
|
Args:
|
||||||
|
backup_path (str, optional): 备份文件路径. Defaults to None.
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功备份配置
|
||||||
"""
|
"""
|
||||||
config_path = Path(DEFAULT_CONFIG_PATH)
|
if not pathlib.Path(str(get_config_path())).exists():
|
||||||
|
init_config()
|
||||||
|
if backup_path is None:
|
||||||
|
backup_path = str(get_config_path()) + ".backup"
|
||||||
|
with open(str(get_config_path()), "r") as f:
|
||||||
|
config = json.load(f)
|
||||||
|
backup_path = backup_path or str(get_config_path()) + ".backup"
|
||||||
|
with open(str(backup_path), "w") as f:
|
||||||
|
json.dump(config, f, indent=4)
|
||||||
|
return True
|
||||||
|
|
||||||
if config_path.exists():
|
def restore_config(backup_path: str = None) -> bool:
|
||||||
backup_success, backup_info = create_backup(config_path)
|
"""
|
||||||
if not backup_success:
|
恢复配置
|
||||||
return False, f"备份失败: {backup_info}"
|
Restore config
|
||||||
|
Args:
|
||||||
|
backup_path (str, optional): 备份文件路径. Defaults to None.
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功恢复配置
|
||||||
|
"""
|
||||||
|
if not pathlib.Path(str(get_config_path())).exists():
|
||||||
|
init_config()
|
||||||
|
if backup_path is None:
|
||||||
|
backup_path = str(get_config_path()) + ".backup"
|
||||||
|
with open(str(backup_path), "r") as f:
|
||||||
|
config = json.load(f)
|
||||||
|
with open(str(get_config_path()), "w") as f:
|
||||||
|
json.dump(config, f, indent=4)
|
||||||
|
return True
|
||||||
|
|
||||||
with open(config_path, "w", encoding="utf-8") as f:
|
def reset_config() -> bool:
|
||||||
json.dump(DEFAULT_CONFIG, f, indent=4)
|
"""
|
||||||
|
重置配置
|
||||||
global g_config_cache
|
Reset config
|
||||||
g_config_cache = None
|
Returns:
|
||||||
return True, "配置已重置为默认值"
|
bool: 是否成功重置配置
|
||||||
|
"""
|
||||||
|
init_config(config=DEFAULT_CONFIG)
|
||||||
|
return True
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
"""
|
"""
|
||||||
环境变量或常量与配置文件
|
环境变量或常量与配置文件
|
||||||
|
Environment variables, constants and configuration files
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# encoding = utf-8
|
||||||
|
# python 3.13.5
|
||||||
|
|
||||||
# 默认配置
|
# 默认配置
|
||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
@ -13,7 +17,7 @@ DEFAULT_CONFIG = {
|
|||||||
"enable_file": True,
|
"enable_file": True,
|
||||||
"console_color": True,
|
"console_color": True,
|
||||||
"console_level": "DEBUG",
|
"console_level": "DEBUG",
|
||||||
"console_format": "{set_color(time, await get_config('time_color'))} {levelname} | {prefix}{message}{suffix}",
|
"console_format": "{time} {levelname} | {prefix}{message}{suffix}",
|
||||||
"console_encoding": "utf-8",
|
"console_encoding": "utf-8",
|
||||||
"asctime_format": "%Y-%m-%d %H:%M:%S",
|
"asctime_format": "%Y-%m-%d %H:%M:%S",
|
||||||
"time_format": "%H:%M:%S",
|
"time_format": "%H:%M:%S",
|
||||||
@ -26,12 +30,12 @@ DEFAULT_CONFIG = {
|
|||||||
|
|
||||||
# 占位符
|
# 占位符
|
||||||
_placeholder: dict[str, str | bytes] = {
|
_placeholder: dict[str, str | bytes] = {
|
||||||
"asctime": "{get_asctime()}",
|
"asctime": "{set_color(get_asctime(), get_config('asctime_color') or '#c1ffff')}",
|
||||||
"time": "{get_time()}",
|
"time": "{set_color(get_time(), get_config('time_color') or '#28ffb6')}",
|
||||||
"weekday": "{get_weekday()}",
|
"weekday": "{get_weekday()}",
|
||||||
"date": "{get_date()}",
|
"date": "{get_date()}",
|
||||||
"levelname": "{await fmt_level_number_to_name(level_number)}",
|
"levelname": "{fmt_level_number_to_name(level_number)}",
|
||||||
"level_number": "{await fmt_level_name_to_number(levelname)}",
|
"level_number": "{level_number}",
|
||||||
"message": "{message}",
|
"message": "{message}",
|
||||||
"prefix": "{prefix}",
|
"prefix": "{prefix}",
|
||||||
"suffix": "{suffix}",
|
"suffix": "{suffix}",
|
||||||
@ -46,3 +50,40 @@ _level_name_map: dict[str, int | float] = {
|
|||||||
"CRIT": 40,
|
"CRIT": 40,
|
||||||
"UNKN": -1,
|
"UNKN": -1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_venv_path() -> str:
|
||||||
|
"""
|
||||||
|
获取虚拟环境路径
|
||||||
|
Get virtual environment path
|
||||||
|
"""
|
||||||
|
from os import path
|
||||||
|
from sys import prefix
|
||||||
|
return str(path.dirname(prefix))
|
||||||
|
|
||||||
|
def get_project_path() -> str:
|
||||||
|
"""
|
||||||
|
获取项目路径
|
||||||
|
Get project path
|
||||||
|
"""
|
||||||
|
from os import path
|
||||||
|
from sys import prefix
|
||||||
|
return str(path.dirname(path.dirname(prefix)))
|
||||||
|
|
||||||
|
def get_config_path() -> str:
|
||||||
|
"""
|
||||||
|
获取配置文件路径
|
||||||
|
Get config file path
|
||||||
|
"""
|
||||||
|
from os import path
|
||||||
|
from sys import prefix
|
||||||
|
return str(path.join(path.dirname(path.dirname(prefix)), "config.json"))
|
||||||
|
|
||||||
|
def get_log_path() -> str:
|
||||||
|
"""
|
||||||
|
获取日志文件路径
|
||||||
|
Get log file path
|
||||||
|
"""
|
||||||
|
from os import path
|
||||||
|
from sys import prefix
|
||||||
|
return str(path.join(path.dirname(path.dirname(prefix)), "logs"))
|
||||||
|
|
@ -1,41 +1,54 @@
|
|||||||
"""
|
"""
|
||||||
格式化工具
|
格式化工具
|
||||||
Formatting tools
|
Formatting tools
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# encoding = utf-8
|
||||||
|
# python 3.13.5
|
||||||
|
|
||||||
from .time import get_asctime, get_time, get_weekday, get_date
|
from .time import get_asctime, get_time, get_weekday, get_date
|
||||||
from .styles import set_color
|
from .styles import set_color
|
||||||
from .configs import get_config
|
from .configs import get_config
|
||||||
from .regex import process_color_formatting, process_html_styles, process_links, process_markdown_formats, process_special_tags
|
from .regex import process_color_formatting, process_html_styles, process_links, process_markdown_formats, process_special_tags
|
||||||
from .env import _placeholder, _level_name_map
|
from .env import _placeholder, _level_name_map, DEFAULT_CONFIG
|
||||||
|
from typing import Any
|
||||||
|
import re
|
||||||
|
|
||||||
async def fmt_level_number_to_name(level_number: int | float) -> str:
|
class SafeDict(dict):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self._placeholder = _placeholder
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return super().__getitem__(key).format(**self)
|
||||||
|
|
||||||
|
def fmt_level_number_to_name(level_number: int | float) -> str:
|
||||||
"""
|
"""
|
||||||
格式化日志级别数字为名称
|
格式化日志级别数字为名称
|
||||||
Format log level number to name\n
|
Format log level number to name
|
||||||
Args:
|
Args:
|
||||||
level_number (int | float): 日志级别数字
|
level_number (int | float): 日志级别数字
|
||||||
Returns:
|
Returns:
|
||||||
str: 日志级别名称
|
str: 日志级别名称
|
||||||
"""
|
"""
|
||||||
if not level_number in range(0, 50):
|
if not level_number in range(0, 50):
|
||||||
return _level_name_map.get(-1)
|
return _level_name_map.get(-1, "UNKNOWN")
|
||||||
if 0 <= level_number <= 9:
|
if 0 <= level_number <= 9:
|
||||||
return _level_name_map.get(0)
|
return _level_name_map.get(0, "DEBUG")
|
||||||
elif 10 <= level_number <= 19:
|
elif 10 <= level_number <= 19:
|
||||||
return _level_name_map.get(10)
|
return _level_name_map.get(10, "INFO")
|
||||||
elif 20 <= level_number <= 29:
|
elif 20 <= level_number <= 29:
|
||||||
return _level_name_map.get(20)
|
return _level_name_map.get(20, "WARNING")
|
||||||
elif 30 <= level_number <= 39:
|
elif 30 <= level_number <= 39:
|
||||||
return _level_name_map.get(30)
|
return _level_name_map.get(30, "ERROR")
|
||||||
elif 40 <= level_number <= 49:
|
elif 40 <= level_number <= 49:
|
||||||
return _level_name_map.get(40)
|
return _level_name_map.get(40, "CRITICAL")
|
||||||
return _level_name_map.get(-1)
|
return _level_name_map.get(-1, "UNKNOWN")
|
||||||
|
|
||||||
async def fmt_level_name_to_number(level_name: str) -> int:
|
def fmt_level_name_to_number(level_name: str) -> int:
|
||||||
"""
|
"""
|
||||||
格式化日志级别名称为数字
|
格式化日志级别名称为数字
|
||||||
Format log level name to number\n
|
Format log level name to number
|
||||||
Args:
|
Args:
|
||||||
level_name (str): 日志级别名称
|
level_name (str): 日志级别名称
|
||||||
Returns:
|
Returns:
|
||||||
@ -43,25 +56,24 @@ async def fmt_level_name_to_number(level_name: str) -> int:
|
|||||||
"""
|
"""
|
||||||
return _level_name_map.get(level_name.upper(), -1)
|
return _level_name_map.get(level_name.upper(), -1)
|
||||||
|
|
||||||
async def fmt_level_list(level_number: int | float,
|
def fmt_level_list(level_number: int | float) -> dict:
|
||||||
level_name: str in _level_name_map.keys(),
|
|
||||||
) -> dict:
|
|
||||||
"""
|
"""
|
||||||
格式化日志级别数据字典
|
格式化日志级别数据字典
|
||||||
Format log level data dict\n
|
Format log level data dict
|
||||||
Args:
|
Args:
|
||||||
level_number (int | float): 日志级别数字
|
level_number (int | float): 日志级别数字
|
||||||
level_name (str): 日志级别名称
|
|
||||||
Returns:
|
Returns:
|
||||||
dict: 日志级别数据字典
|
dict: 日志级别数据字典
|
||||||
"""
|
"""
|
||||||
|
level_name = fmt_level_number_to_name(level_number) or "UNKNOWN"
|
||||||
|
level_nickname_config = get_config("level_nickname") or {}
|
||||||
return {
|
return {
|
||||||
"level_number": level_number,
|
"level_number": level_number,
|
||||||
"level_nickname": get_config("level_nickname").get(level_name.upper(), level_name),
|
"level_nickname": level_nickname_config.get(level_name.upper(), level_name),
|
||||||
"level_name": level_name.upper(),
|
"level_name": level_name.upper(),
|
||||||
}
|
}
|
||||||
|
|
||||||
async def get_level_number(level_list: dict) -> int | float:
|
def get_level_number(level_list: dict) -> int | float:
|
||||||
"""
|
"""
|
||||||
获取日志级别数字
|
获取日志级别数字
|
||||||
Get log level number
|
Get log level number
|
||||||
@ -72,7 +84,7 @@ async def get_level_number(level_list: dict) -> int | float:
|
|||||||
"""
|
"""
|
||||||
return level_list.get("level_number")
|
return level_list.get("level_number")
|
||||||
|
|
||||||
async def get_level_name(level_list: dict) -> str:
|
def get_level_name(level_list: dict) -> str:
|
||||||
"""
|
"""
|
||||||
获取日志级别名称
|
获取日志级别名称
|
||||||
Get log level name
|
Get log level name
|
||||||
@ -83,7 +95,7 @@ async def get_level_name(level_list: dict) -> str:
|
|||||||
"""
|
"""
|
||||||
return level_list.get("level_name", "UNKN")
|
return level_list.get("level_name", "UNKN")
|
||||||
|
|
||||||
async def get_level_nickname(level_list: dict) -> str:
|
def get_level_nickname(level_list: dict) -> str:
|
||||||
"""
|
"""
|
||||||
获取日志级别昵称
|
获取日志级别昵称
|
||||||
Get log level nickname
|
Get log level nickname
|
||||||
@ -94,34 +106,54 @@ async def get_level_nickname(level_list: dict) -> str:
|
|||||||
"""
|
"""
|
||||||
return level_list.get("level_nickname", "UNKN")
|
return level_list.get("level_nickname", "UNKN")
|
||||||
|
|
||||||
async def fmt_placeholder(
|
def fmt_placeholder(
|
||||||
message: str = "",
|
message: str = "",
|
||||||
no_placeholder: bool = False,
|
level_number: int = 0,
|
||||||
**kwargs
|
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
格式化占位符
|
格式化占位符
|
||||||
Format placeholder\n
|
Format placeholder
|
||||||
Args:
|
Args:
|
||||||
message (str, optional): 日志消息. Defaults to "".
|
message (str, optional): 日志消息. Defaults to "".
|
||||||
no_placeholder (bool, optional): 不使用占位符. Defaults to False.
|
|
||||||
Returns:
|
Returns:
|
||||||
str: 格式化后的日志消息或原始消息
|
str: 格式化后的日志消息或原始消息
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if no_placeholder:
|
# 创建上下文字典,包含所有可能用到的函数和变量
|
||||||
return message
|
context = {
|
||||||
for key, value in kwargs.items():
|
'level_number': level_number,
|
||||||
if key in _placeholder:
|
'fmt_level_list': fmt_level_list,
|
||||||
message = message.replace(_placeholder[key], str(value))
|
'fmt_level_number_to_name': fmt_level_number_to_name,
|
||||||
else:
|
'get_config': get_config,
|
||||||
message = message.replace(f"{{{key}}}", str(value))
|
'set_color': set_color,
|
||||||
return message
|
'get_asctime': get_asctime,
|
||||||
|
'get_time': get_time,
|
||||||
|
'get_date': get_date,
|
||||||
|
'get_weekday': get_weekday,
|
||||||
|
}
|
||||||
|
|
||||||
async def add_placeholder(key: str, value: str | bytes) -> None:
|
# 替换所有占位符
|
||||||
|
for key, value in _placeholder.items():
|
||||||
|
placeholder = f"{{{key}}}"
|
||||||
|
if placeholder in message:
|
||||||
|
if isinstance(value, str) and '{' in value and '}' in value:
|
||||||
|
try:
|
||||||
|
# 解析并执行占位符中的表达式
|
||||||
|
expr = value.strip('{}')
|
||||||
|
evaluated_value = eval(expr, {}, context)
|
||||||
|
message = message.replace(placeholder, str(evaluated_value))
|
||||||
|
except Exception as e:
|
||||||
|
# 添加详细的错误信息以帮助调试
|
||||||
|
error_msg = f"{{ERROR: {type(e).__name__} - {str(e)} - Expr: {expr}}}"
|
||||||
|
message = message.replace(placeholder, error_msg)
|
||||||
|
else:
|
||||||
|
message = message.replace(placeholder, str(value))
|
||||||
|
|
||||||
|
return message.format(**SafeDict(level_list=fmt_level_list(level_number)))
|
||||||
|
|
||||||
|
def add_placeholder(key: str, value: str | bytes) -> None:
|
||||||
"""
|
"""
|
||||||
添加新的占位符
|
添加新的占位符
|
||||||
Add new placeholder\n
|
Add new placeholder
|
||||||
Args:
|
Args:
|
||||||
key (str): 占位符键
|
key (str): 占位符键
|
||||||
value (str | bytes): 占位符值
|
value (str | bytes): 占位符值
|
||||||
@ -129,10 +161,10 @@ async def add_placeholder(key: str, value: str | bytes) -> None:
|
|||||||
global _placeholder
|
global _placeholder
|
||||||
_placeholder[key] = value
|
_placeholder[key] = value
|
||||||
|
|
||||||
async def get_placeholder(key: str | None = None) -> str | dict[str, str | bytes]:
|
def get_placeholder(key: str | None = None) -> str | dict[str, str | bytes]:
|
||||||
"""
|
"""
|
||||||
获取占位符
|
获取占位符
|
||||||
Get placeholder\n
|
Get placeholder
|
||||||
Args:
|
Args:
|
||||||
key (str | None, optional): 占位符键. Defaults to None.
|
key (str | None, optional): 占位符键. Defaults to None.
|
||||||
Returns:
|
Returns:
|
||||||
@ -142,15 +174,16 @@ async def get_placeholder(key: str | None = None) -> str | dict[str, str | bytes
|
|||||||
return _placeholder
|
return _placeholder
|
||||||
return _placeholder.get(key, "None") if key in _placeholder else "None"
|
return _placeholder.get(key, "None") if key in _placeholder else "None"
|
||||||
|
|
||||||
async def remove_placeholder(key: str) -> bool:
|
def remove_placeholder(key: str) -> bool:
|
||||||
"""
|
"""
|
||||||
删除占位符
|
删除占位符
|
||||||
Remove placeholder\n
|
Remove placeholder
|
||||||
Args:
|
Args:
|
||||||
key (str): 占位符键
|
key (str): 占位符键
|
||||||
Returns:
|
Returns:
|
||||||
bool: 删除成功返回True, 删除失败返回False
|
bool: 删除成功返回True, 删除失败返回False
|
||||||
"""
|
"""
|
||||||
|
global _placeholder
|
||||||
try:
|
try:
|
||||||
if key in _placeholder:
|
if key in _placeholder:
|
||||||
del _placeholder[key]
|
del _placeholder[key]
|
||||||
@ -160,8 +193,8 @@ async def remove_placeholder(key: str) -> bool:
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def fmt_regex(
|
||||||
async def fmt_regex(message: str,
|
message: str,
|
||||||
no_regex: bool = False,
|
no_regex: bool = False,
|
||||||
no_color: bool = False,
|
no_color: bool = False,
|
||||||
no_html: bool = False,
|
no_html: bool = False,
|
||||||
@ -171,7 +204,7 @@ async def fmt_regex(message: str,
|
|||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
格式化正则表达式
|
格式化正则表达式
|
||||||
Format regex\n
|
Format regex
|
||||||
Args:
|
Args:
|
||||||
message (str): 日志消息
|
message (str): 日志消息
|
||||||
Returns:
|
Returns:
|
||||||
@ -180,11 +213,11 @@ async def fmt_regex(message: str,
|
|||||||
if no_regex | (no_color and no_html and no_link and no_markdown and no_special_tags):
|
if no_regex | (no_color and no_html and no_link and no_markdown and no_special_tags):
|
||||||
return message
|
return message
|
||||||
|
|
||||||
return await process_color_formatting(
|
return process_color_formatting(
|
||||||
await process_html_styles(
|
process_html_styles(
|
||||||
await process_links(
|
process_links(
|
||||||
await process_markdown_formats(
|
process_markdown_formats(
|
||||||
await process_special_tags(message, no_process=no_special_tags),
|
process_special_tags(message, no_process=no_special_tags),
|
||||||
no_process=no_markdown,
|
no_process=no_markdown,
|
||||||
),
|
),
|
||||||
no_process=no_link
|
no_process=no_link
|
||||||
@ -194,8 +227,11 @@ async def fmt_regex(message: str,
|
|||||||
no_process=no_color
|
no_process=no_color
|
||||||
)
|
)
|
||||||
|
|
||||||
async def fmt_content(
|
def fmt_content(
|
||||||
message: str = "",
|
message: str = "",
|
||||||
|
prefix: str = "",
|
||||||
|
suffix: str = "",
|
||||||
|
level_number: int = 0,
|
||||||
no_placeholder: bool = False,
|
no_placeholder: bool = False,
|
||||||
no_regex: bool = False,
|
no_regex: bool = False,
|
||||||
no_color: bool = False,
|
no_color: bool = False,
|
||||||
@ -206,40 +242,117 @@ async def fmt_content(
|
|||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
格式化内容
|
格式化内容
|
||||||
Format content\n
|
Format content
|
||||||
Args:
|
Args:
|
||||||
message (str): 日志消息
|
message (str): 日志消息
|
||||||
Returns:
|
Returns:
|
||||||
str: 格式化后的日志消息
|
str: 格式化后的日志消息
|
||||||
"""
|
"""
|
||||||
message = await fmt_placeholder(message, no_placeholder=no_placeholder)
|
if not no_placeholder:
|
||||||
message = await fmt_regex(message, no_regex=no_regex, no_color=no_color, no_html=no_html, no_link=no_link, no_markdown=no_markdown, no_special_tags=no_special_tags)
|
message = fmt_placeholder(message, level_number=level_number)
|
||||||
return message
|
if not no_regex | no_html and not no_link and not no_markdown and not no_special_tags and no_color:
|
||||||
|
message = fmt_regex(message, no_regex=no_regex, no_color=no_color, no_html=no_html, no_link=no_link, no_markdown=no_markdown, no_special_tags=no_special_tags)
|
||||||
|
return f"{prefix}{message}{suffix}\n"
|
||||||
|
|
||||||
async def fmt_console(
|
|
||||||
message: str = "",
|
def fmt_console(
|
||||||
|
message: Any,
|
||||||
|
level_number: int | float,
|
||||||
|
prefix: str = "",
|
||||||
|
suffix: str = "",
|
||||||
no_placeholder: bool = False,
|
no_placeholder: bool = False,
|
||||||
no_regex: bool = False,
|
no_regex: bool = False,
|
||||||
no_color: bool = False,
|
no_color: bool = False,
|
||||||
no_html: bool = False,
|
no_html: bool = False,
|
||||||
no_link: bool = False,
|
|
||||||
no_markdown: bool = False,
|
no_markdown: bool = False,
|
||||||
no_special_tags: bool = False,
|
no_link: bool = False,
|
||||||
|
no_special_tags: bool = False
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
格式化控制台内容
|
格式化控制台日志
|
||||||
Format console content\n
|
Format console log
|
||||||
Args:
|
Args:
|
||||||
message (str): 日志消息
|
message (Any): 日志消息
|
||||||
|
prefix (str, optional): 前缀
|
||||||
|
suffix (str, optional): 后缀
|
||||||
|
level_number (int, optional): 日志级别数字
|
||||||
|
no_placeholder (bool, optional): 是否不处理占位符
|
||||||
|
no_regex (bool, optional): 是否不处理正则
|
||||||
|
no_color (bool, optional): 是否不处理颜色
|
||||||
|
no_html (bool, optional): 是否不处理HTML
|
||||||
|
no_link (bool, optional): 是否不处理链接
|
||||||
|
no_markdown (bool, optional): 是否不处理Markdown
|
||||||
|
no_special_tags (bool, optional): 是否不处理特殊标签
|
||||||
Returns:
|
Returns:
|
||||||
str: 格式化后的日志消息
|
str: 格式化后的控制台日志
|
||||||
"""
|
"""
|
||||||
message = await fmt_placeholder(message, no_placeholder=no_placeholder)
|
# 获取基础配置
|
||||||
message = await fmt_regex(message, no_regex=no_regex, no_color=no_color, no_html=no_html, no_link=no_link, no_markdown=no_markdown, no_special_tags=no_special_tags)
|
fmt_cfg = get_config("console_format") or DEFAULT_CONFIG["console_format"]
|
||||||
return message
|
level_name = fmt_level_number_to_name(level_number).upper()
|
||||||
|
|
||||||
async def fmt_file(
|
# 处理所有占位符和格式化
|
||||||
|
placeholders = {
|
||||||
|
'asctime': get_asctime(),
|
||||||
|
'time': get_time(),
|
||||||
|
'date': get_date(),
|
||||||
|
'weekday': get_weekday(),
|
||||||
|
'levelname': level_name,
|
||||||
|
'level_number': str(level_number),
|
||||||
|
'prefix': prefix,
|
||||||
|
'suffix': suffix,
|
||||||
|
'message': str(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
# 替换格式字符串中的占位符
|
||||||
|
# 初始化颜色配置
|
||||||
|
color_config = {
|
||||||
|
'time_color': get_config('time_color') or DEFAULT_CONFIG['time_color'],
|
||||||
|
'level_colors': get_config('level_color') or DEFAULT_CONFIG['level_color']
|
||||||
|
}
|
||||||
|
|
||||||
|
# 处理时间相关占位符的颜色
|
||||||
|
time_placeholders = ['asctime', 'time', 'date', 'weekday']
|
||||||
|
for placeholder in time_placeholders:
|
||||||
|
if placeholder in placeholders:
|
||||||
|
placeholders[placeholder] = set_color(placeholders[placeholder], color_config['time_color'])
|
||||||
|
|
||||||
|
# 处理日志级别颜色
|
||||||
|
if 'levelname' in placeholders:
|
||||||
|
level_name = placeholders['levelname']
|
||||||
|
level_color = color_config['level_colors'].get(level_name, DEFAULT_CONFIG['level_color']['DEBUG'])
|
||||||
|
placeholders['levelname'] = set_color(level_name, level_color)
|
||||||
|
|
||||||
|
# 替换占位符
|
||||||
|
for key, value in placeholders.items():
|
||||||
|
fmt_cfg = fmt_cfg.replace(f'{{{key}}}', str(value))
|
||||||
|
|
||||||
|
# 应用内容格式化
|
||||||
|
formatted_content = fmt_content(
|
||||||
|
fmt_cfg,
|
||||||
|
no_placeholder=no_placeholder,
|
||||||
|
no_regex=no_regex,
|
||||||
|
no_color=no_color,
|
||||||
|
no_html=no_html,
|
||||||
|
no_markdown=no_markdown,
|
||||||
|
no_link=no_link,
|
||||||
|
no_special_tags=no_special_tags,
|
||||||
|
)
|
||||||
|
# 处理前缀和后缀
|
||||||
|
if prefix:
|
||||||
|
# 清理前缀中的颜色标签
|
||||||
|
clean_prefix = re.sub(r'<#([0-9a-fA-F]{6})>|</>', '', prefix)
|
||||||
|
formatted_content = f"{set_color(clean_prefix, color_config['time_color'])}{formatted_content}"
|
||||||
|
if suffix:
|
||||||
|
# 清理后缀中的颜色标签
|
||||||
|
clean_suffix = re.sub(r'<#([0-9a-fA-F]{6})>|</>', '', suffix)
|
||||||
|
formatted_content = f"{formatted_content}{set_color(clean_suffix, color_config['time_color'])}"
|
||||||
|
return formatted_content
|
||||||
|
|
||||||
|
def fmt_file(
|
||||||
message: str = "",
|
message: str = "",
|
||||||
|
prefix: str = "",
|
||||||
|
suffix: str = "",
|
||||||
|
level_number: int = 0,
|
||||||
no_placeholder: bool = False,
|
no_placeholder: bool = False,
|
||||||
no_regex: bool = True,
|
no_regex: bool = True,
|
||||||
no_color: bool = False,
|
no_color: bool = False,
|
||||||
@ -250,12 +363,33 @@ async def fmt_file(
|
|||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
格式化文件内容
|
格式化文件内容
|
||||||
Format file content\n
|
Format file content
|
||||||
Args:
|
Args:
|
||||||
message (str): 日志消息
|
message (str): 日志消息
|
||||||
Returns:
|
Returns:
|
||||||
str: 格式化后的日志消息
|
str: 格式化后的日志消息
|
||||||
"""
|
"""
|
||||||
message = await fmt_placeholder(message, no_placeholder=no_placeholder)
|
fmt_cfg = get_config("file_format") if get_config("file_format") else "{asctime} {levelname} | {prefix}{message}{suffix}"
|
||||||
message = await fmt_regex(message, no_regex=no_regex, no_color=no_color, no_html=no_html, no_link=no_link, no_markdown=no_markdown, no_special_tags=no_special_tags)
|
fmt_cfg = fmt_content(
|
||||||
return message
|
message=message,
|
||||||
|
prefix=prefix,
|
||||||
|
suffix=suffix,
|
||||||
|
level_number=level_number,
|
||||||
|
no_placeholder=no_placeholder,
|
||||||
|
no_regex=no_regex,
|
||||||
|
no_color=no_color,
|
||||||
|
no_html=no_html,
|
||||||
|
)
|
||||||
|
return fmt_content(
|
||||||
|
message=fmt_cfg,
|
||||||
|
prefix=prefix,
|
||||||
|
suffix=suffix,
|
||||||
|
level_number=level_number,
|
||||||
|
no_placeholder=no_placeholder,
|
||||||
|
no_regex=no_regex,
|
||||||
|
no_color=no_color,
|
||||||
|
no_html=no_html,
|
||||||
|
no_link=no_link,
|
||||||
|
no_markdown=no_markdown,
|
||||||
|
no_special_tags=no_special_tags,
|
||||||
|
)
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from .styles import set_color, set_bg_color
|
from .styles import set_color
|
||||||
|
|
||||||
|
|
||||||
async def process_links(text: str, no_process: bool = False) -> str:
|
def process_links(text: str, no_process: bool = False) -> str:
|
||||||
"""处理链接标签(HTML和Markdown格式)"""
|
"""处理链接标签(HTML和Markdown格式)"""
|
||||||
if no_process:
|
if no_process:
|
||||||
return text
|
return text
|
||||||
@ -40,7 +40,7 @@ async def process_links(text: str, no_process: bool = False) -> str:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
async def process_markdown_formats(text: str, no_process: bool = False) -> str:
|
def process_markdown_formats(text: str, no_process: bool = False) -> str:
|
||||||
"""处理Markdown格式"""
|
"""处理Markdown格式"""
|
||||||
if no_process:
|
if no_process:
|
||||||
return text
|
return text
|
||||||
@ -55,7 +55,7 @@ async def process_markdown_formats(text: str, no_process: bool = False) -> str:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
async def process_html_styles(text: str, no_process: bool = False) -> str:
|
def process_html_styles(text: str, no_process: bool = False) -> str:
|
||||||
"""处理HTML样式标签"""
|
"""处理HTML样式标签"""
|
||||||
if no_process:
|
if no_process:
|
||||||
return text
|
return text
|
||||||
@ -74,7 +74,7 @@ async def process_html_styles(text: str, no_process: bool = False) -> str:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
async def process_special_tags(text: str, no_process: bool = False) -> str:
|
def process_special_tags(text: str, no_process: bool = False) -> str:
|
||||||
"""处理特殊标签(换行、重置、段落)"""
|
"""处理特殊标签(换行、重置、段落)"""
|
||||||
if no_process:
|
if no_process:
|
||||||
return text
|
return text
|
||||||
@ -87,7 +87,7 @@ async def process_special_tags(text: str, no_process: bool = False) -> str:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
async def process_color_formatting(text: str, no_process: bool = False) -> str:
|
def process_color_formatting(text: str, no_process: bool = False) -> str:
|
||||||
"""处理颜色标签"""
|
"""处理颜色标签"""
|
||||||
if no_process:
|
if no_process:
|
||||||
return text
|
return text
|
||||||
|
@ -8,7 +8,7 @@ py-logiliteal's style tools, used to format log output
|
|||||||
|
|
||||||
from typing import Union, Optional
|
from typing import Union, Optional
|
||||||
|
|
||||||
async def _get_hex_to_ansi(hex_color: str | None) -> Union[Optional[str], None]:
|
def _get_hex_to_ansi(hex_color: str | None) -> Union[Optional[str], None]:
|
||||||
"""
|
"""
|
||||||
将16进制颜色值转换为ANSI转义序列
|
将16进制颜色值转换为ANSI转义序列
|
||||||
Convert hex color value to ANSI escape sequence
|
Convert hex color value to ANSI escape sequence
|
||||||
@ -22,7 +22,7 @@ async def _get_hex_to_ansi(hex_color: str | None) -> Union[Optional[str], None]:
|
|||||||
r, g, b = int(hex_color[1:3], 16), int(hex_color[3:5], 16), int(hex_color[5:7], 16)
|
r, g, b = int(hex_color[1:3], 16), int(hex_color[3:5], 16), int(hex_color[5:7], 16)
|
||||||
return f"\033[38;2;{r};{g};{b}m"
|
return f"\033[38;2;{r};{g};{b}m"
|
||||||
|
|
||||||
async def set_color(text: str | None, color: str | None) -> str:
|
def set_color(text: str | None, color: str | None) -> str:
|
||||||
"""
|
"""
|
||||||
设置文本颜色
|
设置文本颜色
|
||||||
Set text color
|
Set text color
|
||||||
@ -34,12 +34,12 @@ async def set_color(text: str | None, color: str | None) -> str:
|
|||||||
return ""
|
return ""
|
||||||
if not color:
|
if not color:
|
||||||
return text
|
return text
|
||||||
ansi = await _get_hex_to_ansi(color)
|
ansi = str(_get_hex_to_ansi(color))
|
||||||
if not ansi:
|
if not ansi:
|
||||||
return text
|
return text
|
||||||
return f"{ansi}{text}\033[0m"
|
return f"{ansi}{text}\033[0m"
|
||||||
|
|
||||||
async def set_bg_color(text: str | None, color: str | None) -> str:
|
def set_bg_color(text: str | None, color: str | None) -> str:
|
||||||
"""
|
"""
|
||||||
设置文本背景颜色
|
设置文本背景颜色
|
||||||
Set text background color
|
Set text background color
|
||||||
@ -51,13 +51,13 @@ async def set_bg_color(text: str | None, color: str | None) -> str:
|
|||||||
return ""
|
return ""
|
||||||
if not color:
|
if not color:
|
||||||
return text
|
return text
|
||||||
ansi = await _get_hex_to_ansi(color)
|
ansi = str(_get_hex_to_ansi(color))
|
||||||
if not ansi:
|
if not ansi:
|
||||||
return text
|
return text
|
||||||
ansi = ansi.replace("38;", "48;")
|
ansi = ansi.replace("38;", "48;")
|
||||||
return f"{ansi}{text}\033[0m"
|
return f"{ansi}{text}\033[0m"
|
||||||
|
|
||||||
async def set_style(
|
def set_style(
|
||||||
text: str | None,
|
text: str | None,
|
||||||
bold: bool = False,
|
bold: bool = False,
|
||||||
italic: bool = False,
|
italic: bool = False,
|
||||||
|
@ -9,43 +9,43 @@ Time utility module, used for time formatting and output, caching time formattin
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from .configs import get_config
|
from .configs import get_config
|
||||||
|
|
||||||
async def get_asctime() -> str:
|
def get_asctime() -> str:
|
||||||
"""
|
"""
|
||||||
获取当前时间(YYYY-MM-DD HH:MM:SS),并缓存格式化结果
|
获取当前时间(YYYY-MM-DD HH:MM:SS),并缓存格式化结果
|
||||||
Get current time(YYYY-MM-DD HH:MM:SS) and cache formatted result
|
Get current time(YYYY-MM-DD HH:MM:SS) and cache formatted result
|
||||||
:return: 格式化后的时间 Formatted time
|
:return: 格式化后的时间 Formatted time
|
||||||
"""
|
"""
|
||||||
return await _get_time(get_config("asctime_format"))
|
return str(_get_time(get_config("asctime_format")))
|
||||||
|
|
||||||
async def get_time() -> str:
|
def get_time() -> str:
|
||||||
"""
|
"""
|
||||||
获取当前时间(HH:MM:SS),并缓存格式化结果
|
获取当前时间(HH:MM:SS),并缓存格式化结果
|
||||||
Get current time(HH:MM:SS) and cache formatted result
|
Get current time(HH:MM:SS) and cache formatted result
|
||||||
:return: 格式化后的时间 Formatted time
|
:return: 格式化后的时间 Formatted time
|
||||||
"""
|
"""
|
||||||
return await _get_time(get_config("time_format"))
|
return str(_get_time(get_config("time_format")))
|
||||||
|
|
||||||
async def get_date() -> str:
|
def get_date() -> str:
|
||||||
"""
|
"""
|
||||||
获取当前日期(YYYY-MM-DD),并缓存格式化结果
|
获取当前日期(YYYY-MM-DD),并缓存格式化结果
|
||||||
Get current date(YYYY-MM-DD) and cache formatted result
|
Get current date(YYYY-MM-DD) and cache formatted result
|
||||||
:return: 格式化后的日期 Formatted date
|
:return: 格式化后的日期 Formatted date
|
||||||
"""
|
"""
|
||||||
return await _get_time(get_config("date_format"))
|
return str(_get_time(get_config("date_format")))
|
||||||
|
|
||||||
async def get_weekday() -> str:
|
def get_weekday() -> str:
|
||||||
"""
|
"""
|
||||||
获取当前日期(星期几),并缓存格式化结果
|
获取当前日期(星期几),并缓存格式化结果
|
||||||
Get current date(weekday) and cache formatted result
|
Get current date(weekday) and cache formatted result
|
||||||
:return: 格式化后的星期几 Formatted weekday
|
:return: 格式化后的星期几 Formatted weekday
|
||||||
"""
|
"""
|
||||||
return await _get_time(get_config("weekday_format"))
|
return str(_get_time(get_config("weekday_format")))
|
||||||
|
|
||||||
async def _get_time(fmt: str) -> str:
|
def _get_time(fmt: str) -> str:
|
||||||
"""
|
"""
|
||||||
获取当前时间(根据指定格式),并缓存格式化结果
|
获取当前时间(根据指定格式),并缓存格式化结果
|
||||||
Get current time(based on specified format) and cache formatted result
|
Get current time(based on specified format) and cache formatted result
|
||||||
:param fmt: 时间格式 Time format
|
:param fmt: 时间格式 Time format
|
||||||
:return: 格式化后的时间 Formatted time
|
:return: 格式化后的时间 Formatted time
|
||||||
"""
|
"""
|
||||||
return datetime.now().strftime(fmt)
|
return str(datetime.now().strftime(fmt))
|
||||||
|
31
test/t-color.py
Normal file
31
test/t-color.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
project_root = Path(__file__).parent.parent
|
||||||
|
sys.path.append(str(project_root))
|
||||||
|
|
||||||
|
from src.logiliteal import logger
|
||||||
|
|
||||||
|
logger.debug("这是一条调试信息")
|
||||||
|
logger.debug("这是**粗体**")
|
||||||
|
logger.debug("这是*斜体*")
|
||||||
|
logger.debug("这是__下划线__")
|
||||||
|
logger.debug("这是~~删除线~~")
|
||||||
|
logger.debug("这是**粗斜体**")
|
||||||
|
logger.debug("这是__粗下划线__")
|
||||||
|
logger.debug("这是~~删除线~~")
|
||||||
|
logger.debug("这是<#ff0000>红色</>")
|
||||||
|
logger.debug("这是<#00ff00>绿色</>")
|
||||||
|
logger.debug("这是<#0000ff>蓝色</>")
|
||||||
|
logger.debug("这是<#ff0000>嵌<#00ff00>套</></>")
|
||||||
|
logger.debug("这是<#ff0000>不完全闭合")
|
||||||
|
logger.debug("这是<#ff0000>样式<c>清理")
|
||||||
|
logger.debug("这是<b>粗体</b>")
|
||||||
|
logger.debug("这是<i>斜体</i>")
|
||||||
|
logger.debug("这是<u>下划线</u>")
|
||||||
|
logger.debug("这是<s>删除线</s>")
|
||||||
|
logger.debug("这是<b><i>粗斜体</i></b>")
|
||||||
|
logger.debug("这是<b><u>粗下划线</u></b>")
|
||||||
|
logger.debug("这是<b><s>粗删除线</s></b>")
|
||||||
|
logger.debug("这是前缀", prefix="<#ff0000>111")
|
||||||
|
logger.debug("这是后缀", suffix="</>")
|
@ -1,53 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
测试颜色优先级处理功能
|
|
||||||
"""
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
project_root = Path(__file__).parent.parent
|
|
||||||
sys.path.append(str(project_root))
|
|
||||||
|
|
||||||
# 添加项目根目录到Python路径
|
|
||||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
|
||||||
|
|
||||||
from src.logiliteal.utils.fmt import fmt_message
|
|
||||||
|
|
||||||
def test_color_priority():
|
|
||||||
"""测试颜色优先级"""
|
|
||||||
print("=== 颜色优先级测试 ===")
|
|
||||||
|
|
||||||
# 测试1: 基本颜色标签
|
|
||||||
test1 = "<#ff0000>红色文本</>"
|
|
||||||
print(f"基本颜色: {test1}")
|
|
||||||
print(f"结果: {fmt_message(test1)}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# 测试2: 嵌套颜色(内层优先级高)
|
|
||||||
test2 = "<#ff0000>外层<#00ff00>内层</>外层</>"
|
|
||||||
print(f"嵌套颜色: {test2}")
|
|
||||||
print(f"结果: {fmt_message(test2)}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# 测试3: 颜色重叠测试(最后边颜色为主)
|
|
||||||
test3 = "<#ff0000>颜色重叠<#0000ff>测<#ff00c2>试</></></>"
|
|
||||||
print(f"颜色重叠: {test3}")
|
|
||||||
print(f"结果: {fmt_message(test3)}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# 测试4: 多层嵌套
|
|
||||||
test4 = "<#ff0000>1<#00ff00>2<#0000ff>3<#ffff00>4</>3</>2</>1</>"
|
|
||||||
print(f"多层嵌套: {test4}")
|
|
||||||
print(f"结果: {fmt_message(test4)}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# 测试5: 未闭合标签(忽略)
|
|
||||||
test5 = "<#ff0000>未闭合标签"
|
|
||||||
print(f"未闭合标签: {test5}")
|
|
||||||
print(f"结果: {fmt_message(test5)}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
test_color_priority()
|
|
@ -1,26 +0,0 @@
|
|||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
project_root = Path(__file__).parent.parent
|
|
||||||
sys.path.append(str(project_root))
|
|
||||||
|
|
||||||
from src.logiliteal.utils.configs import get_config, set_config, reset_config, create_backup
|
|
||||||
|
|
||||||
print(f"\n配置更换测试")
|
|
||||||
set_config("file_level", "DEBUG")
|
|
||||||
fl = get_config("file_level")
|
|
||||||
print(fl)
|
|
||||||
|
|
||||||
set_config("file_level", "INFO")
|
|
||||||
fl = get_config("file_level")
|
|
||||||
print(fl)
|
|
||||||
|
|
||||||
print(f"\n配置重置测试")
|
|
||||||
print(reset_config())
|
|
||||||
|
|
||||||
print(f"\n配置重置后测试")
|
|
||||||
fl = get_config("file_level")
|
|
||||||
print(fl)
|
|
||||||
|
|
||||||
print(f"\n未指定配置读取测试")
|
|
||||||
print(get_config())
|
|
@ -1,34 +0,0 @@
|
|||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
project_root = Path(__file__).parent.parent
|
|
||||||
sys.path.append(str(project_root))
|
|
||||||
|
|
||||||
from src.logiliteal.levels import Logger
|
|
||||||
|
|
||||||
log = Logger()
|
|
||||||
|
|
||||||
log.info("<i>html斜体</i>")
|
|
||||||
log.info("<b>html加粗</b>")
|
|
||||||
log.info("<u>html下划线</u>")
|
|
||||||
log.info("<s>html删除线</s>")
|
|
||||||
log.info("<p>html段落</p>")
|
|
||||||
log.info("<a href=\"https://www.baidu.com\">html超链接</a>")
|
|
||||||
log.info("**Markdown加粗**")
|
|
||||||
log.info("*Markdown斜体*")
|
|
||||||
log.info("`Markdown代码块`")
|
|
||||||
log.info("~~Markdown删除线~~\n")
|
|
||||||
log.info("[md超链接](https://www.baidu.com)")
|
|
||||||
log.info("--测试<i>重复--")
|
|
||||||
log.info("<#ff0000>颜色重叠<#0000ff>测<#ff00c2>试</></></>")
|
|
||||||
log.info("<a href=\"https://www.baidu.com\">超<link href=\"https://www.bing.cn\">链接[重叠](https://www.360.com)</link></a>")
|
|
||||||
|
|
||||||
"""
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
log.info(get_asctime())
|
|
||||||
time.sleep(1)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
log.info("测试结束")
|
|
||||||
break
|
|
||||||
"""
|
|
@ -1,50 +0,0 @@
|
|||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
project_root = Path(__file__).parent.parent
|
|
||||||
sys.path.append(str(project_root))
|
|
||||||
|
|
||||||
from src.logiliteal.utils.fmt import fmt_level, fmt_level_number, fmt_console, fmt_message, fmt_placeholder
|
|
||||||
|
|
||||||
print("日志级别测试")
|
|
||||||
print(fmt_level("DEBUG"))
|
|
||||||
print(fmt_level("INFO"))
|
|
||||||
print(fmt_level("WARN"))
|
|
||||||
print(fmt_level("ERRO"))
|
|
||||||
print(fmt_level("CRIT"))
|
|
||||||
print(fmt_level("UNKN"))
|
|
||||||
|
|
||||||
print("日志级别数字测试")
|
|
||||||
print(fmt_level_number(10))
|
|
||||||
print(fmt_level_number(20))
|
|
||||||
print(fmt_level_number(30))
|
|
||||||
print(fmt_level_number(40))
|
|
||||||
print(fmt_level_number(50))
|
|
||||||
print(fmt_level_number(-1))
|
|
||||||
print(fmt_level_number(100))
|
|
||||||
|
|
||||||
print("消息格式化测试")
|
|
||||||
print(fmt_message("测试消息: {time},\n {asctime}, \n{unknown}"))
|
|
||||||
|
|
||||||
print("控制台格式化测试")
|
|
||||||
print(fmt_console(10, "测试消息"))
|
|
||||||
print("前缀测试")
|
|
||||||
print(fmt_console(35, "测试消息", "可爱猫猫"))
|
|
||||||
|
|
||||||
print("未知日志级别测试")
|
|
||||||
print(fmt_console(-1, "测试消息"))
|
|
||||||
|
|
||||||
|
|
||||||
print("颜色插值测试")
|
|
||||||
print("分段颜色插值")
|
|
||||||
formatted_msg = fmt_message("测试消息<#ff0000>red</>")
|
|
||||||
processed_msg = fmt_placeholder(formatted_msg)
|
|
||||||
print(fmt_console(15, processed_msg))
|
|
||||||
|
|
||||||
print("单段颜色插值")
|
|
||||||
print(fmt_console(15, fmt_placeholder("测试消息<#00ff00>green{asctime}</>", use_date_color=False)))
|
|
||||||
|
|
||||||
print("不完整颜色插值")
|
|
||||||
print(fmt_console(15, fmt_placeholder("测试消息<#00ff00>green{asctime}", use_date_color=False)))
|
|
||||||
print(fmt_console(15, fmt_placeholder("测试消息</>green{asctime}", use_date_color=False)))
|
|
||||||
print(fmt_console(15, fmt_placeholder("测试消息<#00ff000>green{asctime}</>", use_date_color=False)))
|
|
@ -1,15 +0,0 @@
|
|||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
project_root = Path(__file__).parent.parent
|
|
||||||
sys.path.append(str(project_root))
|
|
||||||
|
|
||||||
from src.logiliteal import Logger
|
|
||||||
|
|
||||||
log = Logger()
|
|
||||||
|
|
||||||
log.debug("测试调试日志")
|
|
||||||
log.info("测试信息日志")
|
|
||||||
log.warn("测试警告日志")
|
|
||||||
log.error("测试错误日志")
|
|
||||||
log.critical("测试严重错误日志")
|
|
@ -1,4 +0,0 @@
|
|||||||
from logiliteal import Logger
|
|
||||||
log = Logger()
|
|
||||||
|
|
||||||
log.info("hello world")
|
|
@ -1,37 +0,0 @@
|
|||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
project_root = Path(__file__).parent.parent
|
|
||||||
sys.path.append(str(project_root))
|
|
||||||
|
|
||||||
from src.logiliteal import Logger
|
|
||||||
|
|
||||||
log = Logger()
|
|
||||||
|
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
import random
|
|
||||||
|
|
||||||
# 定义线程测试函数
|
|
||||||
def thread_logger(thread_id: int):
|
|
||||||
"""
|
|
||||||
线程日志测试函数
|
|
||||||
Thread logger test function
|
|
||||||
Args:
|
|
||||||
thread_id (int): 线程ID Thread ID
|
|
||||||
"""
|
|
||||||
for i in range(10):
|
|
||||||
log.info(f"线程{thread_id}的第{i+1}条日志消息", no_file=True)
|
|
||||||
time.sleep(random.uniform(0.01, 0.05))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
threads = []
|
|
||||||
for i in range(10):
|
|
||||||
thread = threading.Thread(target=thread_logger, args=(i,))
|
|
||||||
threads.append(thread)
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
for thread in threads:
|
|
||||||
thread.join()
|
|
||||||
|
|
||||||
log.info("所有线程日志记录完成", no_file=True)
|
|
@ -1,15 +0,0 @@
|
|||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
project_root = Path(__file__).parent.parent
|
|
||||||
sys.path.append(str(project_root))
|
|
||||||
|
|
||||||
from src.logiliteal import Logger
|
|
||||||
|
|
||||||
log = Logger()
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
while i < 20000:
|
|
||||||
log.info(f"**md** | <#ff0000>测试--重--复~~日志~~: {i}")
|
|
||||||
i += 1
|
|
Reference in New Issue
Block a user