Skip to content

Backward compatible #2934

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

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
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to http://semver.org/spec/v2.0.0.html[Semantic Versioni
when selecting in Tree shows the filename in StatusBar.

=== Changed
- Modified import statements to allow running RIDE without Robot Framework installed or versions older than 6.0.
- On Windows ignore false modification on files when opening Test Suites, causing confirmation dialog.

== https://github.com/robotframework/RIDE/blob/master/doc/releasenotes/ride-2.1.3.rst[2.1.3] - 2025-03-24
Expand Down
2 changes: 1 addition & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Likewise, the current version of wxPython, is 4.2.2, but RIDE is known to work w

`pip install -U robotframework-ride`

(3.8 <= python <= 3.13) Install current development version (**2.2dev17**) with:
(3.8 <= python <= 3.13) Install current development version (**2.2dev18**) with:

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

Expand Down
2 changes: 2 additions & 0 deletions src/robotide/application/CHANGELOG.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
Added divided Status Bar. Left side for main window, right side for Plugins. Working example in Text Editor,
when selecting in Tree shows the filename in StatusBar.
</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="_changed"></a>1.2. Changed</h3></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
Modified import statements to allow running RIDE without Robot Framework installed or versions older than 6.0.
</li><li class="listitem">
On Windows ignore false modification on files when opening Test Suites, causing confirmation dialog.
</li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="_ulink_url_https_github_com_robotframework_ride_blob_master_doc_releasenotes_ride_2_1_3_rst_2_1_3_ulink_2025_03_24"></a>2. <a class="ulink" href="https://github.com/robotframework/RIDE/blob/master/doc/releasenotes/ride-2.1.3.rst" target="_top">2.1.3</a> - 2025-03-24</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="_added_2"></a>2.1. Added</h3></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
Added syntax colorization for the ``GROUP`` marker.
Expand Down
3 changes: 2 additions & 1 deletion src/robotide/application/releasenotes.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ def set_content(self, html_win, content):
</ul>
<p><strong>New Features and Fixes Highlights</strong></p>
<ul class="simple">
<li>Modified import statements to allow running RIDE without Robot Framework installed or versions older than 6.0.</li>
<li>Added Config Panel button to supported installed Plugins next to their name in Plugin Manager dialog.</li>
<li>Added Config Panel button to Plugins, working example in Text Editor.</li>
<li>On Windows ignore false modification on files when opening Test Suites, causing confirmation dialog.</li>
Expand Down Expand Up @@ -229,7 +230,7 @@ def set_content(self, html_win, content):
<pre class="literal-block">python -m robotide.postinstall -install</pre>
<p>or</p>
<pre class="literal-block">ride_postinstall.py -install</pre>
<p>RIDE {VERSION} was released on 30/March/2025.</p>
<p>RIDE {VERSION} was released on 02/April/2025.</p>
<!-- <br/>
<h3>May The Fourth Be With You!</h3>
<h3>Celebrate the bank holiday, 10th June, Day of Portugal, Portuguese Communities and Camões!!</h3>
Expand Down
10 changes: 8 additions & 2 deletions src/robotide/controller/dataloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ def __init__(self, path, settings, language=None):

def _run(self):
if not self.language:
self.language = lang.check_file_language(self._path)
try:
self.language = lang.check_file_language(self._path)
except Exception:
self.language = 'en'
return test_data(source=self._path, settings=self._settings, language=self.language)


Expand All @@ -115,7 +118,10 @@ def _run(self):
language=self.language)
result.initfile = self._path
if not self.language:
self.language = lang.check_file_language(self._path)
try:
self.language = lang.check_file_language(self._path)
except Exception:
self.language = 'en'
robotapi.FromFilePopulator(result, lang=self.language).populate(self._path)
return result

Expand Down
66 changes: 66 additions & 0 deletions src/robotide/editor/texteditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,73 @@ def _set_shared_doc_lang(self, lang='en'):
def set_editor(self, editor):
self._editor = editor


def validate_and_update(self, data, text, lang='en'):

try:
from robot.parsing.parser.parser import get_model # RF > 4.0
except ImportError:
return self._old_validate_and_update(data, text)
return self._new_validate_and_update(data, text, lang)

"""
Backwards compatible code v1.7.4.2
"""

def _old_validate_and_update(self, data, text):
m_text = text.decode("utf-8")
if not self._old_sanity_check(data, m_text):
handled = self._old_handle_sanity_check_failure()
if not handled:
return False
self._editor.reset()
# print("DEBUG: updating text") # %s" % (self._editor.GetCurrentPos()))
data.update_from(m_text)
# print("DEBUG: AFTER updating text")
self._editor.set_editor_caret_position()
# %s" % (self._editor.GetCurrentPos()))
return True

def _old_sanity_check(self, data, text):
formatted_text = data.format_text(text)
# print(f"DEBUG: texteditor old_sanity_check {formatted_text=}")
c = self._normalize(formatted_text)
e = self._normalize(text)
return len(c) == len(e)

@staticmethod
def _normalize(text):
for item in [' ', r'\t', r'\n', r'\r\n', '...', '*']:
if item in text:
# print("DEBUG: _normaliz item %s txt %s" % (item, text))
text = text.replace(item, '')
return text

def _old_handle_sanity_check_failure(self):
if self._last_answer == wx.ID_NO and \
time() - self._last_answer_time <= 0.2:
self._editor._mark_file_dirty()
return False
# TODO: use widgets.Dialog
id = wx.MessageDialog(self._editor,
'ERROR: Data sanity check failed!\n'
'Reset changes?',
'Can not apply changes from Txt Editor',
style=wx.YES | wx.NO).ShowModal()
self._last_answer = id
self._last_answer_time = time()
if id == wx.ID_YES:
self._editor._revert()
return True
else:
self._editor._mark_file_dirty()
return False

