Update logging, update event system, update plugin structure

This commit is contained in:
itdominator 2022-06-14 23:03:04 -05:00
parent ee086f67f4
commit 793621745a
10 changed files with 164 additions and 103 deletions

View File

@ -1,5 +1,5 @@
# Python imports # Python imports
import sys, threading, subprocess, time import os, threading, subprocess, time
# Gtk imports # Gtk imports
import gi import gi
@ -9,45 +9,74 @@ from gi.repository import Gtk
# Application imports # Application imports
# NOTE: Threads will not die with parent's destruction
def threaded(fn): def threaded(fn):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start() threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start()
return wrapper return wrapper
# NOTE: Insure threads die with parent's destruction
def daemon_threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
return wrapper
class Plugin: class Plugin:
def __init__(self, builder, event_system): def __init__(self, builder, event_system):
self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__))
self._plugin_name = "Example Plugin" self._plugin_name = "Example Plugin"
self._plugin_author = "John Doe"
self._plugin_version = "0.0.1"
self._builder = builder self._builder = builder
self._event_system = event_system self._event_system = event_system
self._message = None self._event_sleep_time = .5
self._time_out = 5 self._event_message = None
button = Gtk.Button(label=self._plugin_name) button = Gtk.Button(label=self._plugin_name)
button.connect("button-release-event", self._do_action) button.connect("button-release-event", self.send_message)
# self._module_event_observer() # NOTE: Enable if you want the plugin to watch for events sent to it
plugin_list = self._builder.get_object("plugin_socket") plugin_list = self._builder.get_object("plugin_socket")
plugin_list.add(button) plugin_list.add(button)
plugin_list.show_all() plugin_list.show_all()
@threaded def send_message(self, widget=None, eve=None):
def _do_action(self, widget=None, eve=None):
message = "Hello, World!" message = "Hello, World!"
self._event_system.push_gui_event(["some_type", "display_message", ("warning", message, None)]) self._event_system.push_gui_event([self._plugin_name, "display_message", ("warning", message, None)])
def set_message(self, data):
self._message = data
def get_plugin_name(self): def get_plugin_name(self):
return self._plugin_name return self._plugin_name
def get_plugin_author(self):
return self._plugin_author
def get_plugin_version(self):
return self._plugin_version
def get_socket_id(self): def get_socket_id(self):
return self._socket_id return self._socket_id
def _run_timeout(self): @daemon_threaded
timeout = 0 def _module_event_observer(self):
while not self._message and timeout < self._time_out: while True:
time.sleep(1) time.sleep(self._event_sleep_time)
timeout += 1 event = self._event_system.read_module_event()
if event:
try:
if event[0] is self._plugin_name:
target_id, method_target, data = self._event_system.consume_module_event()
if not method_target:
self._event_message = data
else:
method = getattr(self.__class__, f"{method_target}")
data = method(*(self, *parameters))
except Exception as e:
print(repr(e))

View File

@ -1,5 +1,5 @@
# Python imports # Python imports
import os, sys, threading, subprocess, time import os, threading, subprocess, time
# Gtk imports # Gtk imports
import gi import gi
@ -9,49 +9,78 @@ from gi.repository import Gtk
# Application imports # Application imports
# NOTE: Threads will not die with parent's destruction
def threaded(fn): def threaded(fn):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start() threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start()
return wrapper return wrapper
# NOTE: Insure threads die with parent's destruction
def daemon_threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
return wrapper
class Plugin: class Plugin:
def __init__(self, builder, event_system): def __init__(self, fm_builder, fm_event_system):
self._plugin_name = "Youtube Download"
self._builder = builder
self._event_system = event_system
self._message = None
self._time_out = 5
self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__))
self._plugin_name = "Youtube Download"
self._plugin_author = "ITDominator"
self._plugin_version = "0.0.1"
self._fm_builder = fm_builder
self._fm_event_system = fm_event_system
self._event_sleep_time = .5
self._fm_event_message = None
button = Gtk.Button(label=self._plugin_name) button = Gtk.Button(label=self._plugin_name)
button.connect("button-release-event", self._do_download) button.connect("button-release-event", self._do_download)
plugin_list = self._builder.get_object("plugin_socket") self._module_event_observer()
plugin_list = self._fm_builder.get_object("plugin_socket")
plugin_list.add(button) plugin_list.add(button)
plugin_list.show_all() plugin_list.show_all()
@daemon_threaded
def _module_event_observer(self):
while True:
time.sleep(self._event_sleep_time)
event = self._fm_event_system.read_module_event()
if event:
try:
if event[0] is self._plugin_name:
target_id, method_target, data = self._fm_event_system.consume_module_event()
if not method_target:
self._fm_event_message = data
else:
method = getattr(self.__class__, f"{method_target}")
data = method(*(self, *parameters))
except Exception as e:
print(repr(e))
@threaded @threaded
def _do_download(self, widget=None, eve=None): def _do_download(self, widget=None, eve=None):
self._event_system.push_gui_event([self._plugin_name, "get_current_state", ()]) self._fm_event_system.push_gui_event([self._plugin_name, "get_current_state", ()])
self._run_timeout() while not self._fm_event_message:
pass
if self._message: state = self._fm_event_message
state = self._message
subprocess.Popen([f'{self.SCRIPT_PTH}/download.sh' , state.tab.get_current_directory()]) subprocess.Popen([f'{self.SCRIPT_PTH}/download.sh' , state.tab.get_current_directory()])
self._message = None self._fm_event_message = None
def set_message(self, data):
self._message = data
def get_plugin_name(self): def get_plugin_name(self):
return self._plugin_name return self._plugin_name
def _run_timeout(self): def get_plugin_author(self):
timeout = 0 return self._plugin_author
while not self._message and timeout < self._time_out:
time.sleep(1) def get_plugin_version(self):
timeout += 1 return self._plugin_version

