mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 15:38:19 +08:00
refactor: reorganize backend module boundaries
This commit is contained in:
@@ -91,8 +91,7 @@ class RSAUtils:
|
||||
)
|
||||
|
||||
return message == decrypted_message
|
||||
except Exception as e:
|
||||
print(f"RSA 密钥验证失败: {e}")
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
@@ -142,7 +141,6 @@ class HashUtils:
|
||||
class CryptoJsUtils:
|
||||
"""兼容 CryptoJS OpenSSL 格式的 AES 加解密工具。"""
|
||||
|
||||
|
||||
@staticmethod
|
||||
def bytes_to_key(data: bytes, salt: bytes, output=48) -> bytes:
|
||||
"""
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +0,0 @@
|
||||
"""中文分词工具。"""
|
||||
|
||||
from jieba_next import cut as jieba_next_cut
|
||||
|
||||
|
||||
def cut(text: str, HMM: bool = True, cut_all: bool = False) -> list[str]:
|
||||
"""
|
||||
使用 jieba-next 执行中文分词,并兼容 jieba.cut 的常用参数名。
|
||||
"""
|
||||
return list(jieba_next_cut(text, HMM=HMM, cut_all=cut_all))
|
||||
@@ -1,118 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import importlib
|
||||
import pkgutil
|
||||
from pathlib import Path
|
||||
from typing import List, Any, Callable
|
||||
|
||||
FilterFuncType = Callable[[str, Any], bool]
|
||||
|
||||
|
||||
def _default_filter(name: str, obj: Any) -> bool:
|
||||
"""
|
||||
默认过滤器
|
||||
"""
|
||||
return True if name and obj else False
|
||||
|
||||
|
||||
class ModuleHelper:
|
||||
"""
|
||||
模块动态加载
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def load(cls, package_path: str, filter_func: FilterFuncType = _default_filter) -> List[Any]:
|
||||
"""
|
||||
导入模块
|
||||
:param package_path: 父包名
|
||||
:param filter_func: 子模块过滤函数,入参为模块名和模块对象,返回True则导入,否则不导入
|
||||
:return: 导入的模块对象列表
|
||||
"""
|
||||
|
||||
submodules: list = []
|
||||
loaded_modules = set()
|
||||
packages = importlib.import_module(package_path)
|
||||
for importer, package_name, _ in pkgutil.iter_modules(packages.__path__):
|
||||
try:
|
||||
if package_name.startswith('_'):
|
||||
continue
|
||||
full_package_name = f'{package_path}.{package_name}'
|
||||
module = importlib.import_module(full_package_name)
|
||||
importlib.reload(module)
|
||||
for name, obj in module.__dict__.items():
|
||||
if name.startswith('_'):
|
||||
continue
|
||||
if isinstance(obj, type) and filter_func(name, obj):
|
||||
if name in loaded_modules:
|
||||
continue
|
||||
loaded_modules.add(name)
|
||||
submodules.append(obj)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
return submodules
|
||||
|
||||
@classmethod
|
||||
def load_with_pre_filter(cls, package_path: str, filter_func: FilterFuncType = _default_filter) -> List[Any]:
|
||||
"""
|
||||
导入子模块
|
||||
:param package_path: 父包名
|
||||
:param filter_func: 子模块过滤函数,入参为模块名和模块对象,返回True则导入,否则不导入
|
||||
:return: 导入的模块对象列表
|
||||
"""
|
||||
|
||||
submodules: list = []
|
||||
packages = importlib.import_module(package_path)
|
||||
|
||||
def reload_module_objects(target_module):
|
||||
"""加载模块并返回对象"""
|
||||
importlib.reload(target_module)
|
||||
# reload后,重新过滤已经重新加载后的模块中的对象
|
||||
return [
|
||||
obj for name, obj in target_module.__dict__.items()
|
||||
if not name.startswith('_') and isinstance(obj, type) and filter_func(name, obj)
|
||||
]
|
||||
|
||||
def reload_sub_modules(parent_module, parent_module_name):
|
||||
"""重新加载一级子模块"""
|
||||
for sub_importer, sub_module_name, sub_is_pkg in pkgutil.walk_packages(parent_module.__path__,
|
||||
parent_module_name + '.'):
|
||||
try:
|
||||
full_sub_module = importlib.import_module(sub_module_name)
|
||||
importlib.reload(full_sub_module)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# 遍历包中的所有子模块
|
||||
for importer, package_name, is_pkg in pkgutil.iter_modules(packages.__path__):
|
||||
if package_name.startswith('_'):
|
||||
continue
|
||||
full_package_name = f'{package_path}.{package_name}'
|
||||
try:
|
||||
module = importlib.import_module(full_package_name)
|
||||
# 预检查模块中的对象
|
||||
candidates = [(name, obj) for name, obj in module.__dict__.items() if
|
||||
not name.startswith('_') and isinstance(obj, type)]
|
||||
# 确定是否需要重新加载
|
||||
if any(filter_func(name, obj) for name, obj in candidates):
|
||||
# 如果子模块是包,重新加载其子模块
|
||||
if is_pkg:
|
||||
reload_sub_modules(module, full_package_name)
|
||||
submodules.extend(reload_module_objects(module))
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
return submodules
|
||||
|
||||
@staticmethod
|
||||
def dynamic_import_all_modules(base_path: Path, package_name: str):
|
||||
"""
|
||||
动态导入目录下所有模块
|
||||
"""
|
||||
modules = []
|
||||
# 遍历文件夹,找到所有模块文件
|
||||
for file in base_path.glob("*.py"):
|
||||
file_name = file.stem
|
||||
if file_name != "__init__":
|
||||
modules.append(file_name)
|
||||
full_module_name = f"{package_name}.{file_name}"
|
||||
importlib.import_module(full_module_name)
|
||||
@@ -1,9 +1,113 @@
|
||||
import ast
|
||||
import dis
|
||||
import importlib
|
||||
import inspect
|
||||
import pkgutil
|
||||
import textwrap
|
||||
from pathlib import Path
|
||||
from types import FunctionType
|
||||
from typing import Any, Callable, get_type_hints
|
||||
from typing import Any, Callable, List, get_type_hints
|
||||
|
||||
|
||||
FilterFuncType = Callable[[str, Any], bool]
|
||||
|
||||
|
||||
def _default_filter(name: str, obj: Any) -> bool:
|
||||
"""接受具有名称和值的动态加载对象。"""
|
||||
return bool(name and obj)
|
||||
|
||||
|
||||
class ModuleHelper:
|
||||
"""发现并动态加载 Python 包中的模块类。"""
|
||||
|
||||
@classmethod
|
||||
def load(
|
||||
cls,
|
||||
package_path: str,
|
||||
filter_func: FilterFuncType = _default_filter,
|
||||
) -> List[Any]:
|
||||
"""加载包的一级模块,并返回通过过滤器的去重类对象。"""
|
||||
submodules: list = []
|
||||
loaded_modules = set()
|
||||
packages = importlib.import_module(package_path)
|
||||
for _, package_name, _ in pkgutil.iter_modules(packages.__path__):
|
||||
try:
|
||||
if package_name.startswith("_"):
|
||||
continue
|
||||
full_package_name = f"{package_path}.{package_name}"
|
||||
module = importlib.import_module(full_package_name)
|
||||
importlib.reload(module)
|
||||
for name, obj in module.__dict__.items():
|
||||
if name.startswith("_"):
|
||||
continue
|
||||
if isinstance(obj, type) and filter_func(name, obj):
|
||||
if name in loaded_modules:
|
||||
continue
|
||||
loaded_modules.add(name)
|
||||
submodules.append(obj)
|
||||
except Exception:
|
||||
continue
|
||||
return submodules
|
||||
|
||||
@classmethod
|
||||
def load_with_pre_filter(
|
||||
cls,
|
||||
package_path: str,
|
||||
filter_func: FilterFuncType = _default_filter,
|
||||
) -> List[Any]:
|
||||
"""预检查类对象后重载所需模块,避免无关模块重复初始化。"""
|
||||
submodules = []
|
||||
packages = importlib.import_module(package_path)
|
||||
|
||||
def reload_module_objects(target_module):
|
||||
"""重载一个模块并返回过滤后的类对象。"""
|
||||
importlib.reload(target_module)
|
||||
return [
|
||||
obj
|
||||
for name, obj in target_module.__dict__.items()
|
||||
if not name.startswith("_")
|
||||
and isinstance(obj, type)
|
||||
and filter_func(name, obj)
|
||||
]
|
||||
|
||||
def reload_sub_modules(parent_module, parent_module_name):
|
||||
"""重载父包下能够成功导入的所有子模块。"""
|
||||
for _, sub_module_name, _ in pkgutil.walk_packages(
|
||||
parent_module.__path__,
|
||||
parent_module_name + ".",
|
||||
):
|
||||
try:
|
||||
full_sub_module = importlib.import_module(sub_module_name)
|
||||
importlib.reload(full_sub_module)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
for _, package_name, is_pkg in pkgutil.iter_modules(packages.__path__):
|
||||
if package_name.startswith("_"):
|
||||
continue
|
||||
full_package_name = f"{package_path}.{package_name}"
|
||||
try:
|
||||
module = importlib.import_module(full_package_name)
|
||||
candidates = [
|
||||
(name, obj)
|
||||
for name, obj in module.__dict__.items()
|
||||
if not name.startswith("_") and isinstance(obj, type)
|
||||
]
|
||||
if any(filter_func(name, obj) for name, obj in candidates):
|
||||
if is_pkg:
|
||||
reload_sub_modules(module, full_package_name)
|
||||
submodules.extend(reload_module_objects(module))
|
||||
except Exception:
|
||||
continue
|
||||
return submodules
|
||||
|
||||
@staticmethod
|
||||
def dynamic_import_all_modules(base_path: Path, package_name: str) -> None:
|
||||
"""动态导入指定目录下的全部一级 Python 模块。"""
|
||||
for file in base_path.glob("*.py"):
|
||||
file_name = file.stem
|
||||
if file_name != "__init__":
|
||||
importlib.import_module(f"{package_name}.{file_name}")
|
||||
|
||||
|
||||
class ObjectUtils:
|
||||
@@ -76,8 +180,7 @@ class ObjectUtils:
|
||||
|
||||
return True
|
||||
return False
|
||||
except Exception as err:
|
||||
print(err)
|
||||
except Exception:
|
||||
# 源代码分析失败时,进行字节码分析
|
||||
code_obj = func.__code__ # type: ignore[attr-defined]
|
||||
instructions = list(dis.get_instructions(code_obj))
|
||||
@@ -125,8 +228,7 @@ class ObjectUtils:
|
||||
global_vars = module.__dict__ if module else globals()
|
||||
try:
|
||||
param_type = eval(param_annotation, global_vars)
|
||||
except Exception as err:
|
||||
print(str(err))
|
||||
except Exception:
|
||||
continue
|
||||
else:
|
||||
param_type = param_annotation
|
||||
@@ -0,0 +1,16 @@
|
||||
"""无业务状态的中文分词与简繁转换工具。"""
|
||||
|
||||
from jieba_next import cut as jieba_next_cut
|
||||
from zhconv_rs import zhconv as _zhconv # pylint: disable=no-name-in-module
|
||||
|
||||
|
||||
def cut(text: str, HMM: bool = True, cut_all: bool = False) -> list[str]:
|
||||
"""
|
||||
使用 jieba-next 执行中文分词,并兼容 jieba.cut 的常用参数名。
|
||||
"""
|
||||
return list(jieba_next_cut(text, HMM=HMM, cut_all=cut_all))
|
||||
|
||||
|
||||
def convert(text: str, target: str) -> str:
|
||||
"""使用 zhconv-rs 执行中文简繁转换,并隔离第三方包的函数名差异。"""
|
||||
return _zhconv(text, target)
|
||||
@@ -1,10 +0,0 @@
|
||||
"""中文简繁转换工具。"""
|
||||
|
||||
from zhconv_rs import zhconv as _zhconv # pylint: disable=no-name-in-module
|
||||
|
||||
|
||||
def convert(text: str, target: str) -> str:
|
||||
"""
|
||||
使用 zhconv-rs 执行中文简繁转换,并隔离第三方包的函数名差异。
|
||||
"""
|
||||
return _zhconv(text, target)
|
||||
Reference in New Issue
Block a user