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

Fix multiline vars add new option for RF 7 #2814

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
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ Tools->Preferences->General.

=== Fixed

- Fixed multiline variables in Variables section. In Text Editor they are separated by ... continuation marker.
In Grid Editor use | (pipe) to separate lines.
- Fixed keywords Find Usages in Grid Editor not finding certain values when using Gherkin.
- Fixed plugin Run Anything (Macros) not showing output and broken actions.
- Fixed headers and blank spacing in Templated tests
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.1, but RIDE is known to work w

`pip install -U robotframework-ride`

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

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

Expand Down
3 changes: 3 additions & 0 deletions src/robotide/application/CHANGELOG.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
</li><li class="listitem">
Colorization for language configured files is working in Text Editor.
</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="_fixed"></a>1.2. Fixed</h3></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
Fixed multiline variables in Variables section. In Text Editor they are separated by … continuation marker.
In Grid Editor use | (pipe) to separate lines.
</li><li class="listitem">
Fixed keywords Find Usages in Grid Editor not finding certain values when using Gherkin.
</li><li class="listitem">
Fixed plugin Run Anything (Macros) not showing output and broken actions.
Expand Down
4 changes: 3 additions & 1 deletion src/robotide/application/releasenotes.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ def set_content(self, html_win, content):
</ul>
<p><strong>New Features and Fixes Highlights</strong></p>
<ul class="simple">
<li>Fixed multiline variables in Variables section. In Text Editor they are separated by ... continuation marker.
In Grid Editor use | (pipe) to separate lines.</li>
<li>Added support for new VAR marker, since Robot Framework version 7.0.</li>
<li>Added configurable style of the tabs in notebook pages, Edit, Text, Run, etc. Parameter <b>notebook theme</b>
takes values from 0 to 5. See wxPython, demo for agw.aui for details.</li>
Expand Down Expand Up @@ -305,7 +307,7 @@ def set_content(self, html_win, content):
<pre class="literal-block">
python -m robotide.postinstall -install
</pre>
<p>RIDE {VERSION} was released on 23/June/2024.</p>
<p>RIDE {VERSION} was released on 29/June/2024.</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
6 changes: 3 additions & 3 deletions src/robotide/editor/editordialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ def __init__(self, controller, item=None, plugin=None, title=None):

def _get_editors(self, var):
name = var.name if var and var.name else '${}'
value = var.value[0] if var else ''
value = utils.join_value(var.value) if var else ''
# print(f"DEBUG: editor.editordialogs.py ScalarVariableDialog _get_editors value={value}")
validator = ScalarVariableNameValidator(self._controller, name)
return [VariableNameEditor(self, name, _('Name'), validator),
ValueEditor(self, value, _('Value'))]
return [VariableNameEditor(self, name, _('Name'), validator), ValueEditor(self, value, _('Value'), split=True)]

def _execute(self):
""" Just ignore it """
Expand Down
10 changes: 7 additions & 3 deletions src/robotide/editor/fieldeditors.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from ..context import ctrl_or_cmd, bind_keys_to_evt_menu
from ..editor.contentassist import ContentAssistFileButton
from ..namespace.suggesters import SuggestionSource
from ..utils import split_value
from ..widgets import Label

_ = wx.GetTranslation # To keep linter/code analyser happy
Expand All @@ -34,10 +35,10 @@ class ValueEditor(wx.Panel):
_sizer_flags_for_editor = wx.ALL
_sizer_flags_for_label = wx.ALL

def __init__(self, parent, value, label=None, validator=None,
settings=None):
def __init__(self, parent, value, label=None, validator=None, settings=None, split=False):
wx.Panel.__init__(self, parent)
self._label = label
self.split = split
self._sizer = wx.BoxSizer(wx.VERTICAL)
from ..preferences import RideSettings
_settings = RideSettings()
Expand Down Expand Up @@ -80,7 +81,10 @@ def set_validator(self, validator):

def get_value(self):
# print("DEBUG: ValueEditor get_value: %s" % self.source_editor.GetValue())
return self._editor.GetValue()
value = self._editor.GetValue()
if not self.split:
return value
return split_value(value)

def set_focus(self):
self._editor.SetFocus()
Expand Down
10 changes: 9 additions & 1 deletion src/robotide/lib/robot/parsing/tablepopulators.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,14 @@ def __init__(self, setter):
self._value = []
self._comments = Comments()
self._data_added = False
self.row_continue = False

def add(self, row):
if isinstance(self, VariablePopulator):
if row.head == '...':
self.row_continue = True
else:
self.row_continue = False
if not row.is_commented():
self._add(row)
if row.head.startswith('#') and not isinstance(self, VariablePopulator):
Expand All @@ -303,7 +309,7 @@ def add(self, row):
def _add(self, row):
if row.cells == ['...']:
self._deprecate_continuation_without_values()
self._value.extend(row.tail if not self._data_added else row.data)
self._value.extend(row.tail if self.row_continue or not self._data_added else row.data)
# print(f"DEBUG: tablepopulators.py _PropertyPopulator {self._data_added=} _add row.cells={row.cells}"
# f" ADDED value={self._value}")
self._data_added = True
Expand All @@ -325,6 +331,8 @@ def __init__(self, setter, name):
self._name = name

