diff --git a/src/__builtins__.py b/src/__builtins__.py index 7dc3a0e..2ccc2b4 100644 --- a/src/__builtins__.py +++ b/src/__builtins__.py @@ -48,4 +48,3 @@ builtins.logger = Logger(settings_manager.get_home_config_path(), \ builtins.threaded = threaded_wrapper builtins.daemon_threaded = daemon_threaded_wrapper -builtins.event_sleep_time = 0.05 \ No newline at end of file diff --git a/src/app.py b/src/app.py index f0d74f3..91d9532 100644 --- a/src/app.py +++ b/src/app.py @@ -1,9 +1,11 @@ # Python imports +import signal import os # Lib imports # Application imports +from utils.debugging import debug_signal_handler from utils.ipc_server import IPCServer from core.window import Window @@ -23,7 +25,7 @@ class Application(IPCServer): try: self.create_ipc_listener() except Exception: - ... + self.socket_realization_check() if not self.is_ipc_alive: for arg in unknownargs + [args.new_tab,]: @@ -33,4 +35,22 @@ class Application(IPCServer): raise AppLaunchException(f"{app_name} IPC Server Exists: Will send path(s) to it and close...") + self.setup_debug_hook() + Window(args, unknownargs) + + + def socket_realization_check(self): + self.send_test_ipc_message() + self.create_ipc_listener() + + def setup_debug_hook(self): + try: + # kill -SIGUSR2 from Linux/Unix or SIGBREAK signal from Windows + signal.signal( + vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR1"), + debug_signal_handler + ) + except ValueError: + # Typically: ValueError: signal only works in main thread + ... diff --git a/src/core/controller.py b/src/core/controller.py index b2de605..2fb6781 100644 --- a/src/core/controller.py +++ b/src/core/controller.py @@ -49,6 +49,7 @@ class Controller(SignalsMixins, ControllerData): self.window.connect("key-release-event", self.on_global_key_release_controller) def _subscribe_to_events(self): + event_system.subscribe("shutting_down", lambda: print("Shutting down...")) event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc) event_system.subscribe("set_active_src_view", self.set_active_src_view) event_system.subscribe("get_active_src_view", self.get_active_src_view) diff --git a/src/core/widgets/base/notebook/editor_controller.py b/src/core/widgets/base/notebook/editor_controller.py index e3fcdd4..93d894b 100644 --- a/src/core/widgets/base/notebook/editor_controller.py +++ b/src/core/widgets/base/notebook/editor_controller.py @@ -50,10 +50,10 @@ class EditorControllerMixin: self.keyboard_insert_mark(source_view) if action == "keyboard_clear_marks": self.keyboard_clear_marks(source_view) - if action == "move_lines_up": - self.move_lines_up(source_view) - if action == "move_lines_down": - self.move_lines_down(source_view) + if action == "keyboard_move_lines_up": + self.keyboard_move_lines_up(source_view) + if action == "keyboard_move_lines_down": + self.keyboard_move_lines_down(source_view) if action == "set_buffer_language": self.set_buffer_language(source_view, query) if action == "set_buffer_style": @@ -61,4 +61,4 @@ class EditorControllerMixin: if action == "save_file": source_view.save_file() if action == "save_file_as": - source_view.save_file_as() \ No newline at end of file + source_view.save_file_as() diff --git a/src/core/widgets/base/notebook/editor_events.py b/src/core/widgets/base/notebook/editor_events.py index 0879830..c1dc5be 100644 --- a/src/core/widgets/base/notebook/editor_events.py +++ b/src/core/widgets/base/notebook/editor_events.py @@ -122,14 +122,14 @@ class EditorEventsMixin: def keyboard_clear_marks(self, source_view): source_view.keyboard_clear_marks() - def move_lines_up(self, source_view): - source_view.move_lines_up() + def keyboard_move_lines_up(self, source_view): + source_view.keyboard_move_lines_up() - def move_lines_down(self, source_view): - source_view.move_lines_down() + def keyboard_move_lines_down(self, source_view): + source_view.keyboard_move_lines_down() def set_buffer_language(self, source_view, language = "python3"): source_view.set_buffer_language(language) def set_buffer_style(self, source_view, style = settings.theming.syntax_theme): - source_view.set_buffer_style(style) \ No newline at end of file + source_view.set_buffer_style(style) diff --git a/src/core/widgets/base/notebook/editor_notebook.py b/src/core/widgets/base/notebook/editor_notebook.py index c28a1fa..a795f7f 100644 --- a/src/core/widgets/base/notebook/editor_notebook.py +++ b/src/core/widgets/base/notebook/editor_notebook.py @@ -63,27 +63,29 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook): event_system.subscribe("set_buffer_style", self.action_controller) event_system.subscribe("set_buffer_language", self.action_controller) event_system.subscribe("set_buffer_style", self.action_controller) - event_system.subscribe("toggle_highlight_line", self._toggle_highlight_line) - event_system.subscribe("move_lines_up", self._move_lines_up) - event_system.subscribe("move_lines_down", self._move_lines_down) + + event_system.subscribe("focused_target_changed", self._focused_target_changed) event_system.subscribe("keyboard_create_tab", self._keyboard_create_tab) event_system.subscribe("keyboard_open_file", self._keyboard_open_file) event_system.subscribe("keyboard_close_tab", self._keyboard_close_tab) - event_system.subscribe("keyboard_undo", self._keyboard_undo) - event_system.subscribe("keyboard_redo", self._keyboard_redo) event_system.subscribe("keyboard_prev_tab", self._keyboard_prev_tab) event_system.subscribe("keyboard_next_tab", self._keyboard_next_tab) event_system.subscribe("keyboard_move_tab_left", self._keyboard_move_tab_left) event_system.subscribe("keyboard_move_tab_right", self._keyboard_move_tab_right) - event_system.subscribe("keyboard_insert_mark", self._keyboard_insert_mark) - event_system.subscribe("keyboard_clear_marks", self._keyboard_clear_marks) event_system.subscribe("keyboard_move_tab_to_1", self._keyboard_move_tab_to_1) event_system.subscribe("keyboard_move_tab_to_2", self._keyboard_move_tab_to_2) + + event_system.subscribe("toggle_highlight_line", self._toggle_highlight_line) + event_system.subscribe("keyboard_move_lines_up", self._keyboard_move_lines_up) + event_system.subscribe("keyboard_move_lines_down", self._keyboard_move_lines_down) + event_system.subscribe("keyboard_undo", self._keyboard_undo) + event_system.subscribe("keyboard_redo", self._keyboard_redo) + event_system.subscribe("keyboard_insert_mark", self._keyboard_insert_mark) + event_system.subscribe("keyboard_clear_marks", self._keyboard_clear_marks) event_system.subscribe("keyboard_scale_up_text", self._keyboard_scale_up_text) event_system.subscribe("keyboard_scale_down_text", self._keyboard_scale_down_text) event_system.subscribe("keyboard_save_file", self._keyboard_save_file) event_system.subscribe("keyboard_save_file_as", self._keyboard_save_file_as) - event_system.subscribe("focused_target_changed", self._focused_target_changed) def _focused_target_changed(self, target): @@ -184,11 +186,11 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook): def _keyboard_insert_mark(self): self.action_controller("keyboard_insert_mark") - def _move_lines_up(self): - self.action_controller("move_lines_up") + def _keyboard_move_lines_up(self): + self.action_controller("keyboard_move_lines_up") - def _move_lines_down(self): - self.action_controller("move_lines_down") + def _keyboard_move_lines_down(self): + self.action_controller("keyboard_move_lines_down") def _keyboard_clear_marks(self): self.action_controller("keyboard_clear_marks") @@ -212,4 +214,4 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook): self.action_controller("save_file") def _keyboard_save_file_as(self): - self.action_controller("save_file_as") \ No newline at end of file + self.action_controller("save_file_as") diff --git a/src/core/widgets/base/sourceview/source_view_events.py b/src/core/widgets/base/sourceview/source_view_events.py index 6026273..865cf42 100644 --- a/src/core/widgets/base/sourceview/source_view_events.py +++ b/src/core/widgets/base/sourceview/source_view_events.py @@ -88,10 +88,10 @@ class SourceViewEventsMixin(MarkEventsMixin, FileEventsMixin): def keyboard_redo(self): self._buffer.redo() - def move_lines_up(self): + def keyboard_move_lines_up(self): self.emit("move-lines", *(False,)) - def move_lines_down(self): + def keyboard_move_lines_down(self): self.emit("move-lines", *(True,)) def update_labels(self, gfile = None): @@ -105,4 +105,4 @@ class SourceViewEventsMixin(MarkEventsMixin, FileEventsMixin): if not gfile: return event_system.emit("set_bottom_labels", (gfile, None, self._current_filetype, None)) - self.update_cursor_position() \ No newline at end of file + self.update_cursor_position() diff --git a/src/core/window.py b/src/core/window.py index d9c0ead..17e98ef 100644 --- a/src/core/window.py +++ b/src/core/window.py @@ -100,6 +100,8 @@ class Window(Gtk.ApplicationWindow): def _tear_down(self, widget=None, eve=None): + event_system.emit("shutting_down") + size = self.get_size() pos = self.get_position() @@ -110,5 +112,4 @@ class Window(Gtk.ApplicationWindow): settings_manager.save_settings() settings_manager.clear_pid() - time.sleep(event_sleep_time) Gtk.main_quit() diff --git a/src/utils/debugging.py b/src/utils/debugging.py new file mode 100644 index 0000000..b84193a --- /dev/null +++ b/src/utils/debugging.py @@ -0,0 +1,52 @@ +# Python imports + +# Lib imports + +# Application imports + + + +# Break into a Python console upon SIGUSR1 (Linux) or SIGBREAK (Windows: +# CTRL+Pause/Break). To be included in all production code, just in case. +def debug_signal_handler(signal, frame): + del signal + del frame + + try: + import rpdb2 + logger.debug("\n\nStarting embedded RPDB2 debugger. Password is 'foobar'\n\n") + rpdb2.start_embedded_debugger("foobar", True, True) + rpdb2.setbreak(depth=1) + return + except StandardError: + ... + + try: + from rfoo.utils import rconsole + logger.debug("\n\nStarting embedded rconsole debugger...\n\n") + rconsole.spawn_server() + return + except StandardError as ex: + ... + + try: + from pudb import set_trace + logger.debug("\n\nStarting PuDB debugger...\n\n") + set_trace(paused = True) + return + except StandardError as ex: + ... + + try: + import pdb + logger.debug("\n\nStarting embedded PDB debugger...\n\n") + pdb.Pdb(skip=['gi.*']).set_trace() + return + except StandardError as ex: + ... + + try: + import code + code.interact() + except StandardError as ex: + logger.debug(f"{ex}, returning to normal program flow...") diff --git a/src/utils/ipc_server.py b/src/utils/ipc_server.py index 2ad105f..ef5b7ba 100644 --- a/src/utils/ipc_server.py +++ b/src/utils/ipc_server.py @@ -44,13 +44,12 @@ class IPCServer: if os.path.exists(self._ipc_address) and settings.is_dirty_start(): os.unlink(self._ipc_address) - listener = Listener(address=self._ipc_address, family="AF_UNIX", authkey=self._ipc_authkey) + listener = Listener(address = self._ipc_address, family = "AF_UNIX", authkey = self._ipc_authkey) elif "unsecured" not in self._conn_type: - listener = Listener((self._ipc_address, self._ipc_port), authkey=self._ipc_authkey) + listener = Listener((self._ipc_address, self._ipc_port), authkey = self._ipc_authkey) else: listener = Listener((self._ipc_address, self._ipc_port)) - self.is_ipc_alive = True self._run_ipc_loop(listener) @@ -62,7 +61,7 @@ class IPCServer: start_time = time.perf_counter() GLib.idle_add(self._handle_ipc_message, *(conn, start_time,)) except Exception as e: - ... + logger.debug( repr(e) ) listener.close() @@ -103,6 +102,25 @@ class IPCServer: conn.send(message) conn.close() except ConnectionRefusedError as e: - print("Connection refused...") + logger.error("Connection refused...") except Exception as e: - print(repr(e)) + logger.error( repr(e) ) + + + def send_test_ipc_message(self, message: str = "Empty Data...") -> None: + try: + if self._conn_type == "socket": + conn = Client(address=self._ipc_address, family="AF_UNIX", authkey=self._ipc_authkey) + elif "unsecured" not in self._conn_type: + conn = Client((self._ipc_address, self._ipc_port), authkey=self._ipc_authkey) + else: + conn = Client((self._ipc_address, self._ipc_port)) + + conn.send(message) + conn.close() + except ConnectionRefusedError as e: + if self._conn_type == "socket": + logger.error("IPC Socket no longer valid.... Removing.") + os.unlink(self._ipc_address) + except Exception as e: + logger.error( repr(e) )