feat: thread manager

This commit is contained in:
RedDeadDepresso
2024-07-25 01:03:06 +01:00
parent dfa783a699
commit 758d77fe4b
8 changed files with 84 additions and 82 deletions

View File

@@ -19,12 +19,23 @@ class Logger:
# logger box signal is used to output log to logger box
self.logs = ""
self.logger_signal = signalBus.loggerSignal
self.logger = logging.getLogger("BAAS_Logger")
formatter = logging.Formatter("%(levelname)8s |%(asctime)20s | %(message)s ")
self.logger = logging.getLogger("KAFFIO_Logger")
formatter = logging.Formatter("%(levelname)8s |%(category)s | %(message)s ")
handler1 = logging.StreamHandler(stream=sys.stdout)
handler1.setFormatter(formatter)
self.logger.setLevel(logging.INFO)
self.logger.addHandler(handler1)
self.text = ['INFO', 'SUCCESS', 'ERROR', 'SKIPPED', 'REPLACED', 'RENAMED', 'REMOVED']
# Status Text: INFO, SUCCESS, ERROR, SKIPPED, REPLACED, RENAMED, REMOVED
self.status = ['    INFO', '  SUCCESS', '   ERROR',
' SKIPPED', ' REPLACED', ' RENAMED', ' REMOVED']
# Status Color: Blue, Red, Green, Orange,
self.statusColor = ['#2d8cf0', '#ed3f14', '#f90', '#f90', '#f90', '#f90', '#00c12b']
# Status HTML: <b style="color:$color">status</b>
self.statusHtml = [
f'<b style="color:{_color};">{status}</b>'
for _color, status in zip(self.statusColor, self.status)]
def __out__(self, category: str, message: str, level: int = 1, raw_print=False) -> None:
"""
@@ -41,30 +52,34 @@ class Logger:
while len(logging.root.handlers) > 0:
logging.root.handlers.pop()
# Status Text: INFO, SUCCESS, ERROR, SKIPPED, REPLACED, RENAMED, REMOVED
status = ['&nbsp;&nbsp;&nbsp;&nbsp;INFO', '&nbsp;&nbsp;SUCCESS', '&nbsp;&nbsp;&nbsp;ERROR',
'&nbsp;SKIPPED', '&nbsp;REPLACED', '&nbsp;RENAMED', '&nbsp;REMOVED']
# Status Color: Blue, Red, Green, Orange,
statusColor = ['#2d8cf0', '#ed3f14', '#f90', '#f90', '#f90', '#f90', '#00c12b']
# Status HTML: <b style="color:$color">status</b>
statusHtml = [
f'<b style="color:{_color};">{status}</b>'
for _color, status in zip(statusColor, status)]
# If logger box is not None, output log to logger box
# else output log to console
if self.logger_signal is not None:
if self.logger_signal is not None:
message = message.replace('\n', '<br>').replace(' ', '&nbsp;')
adding = (f'''
<div style="font-family: Consolas, monospace;color:{statusColor[level - 1]};">
{statusHtml[level - 1]} | {category} | {message}
<div style="font-family: Consolas, monospace;color:{self.statusColor[level - 1]};">
{self.statusHtml[level - 1]} | {category} | {message}
</div>
''')
self.logs += adding
self.logger_signal.emit(adding)
else:
print(f'{statusHtml[level - 1]} | {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} | {message}')
print(f'{self.statusHtml[level - 1]} | {category} | {message}')
def colorize(self, line):
adding = line
for i, s in enumerate(self.text):
if s in line:
adding = (f'''
<div style="font-family: Consolas, monospace;color:{self.statusColor[i]};">
{line}
</div>
''')
break
self.logs += adding
self.logger_signal.emit(adding)
def info(self, category: str, message: str) -> None:
"""
@@ -120,7 +135,7 @@ class Logger:
Output warn log
"""
self.__out__(category, message, 6)
self.__out__(category, message, 7)
def line(self) -> None:
"""

View File

