From 4e55c88629bf2f1e0466d16ae000fbf2d63e9dd5 Mon Sep 17 00:00:00 2001 From: Adam Saudagar Date: Wed, 15 Feb 2023 12:38:47 +0530 Subject: [PATCH 1/2] handling keyboard interupt and exiting main thread safely kindof related to #104 --- fishy/__main__.py | 61 +++++++++++++++++++------------------ fishy/helper/active_poll.py | 2 +- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/fishy/__main__.py b/fishy/__main__.py index 68eb611..5035259 100644 --- a/fishy/__main__.py +++ b/fishy/__main__.py @@ -53,43 +53,46 @@ def initialize(window_to_hide): helper.install_required_addons() +def on_gui_load(gui, finish_splash, logger): + finish_splash() + update_dialog.check_update(gui) + logger.connect(gui) + + def main(): print("launching please wait...") - - config.init() - if not check_eula(): - return - - finish_splash = splash.start() - logger = GuiLogger() - config.start_backup_scheduler() - active.init() - hotkey.init() - - def on_gui_load(): - finish_splash() - update_dialog.check_update(gui) - logger.connect(gui) - - window_to_hide = win32gui.GetForegroundWindow() - bot = EngineEventHandler(lambda: gui) - gui = GUI(lambda: bot, on_gui_load) + gui = GUI(lambda: bot, lambda: on_gui_load(gui, finish_splash, logger)) + window_to_hide = win32gui.GetForegroundWindow() + logger = GuiLogger() + hotkey.init() + active.init() - hotkey.start() + try: + config.init() + if not check_eula(): + return - logging.info(f"Fishybot v{fishy.__version__}") - initialize(window_to_hide) + logging.info(f"Fishybot v{fishy.__version__}") - gui.start() - active.start() + finish_splash = splash.start() + config.start_backup_scheduler() - bot.start_event_handler() # main thread loop + initialize(window_to_hide) - hotkey.stop() - active.stop() - config.stop() - bot.stop() + hotkey.start() + gui.start() + active.start() + + bot.start_event_handler() # main thread loop + except KeyboardInterrupt as e: + ... + finally: + gui._destroyed = True + hotkey.stop() + active.stop() + config.stop() + bot.stop() if __name__ == "__main__": diff --git a/fishy/helper/active_poll.py b/fishy/helper/active_poll.py index 5406dc8..28b5144 100644 --- a/fishy/helper/active_poll.py +++ b/fishy/helper/active_poll.py @@ -14,12 +14,12 @@ class active: return active._scheduler = EventScheduler() - active._scheduler.start() logging.debug("active scheduler initialized") @staticmethod def start(): web.ping() + active._scheduler.start() active._scheduler.enter_recurring(60, 1, web.ping) logging.debug("active scheduler started") From 2118e10d5d569a6bef96a698f82d37ed4ccb2409 Mon Sep 17 00:00:00 2001 From: Adam Saudagar Date: Tue, 7 Mar 2023 00:03:24 +0530 Subject: [PATCH 2/2] using splash object instead of using finish function using gui method instead of directly accessing private members --- fishy/__main__.py | 17 +++++----- fishy/gui/gui.py | 3 ++ fishy/gui/splash.py | 78 ++++++++++++++++++++++----------------------- 3 files changed, 51 insertions(+), 47 deletions(-) diff --git a/fishy/__main__.py b/fishy/__main__.py index 5035259..45e8240 100644 --- a/fishy/__main__.py +++ b/fishy/__main__.py @@ -7,10 +7,11 @@ import win32con import win32gui import fishy -from fishy.gui import GUI, splash, update_dialog, check_eula +from fishy.gui import GUI, update_dialog, check_eula from fishy import helper, web from fishy.engine.common.event_handler import EngineEventHandler from fishy.gui.log_config import GuiLogger +from fishy.gui.splash import Splash from fishy.helper import hotkey from fishy.helper.active_poll import active from fishy.helper.config import config @@ -53,8 +54,8 @@ def initialize(window_to_hide): helper.install_required_addons() -def on_gui_load(gui, finish_splash, logger): - finish_splash() +def on_gui_load(gui, splash, logger): + splash.finish() update_dialog.check_update(gui) logger.connect(gui) @@ -62,7 +63,7 @@ def on_gui_load(gui, finish_splash, logger): def main(): print("launching please wait...") bot = EngineEventHandler(lambda: gui) - gui = GUI(lambda: bot, lambda: on_gui_load(gui, finish_splash, logger)) + gui = GUI(lambda: bot, lambda: on_gui_load(gui, splash, logger)) window_to_hide = win32gui.GetForegroundWindow() logger = GuiLogger() hotkey.init() @@ -75,7 +76,7 @@ def main(): logging.info(f"Fishybot v{fishy.__version__}") - finish_splash = splash.start() + splash = Splash().start() config.start_backup_scheduler() initialize(window_to_hide) @@ -85,10 +86,10 @@ def main(): active.start() bot.start_event_handler() # main thread loop - except KeyboardInterrupt as e: - ... + except KeyboardInterrupt: + print("caught KeyboardInterrupt, Stopping main thread") finally: - gui._destroyed = True + gui.stop() hotkey.stop() active.stop() config.stop() diff --git a/fishy/gui/gui.py b/fishy/gui/gui.py index a01272d..9371172 100644 --- a/fishy/gui/gui.py +++ b/fishy/gui/gui.py @@ -69,6 +69,9 @@ class GUI: def create(self): main_gui._create(self) + def stop(self): + self._destroyed = True + def start(self): self._thread.start() diff --git a/fishy/gui/splash.py b/fishy/gui/splash.py index e2a2b7d..e7296f0 100644 --- a/fishy/gui/splash.py +++ b/fishy/gui/splash.py @@ -10,54 +10,54 @@ from fishy.helper import helper from fishy.helper.config import config -def show(win_loc, q): - logging.debug("started splash process") - dim = (300, 200) - top = tk.Tk() +class Splash: + def __init__(self): + self.q = Queue() + self.process = Process(name=Splash.__name__, target=self.show, args=(config.get("win_loc"), self.q,)) - top.overrideredirect(True) - top.lift() - top.attributes('-topmost', True) + def finish(self): + self.q.put("stop") - top.title("Loading...") - top.resizable(False, False) - top.iconbitmap(helper.manifest_file('icon.ico')) + def start(self): + self.process.start() + return self - canvas = tk.Canvas(top, width=dim[0], height=dim[1], bg='white') - canvas.pack() - top.image = Image.open(helper.manifest_file('fishybot_logo.png')).resize(dim) - top.image = ImageTk.PhotoImage(top.image) - canvas.create_image(0, 0, anchor=tk.NW, image=top.image) + def show(self, win_loc, q): + logging.debug("started splash process") + dim = (300, 200) + top = tk.Tk() - # Position splash at the center of the main window + top.overrideredirect(True) + top.lift() + top.attributes('-topmost', True) - default_loc = (str(top.winfo_reqwidth()) + "+" + str(top.winfo_reqheight()) + "+" + "0" + "0") - loc = (win_loc or default_loc).split(":")[-1].split("+")[1:] - top.geometry("{}x{}+{}+{}".format(dim[0], dim[1], int(loc[0]) + int(dim[0] / 2), int(loc[1]) + int(dim[1] / 2))) + top.title("Loading...") + top.resizable(False, False) + top.iconbitmap(helper.manifest_file('icon.ico')) - def waiting(): - q.get() - time.sleep(0.2) - running[0] = False - Thread(target=waiting).start() + canvas = tk.Canvas(top, width=dim[0], height=dim[1], bg='white') + canvas.pack() + top.image = Image.open(helper.manifest_file('fishybot_logo.png')).resize(dim) + top.image = ImageTk.PhotoImage(top.image) + canvas.create_image(0, 0, anchor=tk.NW, image=top.image) - running = [True] - while running[0]: - top.update() - time.sleep(0.1) + # Position splash at the center of the main window - top.destroy() - logging.debug("ended splash process") + default_loc = (str(top.winfo_reqwidth()) + "+" + str(top.winfo_reqheight()) + "+" + "0" + "0") + loc = (win_loc or default_loc).split(":")[-1].split("+")[1:] + top.geometry("{}x{}+{}+{}".format(dim[0], dim[1], int(loc[0]) + int(dim[0] / 2), int(loc[1]) + int(dim[1] / 2))) + def waiting(): + q.get() + time.sleep(0.2) + running[0] = False -def create_finish(q): - def finish(): - q.put("stop") + Thread(target=waiting).start() - return finish + running = [True] + while running[0]: + top.update() + time.sleep(0.1) - -def start(): - q = Queue() - Process(target=show, args=(config.get("win_loc"), q,)).start() - return create_finish(q) + top.destroy() + logging.debug("ended splash process")