def populate(self):
# print(f"DEBUG: tablepopulators.py VariablePopulator populate {self._data_added=}"
# f" varaible name={self._name} current value={self._value} setter={self._setter}")
self._setter(self._name, self._value, self._comments.value)

def _get_deprecation_location(self):
Expand Down
28 changes: 19 additions & 9 deletions src/robotide/lib/robot/variables/tablesetter.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,17 @@ def read(self, variables):
except DataError as err:
var.report_invalid_syntax(err)

def get_name_and_value(self, name, value, error_reporter):
@staticmethod
def get_name_and_value(name, value, error_reporter):
return name[2:-1], VariableTableValue(value, name, error_reporter)


def VariableTableValue(value, name, error_reporter=None):
validate_var(name)
VariableTableValue = {'$': ScalarVariableTableValue,
variabletablevalue = {'$': ScalarVariableTableValue,
'@': ListVariableTableValue,
'&': DictVariableTableValue}[name[0]]
return VariableTableValue(value, error_reporter)
return variabletablevalue(value, error_reporter)


class VariableTableValueBase(object):
Expand Down Expand Up @@ -95,9 +96,15 @@ def _format_values(self, values):
separator = None
if is_string(values):
values = [values]
elif values and values[0].startswith('SEPARATOR='):
separator = values[0][10:]
values = values[1:]
elif values:
if values[0].startswith('SEPARATOR='):
separator = values[0][10:]
values = values[1:]
elif values[-1].startswith('separator='): # New in RF 7.0
separator = values[-1][10:]
values = values[:-2]
# if '...' in values:
# values = [elem for elem in values if elem != '...']
return separator, values

def _replace_variables(self, values, variables):
Expand All @@ -111,7 +118,8 @@ def _replace_variables(self, values, variables):
values = variables.replace_list(values)
return separator.join(unic(item) for item in values)

def _is_single_value(self, separator, values):
@staticmethod
def _is_single_value(separator, values):
return (separator is None and len(values) == 1 and
not VariableSplitter(values[0]).is_list_variable())

Expand All @@ -127,7 +135,8 @@ class DictVariableTableValue(VariableTableValueBase):
def _format_values(self, values):
return list(self._yield_formatted(values))

def _yield_formatted(self, values):
@staticmethod
def _yield_formatted(values):
for item in values:
if VariableSplitter(item).is_dict_variable():
yield item
Expand All @@ -145,7 +154,8 @@ def _replace_variables(self, values, variables):
except TypeError as err:
raise DataError('Creating dictionary failed: %s' % err)

def _yield_replaced(self, values, replace_scalar):
@staticmethod
def _yield_replaced(values, replace_scalar):
for item in values:
if isinstance(item, tuple):
key, values = item
Expand Down
25 changes: 19 additions & 6 deletions src/robotide/lib/robot/writer/rowsplitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@ class RowSplitter(object):
_line_continuation = '...'
setting_table = 'setting'
_indented_tables = ('test case', 'keyword')
_split_from = ('ELSE', 'ELSE IF', 'AND')
_split_from = ('ELSE', 'ELSE IF', 'AND', 'VAR')

def __init__(self, cols=8, split_multiline_doc=False, language=None):
def __init__(self, cols=8, split_multiline_doc=False, split_multiline_var=True, language=None):
self._cols = cols
self._split_multiline_doc = split_multiline_doc
self._split_multiline_var = split_multiline_var
self._language = language
self._table_type = None

def split(self, row, table_type):
self._table_type = table_type
if not row:
return self._split_empty_row()
indent = self._get_indent(row, table_type)
Expand All @@ -44,6 +47,7 @@ def _split_empty_row():

def _get_indent(self, row, table_type):
indent = self._get_first_non_empty_index(row)
# print(f"DEBUG: rowsplitter.py RowSplitter _get_indent indent={indent} row={row} ")
min_indent = 1 if table_type in self._indented_tables else 0
return max(indent, min_indent)

Expand Down Expand Up @@ -78,15 +82,24 @@ def _split_doc(doc):
return doc.split('\\n', 1)

def _split_row(self, row, indent):
if self._table_type == 'variable' and self._split_multiline_var:
# print(f"DEBUG: rowsplitter.py RowSplitter _split_row tabel Variable row={row}")
split_at = 2
else:
split_at = None
while row:
current, row = self._split(row)
# print(f"DEBUG: rowsplitter.py RowSplitter _split_row current={current} row={row}")
current, row = self._split(row, forced_index=split_at)
# print(f"DEBUG: rowsplitter.py RowSplitter _split_row current={current} row={row} table "
# f"type={self._table_type}")
yield self._escape_last_cell_if_empty(current)
if row:
row = self._continue_row(row, indent)

def _split(self, data):
index = min(self._get_possible_split_indices(data))
def _split(self, data, forced_index=None):
if not forced_index:
index = min(self._get_possible_split_indices(data))
else:
index = forced_index if len(data) > forced_index else min(self._get_possible_split_indices(data))
current, rest = data[:index], data[index:]
rest = self._comment_rest_if_needed(current, rest)
return current, rest
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.1dev53'
VERSION = 'v2.1dev54'
Loading