From bff54995fd116e78bf61b8b361a6e1fb756c35de Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Fri, 12 Aug 2022 22:54:16 -0500 Subject: [PATCH] Reworked plugin manifest; decoupled event system and ipc --- plugins/file_properties/__main__.py | 3 + plugins/file_properties/manifest.json | 12 +++ plugins/file_properties/plugin.py | 16 +--- plugins/searcher/__main__.py | 3 + plugins/searcher/manifest.json | 13 ++++ plugins/searcher/plugin.py | 20 +---- plugins/template/__main__.py | 3 + plugins/template/manifest.json | 13 ++++ plugins/template/plugin.py | 18 +---- plugins/vod_thumbnailer/__main__.py | 3 + plugins/vod_thumbnailer/manifest.json | 12 +++ plugins/vod_thumbnailer/plugin.py | 16 +--- plugins/youtube_download/__main__.py | 3 + plugins/youtube_download/manifest.json | 12 +++ plugins/youtube_download/plugin.py | 17 +---- .../SolarFM/solarfm/__builtins__.py | 67 ++-------------- .../solarfm-0.0.1/SolarFM/solarfm/app.py | 16 ++-- .../SolarFM/solarfm/core/controller.py | 1 - .../SolarFM/solarfm/plugins/manifest.py | 76 +++++++++++++++++++ .../SolarFM/solarfm/plugins/plugins.py | 69 ++--------------- .../SolarFM/solarfm/utils/event_system.py | 59 ++++++++++++++ .../SolarFM/solarfm/utils/ipc_server.py | 8 +- 22 files changed, 253 insertions(+), 207 deletions(-) create mode 100644 plugins/file_properties/__main__.py create mode 100644 plugins/file_properties/manifest.json create mode 100644 plugins/searcher/__main__.py create mode 100644 plugins/searcher/manifest.json create mode 100644 plugins/template/__main__.py create mode 100644 plugins/template/manifest.json create mode 100644 plugins/vod_thumbnailer/__main__.py create mode 100644 plugins/vod_thumbnailer/manifest.json create mode 100644 plugins/youtube_download/__main__.py create mode 100644 plugins/youtube_download/manifest.json create mode 100644 src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/manifest.py create mode 100644 src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/event_system.py diff --git a/plugins/file_properties/__main__.py b/plugins/file_properties/__main__.py new file mode 100644 index 0000000..a576329 --- /dev/null +++ b/plugins/file_properties/__main__.py @@ -0,0 +1,3 @@ +""" + Pligin Package +""" diff --git a/plugins/file_properties/manifest.json b/plugins/file_properties/manifest.json new file mode 100644 index 0000000..7ba667d --- /dev/null +++ b/plugins/file_properties/manifest.json @@ -0,0 +1,12 @@ +{ + "manifest": { + "name": "Properties", + "author": "ITDominator", + "version": "0.0.1", + "support": "", + "requests": { + "ui_target": "context_menu", + "pass_fm_events": "true" + } + } +} diff --git a/plugins/file_properties/plugin.py b/plugins/file_properties/plugin.py index 5a4b2a4..a7f6d8e 100644 --- a/plugins/file_properties/plugin.py +++ b/plugins/file_properties/plugin.py @@ -25,17 +25,6 @@ def daemon_threaded(fn): -class Manifest: - path: str = os.path.dirname(os.path.realpath(__file__)) - name: str = "Properties" - author: str = "ITDominator" - version: str = "0.0.1" - support: str = "" - requests: {} = { - 'ui_target': "context_menu", - 'pass_fm_events': "true" - } - class Properties: file_uri: str = None file_name: str = None @@ -50,8 +39,11 @@ class Properties: chmod_stat: str = None -class Plugin(Manifest): +class Plugin: def __init__(self): + self.path = os.path.dirname(os.path.realpath(__file__)) + self.name = "Properties" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus + # where self.name should not be needed for message comms self._GLADE_FILE = f"{self.path}/file_properties.glade" self._builder = None self._properties_dialog = None diff --git a/plugins/searcher/__main__.py b/plugins/searcher/__main__.py new file mode 100644 index 0000000..a576329 --- /dev/null +++ b/plugins/searcher/__main__.py @@ -0,0 +1,3 @@ +""" + Pligin Package +""" diff --git a/plugins/searcher/manifest.json b/plugins/searcher/manifest.json new file mode 100644 index 0000000..845a31f --- /dev/null +++ b/plugins/searcher/manifest.json @@ -0,0 +1,13 @@ +{ + "manifest": { + "name": "Search", + "author": "ITDominator", + "version": "0.0.1", + "support": "", + "requests": { + "ui_target": "context_menu", + "pass_fm_events": "true", + "bind_keys": ["Search||_show_grep_list_page:f"] + } + } +} diff --git a/plugins/searcher/plugin.py b/plugins/searcher/plugin.py index ea295eb..4721b32 100644 --- a/plugins/searcher/plugin.py +++ b/plugins/searcher/plugin.py @@ -25,21 +25,6 @@ def daemon_threaded(fn): -class Manifest: - path: str = os.path.dirname(os.path.realpath(__file__)) - name: str = "Search" - author: str = "ITDominator" - version: str = "0.0.1" - support: str = "" - requests: {} = { - 'ui_target': "context_menu", - 'pass_fm_events': "true", - 'bind_keys': [f"{name}||_show_grep_list_page:f"] - } - - - - class FilePreviewWidget(Gtk.LinkButton): def __init__(self, path, file): super(FilePreviewWidget, self).__init__() @@ -89,8 +74,11 @@ grep_result_set = manager.dict() file_result_set = manager.list() -class Plugin(Manifest): +class Plugin: def __init__(self): + self.path = os.path.dirname(os.path.realpath(__file__)) + self.name = "Search" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus + # where self.name should not be needed for message comms self._GLADE_FILE = f"{self.path}/search_dialog.glade" self._builder = None self._search_dialog = None diff --git a/plugins/template/__main__.py b/plugins/template/__main__.py new file mode 100644 index 0000000..a576329 --- /dev/null +++ b/plugins/template/__main__.py @@ -0,0 +1,3 @@ +""" + Pligin Package +""" diff --git a/plugins/template/manifest.json b/plugins/template/manifest.json new file mode 100644 index 0000000..4dcbf47 --- /dev/null +++ b/plugins/template/manifest.json @@ -0,0 +1,13 @@ +{ + "manifest": { + "name": "Example Plugin", + "author": "John Doe", + "version": "0.0.1", + "support": "", + "requests": { + "ui_target": "plugin_control_list", + "pass_fm_events": "true", + "bind_keys": ["Example Plugin||send_message:f"] + } + } +} diff --git a/plugins/template/plugin.py b/plugins/template/plugin.py index bc22725..21a5d5b 100644 --- a/plugins/template/plugin.py +++ b/plugins/template/plugin.py @@ -24,21 +24,10 @@ def daemon_threaded(fn): -class Manifest: - path: str = os.path.dirname(os.path.realpath(__file__)) - name: str = "Example Plugin" - author: str = "John Doe" - version: str = "0.0.1" - support: str = "" - requests: {} = { - 'ui_target': "plugin_control_list", - 'pass_fm_events': "true", - 'bind_keys': [f"{name}||send_message:f"] - } - - -class Plugin(Manifest): +class Plugin: def __init__(self): + self.name = "Example Plugin" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus + # where self.name should not be needed for message comms self._event_system = None self._event_sleep_time = .5 self._event_message = None @@ -58,7 +47,6 @@ class Plugin(Manifest): def send_message(self, widget=None, eve=None): message = "Hello, World!" - print("here") self._event_system.push_gui_event([self.name, "display_message", ("warning", message, None)]) diff --git a/plugins/vod_thumbnailer/__main__.py b/plugins/vod_thumbnailer/__main__.py new file mode 100644 index 0000000..a576329 --- /dev/null +++ b/plugins/vod_thumbnailer/__main__.py @@ -0,0 +1,3 @@ +""" + Pligin Package +""" diff --git a/plugins/vod_thumbnailer/manifest.json b/plugins/vod_thumbnailer/manifest.json new file mode 100644 index 0000000..154bd40 --- /dev/null +++ b/plugins/vod_thumbnailer/manifest.json @@ -0,0 +1,12 @@ +{ + "manifest": { + "name": "VOD Thumbnailer", + "author": "ITDominator", + "version": "0.0.1", + "support": "", + "requests": { + "ui_target": "context_menu", + "pass_fm_events": "true" + } + } +} diff --git a/plugins/vod_thumbnailer/plugin.py b/plugins/vod_thumbnailer/plugin.py index 44deeb2..1fbc4ac 100644 --- a/plugins/vod_thumbnailer/plugin.py +++ b/plugins/vod_thumbnailer/plugin.py @@ -26,19 +26,11 @@ def daemon_threaded(fn): -class Manifest: - path: str = os.path.dirname(os.path.realpath(__file__)) - name: str = "VOD Thumbnailer" - author: str = "ITDominator" - version: str = "0.0.1" - support: str = "" - requests: {} = { - 'ui_target': "context_menu", - 'pass_fm_events': "true" - } - -class Plugin(Manifest): +class Plugin: def __init__(self): + self.path = os.path.dirname(os.path.realpath(__file__)) + self.name = "VOD Thumbnailer" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus + # where self.name should not be needed for message comms self._GLADE_FILE = f"{self.path}/re_thumbnailer.glade" self._builder = None self._thumbnailer_dialog = None diff --git a/plugins/youtube_download/__main__.py b/plugins/youtube_download/__main__.py new file mode 100644 index 0000000..a576329 --- /dev/null +++ b/plugins/youtube_download/__main__.py @@ -0,0 +1,3 @@ +""" + Pligin Package +""" diff --git a/plugins/youtube_download/manifest.json b/plugins/youtube_download/manifest.json new file mode 100644 index 0000000..554ce1e --- /dev/null +++ b/plugins/youtube_download/manifest.json @@ -0,0 +1,12 @@ +{ + "manifest": { + "name": "Youtube Download", + "author": "ITDominator", + "version": "0.0.1", + "support": "", + "requests": { + "ui_target": "plugin_control_list", + "pass_fm_events": "true" + } + } +} diff --git a/plugins/youtube_download/plugin.py b/plugins/youtube_download/plugin.py index cd98a37..122cc99 100644 --- a/plugins/youtube_download/plugin.py +++ b/plugins/youtube_download/plugin.py @@ -24,21 +24,10 @@ def daemon_threaded(fn): -class Manifest: - path: str = os.path.dirname(os.path.realpath(__file__)) - name: str = "Youtube Download" - author: str = "ITDominator" - version: str = "0.0.1" - support: str = "" - requests: {} = { - 'ui_target': "plugin_control_list", - 'pass_fm_events': "true" - - } - - -class Plugin(Manifest): +class Plugin: def __init__(self): + self.name = "Youtube Download" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus + # where self.name should not be needed for message comms self._event_system = None self._event_sleep_time = .5 self._event_message = None diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py index 15a4f9d..d9a77d8 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/__builtins__.py @@ -4,16 +4,18 @@ import builtins, threading # Lib imports # Application imports -from utils.ipc_server import IPCServer +from utils.event_system import EventSystem -# NOTE: Threads will not die with parent's destruction + + +# NOTE: Threads WILL NOT die with parent's destruction. def threaded_wrapper(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 +# NOTE: Threads WILL die with parent's destruction. def daemon_threaded_wrapper(fn): def wrapper(*args, **kwargs): threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start() @@ -22,71 +24,12 @@ def daemon_threaded_wrapper(fn): - - -class EventSystem(IPCServer): - """ Inheret IPCServerMixin. Create an pub/sub systems. """ - - def __init__(self): - super(EventSystem, self).__init__() - - # NOTE: The format used is list of ['who', target, (data,)] Where: - # who is the sender or target ID and is used for context and control flow, - # method_target is the method to call, - # data is the method parameters OR message data to give - # Where data may be any kind of data - self._gui_events = [] - self._module_events = [] - - - - # Makeshift "events" system FIFO - def _pop_gui_event(self) -> None: - if len(self._gui_events) > 0: - return self._gui_events.pop(0) - return None - - def _pop_module_event(self) -> None: - if len(self._module_events) > 0: - return self._module_events.pop(0) - return None - - - def push_gui_event(self, event: list) -> None: - if len(event) == 3: - self._gui_events.append(event) - return None - - raise Exception("Invald event format! Please do: ['sender_id': str, method_target: method, (data,): any]") - - def push_module_event(self, event: list) -> None: - if len(event) == 3: - self._module_events.append(event) - return None - - raise Exception("Invald event format! Please do: ['target_id': str, method_target: method, (data,): any]") - - def read_gui_event(self) -> list: - return self._gui_events[0] if self._gui_events else None - - def read_module_event(self) -> list: - return self._module_events[0] if self._module_events else None - - def consume_gui_event(self) -> list: - return self._pop_gui_event() - - def consume_module_event(self) -> list: - return self._pop_module_event() - - - class EndpointRegistry(): def __init__(self): self._endpoints = {} def register(self, rule, **options): def decorator(f): - _endpoint = options.pop("endpoint", None) self._endpoints[rule] = f return f diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/app.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/app.py index e7b0d5f..a0e36e9 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/app.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/app.py @@ -4,31 +4,33 @@ import os, inspect, time # Lib imports # Application imports -from __builtins__ import EventSystem +from __builtins__ import * +from utils.ipc_server import IPCServer from utils.settings import Settings from core.controller import Controller - -class Application(EventSystem): +class Application(IPCServer): """ Create Settings and Controller classes. Bind signal to Builder. Inherit from Builtins to bind global methods and classes. """ def __init__(self, args, unknownargs): + super(Application, self).__init__() + if not trace_debug: - event_system.create_ipc_listener() + self.create_ipc_listener() time.sleep(0.05) - if not event_system.is_ipc_alive: + if not self.is_ipc_alive: if unknownargs: for arg in unknownargs: if os.path.isdir(arg): message = f"FILE|{arg}" - event_system.send_ipc_message(message) + self.send_ipc_message(message) if args.new_tab and os.path.isdir(args.new_tab): message = f"FILE|{args.new_tab}" - event_system.send_ipc_message(message) + self.send_ipc_message(message) raise Exception("IPC Server Exists: Will send path(s) to it and close...\nNote: If no fm exists, remove /tmp/solarfm-ipc.sock") diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller.py index 6ddb4c9..d476cbf 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/controller.py @@ -43,7 +43,6 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMi def tear_down(self, widget=None, eve=None): - event_system.send_ipc_message("close server") self.fm_controller.save_state() time.sleep(event_sleep_time) Gtk.main_quit() diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/manifest.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/manifest.py new file mode 100644 index 0000000..6aa3f0a --- /dev/null +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/manifest.py @@ -0,0 +1,76 @@ +# Python imports +import os, json +from os.path import join + +# Lib imports + +# Application imports + + + + +class Plugin: + path: str = None + name: str = None + author: str = None + version: str = None + support: str = None + requests:{} = None + reference: type = None + + +class ManifestProcessor: + def __init__(self, path, builder): + manifest = join(path, "manifest.json") + if not os.path.exists(manifest): + raise Exception("Invalid Plugin Structure: Plugin doesn't have 'manifest.json'. Aboarting load...") + + self._path = path + self._builder = builder + with open(manifest) as f: + data = json.load(f) + self._manifest = data["manifest"] + self._plugin = self.collect_info() + + def collect_info(self) -> Plugin: + plugin = Plugin() + plugin.path = self._path + plugin.name = self._manifest["name"] + plugin.author = self._manifest["author"] + plugin.version = self._manifest["version"] + plugin.support = self._manifest["support"] + plugin.requests = self._manifest["requests"] + + return plugin + + def get_loading_data(self): + loading_data = {} + requests = self._plugin.requests + keys = requests.keys() + + if "ui_target" in keys: + if requests["ui_target"] in [ + "none", "other", "main_Window", "main_menu_bar", "path_menu_bar", "plugin_control_list", + "context_menu", "window_1", "window_2", "window_3", "window_4" + ]: + if requests["ui_target"] == "other": + if "ui_target_id" in keys: + loading_data["ui_target"] = self._builder.get_object(requests["ui_target_id"]) + if loading_data["ui_target"] == None: + raise Exception('Invalid "ui_target_id" given in requests. Must have one if setting "ui_target" to "other"...') + else: + raise Exception('Invalid "ui_target_id" given in requests. Must have one if setting "ui_target" to "other"...') + else: + loading_data["ui_target"] = self._builder.get_object(requests["ui_target"]) + else: + raise Exception('Unknown "ui_target" given in requests.') + + if "pass_fm_events" in keys: + if requests["pass_fm_events"] in ["true"]: + loading_data["pass_fm_events"] = True + + if "bind_keys" in keys: + if isinstance(requests["bind_keys"], list): + loading_data["bind_keys"] = requests["bind_keys"] + + return self._plugin, loading_data diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins.py index 2d547b4..b14a1a9 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/plugins/plugins.py @@ -8,17 +8,9 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk, Gio # Application imports +from .manifest import Plugin, ManifestProcessor -class Plugin: - path: str = None - name: str = None - author: str = None - version: str = None - support: str = None - requests:{} = None - reference: type = None - class Plugins: @@ -28,7 +20,7 @@ class Plugins: self._settings = settings self._builder = self._settings.get_builder() self._plugins_path = self._settings.get_plugins_path() - self._keybindings = self._settings.get_keybindings() + self._keybindings = self._settings.get_keybindings() self._plugins_dir_watcher = None self._plugin_collection = [] @@ -55,20 +47,18 @@ class Plugins: for path, folder in [[join(self._plugins_path, item), item] if os.path.isdir(join(self._plugins_path, item)) else None for item in os.listdir(self._plugins_path)]: try: - target = join(path, "plugin.py") + target = join(path, "plugin.py") + manifest = ManifestProcessor(path, self._builder) + if not os.path.exists(target): raise Exception("Invalid Plugin Structure: Plugin doesn't have 'plugin.py'. Aboarting load...") - module = self.load_plugin_module(path, folder, target) - plugin = self.collect_info(module, path) - loading_data = self.parse_requests(plugin) - + plugin, loading_data = manifest.get_loading_data() + module = self.load_plugin_module(path, folder, target) self.execute_plugin(module, plugin, loading_data) except Exception as e: print(f"Malformed Plugin: Not loading -->: '{folder}' !") - traceback.print_exc() - # if debug: - # traceback.print_exc() + traceback.print_exc() os.chdir(parent_path) @@ -82,49 +72,6 @@ class Plugins: return module - def collect_info(self, module, path) -> Plugin: - plugin = Plugin() - plugin.path = module.Manifest.path - plugin.name = module.Manifest.name - plugin.author = module.Manifest.author - plugin.version = module.Manifest.version - plugin.support = module.Manifest.support - plugin.requests = module.Manifest.requests - - return plugin - - def parse_requests(self, plugin): - loading_data = {} - requests = plugin.requests - keys = requests.keys() - - if "ui_target" in keys: - if requests["ui_target"] in [ - "none", "other", "main_Window", "main_menu_bar", "path_menu_bar", "plugin_control_list", - "context_menu", "window_1", "window_2", "window_3", "window_4" - ]: - if requests["ui_target"] == "other": - if "ui_target_id" in keys: - loading_data["ui_target"] = self._builder.get_object(requests["ui_target_id"]) - if loading_data["ui_target"] == None: - raise Exception('Invalid "ui_target_id" given in requests. Must have one if setting "ui_target" to "other"...') - else: - raise Exception('Invalid "ui_target_id" given in requests. Must have one if setting "ui_target" to "other"...') - else: - loading_data["ui_target"] = self._builder.get_object(requests["ui_target"]) - else: - raise Exception('Unknown "ui_target" given in requests.') - - - if "pass_fm_events" in keys: - if requests["pass_fm_events"] in ["true"]: - loading_data["pass_fm_events"] = True - - if "bind_keys" in keys: - if isinstance(requests["bind_keys"], list): - loading_data["bind_keys"] = requests["bind_keys"] - - return loading_data def execute_plugin(self, module: type, plugin: Plugin, loading_data: []): plugin.reference = module.Plugin() diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/event_system.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/event_system.py new file mode 100644 index 0000000..1dcd7fa --- /dev/null +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/event_system.py @@ -0,0 +1,59 @@ +# Python imports + +# Lib imports + +# Application imports + + + + +class EventSystem: + """ Inheret IPCServerMixin. Create an pub/sub systems. """ + + def __init__(self): + # NOTE: The format used is list of ['who', target, (data,)] Where: + # who is the sender or target ID and is used for context and control flow, + # method_target is the method to call, + # data is the method parameters OR message data to give + # Where data may be any kind of data + self._gui_events = [] + self._module_events = [] + + + # Makeshift "events" system FIFO + def _pop_gui_event(self) -> None: + if len(self._gui_events) > 0: + return self._gui_events.pop(0) + return None + + def _pop_module_event(self) -> None: + if len(self._module_events) > 0: + return self._module_events.pop(0) + return None + + + def push_gui_event(self, event: list) -> None: + if len(event) == 3: + self._gui_events.append(event) + return None + + raise Exception("Invald event format! Please do: ['sender_id': str, method_target: method, (data,): any]") + + def push_module_event(self, event: list) -> None: + if len(event) == 3: + self._module_events.append(event) + return None + + raise Exception("Invald event format! Please do: ['target_id': str, method_target: method, (data,): any]") + + def read_gui_event(self) -> list: + return self._gui_events[0] if self._gui_events else None + + def read_module_event(self) -> list: + return self._module_events[0] if self._module_events else None + + def consume_gui_event(self) -> list: + return self._pop_gui_event() + + def consume_module_event(self) -> list: + return self._pop_module_event() diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py index 5ad037d..3b88c16 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py @@ -7,12 +7,6 @@ from multiprocessing.connection import Listener, Client # Application imports -def threaded(fn): - def wrapper(*args, **kwargs): - threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start() - return wrapper - - class IPCServer: @@ -36,7 +30,7 @@ class IPCServer: self._ipc_authkey = None - @threaded + @daemon_threaded def create_ipc_listener(self) -> None: if self._conn_type == "socket": if os.path.exists(self._ipc_address):