Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update settings and make custom File Manager available in Run tab #2758

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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 &lt;= 3.11) Install current released version (*2.0.8.1*) with:

`pip install -U robotframework-ride`

(3.8 < python &lt;= 3.12) Install current development version (**2.1dev30**) with:
(3.8 < python &lt;= 3.12) Install current development version (**2.1dev31**) with:

`pip install -U https://github.com/robotframework/RIDE/archive/master.zip`

Expand Down
42 changes: 8 additions & 34 deletions src/robotide/contrib/testrunner/testrunnerplugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -115,6 +116,7 @@
STYLE_PASS = 1
STYLE_SKIP = 3
STYLE_FAIL = 4
FILE_MANAGER = 'file manager'

ATEXIT_LOCK = threading.RLock()

Expand All @@ -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,
Expand Down Expand Up @@ -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()

Expand Down
93 changes: 42 additions & 51 deletions src/robotide/controller/filecontrollers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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
Expand Down
10 changes: 7 additions & 3 deletions src/robotide/preferences/settings.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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
Expand Down Expand Up @@ -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]]
Expand Down
2 changes: 1 addition & 1 deletion src/robotide/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
# limitations under the License.
#
# Automatically generated by `tasks.py`.
VERSION = 'v2.1dev30'
VERSION = 'v2.1dev31'
64 changes: 49 additions & 15 deletions utest/controller/test_filecontrollers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand All @@ -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'

Expand Down Expand Up @@ -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[:]
Expand Down Expand Up @@ -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'

Expand Down Expand Up @@ -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]
Expand All @@ -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):
Expand Down Expand Up @@ -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

Expand All @@ -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()
Loading