"""
End Backwards compatible code v1.7.4.2
"""

def _new_validate_and_update(self, data, text, lang='en'):
from robotide.lib.robot.errors import DataError
m_text = text.decode("utf-8")
# print(f"DEBUG: textedit.py validate_and_update ENTER"
Expand Down
10 changes: 8 additions & 2 deletions src/robotide/lib/compat/parsing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from .validator import ErrorReporter
try:
from .validator import ErrorReporter
except ImportError:
pass
from .language import get_english_label, get_localized_setting
from .languages import *
try:
from .languages import *
except ImportError:
pass
8 changes: 5 additions & 3 deletions src/robotide/lib/compat/parsing/language.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
try:
# Using local copy of https://github.com/robotframework/robotframework/blob/v7.0.1/src/robot/conf/languages.py
from .languages import Language
except ImportError:
except ImportError as e:
sys.stderr.write(f"RIDE: Trying to import robot's languages module returned error: {repr(e)}\n")
Language = None
from robot.errors import DataError
from robotide.lib.robot.utils import Utf8Reader
Expand Down Expand Up @@ -236,11 +237,12 @@ def get_english_label(lang, label):
try:
mlang = Language.from_name(lang[0].replace('_', '-')) # Only care for a single language
except ValueError:
print(f"DEBUG: language.py get_english_label Exception at language={lang}")
# print(f"DEBUG: language.py get_english_label Exception at language={lang}")
pass
else:
mlang = Language.from_name(lang.replace('_', '-'))
if not mlang:
print(f"DEBUG: language.py get_english_label lang={lang} not found")
# print(f"DEBUG: language.py get_english_label lang={lang} not found")
return None
setting_names = list(mlang.settings.keys())
try:
Expand Down
31 changes: 30 additions & 1 deletion src/robotide/lib/compat/parsing/languages.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,36 @@
from typing import cast, Iterable, Iterator, Union

from robot.errors import DataError
from robot.utils import classproperty, is_list_like, Importer, normalize
from robot.utils import is_list_like, Importer, normalize
try:
from robot.utils import classproperty
except ImportError: # This is when using RF older than 6.0

class classproperty(property):
"""Property that works with classes in addition to instances.

Only supports getters. Setters and deleters cannot work with classes due
to how the descriptor protocol works, and they are thus explicitly disabled.
Metaclasses must be used if they are needed.
"""

def __init__(self, fget, fset=None, fdel=None, doc=None):
if fset:
self.setter(fset)
if fdel:
self.deleter(fset)
super().__init__(fget)
if doc:
self.__doc__ = doc

def __get__(self, instance, owner):
return self.fget(owner)

def setter(self, fset):
raise TypeError('Setters are not supported.')

def deleter(self, fset):
raise TypeError('Deleters are not supported.')


LanguageLike = Union['Language', str, Path]
Expand Down
6 changes: 4 additions & 2 deletions src/robotide/lib/robot/parsing/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,10 @@ def __iter__(self):
for table in self.tables:
yield table


from robotide.lib.compat.parsing.language import get_headers_for
try:
from robotide.lib.compat.parsing.language import get_headers_for
except ImportError:
get_headers_for = lambda l, t, lowercase=False: t


class _Table(object):
Expand Down
5 changes: 4 additions & 1 deletion src/robotide/lib/robot/parsing/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@

from multiprocessing import shared_memory
from robotide.lib.robot.utils import is_string, unicode
from robotide.lib.compat.parsing.language import get_localized_setting
try:
from robotide.lib.compat.parsing.language import get_localized_setting
except ImportError:
get_localized_setting = lambda l, item: item

from .comments import Comment
from ..version import ALIAS_MARKER
Expand Down
9 changes: 7 additions & 2 deletions src/robotide/lib/robot/writer/formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import re

from multiprocessing import shared_memory
from robotide.lib.compat.parsing.language import get_headers_for
from .aligners import FirstColumnAligner, ColumnAligner, NullAligner
from .dataextractor import DataExtractor
from .rowsplitter import RowSplitter
Expand Down Expand Up @@ -123,7 +122,13 @@ def _pad(self, row):


def translate_header(header: str, language=None) -> str:
if not language:
can_translate = True
try:
from robotide.lib.compat.parsing.language import get_headers_for
except ImportError:
get_headers_for = lambda l, t, lowercase=False: t
can_translate = False
if not language or not can_translate:
return header
tr_header = list(get_headers_for(language, header, lowercase=False))
if len(tr_header) > 1:
Expand Down
8 changes: 7 additions & 1 deletion src/robotide/lib/robot/writer/rowsplitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import itertools
from multiprocessing import shared_memory
from robotide.lib.compat.parsing.language import get_settings_for


class RowSplitter(object):
Expand Down Expand Up @@ -65,6 +64,13 @@ def _get_first_non_empty_index(row, indented=False):
return len(list(itertools.takewhile(lambda x: x in ignore, row)))

def _is_doc_row(self, row, table_type):
can_translate = True
try:
from robotide.lib.compat.parsing.language import get_settings_for
except ImportError:
can_translate = False
if not can_translate:
get_settings_for = lambda l, t: ['Documentation']
if table_type == self.setting_table:
# print(f"DEBUG: writer.rowsplitter.py RowSplitter _is_doc_row in setting {self._language=}"
# f"\n row={row}")
Expand Down
2 changes: 1 addition & 1 deletion src/robotide/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
#
# Automatically generated by `tasks.py`.

VERSION = 'v2.2dev17'
VERSION = 'v2.2dev18'