View File

@ -15,17 +15,17 @@ class EventSystem(IPCServer):
def __init__(self): def __init__(self):
super(EventSystem, self).__init__() super(EventSystem, self).__init__()
# NOTE: The format used is list of [type, target, (data,)] Where: # NOTE: The format used is list of ['who', target, (data,)] Where:
# type is useful context for control flow, # who is the sender or target ID and is used for context and control flow,
# target is the method to call, # method_target is the method to call,
# data is the method parameters to give # data is the method parameters OR message data to give
# Where data may be any kind of data # Where data may be any kind of data
self._gui_events = [] self._gui_events = []
self._module_events = [] self._module_events = []
# Makeshift fake "events" type system FIFO # Makeshift "events" system FIFO
def _pop_gui_event(self) -> None: def _pop_gui_event(self) -> None:
if len(self._gui_events) > 0: if len(self._gui_events) > 0:
return self._gui_events.pop(0) return self._gui_events.pop(0)
@ -42,20 +42,20 @@ class EventSystem(IPCServer):
self._gui_events.append(event) self._gui_events.append(event)
return None return None
raise Exception("Invald event format! Please do: [type, target, (data,)]") raise Exception("Invald event format! Please do: ['sender_id': str, method_target: method, (data,): any]")
def push_module_event(self, event: list) -> None: def push_module_event(self, event: list) -> None:
if len(event) == 3: if len(event) == 3:
self._module_events.append(event) self._module_events.append(event)
return None return None
raise Exception("Invald event format! Please do: [type, target, (data,)]") raise Exception("Invald event format! Please do: ['target_id': str, method_target: method, (data,): any]")
def read_gui_event(self) -> list: def read_gui_event(self) -> list:
return self._gui_events[0] return self._gui_events[0] if self._gui_events else None
def read_module_event(self) -> list: def read_module_event(self) -> list:
return self._module_events[0] return self._module_events[0] if self._module_events else None
def consume_gui_event(self) -> list: def consume_gui_event(self) -> list:
return self._pop_gui_event() return self._pop_gui_event()
@ -69,6 +69,6 @@ class EventSystem(IPCServer):
# __builtins__.update({"event_system": Builtins()}) # __builtins__.update({"event_system": Builtins()})
builtins.app_name = "SolarFM" builtins.app_name = "SolarFM"
builtins.event_system = EventSystem() builtins.event_system = EventSystem()
builtins.event_sleep_time = 0.2 builtins.event_sleep_time = 0.05
builtins.trace_debug = False builtins.trace_debug = False
builtins.debug = False builtins.debug = False

View File

@ -17,7 +17,7 @@ class Application(EventSystem):
def __init__(self, args, unknownargs): def __init__(self, args, unknownargs):
if not trace_debug: if not trace_debug:
event_system.create_ipc_listener() event_system.create_ipc_listener()
time.sleep(0.1) time.sleep(0.05)
if not event_system.is_ipc_alive: if not event_system.is_ipc_alive:
if unknownargs: if unknownargs:

View File

