Files
model_team_tools/core/plugin/plugin_registry.py
T
2026-07-17 15:27:33 +08:00

127 lines
4.7 KiB
Python

import os
import sys
import time
import logging
import importlib
import threading
from pathlib import Path
from enum import Enum, auto
from PySide6.QtCore import QObject,Signal
from dataclasses import dataclass, field, fields
LOCAL_PLUGINS_PATH = Path("./plugins")
REMOTE_PLUGINS_PATH = Path('Y:/SE/xufeifei/plugins')
logger = logging.getLogger(__name__)
class Event(Enum):
Update = auto()
Install = auto()
Uninstall = auto()
class PluginRegistry(QObject):
"""插件注册中心。"""
plugins_loader_signal = Signal(dict)
update_plugins_card_signal = Signal(dict)
def __init__(self, parent = None) -> None:
super().__init__(parent)
self.plugins = dict()
self.start_discover_local(LOCAL_PLUGINS_PATH, self.plugins)
self.start_discover_remote(REMOTE_PLUGINS_PATH, self.plugins)
def start_discover_local(self,plugins_dir: Path, plugins:dict):
self.thread_local = threading.Thread(target= self.discover_local_event,args=(plugins_dir, plugins,))
self.thread_local.start()
def discover_local_event(self, plugins_dir: Path, plugins:dict):
if not os.path.exists(plugins_dir):
os.mkdir(plugins_dir)
return
sys.path.append(str(plugins_dir))
for tool in Path(plugins_dir).glob("*.pyd"):
tool_name = tool.stem
try:
module = importlib.import_module(tool_name)
obj = module.create_plugin()
name = module.read_plugin_name()
version = module.read_plugin_version()
if name in plugins.keys():
pass
else:
plugins[name] = {}
plugins[name]['obj'] = obj
plugins[name]['local version'] = version
except Exception as e:
logger.error(f"插件{tool_name}注册失败,{str(e)}")
sys.path.remove(str(LOCAL_PLUGINS_PATH))
self.plugins_loader_signal.emit(plugins)
def start_discover_remote(self,plugins_dir: Path, plugins:dict):
self.thread_remote = threading.Thread(target= self.discover_remote_event,args=(plugins_dir, plugins,))
self.thread_remote.start()
def discover_remote_event(self, plugins_dir: Path, plugins:dict):
if not os.path.exists(plugins_dir):
logger.error("服务器链接错误!")
return
#读取服务器工具信息
time.sleep(0.01)
sys.path.append(str(plugins_dir))
for tool in Path(plugins_dir).glob("*.pyd"):
tool_name = tool.stem
try:
module = importlib.import_module(tool_name)
name = module.read_plugin_name()
version = module.read_plugin_version()
description = module.read_plugin_description()
if name in plugins.keys():
pass
else:
print("discover_remote_event")
plugins[name] = {}
plugins[name]["tool_name"] = tool_name
plugins[name]["local version"] = None
plugins[name]["local description"] = None
plugins[name]["remote version"] = version
plugins[name]["remote description"] = description
plugins[name]['remote path'] = plugins_dir
except Exception as e:
logger.error(f"服务器{tool_name}无法加载:{str(e)}")
sys.path.remove(str(plugins_dir))
self.update_plugins_card_signal.emit(plugins)
def start_plugins_event(self, event:Event, name:str):
if event == Event.Install:
local_path = str(LOCAL_PLUGINS_PATH) + '\\' + f"{self.plugins[name]['tool_name']}.pyd"
remote_path = str(REMOTE_PLUGINS_PATH) + '\\' + f"{self.plugins[name]['tool_name']}.pyd"
self.sub_thread = threading.Thread(target= self.install_plugins_event,args=(local_path,remote_path,))
self.sub_thread.start()
pass
def install_plugins_event(self, local_path, remote_path):
try:
total_size = os.path.getsize(remote_path)
copied_size = 0
with open(remote_path, 'rb') as fsrc, open(local_path, 'wb') as fdst:
while True:
buf = fsrc.read(1024*1024)
if not buf:
break
fdst.write(buf)
copied_size += len(buf)
logger.info(f"安装进度: {copied_size/1024/1024:.2f} MB / {total_size/1024/1024:.2f} MB")
time.sleep(0.1)
logger.info(f"{local_path}安装成功!!!")
except Exception as e:
logger.error(f"{remote_path}安装失败{e.args}")
return