@@ -0,0 +1,41 @@
import os
import subprocess
import threading
from app.common.signal_bus import signalBus
from app.common.logger import logger
class ThreadManager:
def __init__(self):
super().__init__()
self._script = None
def start(self):
if self._script is not None:
self.stop()
else:
args = []
if os.path.exists("script.exe"):
args = ["script.exe"]
elif os.path.exists("script.py"):
args = ["python", "script.py"]
self._script = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
threading.Thread(target=self.readOutput).start()
def readOutput(self):
while self._script is not None:
line = self._script.stdout.readline().decode('utf-8')
if not line:
signalBus.stopSignal.emit()
else:
logger.colorize(line)
def stop(self):
self._script.terminate()
self._script = None
threadManager = ThreadManager()
signalBus.startSignal.connect(threadManager.start)
signalBus.stopSignal.connect(threadManager.stop)

View File

@@ -37,6 +37,7 @@ class NavigationActionButtons(QWidget):
def __connectSignalToSlot(self):
self.selectAllButton.clicked.connect(self.onSelectAllClicked)
self.clearAllButton.clicked.connect(self.onClearAllClicked)
self.startButton.clicked.connect(self.onStartClicked)
signalBus.startSignal.connect(lambda: self.startButton.setText("Stop"))
signalBus.stopSignal.connect(lambda: self.startButton.setText("Start"))

View File

@@ -4,7 +4,8 @@ class Handler:
def loadConfig(self, config):
self.gamePath = config.get("Core", "GamePath")
self.config = config.get(str(self))
key = str(self).replace(" ", "")
self.config = config.get(key)
def handle(self, request):
pass

View File

@@ -19,6 +19,9 @@ class Request:
logger.info("SCRIPT", "Validating config")
self.validateGamepath()
self._handlers = [x for x in self.handlers if self.isTaskEnabled(x)]
if not self._handlers:
logger.error("SCRIPT", "No task enabled")
if not self._isValid:
raise Exception()

View File

@@ -20,6 +20,7 @@ class LoggerInterface(QFrame):
self.autoscrollButton = PushButton('Autoscroll Off')
self.loggerBox = TextEdit()
self.loggerBox.setReadOnly(True)
signalBus.guiMode = True
self.__initWidget()

View File

@@ -12,6 +12,7 @@ from .logger_interface import LoggerInterface
from .setting_interface import SettingInterface
from ..common.config import ZH_SUPPORT_URL, EN_SUPPORT_URL, cfg
from ..common.signal_bus import signalBus
from ..common.thread_manager import threadManager
from ..common import resource
from ..components.navigation_checkbox import NavigationCheckBox
from ..components.navigation_action_buttons import NavigationActionButtons

View File

@@ -1,66 +1,5 @@
import sys
import traceback
try:
with open('traceback.log', 'w') as f:
pass
from app.modules.request import Request
from app.common.logger import logger
from app.modules.install_chara import InstallChara
from app.modules.remove_chara import RemoveChara
from app.modules.fc_kks import FilterConvertKKS
from app.modules.create_backup import CreateBackup
class Script:
def __init__(self, config, file_manager):
"""Initializes the primary azurlane-auto instance with the passed in
Config instance;
Args:
config (Config): BAAuto Config instance
"""
self.config = config
fileManager = file_manager
self.modules = {
'InstallChara': None,
'RemoveChara': None,
'CreateBackup': None,
'FCKKS': None,
}
if self.config.install_chara['Enable']:
self.modules['InstallChara'] = InstallChara(self.config, fileManager)
if self.config.remove_chara['Enable']:
self.modules['RemoveChara'] = RemoveChara(self.config, fileManager)
if self.config.create_backup['Enable']:
self.modules['CreateBackup'] = CreateBackup(self.config, fileManager)
if self.config.fc_kks["Enable"]:
self.modules['FCKKS'] = FilterConvertKKS(self.config, fileManager)
def run(self):
for task in self.config.tasks:
if self.modules[task]:
logger.info("SCRIPT", f'Start Task: {task}')
try:
self.modules[task].logic_wrapper()
except:
logger.error("SCRIPT", f'Task error: {task}. For more info, check the traceback.log file.')
with open('traceback.log', 'a') as f:
f.write(f'[{task}]\n')
traceback.print_exc(None, f, True)
f.write('\n')
sys.exit(1)
sys.exit(0)
except:
print(f'[ERROR] Script Initialisation Error. For more info, check the traceback.log file.')
with open('traceback.log', 'w') as f:
f.write(f'Script Initialisation Error\n')
traceback.print_exc(None, f, True)
f.write('\n')
sys.exit(1)
if __name__ == "__main__":
config = Config('config.json')
file_manager = FileManager(config)
script = Script(config, file_manager)
script.run()
request = Request()
request.process()