@ -1,5 +1,5 @@
# Python imports # Python imports
import os, gc, threading, time, shlex import os, gc, threading, time
# Lib imports # Lib imports
import gi import gi
@ -14,7 +14,14 @@ from .signals.keyboard_signals_mixin import KeyboardSignalsMixin
from .controller_data import Controller_Data from .controller_data import Controller_Data
# NOTE: Threads will not die with parent's destruction
def threaded(fn): def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start()
return wrapper
# NOTE: Insure threads die with parent's destruction
def daemon_threaded(fn):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start() threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
return wrapper return wrapper
@ -62,20 +69,20 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi
event = event_system.consume_gui_event() event = event_system.consume_gui_event()
if event: if event:
try: try:
type, target, data = event sender_id, method_target, parameters = event
if type: if sender_id:
method = getattr(self.__class__, "handle_gui_event_and_set_message") method = getattr(self.__class__, "handle_gui_event_and_return_message")
GLib.idle_add(method, *(self, type, target, data)) GLib.idle_add(method, *(self, sender_id, method_target, parameters))
else: else:
method = getattr(self.__class__, target) method = getattr(self.__class__, method_target)
GLib.idle_add(method, *(self, *data,)) GLib.idle_add(method, *(self, *parameters,))
except Exception as e: except Exception as e:
print(repr(e)) print(repr(e))
def handle_gui_event_and_set_message(self, type, target, parameters): def handle_gui_event_and_return_message(self, sender, method_target, parameters):
method = getattr(self.__class__, f"{target}") method = getattr(self.__class__, f"{method_target}")
data = method(*(self, *parameters)) data = method(*(self, *parameters))
self.plugins.send_message_to_plugin(type, data) event_system.push_module_event([sender, None, data])
def save_load_session(self, action="save_session"): def save_load_session(self, action="save_session"):
wid, tid = self.fm_controller.get_active_wid_and_tid() wid, tid = self.fm_controller.get_active_wid_and_tid()
@ -110,7 +117,7 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi
def load_session(self, session_json): def load_session(self, session_json):
if debug: if debug:
print(f"Session Data: {session_json}") self.logger.debug(f"Session Data: {session_json}")
self.ctrl_down = False self.ctrl_down = False
self.shift_down = False self.shift_down = False
@ -186,5 +193,4 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi
def open_terminal(self, widget=None, eve=None): def open_terminal(self, widget=None, eve=None):
wid, tid = self.fm_controller.get_active_wid_and_tid() wid, tid = self.fm_controller.get_active_wid_and_tid()
tab = self.get_fm_window(wid).get_tab_by_id(tid) tab = self.get_fm_window(wid).get_tab_by_id(tid)
dir = tab.get_current_directory() tab.execute([f"{tab.terminal_app}"], start_dir=tab.get_current_directory())
tab.execute([f"{tab.terminal_app}"], start_dir=shlex.quote(dir))

View File

@ -45,7 +45,7 @@ class WidgetFileActionMixin:
watcher = tab.get_dir_watcher() watcher = tab.get_dir_watcher()
watcher.cancel() watcher.cancel()
if debug: if debug:
print(f"Watcher Is Cancelled: {watcher.is_cancelled()}") self.logger.debug(f"Watcher Is Cancelled: {watcher.is_cancelled()}")
cur_dir = tab.get_current_directory() cur_dir = tab.get_current_directory()
@ -64,7 +64,7 @@ class WidgetFileActionMixin:
Gio.FileMonitorEvent.RENAMED, Gio.FileMonitorEvent.MOVED_IN, Gio.FileMonitorEvent.RENAMED, Gio.FileMonitorEvent.MOVED_IN,
Gio.FileMonitorEvent.MOVED_OUT]: Gio.FileMonitorEvent.MOVED_OUT]:
if debug: if debug:
print(eve_type) self.logger.debug(eve_type)
if eve_type in [Gio.FileMonitorEvent.MOVED_IN, Gio.FileMonitorEvent.MOVED_OUT]: if eve_type in [Gio.FileMonitorEvent.MOVED_IN, Gio.FileMonitorEvent.MOVED_OUT]:
self.update_on_soft_lock_end(data[0]) self.update_on_soft_lock_end(data[0])
@ -85,7 +85,6 @@ class WidgetFileActionMixin:
if (current_time - last_update_time) > 0.6: if (current_time - last_update_time) > 0.6:
lock = False lock = False
self.soft_update_lock.pop(tab_widget, None) self.soft_update_lock.pop(tab_widget, None)
GLib.idle_add(self.update_on_soft_lock_end, *(tab_widget,)) GLib.idle_add(self.update_on_soft_lock_end, *(tab_widget,))
@ -427,10 +426,10 @@ class WidgetFileActionMixin:
start = "-copy" start = "-copy"
if debug: if debug:
print(f"Path: {full_path}") self.logger.debug(f"Path: {full_path}")
print(f"Base Path: {base_path}") self.logger.debug(f"Base Path: {base_path}")
print(f'Name: {file_name}') self.logger.debug(f'Name: {file_name}')
print(f"Extension: {extension}") self.logger.debug(f"Extension: {extension}")
i = 2 i = 2
while target.query_exists(): while target.query_exists():

View File

