mirror of
https://github.com/Nanaloveyuki/py-logiliteal.git
synced 2025-09-05 02:56:24 +00:00
🚀 发布了Beta0.1.0测试版
This commit is contained in:
27
src/logiliteal/__init__.py
Normal file
27
src/logiliteal/__init__.py
Normal file
@ -0,0 +1,27 @@
|
||||
"""
|
||||
py-logiliteal - 简易,现代化具有色彩的日志记录器
|
||||
py-logiliteal's config settings, used to set py-logiliteal's global config
|
||||
"""
|
||||
# encoding = utf-8
|
||||
# python 3.13.5
|
||||
|
||||
from .utils import get_config, set_config, reset_config, get_asctime, get_date, get_time, get_weekday, fmt_console, fmt_placeholder, fmt_message, fmt_level_name, set_style
|
||||
from .levels import Logger
|
||||
|
||||
__all__ = [
|
||||
"get_config",
|
||||
"set_config",
|
||||
"reset_config",
|
||||
"get_asctime",
|
||||
"get_date",
|
||||
"get_time",
|
||||
"get_weekday",
|
||||
"fmt_console",
|
||||
"fmt_placeholder",
|
||||
"fmt_message",
|
||||
"fmt_level_name",
|
||||
"set_style",
|
||||
"set_color",
|
||||
"set_bg_color",
|
||||
"Logger" # 日志记录器非实例化
|
||||
]
|
11
src/logiliteal/levels/__init__.py
Normal file
11
src/logiliteal/levels/__init__.py
Normal file
@ -0,0 +1,11 @@
|
||||
"""
|
||||
日志级别模块
|
||||
Log level module
|
||||
|
||||
"""
|
||||
# encoding: utf-8
|
||||
# python 3.13.5
|
||||
|
||||
from .levels import Logger
|
||||
|
||||
__all__ = ["Logger"]
|
128
src/logiliteal/levels/levels.py
Normal file
128
src/logiliteal/levels/levels.py
Normal file
@ -0,0 +1,128 @@
|
||||
"""
|
||||
日志级别模块
|
||||
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
|
||||
|
||||
def _get_full_path(file_path, file_name):
|
||||
file_path.mkdir(parents=True, exist_ok=True)
|
||||
return file_path / file_name
|
||||
|
||||
file_path = pathlib.Path(get_config("file_path"))
|
||||
file_name = get_config("file_name")
|
||||
file_format = get_config("file_format")
|
||||
file_encoding = get_config("file_encoding")
|
||||
is_enable_console = get_config("enable_console")
|
||||
is_enable_file = get_config("enable_file")
|
||||
|
||||
class Logger:
|
||||
def __init__(self):
|
||||
if pathlib.Path(file_path).exists():
|
||||
if not pathlib.Path(file_path).is_dir():
|
||||
self.warn("日志文件路径不是目录,已自动自动使用默认目录")
|
||||
set_config("file_path", "./logs")
|
||||
pathlib.Path("./logs").mkdir(parents=True, exist_ok=True)
|
||||
if _get_full_path(file_path, file_name).exists():
|
||||
from os import rename
|
||||
rename(_get_full_path(file_path, file_name), _get_full_path(file_path, f"{get_asctime().replace(':', '-')}.log"))
|
||||
self.debug("日志文件已存在,已自动重命名")
|
||||
|
||||
@staticmethod
|
||||
def info(message: Any, prefix: str | None = None, level: int = 20) -> Optional[str]:
|
||||
"""
|
||||
信息日志
|
||||
Info log
|
||||
:param message: 消息内容 Message content
|
||||
:param prefix: 前缀 Prefix
|
||||
:param level: 日志级别 Log level(11~20)
|
||||
"""
|
||||
if level < 11 or level > 20:
|
||||
return None
|
||||
if is_enable_file:
|
||||
with open(_get_full_path(file_path, file_name), "a", encoding=file_encoding) as f:
|
||||
f.write(fmt_file(level, fmt_message(message, no_placeholder=True), prefix))
|
||||
if is_enable_console:
|
||||
print(fmt_console(level, fmt_message(message, no_placeholder=True), prefix))
|
||||
return fmt_console(level, fmt_message(message, no_placeholder=True), prefix)
|
||||
|
||||
@staticmethod
|
||||
def debug(message: Any, prefix: str | None = None, level: int = 10) -> Optional[str]:
|
||||
"""
|
||||
调试日志
|
||||
Debug log
|
||||
:param message: 消息内容 Message content
|
||||
:param prefix: 前缀 Prefix
|
||||
:param level: 日志级别 Log level(0~10)
|
||||
"""
|
||||
if level < 0 or level > 10:
|
||||
return None
|
||||
if is_enable_file:
|
||||
with open(_get_full_path(file_path, file_name), "a", encoding=file_encoding) as f:
|
||||
f.write(fmt_file(level, fmt_message(message, no_placeholder=True), prefix))
|
||||
if is_enable_console:
|
||||
print(fmt_console(level, fmt_message(message, no_placeholder=True), prefix))
|
||||
return fmt_console(level, fmt_message(message, no_placeholder=True), prefix)
|
||||
|
||||
@staticmethod
|
||||
def warn(message: Any, prefix: str | None = None, level: int = 31) -> Optional[str]:
|
||||
"""
|
||||
警告日志
|
||||
Warn log
|
||||
:param message: 消息内容 Message content
|
||||
:param prefix: 前缀 Prefix
|
||||
:param level: 日志级别 Log level(31~40)
|
||||
"""
|
||||
if level < 30 or level > 40:
|
||||
return None
|
||||
if is_enable_file:
|
||||
with open(_get_full_path(file_path, file_name), "a", encoding=file_encoding) as f:
|
||||
f.write(fmt_file(level, fmt_message(message, no_placeholder=True), prefix))
|
||||
if is_enable_console:
|
||||
print(fmt_console(level, fmt_message(message, no_placeholder=True), prefix))
|
||||
return fmt_console(level, fmt_message(message, no_placeholder=True), prefix)
|
||||
|
||||
@staticmethod
|
||||
def error(message: Any, prefix: str | None = None, level: int = 41) -> Optional[str]:
|
||||
"""
|
||||
错误日志
|
||||
Error log
|
||||
:param message: 消息内容 Message content
|
||||
:param prefix: 前缀 Prefix
|
||||
:param level: 日志级别 Log level(41~50)
|
||||
"""
|
||||
if level < 40 or level > 50:
|
||||
return None
|
||||
if is_enable_file:
|
||||
with open(_get_full_path(file_path, file_name), "a", encoding=file_encoding) as f:
|
||||
f.write(fmt_file(level, fmt_message(message, no_placeholder=True), prefix))
|
||||
if is_enable_console:
|
||||
print(fmt_console(level, fmt_message(message, no_placeholder=True), prefix))
|
||||
return fmt_console(level, fmt_message(message, no_placeholder=True), prefix)
|
||||
|
||||
@staticmethod
|
||||
def critical(message: Any, prefix: str | None = None, level: int = 51) -> Optional[str]:
|
||||
"""
|
||||
严重错误日志
|
||||
Critical error log
|
||||
:param message: 消息内容 Message content
|
||||
:param prefix: 前缀 Prefix
|
||||
:param level: 日志级别 Log level(51~60)
|
||||
"""
|
||||
if level < 50 or level > 60:
|
||||
return None
|
||||
if is_enable_file:
|
||||
with open(_get_full_path(file_path, file_name), "a", encoding=file_encoding) as f:
|
||||
f.write(fmt_file(level, fmt_message(message, no_placeholder=True), prefix))
|
||||
if is_enable_console:
|
||||
print(fmt_console(level, fmt_message(message, no_placeholder=True), prefix))
|
||||
return fmt_console(level, fmt_message(message, no_placeholder=True), prefix)
|
||||
|
||||
|
28
src/logiliteal/utils/__init__.py
Normal file
28
src/logiliteal/utils/__init__.py
Normal file
@ -0,0 +1,28 @@
|
||||
"""
|
||||
工具函数
|
||||
Utility functions
|
||||
"""
|
||||
# encoding = utf-8
|
||||
# python 3.13.5
|
||||
|
||||
from .configs import get_config, set_config, reset_config
|
||||
from .time import get_asctime, get_date, get_time, get_weekday
|
||||
from .fmt import fmt_console, fmt_placeholder, fmt_message, fmt_level_name
|
||||
from .styles import set_color, set_bg_color, set_style
|
||||
|
||||
__all__ = [
|
||||
"get_config",
|
||||
"set_config",
|
||||
"reset_config",
|
||||
"get_asctime",
|
||||
"get_date",
|
||||
"get_time",
|
||||
"get_weekday",
|
||||
"fmt_console",
|
||||
"fmt_placeholder",
|
||||
"fmt_message",
|
||||
"fmt_level_name",
|
||||
"set_color",
|
||||
"set_bg_color",
|
||||
"set_style"
|
||||
]
|
138
src/logiliteal/utils/configs.py
Normal file
138
src/logiliteal/utils/configs.py
Normal file
@ -0,0 +1,138 @@
|
||||
"""
|
||||
py-logiliteal的配置设置,用于设置py-logiliteal的全局配置
|
||||
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"
|
||||
DEFAULT_CONFIG = {
|
||||
"file_level": "DEBUG",
|
||||
"file_name": "latest.log",
|
||||
"file_path": "./logs",
|
||||
"file_format": "{asctime} {levelname} | {prefix}{message}",
|
||||
"file_encoding": "utf-8",
|
||||
"enable_console": True,
|
||||
"enable_file": True,
|
||||
"console_color": True,
|
||||
"console_level": "INFO",
|
||||
"console_format": "{asctime} {levelname} | {prefix}{message}",
|
||||
"console_prefix": "Auto",
|
||||
"console_encoding": "utf-8",
|
||||
"date_format": "%Y-%m-%d %H:%M:%S",
|
||||
"level_name": {"DEBUG": "DEBUG", "INFO": "INFO", "WARN": "WARN", "ERRO": "ERRO", "CRIT": "CRIT"},
|
||||
"level_color": {"DEBUG": "#c1d5ff", "INFO": "#c1ffff", "WARN": "#fff600", "ERRO": "#ffa000", "CRIT": "#ff8181"},
|
||||
}
|
||||
|
||||
from typing import Union, Optional
|
||||
from logging import error, info
|
||||
import json
|
||||
|
||||
def get_config(select: str = None) -> Union[dict, str, bool, int, None]:
|
||||
"""
|
||||
获取配置信息 Get config info
|
||||
: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
|
||||
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
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)
|
||||
"""
|
||||
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}' 设置成功"
|
||||
|
||||
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 Path(backup_path).exists():
|
||||
shutil.move(backup_path, DEFAULT_CONFIG_PATH)
|
||||
return False, f"设置失败,已恢复备份: {str(e)}"
|
||||
return False, f"设置配置文件失败: {str(e)}"
|
||||
|
||||
@staticmethod
|
||||
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, "配置文件不存在,已创建默认配置"
|
||||
|
||||
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)}"
|
196
src/logiliteal/utils/fmt.py
Normal file
196
src/logiliteal/utils/fmt.py
Normal file
@ -0,0 +1,196 @@
|
||||
"""
|
||||
py-logiliteal的格式化工具,用于格式化日志输出
|
||||
py-logiliteal's formatter, used to format log output
|
||||
|
||||
"""
|
||||
# encoding = utf-8
|
||||
# python 3.13.5
|
||||
|
||||
from .configs import get_config
|
||||
from typing import Any, Optional, Union
|
||||
from .time import get_asctime, get_time, get_weekday, get_date
|
||||
from .styles import set_color, set_bg_color
|
||||
import re
|
||||
|
||||
def fmt_level(level: str) -> int:
|
||||
"""
|
||||
格式化日志级别
|
||||
Format log level
|
||||
:param level: 日志级别 Log level
|
||||
:return: 格式化后的日志级别 Formatted log level
|
||||
"""
|
||||
level_map = {
|
||||
"DEBUG": 10,
|
||||
"INFO": 20,
|
||||
"WARN": 30,
|
||||
"ERRO": 40,
|
||||
"CRIT": 50,
|
||||
}
|
||||
if level == "UNKN":
|
||||
return -1
|
||||
return level_map.get(level.upper(), 0)
|
||||
|
||||
def fmt_level_number(level: int) -> str:
|
||||
"""
|
||||
格式化日志级别数字
|
||||
Format log level number
|
||||
:param level: 日志级别数字 Log level number
|
||||
:return: 格式化后的日志级别 Formatted log level
|
||||
"""
|
||||
if level <= 10 and level >= 0:
|
||||
return "DEBUG"
|
||||
elif level <= 20 and level > 10:
|
||||
return "INFO"
|
||||
elif level <= 30 and level > 20:
|
||||
return "WARN"
|
||||
elif level <= 40 and level > 30:
|
||||
return "ERRO"
|
||||
elif level <= 50 and level > 40:
|
||||
return "CRIT"
|
||||
else:
|
||||
return "UNKN"
|
||||
|
||||
def fmt_placeholder(message: Any, use_date_color: bool = True) -> str:
|
||||
"""
|
||||
格式化占位符
|
||||
Format placeholder
|
||||
:param message: 消息内容 Message content
|
||||
:return: 格式化后的消息 Formatted message
|
||||
"""
|
||||
class SafeDict(dict):
|
||||
def __missing__(self, key):
|
||||
return f'{{{key}}}'
|
||||
|
||||
if not isinstance(message, str):
|
||||
message = str(message)
|
||||
if use_date_color:
|
||||
message = message.format_map(SafeDict(
|
||||
asctime = set_color(get_asctime(),"#28ffb6"),
|
||||
time = set_color(get_time(),"#28ffb6"),
|
||||
weekday = set_color(get_weekday(),"#28ffb6"),
|
||||
date = set_color(get_date(),"#28ffb6")
|
||||
))
|
||||
else:
|
||||
message = message.format_map(SafeDict(
|
||||
asctime = get_asctime(),
|
||||
time = get_time(),
|
||||
weekday = get_weekday(),
|
||||
date = get_date(),
|
||||
))
|
||||
return message
|
||||
|
||||
def fmt_message(message: Any, no_placeholder: bool = False, no_color: bool = False) -> str:
|
||||
"""
|
||||
格式化消息内容
|
||||
Format message content
|
||||
:param message: 消息内容 Message content
|
||||
:return: 格式化后的消息 Formatted message
|
||||
"""
|
||||
|
||||
def process_color_tags(msg: str) -> str:
|
||||
stack = []
|
||||
result = []
|
||||
current_content = []
|
||||
last_end = 0
|
||||
pattern = re.compile(r'(<#([0-9a-fA-F]{6})>|</>)')
|
||||
|
||||
for match in pattern.finditer(msg):
|
||||
text_between = msg[last_end:match.start()]
|
||||
if stack:
|
||||
current_content.append(text_between)
|
||||
else:
|
||||
result.append(text_between)
|
||||
|
||||
last_end = match.end()
|
||||
tag = match.group(1)
|
||||
|
||||
if tag.startswith('<#'):
|
||||
color_code = match.group(2)
|
||||
stack.append(color_code)
|
||||
else:
|
||||
if stack:
|
||||
color = stack.pop()
|
||||
colored_content = set_color(''.join(current_content), f'#{color}')
|
||||
result.append(colored_content)
|
||||
current_content = []
|
||||
else:
|
||||
result.append(tag)
|
||||
|
||||
remaining_text = msg[last_end:]
|
||||
if stack:
|
||||
current_content.append(remaining_text)
|
||||
else:
|
||||
result.append(remaining_text)
|
||||
|
||||
for color in reversed(stack):
|
||||
result.append(f'<#{color}>')
|
||||
result.append(''.join(current_content))
|
||||
current_content = []
|
||||
|
||||
return ''.join(result)
|
||||
if no_color:
|
||||
processed_message = str(message)
|
||||
else:
|
||||
processed_message = process_color_tags(str(message))
|
||||
if no_placeholder:
|
||||
return processed_message
|
||||
else:
|
||||
return process_color_tags(fmt_placeholder(processed_message)) if not no_color else fmt_placeholder(processed_message)
|
||||
|
||||
def fmt_level_name(level_name: str) -> str:
|
||||
if get_config("console_color") != True:
|
||||
return level_name
|
||||
level_name_nick_map = get_config("level_name")
|
||||
|
||||
if level_name in level_name_nick_map:
|
||||
_lnn = level_name_nick_map[level_name]
|
||||
level_color_map = get_config("level_color")
|
||||
|
||||
if level_name in level_color_map:
|
||||
if level_name == "DEBUG":
|
||||
return set_bg_color(set_color(_lnn, level_color_map[level_name]), "#34495e")
|
||||
return set_color(_lnn, level_color_map[level_name])
|
||||
return set_color(_lnn)
|
||||
return "UNKN"
|
||||
|
||||
def fmt_console(level: int, message: Any, prefix: str | None = None) -> Optional[str]:
|
||||
"""
|
||||
格式化控制台输出
|
||||
Format console output
|
||||
:param level: 日志级别 Log level
|
||||
:param message: 消息内容 Message content
|
||||
:return: 格式化后的消息 Formatted message
|
||||
"""
|
||||
cl = get_config("console_level")
|
||||
fmt = get_config("console_format")
|
||||
if fmt_level(cl) > level:
|
||||
return None
|
||||
if prefix is None:
|
||||
prefix = ""
|
||||
fmt = fmt_placeholder(fmt)
|
||||
return fmt.format(
|
||||
levelname = fmt_level_name(fmt_level_number(level)),
|
||||
prefix = fmt_message(prefix, no_placeholder=True),
|
||||
message = fmt_message(message, no_placeholder=True)
|
||||
)
|
||||
|
||||
def fmt_file(level: int, message: Any, prefix: str | None = None) -> Optional[str]:
|
||||
"""
|
||||
格式化文件输出
|
||||
Format file output
|
||||
:param level: 日志级别 Log level
|
||||
:param message: 消息内容 Message content
|
||||
:return: 格式化后的消息 Formatted message
|
||||
"""
|
||||
fl = get_config("file_level")
|
||||
fmt = get_config("file_format")
|
||||
if fmt_level(fl) > level:
|
||||
return None
|
||||
if prefix is None:
|
||||
prefix = ""
|
||||
fmt = fmt_placeholder(fmt, use_date_color=False)
|
||||
return f"{fmt.format(
|
||||
levelname = fmt_level_number(level),
|
||||
prefix = fmt_message(prefix, no_placeholder=True, no_color=True),
|
||||
message = fmt_message(message, no_placeholder=True, no_color=True)
|
||||
)}\n"
|
68
src/logiliteal/utils/styles.py
Normal file
68
src/logiliteal/utils/styles.py
Normal file
@ -0,0 +1,68 @@
|
||||
"""
|
||||
py-logiliteal的样式工具,用于格式化日志输出
|
||||
py-logiliteal's style tools, used to format log output
|
||||
|
||||
"""
|
||||
# encoding = utf-8
|
||||
# python 3.13.5
|
||||
|
||||
from typing import Union, Optional
|
||||
|
||||
def _get_hex_to_ansi(hex_color: str) -> Union[Optional[str], None]:
|
||||
"""
|
||||
将16进制颜色值转换为ANSI转义序列
|
||||
Convert hex color value to ANSI escape sequence
|
||||
:param hex_color: 16进制颜色值 Hex color value
|
||||
:return: ANSI转义序列 ANSI escape sequence
|
||||
"""
|
||||
if not hex_color.startswith("#"):
|
||||
return None
|
||||
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"
|
||||
|
||||
def set_color(text: str, color: str) -> str:
|
||||
"""
|
||||
设置文本颜色
|
||||
Set text color
|
||||
:param text: 文本内容 Text content
|
||||
:param color: 颜色值 Color value
|
||||
:return: 格式化后的文本 Formatted text
|
||||
"""
|
||||
ansi = _get_hex_to_ansi(color)
|
||||
if not ansi:
|
||||
return text
|
||||
return f"{ansi}{text}\033[0m"
|
||||
|
||||
def set_bg_color(text: str, color: str) -> str:
|
||||
"""
|
||||
设置文本背景颜色
|
||||
Set text background color
|
||||
:param text: 文本内容 Text content
|
||||
:param color: 颜色值 Color value
|
||||
:return: 格式化后的文本 Formatted text
|
||||
"""
|
||||
ansi = _get_hex_to_ansi(color)
|
||||
if not ansi:
|
||||
return text
|
||||
# 将前景色ANSI代码转换为背景色代码 (38→48)
|
||||
ansi = ansi.replace("38;", "48;")
|
||||
return f"{ansi}{text}\033[0m"
|
||||
|
||||
def set_style(text: str, bold: bool = False, underline: bool = False, reverse: bool = False) -> str:
|
||||
"""
|
||||
设置文本样式
|
||||
Set text style
|
||||
:param text: 文本内容 Text content
|
||||
:param bold: 是否加粗 Is bold
|
||||
:param underline: 是否下划线 Is underline
|
||||
:param reverse: 是否反相 Is reverse
|
||||
:return: 格式化后的文本 Formatted text
|
||||
"""
|
||||
ansi = ""
|
||||
if bold:
|
||||
ansi += "\033[1m"
|
||||
if underline:
|
||||
ansi += "\033[4m"
|
||||
if reverse:
|
||||
ansi += "\033[7m"
|
||||
return f"{ansi}{text}\033[0m"
|
64
src/logiliteal/utils/time.py
Normal file
64
src/logiliteal/utils/time.py
Normal file
@ -0,0 +1,64 @@
|
||||
"""
|
||||
时间工具模块,用于时间格式化和输出,缓存时间格式化结果
|
||||
Time utility module, used for time formatting and output, caching time formatting results
|
||||
|
||||
"""
|
||||
# encoding = utf-8
|
||||
# python 3.13.5
|
||||
|
||||
from datetime import datetime
|
||||
from .configs import get_config
|
||||
|
||||
cache_time: str = ""
|
||||
cache_asctime: str = ""
|
||||
cache_date: str = ""
|
||||
cache_weekday: str = ""
|
||||
|
||||
def get_asctime() -> str:
|
||||
"""
|
||||
获取当前时间(YYYY-MM-DD HH:MM:SS),并缓存格式化结果
|
||||
Get current time(YYYY-MM-DD HH:MM:SS) and cache formatted result
|
||||
:return: 格式化后的时间 Formatted time
|
||||
"""
|
||||
global cache_asctime
|
||||
if cache_asctime:
|
||||
return cache_asctime
|
||||
cache_asctime = datetime.now().strftime(get_config("date_format"))
|
||||
return cache_asctime
|
||||
|
||||
def get_time() -> str:
|
||||
"""
|
||||
获取当前时间(HH:MM:SS),并缓存格式化结果
|
||||
Get current time(HH:MM:SS) and cache formatted result
|
||||
:return: 格式化后的时间 Formatted time
|
||||
"""
|
||||
global cache_time
|
||||
if cache_time:
|
||||
return cache_time
|
||||
cache_time = datetime.now().strftime("%H:%M:%S")
|
||||
return cache_time
|
||||
|
||||
def get_date() -> str:
|
||||
"""
|
||||
获取当前日期(YYYY-MM-DD),并缓存格式化结果
|
||||
获取当前日期(星期几),并缓存格式化结果
|
||||
Get current date(YYYY-MM-DD) and cache formatted result
|
||||
:return: 格式化后的日期 Formatted date
|
||||
"""
|
||||
global cache_date
|
||||
if cache_date:
|
||||
return cache_date
|
||||
cache_date = datetime.now().strftime("%Y-%m-%d")
|
||||
return cache_date
|
||||
|
||||
def get_weekday() -> str:
|
||||
"""
|
||||
获取当前日期(星期几),并缓存格式化结果
|
||||
Get current date(weekday) and cache formatted result
|
||||
:return: 格式化后的星期几 Formatted weekday
|
||||
"""
|
||||
global cache_weekday
|
||||
if cache_weekday:
|
||||
return cache_weekday
|
||||
cache_weekday = datetime.now().strftime("%A")
|
||||
return cache_weekday
|
Reference in New Issue
Block a user