From a2f91f3ca3f6c4aaaddafb8d273282a8031e9d97 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Sat, 4 May 2024 18:59:41 +0100 Subject: [PATCH 1/2] Improve documentation in default settings --- src/robotide/preferences/settings.cfg | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/robotide/preferences/settings.cfg b/src/robotide/preferences/settings.cfg index b252cc6af..ab51ee211 100644 --- a/src/robotide/preferences/settings.cfg +++ b/src/robotide/preferences/settings.cfg @@ -23,8 +23,9 @@ line separator = 'native' default file format = 'robot' tasks = False reformat = False -doc language = None # Test Suites will have sections and parameters in the selected language - # Possible values are the ones from Robot Framework >= 6.0. +# doc language: Test Suites will have sections and parameters in the selected language +# doc language: Possible values are the ones from Robot Framework >= 6.0. +doc language = None [General] @@ -38,6 +39,8 @@ background help = (240, 242, 80) foreground text = (7, 0, 70) apply to panels = True ui language = 'English' +# file manager: When set to full path or known command use it to open folders +;file manager = None [Text Edit] font size = 10 @@ -81,7 +84,8 @@ background error = '#FF9385' background highlight = '#FFFF77' word wrap = True enable auto suggestions = False -filter newlines = False # When enabled, newlines are not shown as \n in the cells. On Windows this may cause a lock. +# filter newlines: When enabled, newlines are not shown as \n in the cells. On Windows this may cause a lock. +filter newlines = False [Plugins] [[Test Runner]] From c598eecde2a33703d43485e0454a1f09062cc614 Mon Sep 17 00:00:00 2001 From: HelioGuilherme66 Date: Sat, 4 May 2024 23:03:54 +0100 Subject: [PATCH 2/2] Make custom File Manager working at Run tab. Code simplification --- README.adoc | 4 +- .../contrib/testrunner/testrunnerplugin.py | 42 ++------- src/robotide/controller/filecontrollers.py | 93 +++++++++---------- src/robotide/version.py | 2 +- utest/controller/test_filecontrollers.py | 64 ++++++++++--- 5 files changed, 102 insertions(+), 103 deletions(-) diff --git a/README.adoc b/README.adoc index ea9f1c412..85e2c32cb 100644 --- a/README.adoc +++ b/README.adoc @@ -33,14 +33,14 @@ See the https://github.com/robotframework/RIDE/blob/master/doc/releasenotes/ride **The current development version is based on 2.0.8.1, supports Python from 3.8 up to 3.12 (09th February 2024).** -Currently the unit tests are tested on Python 3.10, and 3.11 (which is the recommended version). +Currently the unit tests are tested on Python 3.10, and 3.12 (which is the recommended version). Likewise, the current version of wxPython, is 4.2.1, but RIDE is known to work with 4.0.7 and 4.1.1 versions. (3.6 < python <= 3.11) Install current released version (*2.0.8.1*) with: `pip install -U robotframework-ride` -(3.8 < python <= 3.12) Install current development version (**2.1dev30**) with: +(3.8 < python <= 3.12) Install current development version (**2.1dev31**) with: `pip install -U https://github.com/robotframework/RIDE/archive/master.zip` diff --git a/src/robotide/contrib/testrunner/testrunnerplugin.py b/src/robotide/contrib/testrunner/testrunnerplugin.py index ec9cfcd38..99d9ec560 100644 --- a/src/robotide/contrib/testrunner/testrunnerplugin.py +++ b/src/robotide/contrib/testrunner/testrunnerplugin.py @@ -72,6 +72,7 @@ from robotide.contrib.testrunner.FileWriter import FileWriter from robotide.contrib.testrunner.SettingsParser import SettingsParser from robotide.controller.macrocontrollers import TestCaseController +from robotide.controller.filecontrollers import start_filemanager from robotide.publish import RideSettingsChanged, PUBLISHER from robotide.publish.messages import RideTestSelectedForRunningChanged from robotide.pluginapi import Plugin, ActionInfo @@ -115,6 +116,7 @@ STYLE_PASS = 1 STYLE_SKIP = 3 STYLE_FAIL = 4 +FILE_MANAGER = 'file manager' ATEXIT_LOCK = threading.RLock() @@ -124,39 +126,6 @@ def _run_profile(name, run_prefix): {'name': name, 'get_command': lambda self: run_prefix}) -def open_filemanager(path=None): - path = path or os.path.curdir - path_dir = os.path.dirname(path) if os.path.isfile(path) else path - if os.path.exists(path_dir): - if platform == 'win32': - # There was encoding errors if directory had unicode chars - # DEBUG: test on all OS directory names with accented chars, for example 'ccedilla' - os.startfile(r"%s" % path_dir, 'explore') - elif platform.startswith('linux'): - # how to detect which explorer is used? - # nautilus, dolphin, konqueror - # DEBUG: check if explorer exists - # DEBUG: get prefered explorer from preferences - try: - subprocess.Popen(["nautilus", "{}".format(path_dir)]) - except OSError: - try: - subprocess.Popen( - ["dolphin", "{}".format(path_dir)]) - except OSError: - try: - subprocess.Popen( - ["konqueror", "{}".format(path_dir)]) - except OSError: - print("Could not launch explorer. Tried nautilus, " - "dolphin and konqueror.") - else: - try: - subprocess.Popen(["finder", "{}".format(path_dir)]) - except OSError: - subprocess.Popen(["open", "{}".format(path_dir)]) - - class TestRunnerPlugin(Plugin): __doc__ = _("""A plugin for running tests from within RIDE""") defaults = {"auto_save": False, @@ -514,8 +483,13 @@ def _clear_text_ctrl(text_ctrl): def on_open_logs_directory(self, event): """Called when the user clicks on the "Open Logs Directory" button""" __ = event + # Determine explorer defined tool + try: + tool = self.global_settings['General'][FILE_MANAGER] + except KeyError: + tool = None if os.path.exists(self._logs_directory): - open_filemanager(self._logs_directory) + start_filemanager(self._logs_directory, tool) else: self._notify_user_no_logs_directory() diff --git a/src/robotide/controller/filecontrollers.py b/src/robotide/controller/filecontrollers.py index eb5b7be6a..f967b306f 100644 --- a/src/robotide/controller/filecontrollers.py +++ b/src/robotide/controller/filecontrollers.py @@ -64,6 +64,47 @@ def data_controller(data, project, parent=None, tasks=False): return _get_controller(project, data, parent, tasks=tasks) +def explorer_linux(folder): + try: + subprocess.Popen(["nautilus", folder]) + except OSError: + try: + subprocess.Popen(["dolphin", folder]) + except OSError: + try: + subprocess.Popen(["konqueror", folder]) + except OSError: + print("Could not launch explorer. Tried nautilus, dolphin and konqueror.") + + +def explorer_mac(folder): + try: + subprocess.Popen(["finder", folder]) + except OSError: + subprocess.Popen(["open", folder]) + + +def start_filemanager(path=None, tool=None): + if not os.path.exists(path): + return + if not os.path.isfile(path): + folder = path + else: + folder = os.path.dirname(path) + if tool: + try: + subprocess.Popen([tool, folder]) + return + except OSError: + print(f"DEBUG: Error when launching tool={tool}") + if sys.platform == 'win32': + os.startfile(folder, 'explore') + elif sys.platform.startswith('linux'): + explorer_linux(folder) + else: + explorer_mac(folder) + + class _FileSystemElement(object): def __init__(self, filename, directory): @@ -341,59 +382,9 @@ def remove_readonly(self, path=None): path = path or self.filename os.chmod(path, stat.S_IWRITE) - @staticmethod - def _explorer_linux(path, tool): - if not os.path.isfile(path): - folder = path - else: - folder = os.path.dirname(path) - if tool: - try: - subprocess.Popen([tool, folder]) - # print(f"DEBUG: After starting _explorer_linux ={tool}") - return - except OSError: # : - print(f"DEBUG: Error when launching tool={tool}") - try: - subprocess.Popen(["nautilus", folder]) - except OSError: - try: - subprocess.Popen(["dolphin", folder]) - except OSError: - try: - subprocess.Popen(["konqueror", folder]) - except OSError: - print("Could not launch explorer. Tried nautilus, dolphin and konqueror.") - def open_filemanager(self, path=None, tool=None): path = path or self.filename - if not os.path.exists(path): - return - if not os.path.isfile(path): - folder = path - else: - folder = os.path.dirname(path) - if sys.platform == 'win32': - if tool: - try: - subprocess.Popen([tool, folder]) - return - except OSError: - print(f"DEBUG: Error when launching tool={tool}") - os.startfile(folder, 'explore') - elif sys.platform.startswith('linux'): - self._explorer_linux(folder, tool) - else: - if tool: - try: - subprocess.Popen([tool, folder]) - return - except OSError: - print(f"DEBUG: Error when launching tool={tool}") - try: - subprocess.Popen(["finder", folder]) - except OSError: - subprocess.Popen(["open", folder]) + start_filemanager(path, tool) def remove_from_filesystem(self, path=None): path = path or self.filename diff --git a/src/robotide/version.py b/src/robotide/version.py index 8db17c120..7bb723f72 100644 --- a/src/robotide/version.py +++ b/src/robotide/version.py @@ -14,4 +14,4 @@ # limitations under the License. # # Automatically generated by `tasks.py`. -VERSION = 'v2.1dev30' +VERSION = 'v2.1dev31' diff --git a/utest/controller/test_filecontrollers.py b/utest/controller/test_filecontrollers.py index a487e68cc..735e1f645 100644 --- a/utest/controller/test_filecontrollers.py +++ b/utest/controller/test_filecontrollers.py @@ -20,9 +20,9 @@ from robotide.robotapi import TestCase, TestCaseFile, TestDataDirectory from robotide.controller.filecontrollers import TestCaseFileController, \ - TestDataDirectoryController, _FileSystemElement + TestDataDirectoryController, _FileSystemElement, start_filemanager, explorer_linux, explorer_mac from robotide.controller.macrocontrollers import TestCaseController -from robotide.controller.ctrlcommands import AddTestCaseFile, AddTestDataDirectory,\ +from robotide.controller.ctrlcommands import AddTestCaseFile, AddTestDataDirectory, \ SortKeywords, SortTests, SortVariables, Undo, Redo from robotide.publish import PUBLISHER from robotide.publish.messages import RideDataChangedToDirty, RideDataDirtyCleared @@ -69,13 +69,13 @@ def test_remarking_data_dirty_does_not_publish_data_has_changes_message(self): self.ctrl.mark_dirty() self._has_unsaved_changes = None self.ctrl.mark_dirty() - assert self._has_unsaved_changes == None + assert self._has_unsaved_changes is None def test_reclearing_dirty_mark_does_not_publish_data_saved_message(self): self.ctrl.unmark_dirty() self._saved = None self.ctrl.unmark_dirty() - assert self._saved == None + assert self._saved is None class TestCaseFileControllerTest(unittest.TestCase): @@ -102,7 +102,7 @@ def test_source(self): def test_longname(self): assert self.ctrl.longname == 'Test.Cases' - self.ctrl.parent = lambda:0 + self.ctrl.parent = lambda: 0 self.ctrl.parent.longname = 'Parent' assert self.ctrl.longname == 'Parent.Test.Cases' @@ -179,6 +179,8 @@ def test_resource_file_display_name_is_file_name_with_extension(self): def test_sort_and_restore_keywords(self): resource_ctrl = self._get_ctrl_by_name(datafilereader.SIMPLE_TEST_SUITE_RESOURCE_NAME) + assert resource_ctrl is not None + # Capture keyword list before sorting original_keywords = self.ctrl.get_keyword_names() list_for_undo_comparison = original_keywords[:] @@ -261,7 +263,7 @@ def test_set_format(self): def test_longname(self): ctrl = TestDataDirectoryController(self.data) assert ctrl.longname == 'Source' - ctrl.parent = lambda:0 + ctrl.parent = lambda: 0 ctrl.parent.longname = 'Parent' assert ctrl.longname == 'Parent.Source' @@ -290,7 +292,7 @@ def test_adding_test_data_directory_using_command(self): assert suite.data.parent == ctrl.data def test_exclude(self): - parent = lambda:0 + parent = lambda: 0 project = self._mock_project() ctrl = TestDataDirectoryController(self.data, project, parent) parent.children = [ctrl] @@ -300,12 +302,12 @@ def test_exclude(self): self.assertTrue(self.called) def _mock_project(self): - project = lambda:0 - project.namespace = lambda:0 - project.resource_file_controller_factory = lambda:0 - project.is_datafile_dirty = lambda *_:False - project.internal_settings = lambda:0 - project.internal_settings.excludes = lambda:0 + project = lambda: 0 + project.namespace = lambda: 0 + project.resource_file_controller_factory = lambda: 0 + project.is_datafile_dirty = lambda *_: False + project.internal_settings = lambda: 0 + project.internal_settings.excludes = lambda: 0 self.called = False def update_excludes(new_excludes): @@ -334,8 +336,7 @@ def __call__(self, controller): if controller.filename and controller.filename.endswith('test.robot'): self.in_sub_dir = True check_count_and_sub_dir = Checker() - [check_count_and_sub_dir(df) for df - in self.directory_controller.iter_datafiles()] + [check_count_and_sub_dir(df) for df in self.directory_controller.iter_datafiles()] assert check_count_and_sub_dir.iteration_count == 5 assert check_count_and_sub_dir.in_sub_dir @@ -349,5 +350,38 @@ def test_relative_path_to(self): self.assertEqual('../bar/foo.robot', fse2.relative_path_to(fse1)) +class TestFileManager(unittest.TestCase): + + def test_explorer_linux(self): + try: + explorer_linux('this_path_does_not_exist') + except Exception as e: + print(f"DEBUG: TestFileManager raised ERROR {e}") + + def test_explorer_mac(self): + try: + explorer_mac('this_path_does_not_exist') + except Exception as e: + print(f"DEBUG: TestFileManager raised ERROR {e}") + + def test_start_filemanager_bad_path(self): + try: + start_filemanager(path='this_path_does_not_exist') + except Exception as e: + print(f"DEBUG: TestFileManager raised ERROR {e}") + + def test_start_filemanager_bad_tool(self): + try: + start_filemanager(path=__file__, tool='this_tool_does_not_exist') + except Exception as e: + print(f"DEBUG: TestFileManager raised ERROR {e}") + + def test_start_filemanager_good_path(self): + try: + start_filemanager(path=__file__) + except Exception as e: + print(f"DEBUG: TestFileManager raised ERROR {e}") + + if __name__ == '__main__': unittest.main()