@ -12,6 +12,8 @@ from gi.repository import Gtk, Gio
class Plugin: class Plugin:
name: str = None name: str = None
author: str = None
version: str = None
module: str = None module: str = None
reference: type = None reference: type = None
@ -61,6 +63,9 @@ class Plugins:
plugin_reference = app.Plugin(self._builder, event_system) plugin_reference = app.Plugin(self._builder, event_system)
plugin = Plugin() plugin = Plugin()
plugin.name = plugin_reference.get_plugin_name() plugin.name = plugin_reference.get_plugin_name()
plugin.author = plugin_reference.get_plugin_author()
plugin.version = plugin_reference.get_plugin_version()
plugin.module = path plugin.module = path
plugin.reference = plugin_reference plugin.reference = plugin_reference
@ -74,10 +79,3 @@ class Plugins:
def reload_plugins(self, file: str = None) -> None: def reload_plugins(self, file: str = None) -> None:
print(f"Reloading plugins... stub.") print(f"Reloading plugins... stub.")
def send_message_to_plugin(self, target: str , data: type) -> None:
print("Trying to send message to plugin...")
for plugin in self._plugin_collection:
if target in plugin.name:
print('Found plugin; posting message...')
plugin.reference.set_message(data)

View File

@ -59,7 +59,7 @@ class Launcher:
app_info.launch_uris_async(uris) app_info.launch_uris_async(uris)
def remux_video(self, hash, file): def remux_video(self, hash, file):
remux_vid_pth = self.REMUX_FOLDER + "/" + hash + ".mp4" remux_vid_pth = "{self.REMUX_FOLDER}/{hash}.mp4"
self.logger.debug(remux_vid_pth) self.logger.debug(remux_vid_pth)
if not os.path.isfile(remux_vid_pth): if not os.path.isfile(remux_vid_pth):

View File

@ -5,10 +5,6 @@ import os, logging
class Logger: class Logger:
def __init__(self, config_path: str):
self._CONFIG_PATH = config_path
def get_logger(self, loggerName: str = "NO_LOGGER_NAME_PASSED", createFile: bool = True) -> logging.Logger:
""" """
Create a new logging object and return it. Create a new logging object and return it.
:note: :note:
@ -26,18 +22,22 @@ class Logger:
:return: the logging object we created :return: the logging object we created
""" """
globalLogLvl = logging.DEBUG # Keep this at highest so that handlers can filter to their desired levels def __init__(self, config_path: str, _ch_log_lvl = logging.CRITICAL, _fh_log_lvl = logging.INFO):
chLogLevel = logging.CRITICAL # Prety musch the only one we change ever self._CONFIG_PATH = config_path
fhLogLevel = logging.DEBUG self.global_lvl = logging.DEBUG # Keep this at highest so that handlers can filter to their desired levels
self.ch_log_lvl = _ch_log_lvl # Prety much the only one we ever change
self.fh_log_lvl = _fh_log_lvl
def get_logger(self, loggerName: str = "NO_LOGGER_NAME_PASSED", createFile: bool = True) -> logging.Logger:
log = logging.getLogger(loggerName) log = logging.getLogger(loggerName)
log.setLevel(globalLogLvl) log.setLevel(self.global_lvl)
# Set our log output styles # Set our log output styles
fFormatter = logging.Formatter('[%(asctime)s] %(pathname)s:%(lineno)d %(levelname)s - %(message)s', '%m-%d %H:%M:%S') fFormatter = logging.Formatter('[%(asctime)s] %(pathname)s:%(lineno)d %(levelname)s - %(message)s', '%m-%d %H:%M:%S')
cFormatter = logging.Formatter('%(pathname)s:%(lineno)d] %(levelname)s - %(message)s') cFormatter = logging.Formatter('%(pathname)s:%(lineno)d] %(levelname)s - %(message)s')
ch = logging.StreamHandler() ch = logging.StreamHandler()
ch.setLevel(level=chLogLevel) ch.setLevel(level=self.ch_log_lvl)
ch.setFormatter(cFormatter) ch.setFormatter(cFormatter)
log.addHandler(ch) log.addHandler(ch)
@ -49,7 +49,7 @@ class Logger:
os.mkdir(folder) os.mkdir(folder)
fh = logging.FileHandler(file) fh = logging.FileHandler(file)
fh.setLevel(level=fhLogLevel) fh.setLevel(level=self.fh_log_lvl)
fh.setFormatter(fFormatter) fh.setFormatter(fFormatter)
log.addHandler(fh) log.addHandler(fh)

View File

@ -59,7 +59,7 @@ class Settings:
self._keybindings.configure(keybindings) self._keybindings.configure(keybindings)
self._main_window = None self._main_window = None
self._logger = Logger(self._CONFIG_PATH).get_logger() self._logger = Logger(self._CONFIG_PATH, _fh_log_lvl=20).get_logger()
self._builder = Gtk.Builder() self._builder = Gtk.Builder()
self._builder.add_from_file(self._GLADE_FILE) self._builder.add_from_file(self._GLADE_FILE)