From 3e31d29e2640f41f437042ca36520ec2bae4ebba Mon Sep 17 00:00:00 2001 From: BigBoyBarney Date: Fri, 12 Jan 2024 13:29:20 +0100 Subject: [PATCH 1/7] Initial unification of open-folder command. - Moved main open function to `utils.py` - Changed `usr/bin/xdg-open` to `xdg-open` --- trackma/ui/cli.py | 27 ++------------------------- trackma/ui/curses.py | 22 +--------------------- trackma/ui/gtk/window.py | 24 +----------------------- trackma/ui/qt/mainwindow.py | 21 +-------------------- trackma/utils.py | 31 +++++++++++++++++++++++++++++++ 5 files changed, 36 insertions(+), 89 deletions(-) diff --git a/trackma/ui/cli.py b/trackma/ui/cli.py index 76ed5b4d..c22f8d4c 100644 --- a/trackma/ui/cli.py +++ b/trackma/ui/cli.py @@ -523,31 +523,8 @@ def do_play(self, args): self.display_error(e) def do_openfolder(self, args): - """ - Opens the folder containing the show - - :param show Show index or name. - :usage openfolder - """ - - try: - show = self._get_show(args[0]) - filename = self.engine.get_episode_path(show) - with open(os.devnull, 'wb') as DEVNULL: - if sys.platform == 'darwin': - subprocess.Popen(["open", - os.path.dirname(filename)], stdout=DEVNULL, stderr=DEVNULL) - elif sys.platform == 'win32': - subprocess.Popen(["explorer", - os.path.dirname(filename)], stdout=DEVNULL, stderr=DEVNULL) - else: - subprocess.Popen(["/usr/bin/xdg-open", - os.path.dirname(filename)], stdout=DEVNULL, stderr=DEVNULL) - except OSError: - # xdg-open failed. - self.display_error("Could not open folder.") - except utils.TrackmaError as e: - self.display_error(e) + show = self._get_show(args[0]) + utils.open_folder(self.engine, show.id, error_callback=self.display_error) def do_update(self, args): """ diff --git a/trackma/ui/curses.py b/trackma/ui/curses.py index 7b7f3a1b..b4a48d4d 100644 --- a/trackma/ui/curses.py +++ b/trackma/ui/curses.py @@ -365,27 +365,7 @@ def do_play(self): def do_openfolder(self): item = self._get_selected_item() - - try: - show = self.engine.get_show_info(item.showid) - filename = self.engine.get_episode_path(show) - with open(os.devnull, 'wb') as DEVNULL: - if sys.platform == 'darwin': - subprocess.Popen(["open", - os.path.dirname(filename)], stdout=DEVNULL, stderr=DEVNULL) - elif sys.platform == 'win32': - subprocess.Popen(["explorer", - os.path.dirname(filename)], stdout=DEVNULL, stderr=DEVNULL) - else: - subprocess.Popen(["/usr/bin/xdg-open", - os.path.dirname(filename)], stdout=DEVNULL, stderr=DEVNULL) - except OSError: - # xdg-open failed. - raise utils.EngineError("Could not open folder.") - - except utils.EngineError: - # Show not in library. - self.error("No folder found.") + utils.open_folder(self.engine, item.showid, error_callback=self.error) def do_play_random(self): try: diff --git a/trackma/ui/gtk/window.py b/trackma/ui/gtk/window.py index dcebccb3..5cfb2037 100644 --- a/trackma/ui/gtk/window.py +++ b/trackma/ui/gtk/window.py @@ -573,29 +573,7 @@ def _open_website(self, show_id): Gtk.show_uri(None, show['url'], Gdk.CURRENT_TIME) def _open_folder(self, show_id): - show = self._engine.get_show_info(show_id) - try: - filename = self._engine.get_episode_path(show) - with open(os.devnull, 'wb') as DEVNULL: - if sys.platform == 'darwin': - subprocess.Popen(["open", os.path.dirname(filename)], - stdout=DEVNULL, - stderr=DEVNULL) - elif sys.platform == 'win32': - subprocess.Popen(["explorer", os.path.dirname(filename)], - stdout=DEVNULL, - stderr=DEVNULL) - else: - subprocess.Popen(["/usr/bin/xdg-open", os.path.dirname(filename)], - stdout=DEVNULL, - stderr=DEVNULL) - except OSError: - # xdg-open failed. - raise utils.EngineError("Could not open folder.") - - except utils.EngineError: - # Show not in library. - self._error_dialog_idle("No folder found.") + utils.open_folder(self._engine, show_id, error_callback=self._error_dialog_idle) def _copy_title(self, show_id): show = self._engine.get_show_info(show_id) diff --git a/trackma/ui/qt/mainwindow.py b/trackma/ui/qt/mainwindow.py index d08db66f..db51103d 100644 --- a/trackma/ui/qt/mainwindow.py +++ b/trackma/ui/qt/mainwindow.py @@ -1183,26 +1183,7 @@ def s_altname(self): self.ws_changed_show(show, altname=new_altname) def s_open_folder(self): - show = self.worker.engine.get_show_info(self.selected_show_id) - try: - filename = self.worker.engine.get_episode_path(show) - with open(os.devnull, 'wb') as DEVNULL: - if sys.platform == 'darwin': - subprocess.Popen(["open", - os.path.dirname(filename)], stdout=DEVNULL, stderr=DEVNULL) - elif sys.platform == 'win32': - subprocess.Popen(["explorer", - os.path.dirname(filename)], stdout=DEVNULL, stderr=DEVNULL) - else: - subprocess.Popen(["/usr/bin/xdg-open", - os.path.dirname(filename)], stdout=DEVNULL, stderr=DEVNULL) - except OSError: - # xdg-open failed. - raise utils.EngineError("Could not open folder.") - - except utils.EngineError: - # Show not in library. - self.error("No folder found.") + utils.open_folder(self.worker.engine, self.selected_show_id, error_callback=self.error) def s_retrieve(self): queue = self.worker.engine.get_queue() diff --git a/trackma/utils.py b/trackma/utils.py index c4ddd309..a4c94ccd 100644 --- a/trackma/utils.py +++ b/trackma/utils.py @@ -490,6 +490,37 @@ def get_terminal_size(fd=1): return hw +def open_folder(engine, show_id, error_callback=None): + try: + show_to_open = engine.get_show_info(show_id) + filename = engine.get_episode_path(show_to_open) + with open(os.devnull, 'wb') as DEVNULL: + if sys.platform == 'darwin': + subprocess.Popen(["open", os.path.dirname(filename)], + stdout=DEVNULL, + stderr=DEVNULL) + elif sys.platform == 'win32': + subprocess.Popen(["explorer", os.path.dirname(filename)], + stdout=DEVNULL, + stderr=DEVNULL) + else: + subprocess.Popen(["xdg-open", os.path.dirname(filename)], + stdout=DEVNULL, + stderr=DEVNULL) + except OSError: + # Open failed. + if error_callback: + error_callback("Could not open folder.") + else: + raise EngineError("Could not open folder.") + except EngineError: + # Show not in library. + if error_callback: + error_callback("No folder found.") + else: + raise EngineError("No folder found.") + + def show(): return { 'id': 0, From dd4b7cc94843cbc9eeaa32298d9163e5ed9d7dcb Mon Sep 17 00:00:00 2001 From: BigBoyBarney Date: Fri, 12 Jan 2024 14:13:35 +0100 Subject: [PATCH 2/7] Fixed CLI open-folder - Now correctly passes ID --- trackma/ui/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trackma/ui/cli.py b/trackma/ui/cli.py index c22f8d4c..dfec50dc 100644 --- a/trackma/ui/cli.py +++ b/trackma/ui/cli.py @@ -523,8 +523,8 @@ def do_play(self, args): self.display_error(e) def do_openfolder(self, args): - show = self._get_show(args[0]) - utils.open_folder(self.engine, show.id, error_callback=self.display_error) + show_id = self._get_show(args[0])['id'] + utils.open_folder(self.engine, show_id, error_callback=self.display_error) def do_update(self, args): """ From 183a803dc5a04fa5e099a4d990e7c2e411cbfc4d Mon Sep 17 00:00:00 2001 From: BigBoyBarney Date: Fri, 12 Jan 2024 14:21:28 +0100 Subject: [PATCH 3/7] Fixed CLI out of range ID call --- trackma/ui/cli.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/trackma/ui/cli.py b/trackma/ui/cli.py index dfec50dc..8784f2c0 100644 --- a/trackma/ui/cli.py +++ b/trackma/ui/cli.py @@ -523,8 +523,11 @@ def do_play(self, args): self.display_error(e) def do_openfolder(self, args): - show_id = self._get_show(args[0])['id'] - utils.open_folder(self.engine, show_id, error_callback=self.display_error) + try: + show_id = self._get_show(args[0])['id'] + utils.open_folder(self.engine, show_id, error_callback=self.display_error) + except utils.TrackmaError as e: + self.display_error(e) def do_update(self, args): """ From f031c43733e9e98a7822348e831c2de53d47d92a Mon Sep 17 00:00:00 2001 From: BigBoyBarney Date: Fri, 12 Jan 2024 14:44:45 +0100 Subject: [PATCH 4/7] Simplified errors --- trackma/utils.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/trackma/utils.py b/trackma/utils.py index a4c94ccd..4f994361 100644 --- a/trackma/utils.py +++ b/trackma/utils.py @@ -507,18 +507,11 @@ def open_folder(engine, show_id, error_callback=None): subprocess.Popen(["xdg-open", os.path.dirname(filename)], stdout=DEVNULL, stderr=DEVNULL) - except OSError: - # Open failed. + except Exception as e: if error_callback: - error_callback("Could not open folder.") + error_callback(e) else: - raise EngineError("Could not open folder.") - except EngineError: - # Show not in library. - if error_callback: - error_callback("No folder found.") - else: - raise EngineError("No folder found.") + raise e def show(): From 9a61d2840bf09c0b9fecde14fdcb65891b3ac005 Mon Sep 17 00:00:00 2001 From: BigBoyBarney Date: Fri, 12 Jan 2024 15:00:27 +0100 Subject: [PATCH 5/7] Raise errors when folders change during runtime - OSError is raised even if the folder was initially successfully read into the librbary, but is no longer available during runtime --- trackma/utils.py | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/trackma/utils.py b/trackma/utils.py index 4f994361..26eff010 100644 --- a/trackma/utils.py +++ b/trackma/utils.py @@ -494,19 +494,29 @@ def open_folder(engine, show_id, error_callback=None): try: show_to_open = engine.get_show_info(show_id) filename = engine.get_episode_path(show_to_open) + with open(os.devnull, 'wb') as DEVNULL: - if sys.platform == 'darwin': - subprocess.Popen(["open", os.path.dirname(filename)], - stdout=DEVNULL, - stderr=DEVNULL) - elif sys.platform == 'win32': - subprocess.Popen(["explorer", os.path.dirname(filename)], - stdout=DEVNULL, - stderr=DEVNULL) - else: - subprocess.Popen(["xdg-open", os.path.dirname(filename)], - stdout=DEVNULL, - stderr=DEVNULL) + command = [] + + match sys.platform: + case 'darwin': + command = ["open", os.path.dirname(filename)] + case 'win32': + command = ["explorer", os.path.dirname(filename)] + case _: + command = ["xdg-open", os.path.dirname(filename)] + + process = subprocess.Popen(command, + stdout=DEVNULL, + stderr=subprocess.PIPE, + universal_newlines=True) + + _, stderr = process.communicate() + + if process.returncode != 0: + # Command failed. + raise OSError(stderr) + except Exception as e: if error_callback: error_callback(e) @@ -514,6 +524,7 @@ def open_folder(engine, show_id, error_callback=None): raise e + def show(): return { 'id': 0, From 1d9477a07c286e1b6d1c52e0ab6a023734d3606e Mon Sep 17 00:00:00 2001 From: BigBoyBarney Date: Fri, 12 Jan 2024 15:11:17 +0100 Subject: [PATCH 6/7] Added clearer OSError message --- trackma/utils.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/trackma/utils.py b/trackma/utils.py index 26eff010..351a509d 100644 --- a/trackma/utils.py +++ b/trackma/utils.py @@ -517,6 +517,12 @@ def open_folder(engine, show_id, error_callback=None): # Command failed. raise OSError(stderr) + except OSError as e: + if error_callback: + error_callback(f'Could not open folder.\n{e}') + else: + raise e + except Exception as e: if error_callback: error_callback(e) @@ -524,7 +530,6 @@ def open_folder(engine, show_id, error_callback=None): raise e - def show(): return { 'id': 0, From b0e48219401e8ff0a726ce860cc547d2875b7424 Mon Sep 17 00:00:00 2001 From: BigBoyBarney Date: Fri, 12 Jan 2024 15:22:18 +0100 Subject: [PATCH 7/7] Added comments --- trackma/ui/cli.py | 7 +++++++ trackma/utils.py | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/trackma/ui/cli.py b/trackma/ui/cli.py index 8784f2c0..36cefec1 100644 --- a/trackma/ui/cli.py +++ b/trackma/ui/cli.py @@ -523,6 +523,13 @@ def do_play(self, args): self.display_error(e) def do_openfolder(self, args): + """ + Opens the folder containing the show + + :param show Show index or name. + :usage openfolder + """ + try: show_id = self._get_show(args[0])['id'] utils.open_folder(self.engine, show_id, error_callback=self.display_error) diff --git a/trackma/utils.py b/trackma/utils.py index 351a509d..61f6d1a1 100644 --- a/trackma/utils.py +++ b/trackma/utils.py @@ -490,7 +490,14 @@ def get_terminal_size(fd=1): return hw +# Default 'open folder' function def open_folder(engine, show_id, error_callback=None): + """ + Tries to open the folder containing the show of the passed ID. + Takes an optional 'error_callback' parameter that lets the invoker specify an error callback method. + If no error callback is passed, it defaults to simply raising. + """ + try: show_to_open = engine.get_show_info(show_id) filename = engine.get_episode_path(show_to_open)