Robot Framework Integrated Development Environment (RIDE)
stepcontrollers.py
Go to the documentation of this file.
1 # Copyright 2008-2015 Nokia Networks
2 # Copyright 2016- Robot Framework Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 import re
17 
18 from .. import robotapi, utils
19 from .basecontroller import _BaseController
20 from .cellinfo import (CellPosition, CellType, CellInfo, CellContent, ContentType)
21 from ..namespace.local_namespace import LocalNamespace
22 from ..utils import variablematcher
23 
24 
26 
27 
30  _GIVEN_WHEN_THEN_MATCHER = re.compile(r'^(given|when|then|and|but)\s*',
31  re.I)
32 
33  def __init__(self, parent, step):
34  self._init_init(parent, step)
35  # print(f"DEBUG: StepController After _init type(step):{type(self._step)} values: {self._step}")
36  self._step_step.args = self._change_last_empty_to_empty_var_change_last_empty_to_empty_var(self._step_step.args, self._step_step.comment)
37 
38  def _init(self, parent, step):
39  self.parentparent = parent
40  self._step_step = step
41  # print(f"DEBUG: StepController _init type(step):{type(self._step)} values: {self._step}")
42  self.indentindent = []
43  index = 0
44  if isinstance(self._step_step, list):
45  while index < len(self._step_step) and self._step_step[index] == '':
46  self.indentindent.append('')
47  #elif isinstance(self._step, robotapi.ForLoop):
48  elif isinstance(self._step_step, robotapi.Step):
49  cells = self._step_step.as_list()
50  # print(f"DEBUG: StepController _init step not list: len:{len(cells)} cells:{cells[:]}")
51  for index in range(0, len(cells)):
52  if cells[index] == '':
53  self.increase_indentincrease_indent()
54  else:
55  # print(f"DEBUG: StepController _init step is not list nor Step: {type(self._step)}")
56  self._step_step.args = self._step_step.comment= []
57  # raise AttributeError
58 
59  @property
60  display_name = property
61 
62  def display_name(self):
63  return 'Step'
64 
65  @property
66  datafile_controller = property
67 
69  return self.parentparent.datafile_controller
70 
71  def _change_last_empty_to_empty_var(self, args, comment):
72  if not args: # and not comment:
73  return []
74  if comment:
75  return args
76  return args[:-1] + ['${EMPTY}'] if args and args[-1] == '' else args
77 
78  def get_keyword_info(self, kw):
79  if not kw:
80  return None
81  return self.parentparent.get_keyword_info(kw)
82 
83  def __eq__(self, other):
84  if self is other:
85  return True
86  return self._steps_are_equal_steps_are_equal(self._step_step, other._step)
87 
88  def _steps_are_equal(self, fst, snd):
89  if fst is snd:
90  return True
91  if not snd:
92  return False
93  return (fst.assign == snd.assign and
94  fst.name == snd.name and
95  fst.args == snd.args)
96 
97  def get_value(self, col):
98  values = self.as_listas_list()
99  if len(values) <= col:
100  return ''
101  return values[col]
102 
103  def get_cell_info(self, col):
104  position = self._get_cell_position_get_cell_position(col)
105  content = self._get_content_with_type_get_content_with_type(col, position)
106  if content.type == ContentType.COMMENTED:
107  return self._build_cell_info_build_cell_info(content, CellPosition(CellType.OPTIONAL, None))
108  return self._build_cell_info_build_cell_info(content, position)
109 
110  @property
111  assignments = property
112 
113  def assignments(self):
114  return self._step_step.assign
115 
116  def is_assigning(self, value):
117  for assignment in self.assignmentsassignmentsassignments:
118  if assignment.replace('=', '').strip() == value.replace('=', '').strip():
119  return True
120  if value.strip().endswith('='):
121  return True
122  return False
123 
124  def _build_cell_info(self, content, position):
125  return CellInfo(content, position)
126 
127  def _get_cell_position(self, column):
128  col = column
129  if self.parentparent.has_template():
130  return CellPosition(CellType.UNKNOWN, None)
131  column -= len(self._step_step.assign)
132  value_at_col = self.get_valueget_value(col)
133  info = self.get_keyword_infoget_keyword_info(value_at_col) # Getting info for the keyword cell
134  keyword_col = col if col >= self._keyword_column_keyword_column_keyword_column else self._keyword_column_keyword_column_keyword_column
135  if info:
136  return CellPosition(CellType.KEYWORD, None)
137  else:
138  while not info and keyword_col > 0 and keyword_col > self._keyword_column_keyword_column_keyword_column:
139  keyword_col -= 1
140  info = self.get_keyword_infoget_keyword_info(self.get_valueget_value(keyword_col)) # Getting info for the previous cell
141  if info:
142  args = info.arguments
143  else:
144  args = []
145  args_amount = len(args)
146  # print(f"DEBUG: StepController _get_cell_position step is FOR?"
147  # f" {self.get_value(keyword_col) == 'FOR'} is assigning? {self.is_assigning(value_at_col)}")
148  if column > keyword_col and self.get_valueget_value(keyword_col) == "FOR" and self.is_assigningis_assigning(value_at_col):
149  return CellPosition(CellType.ASSIGN, None)
150  if column <= keyword_col and self.is_assigningis_assigning(value_at_col):
151  return CellPosition(CellType.ASSIGN, None)
152  if col < keyword_col:
153  return CellPosition(CellType.UNKNOWN, None)
154  if not info and not self.is_assigningis_assigning(value_at_col)\
155  and not self.is_assigningis_assigning(self.get_valueget_value(self._keyword_column_keyword_column_keyword_column)) and col >= keyword_col:
156  return CellPosition(CellType.UNKNOWN, None)
157  if args_amount == 0:
158  return CellPosition(CellType.MUST_BE_EMPTY, None)
159  mandatory_args_amount = self._number_of_mandatory_arguments_number_of_mandatory_arguments(args, args_amount)
160  if self._has_list_or_dict_var_value_before_has_list_or_dict_var_value_before(col - 1):
161  return CellPosition(CellType.UNKNOWN, None)
162  if col <= keyword_col + mandatory_args_amount:
163  return CellPosition(CellType.MANDATORY, args[col-keyword_col - 1])
164  if col >= keyword_col + args_amount - mandatory_args_amount and self._last_argument_is_varargs_last_argument_is_varargs(args):
165  return CellPosition(CellType.OPTIONAL, args[-1])
166  if keyword_col + mandatory_args_amount < col <= keyword_col + args_amount:
167  return CellPosition(CellType.OPTIONAL, args[col-keyword_col-1])
168  return CellPosition(CellType.MUST_BE_EMPTY, None)
169 
170  def _number_of_mandatory_arguments(self, args, args_amount):
171  defaults = [arg for arg in args if '=' in arg]
172  n = args_amount - len(defaults)
173  if self._last_argument_is_varargs_last_argument_is_varargs(args):
174  n -= 1
175  return n
176 
177  def _last_argument_is_varargs(self, args):
178  return args[-1].startswith('*')
179 
181  if self.argsargsargs:
182  for idx, value in enumerate(self.argsargsargs):
183  if idx > arg_index:
184  return False
185  if variablematcher.is_list_variable(value) and \
186  not variablematcher.is_list_variable_subitem(value):
187  return True
188  if robotapi.is_dict_var(value) and \
189  not variablematcher.is_dict_var_access(value):
190  return True
191  return False
192 
193  def _get_content_with_type(self, col, position):
194  value = self.get_valueget_value(col)
195  if self._is_commented_is_commented(col):
196  return CellContent(ContentType.COMMENTED, value)
197  last_none_empty = self._get_last_none_empty_col_idx_get_last_none_empty_col_idx()
198  if isinstance(last_none_empty, int) and last_none_empty < col:
199  return CellContent(ContentType.EMPTY, value)
200  if variablematcher.is_variable(value):
201  if self._is_unknow_variable_is_unknow_variable(value, position):
202  return CellContent(ContentType.UNKNOWN_VARIABLE, value)
203  return CellContent(ContentType.VARIABLE, value)
204  if self.is_user_keywordis_user_keyword(value):
205  return CellContent(
206  ContentType.USER_KEYWORD, value,
207  self.get_keyword_infoget_keyword_info(value).source)
208  if self.is_library_keywordis_library_keyword(value):
209  return CellContent(
210  ContentType.LIBRARY_KEYWORD, value,
211  self.get_keyword_infoget_keyword_info(value).source)
212  if value == 'END': # DEBUG Don't consider start column (col == 0 and)
213  return CellContent(ContentType.END, value)
214  return CellContent(ContentType.STRING, value)
215 
216  def _is_unknow_variable(self, value, position):
217  if position.type == CellType.ASSIGN:
218  return False
219  try:
220  is_known = self._get_local_namespace_get_local_namespace().has_name(value)
221  except AttributeError:
222  return False
223  if is_known:
224  return False
225  inner_value = value[2:-1]
226  modified = re.split(r'\W', inner_value, 1)[0]
227  # print(f"\nDEBUG: Stepcontrollers value: {value} inner_value: {inner_value} modified: {modified}")
228  return not self._get_local_namespace_get_local_namespace().has_name(
229  '%s{%s}' % (value[0], modified))
230 
232  index = self.parentparent.index_of_step(self._step_step)
233  return LocalNamespace(
234  self.parentparent, self.datafile_controllerdatafile_controllerdatafile_controller._namespace, index)
235 
237  values = self.as_listas_list()
238  for i in reversed(range(len(values))):
239  if values[i].strip() != '':
240  return i
241  return None
242 
243  def is_modifiable(self):
244  return self.datafile_controllerdatafile_controllerdatafile_controller.is_modifiable()
245 
246  def is_user_keyword(self, value):
247  return self.parentparent.is_user_keyword(value)
248 
249  def is_library_keyword(self, value):
250  return self.parentparent.is_library_keyword(value)
251 
252  def as_list(self):
253  # print(f"\nDEBUG: Stepcontrollers enter as_list")
254  return self._step_step.as_list()
255 
256  def contains_variable(self, name):
257  return any(variablematcher.value_contains_variable(item, name)
258  for item in self.as_listas_list())
259 
261  return any(variablematcher.value_contains_variable(item, "%s=" % name)
262  for item in self.as_listas_list())
263 
264  def contains_keyword(self, name):
265  return any(self._kw_name_match_kw_name_match(item, name)
266  for item in [self.keywordkeywordkeyword or ''] + self.argsargsargs)
267 
268  def _kw_name_match(self, item, expected):
269  if isinstance(expected, str):
270  return utils.eq(item, expected) or (
271  self._GIVEN_WHEN_THEN_MATCHER_GIVEN_WHEN_THEN_MATCHER.match(item) and
272  utils.eq(
273  self._GIVEN_WHEN_THEN_MATCHER_GIVEN_WHEN_THEN_MATCHER.sub('', item), expected))
274  return expected.match(item)
275 
276  def replace_keyword(self, new_name, old_name):
277  # TODO: Create setters for Step.name and Step.args
278  # print(f"DEBUG: Stepcontrollers ENTER replace_keyword new_name={new_name} old_name={old_name}")
279  if self._kw_name_match_kw_name_match(self.keywordkeywordkeyword or '', old_name):
280  self._step_step.name = self._step_step.cells[self._step_step.inner_kw_pos] = self._kw_name_replace_kw_name_replace(
281  self.keywordkeywordkeyword, new_name, old_name)
282  for index, value in enumerate(self.argsargsargs):
283  if self._kw_name_match_kw_name_match(value, old_name):
284  self._step_step.args[index] = self._step_step.cells[self._step_step.inner_kw_pos + 1 + index] = self._kw_name_replace_kw_name_replace(
285  value, new_name, old_name)
286 
287  def _kw_name_replace(self, old_value, new_match, old_match):
288  old_prefix_matcher = self._GIVEN_WHEN_THEN_MATCHER_GIVEN_WHEN_THEN_MATCHER.match(old_value)
289  if not old_prefix_matcher:
290  return new_match
291  old_prefix = old_prefix_matcher.group(0)
292  old_match_matcher = self._GIVEN_WHEN_THEN_MATCHER_GIVEN_WHEN_THEN_MATCHER.match(old_match)
293  if old_match_matcher and old_match_matcher.group(0) == old_prefix:
294  return new_match
295  return old_prefix + new_match
296 
297  @property
298  datafile = property
299 
300  def datafile(self):
301  return self.parentparent.datafile
302 
303  @property
304  keyword = property
305 
306  def keyword(self):
307  return self._step_step.name
308 
309  @property
310  assign = property
311 
312  def assign(self):
313  return self._step_step.assign
314 
315  @property
316  args = property
317 
318  def args(self):
319  return self._step_step.args
320 
321  @property
322  vars = property
323 
324  def vars(self):
325  return self._step_step.vars
326 
327  def change(self, col, new_value, delete=False):
328  cells = self.as_listas_list()
329  if col >= len(cells):
330  cells = cells + ['' for _ in range(col - len(cells) + 1)]
331  cells[col] = new_value
332  comment = self._get_comment_get_comment(cells)
333  if comment:
334  cells.pop()
335  # print(f"\nDEBUG: Stepcontrollers change calling recreate: cells={cells[:]} comment={comment}")
336  self._recreate_recreate(cells, comment, delete)
337 
338  def insert_value_before(self, col, new_value):
339  self.shift_rightshift_right(col)
340  cells = self.as_listas_list()
341  # print(f"\nDEBUG: Stepcontrollers insert_value_before after shift_right: cells={cells[:]} \n"
342  # f"col={col} new_value={new_value} inner_kw={self._step.inner_kw_pos}")
343  self.changechange(col, new_value)
344 
345  def comment(self):
346  col = self._first_non_empty_cell_first_non_empty_cell() # ._step.inner_kw_pos
347  # col = self._keyword_column if self._keyword_column > 1 else 0
348  # print(f"DEBUG: Stepcontrollers COMMENT ENTER: INNER={self._step.inner_kw_pos} cells={self._step.as_list()} \ncol={col}")
349  self.insert_value_beforeinsert_value_before(col, 'Comment')
350 
351  def _is_commented(self, col):
352  if self._has_comment_keyword_has_comment_keyword():
353  return col > self._keyword_column_keyword_column_keyword_column
354  for i in range(min(col + 1, len(self.as_listas_list()))):
355  if self.get_valueget_value(i).startswith('#'):
356  return True
357  return False
358 
360  # cells = self.as_list()
361  index = self._step_step.first_non_empty_cell()
362  # index = 0
363  # while index < len(cells) and cells[index] == '':
364  # index += 1
365  # print(f"\nDEBUG: Stepcontrollers enter _first_non_empty_cell: index1={index1} index={index}") # cells={cells[:]}")
366  return index
367 
368  @property
369  _keyword_column = property
370 
371  def _keyword_column(self):
372  return self._step_step.inner_kw_pos # ._first_non_empty_cell()
373 
375  # print(f"\nDEBUG: Stepcontrollers Enter recalculate_keyword_column: index={self._step.inner_kw_pos }")
376  # self._step.inner_kw_pos = self._first_non_empty_cell()
377  index = self._first_non_empty_cell_first_non_empty_cell()
378  cells = self.as_listas_list()
379  if 0 < len(cells) == index:
380  self._step_step.inner_kw_pos = index - 1
381  return
382  # print(f"\nDEBUG: Stepcontrollers enter _first_non_empty_cell: index={index} cells={cells[:]}")
383  if index < len(cells) and cells[index] == '':
384  return
385  while index < len(cells) and (len(cells[index]) > 0 and cells[index][0] in ['$', '@', '&', '%']):
386  index += 1
387  self._step_step.inner_kw_pos = index
388  # print(f"\nDEBUG: Stepcontrollers Leave recalculate_keyword_column: index={self._step.inner_kw_pos}")
389 
391  if self.keywordkeywordkeyword is None:
392  return False
393  return self.keywordkeywordkeyword.strip().lower() == "comment" or self.keywordkeywordkeyword.strip().lower() == 'builtin.comment'
394 
395  def uncomment(self):
396  index_of_comment = self._first_non_empty_cell_first_non_empty_cell()
397  # print(f"DEBUG: stepcontrollers.py ENTER uncomment index_of_comment={index_of_comment}")
398  if self._step_step.as_list()[index_of_comment].lower() == 'comment' or\
399  self._step_step.as_list()[index_of_comment].lower() == 'builtin.comment':
400  # self.change(index_of_comment, '')
401  self.shift_leftshift_left(index_of_comment, True)
402  self.recalculate_keyword_columnrecalculate_keyword_column()
403 
404  def shift_right(self, from_column, delete=False):
405  cells = self.as_listas_list()
406  comment = self._get_comment_get_comment(cells)
407  if len(cells) > from_column:
408  if comment:
409  cells.pop()
410  cells = cells[:from_column] + [''] + cells[from_column:]
411  # print(f"\nDEBUG: Stepcontrollers shift_right calling recreate: cells={cells[:]}")
412  self._recreate_recreate(cells, comment, delete)
413 
414  def shift_left(self, from_column, delete=False):
415  cells = self.as_listas_list()
416  # print(f"DEBUG: shift_left enter cells: ")
417  #{cells[:]} from_column: {from_column}")
418  while not delete and from_column > 0 and cells[from_column] != '':
419  from_column -= 1
420  if not delete and from_column == 0 and cells[from_column] != '':
421  return
422  comment = self._get_comment_get_comment(cells)
423  if len(cells) > from_column:
424  if comment:
425  cells.pop()
426  cells = cells[:from_column] + cells[from_column + 1:]
427  # print(f"DEBUG: shift_left calling recreate cells: {cells} comment: {comment} kwColumn={self._keyword_column}")
428  self._recreate_recreate(cells, comment, delete=delete)
429 
430  @staticmethod
432  index = 0
433  while index < len(cells) and cells[index] == '':
434  index += 1
435  return index
436 
437  def insert_before(self, new_step):
438  steps = self.parentparent.get_raw_steps()
439  index = steps.index(self._step_step)
440  if not new_step or not new_step.as_list():
441  new_step = robotapi.Step([])
442  # print(f"DEBUG: StepController, insert_before, enter: len(steps)={len(steps)} index: {index} \n"
443  # f"new_step: {new_step.as_list()} self._step={self._step.as_list()}")
444  if index > 0:
445  upper_indent = steps[index-1].first_non_empty_cell() # self.first_non_empty_cell(steps[index-1].as_list())
446  current_indent = new_step.first_non_empty_cell() # self.first_non_empty_cell(new_step.as_list())
447  delta_indent = upper_indent - current_indent
448  # print(f"DEBUG: StepController, insert_before, logic: index: {index} new_step: {new_step.as_list()}\n"
449  # f"upper_indent({upper_indent}) current_indent({current_indent}) "
450  # f"steps[index-1]={steps[index-1].as_list()}")
451  if delta_indent > 0:
452  e_list = []
453  for _ in range(1, delta_indent):
454  e_list.append('')
455  new_step = robotapi.Step(e_list + new_step.as_list(indent=True))
456  # print(f"DEBUG: StepController, insert_before: new_step: {new_step.as_list()}")
457  elif delta_indent < 0 and len(new_step.as_list()) > 1:
458  for _ in range(delta_indent, 0):
459  if new_step.as_list()[0] == '':
460  new_step = robotapi.Step(new_step.as_list(indent=True)[1:])
461  elif delta_indent == 0 and len(steps[index-1].as_list()) > upper_indent:
462  if steps[index-1].as_list()[upper_indent-1] in ['END'] \
463  or steps[index-1].as_list()[upper_indent] in ['FOR']:
464  new_step = robotapi.Step([''] + new_step.as_list(indent=True))
465  self.parentparent.set_raw_steps(steps[:index] + [new_step] + steps[index:])
466  else:
467  # DEBUG current_indent = self.first_non_empty_cell(new_step.as_list())
468  current_indent = len(new_step.indent)
469  # print(f"DEBUG: StepController, new_step.ident={new_step.indent[:]} current_indent:{current_indent}")
470  delta_indent = current_indent - len(self._step_step.indent)
471  # print(f"DEBUG: StepController, remove indent: delta={delta_indent} {new_step.as_list()}")
472  if delta_indent > 0:
473  for _ in range(0, delta_indent):
474  if new_step.as_list()[0] == '':
475  new_step = robotapi.Step(new_step.as_list(indent=False)[1:])
476  else:
477  new_step = robotapi.Step(new_step.as_list(indent=False))
478  self.parentparent.set_raw_steps([new_step] + steps[index:])
479 
480  def insert_after(self, new_step):
481  steps = self.parentparent.get_raw_steps()
482  index = steps.index(self._step_step) + 1
483  if not self._is_end_step_is_end_step(new_step.as_list()):
484  if self._is_intended_step_is_intended_step(steps[index-1].as_list()):
485  if not self._is_intended_step_is_intended_step(new_step.as_list()):
486  # print(f"DEBUG: StepController, INCREASE insert_after {new_step.as_list()}")
487  new_step.increase_indent() # shift_right(0) # DEBUG Hard coded!
488  else:
489  if self._is_intended_step_is_intended_step(new_step.as_list()) and isinstance(new_step, StepController):
490  # print(f"DEBUG: StepController, DECREASE insert_after {new_step.as_list()}")
491  new_step.decrease_indent() # shift_left(1) # DEBUG Hard coded!
492  self.parentparent.set_raw_steps(steps[:index] + [new_step] + steps[index:])
493 
494  def remove_empty_columns_from_end(self, delete=True):
495  cells = self.as_listas_list()
496  while cells != [] and cells[-1].strip() == '':
497  cells.pop()
498  self._recreate_recreate(cells, delete=delete)
499 
501  cells = self._step_step.as_list()
502  if cells != [] and cells[0].strip() == '':
503  cells = cells[1:]
504  self._recreate_recreate(cells)
505 
506  def remove(self):
507  self.parentparent.data.steps.remove(self._step_step)
508  self.parentparent._clear_cached_steps()
509 
510  def move_up(self):
511  previous_step = self.parentparent.step(self._index_index() - 1)
512  # print(f"DEBUG: StepController, move_up: before remove previous_step: {previous_step.as_list()}")
513  # print(f"DEBUG: StepController, move_up: type(self): {type(self)} self={self.as_list()}")
514  self.removeremove()
515  previous_step.insert_before(self._step_step)
516 
517  def move_down(self):
518  next_step = self.parentparent.step(self._index_index() + 1)
519  # print(f"DEBUG: StepController, move_down: before remove current_step: {self._step.as_list()}"
520  # f"\n next_step={next_step.as_list()}")
521  self.removeremove()
522  next_step.insert_after(self._step_step)
523 
524  def _index(self):
525  return self.parentparent.index_of_step(self._step_step)
526 
527  def has_only_comment(self):
528  non_empty_cells = [cell for cell
529  in self._step_step.as_list() if cell.strip() != '']
530  return len(non_empty_cells) == 1 and \
531  non_empty_cells[0].startswith('#')
532 
533  def _get_comment(self, cells):
534  if not cells:
535  return None
536  # print(f"DEBUG: Stepcontroller _get_comment returning: {cells[-1].strip() if cells[-1].startswith('#') else None}")
537  return cells[-1].strip() if cells[-1].startswith('#') else None
538 
539  def _recreate(self, cells, comment=None, delete=False):
540  # print(f"DEBUG: _recreate ENTER cells: {cells} comment: {comment}")
541  self._step_step.__init__(cells, comment)
542  # print(f"DEBUG: Stepcontrollers recreated: self._step={self._step.as_list()}")
543  self.recalculate_keyword_columnrecalculate_keyword_column()
544 
545  def _is_partial_for_loop_step(self, cells):
546  return cells and (cells[self._keyword_column_keyword_column_keyword_column].replace(' ', '').upper() == ':FOR'
547  or cells[self._keyword_column_keyword_column_keyword_column] == 'FOR')
548 
549  def _is_for_loop(self):
550  return self.keywordkeywordkeyword == 'FOR'
551 
552  def _is_intended_step(self, cells):
553  return cells and not cells[0].strip() and any(c.strip() for c in cells) and self._index_index() > 0
554 
555  def _is_end_step(self, cells):
556  return cells and ('END' in cells) # cells[0] == 'END' # TODO Improve check
557 
558  """
559  def _recreate_as_partial_for_loop(self, cells, comment):
560  index = self._index()
561  self.parent.replace_step(index, PartialForLoop(
562  cells[1:] if len(cells) > 1 else [''], first_cell=cells[0], comment=comment))
563  self._recreate_next_step(index)
564  """
565 
566  def _recreate_as_intended_step(self, for_loop_step, cells, comment, index):
567  self.removeremove()
568  for_loop_step.add_step(robotapi.Step(cells[:], comment))
569  self._recreate_next_step_recreate_next_step(index)
570 
571  def _recreate_next_step(self, index):
572  if len(self.parentparent.steps) > index + 1:
573  next_step = self.parentparent.step(index + 1)
574  next_step._recreate(next_step.as_list())
575 
577  self.parentparent.notify_steps_changed()
578 
579  def increase_indent(self):
580  self.indentindent.append('')
581  return len(self.indentindent)
582 
583  def decrease_indent(self):
584  self.indentindent = self.indentindent[:-1] if len(self.indentindent) > 0 else []
585  return len(self.indentindent)
586 
587  @property
588  steps = property
589 
590  def steps(self):
591  return [IntendedStepController(self, sub_step)
592  for sub_step in self.get_raw_steps()]
593 
594  def __len__(self):
595  return len(self._step_step)
596 
597 """
598 class PartialForLoop(robotapi.ForLoop):
599 
600  parent = None
601 
602  def __init__(self, cells, first_cell='FOR', comment=None):
603  self._cells = cells
604  self._first_cell = first_cell
605  robotapi.ForLoop.__init__(self, self.parent, cells, comment)
606 
607  def as_list(self, indent=False, include_comment=False):
608  return [self._first_cell] + self._cells + [self.comment]
609 """
610 
611 
613 
614  def __init__(self, parent, step):
615  # print(f"DEBUG: ForLoopStepController __init__ step={step} type(parent)={type(parent)}, name parent={parent.name}")
616  StepController.__init__(self, parent, step)
617  self.inner_kw_posinner_kw_pos = self._first_non_empty_cell_first_non_empty_cell()
618 
619  @property
620  name = property
621 
622  def name(self):
623  return self.parentparent.name
624 
625  @property
626  assignments = property
627 
628  def assignments(self):
629  return self._step_step.vars
630 
631  """
632  @property
633  def _keyword_column(self):
634  return self.inner_kw_pos
635  """
636 
637  def move_up(self):
638  # print(f"DEBUG: ForLoopStepController move_up Enter")
639  # for k in self.parent.get_raw_steps():
640  # print(f"DEBUG: ForLoopStepController move_up steps={k.as_list()}")
641  previous_step = self.parentparent.step(self._index_index() - 1)
642  # print(f"DEBUG: ForLoopStepController move_up Before decision previous_step={previous_step.as_list()}")
643  if isinstance(previous_step, ForLoopStepController):
644  # print(f"DEBUG: ForLoopStepController move_up SWAPPING")
645  self._swap_forloop_headers_swap_forloop_headers(previous_step)
646  else:
647  # print(f"DEBUG: ForLoopStepController move_up {self.steps[:]}")
648  self.get_raw_stepsget_raw_steps().insert(0, previous_step._step)
649  previous_step.remove()
650 
651  def _swap_forloop_headers(self, previous_step):
652  previous_step._step.steps = self._step_step.steps
653  self._step_step.steps = []
654  # print(f"DEBUG: ForLoopStepController _swap_forloop_headers self._step={self._step.as_list()}")
655  steps = self.parentparent.get_raw_steps()
656  i = steps.index(self._step_step)
657  # for k in steps:
658  # print(f"DEBUG: ForLoopStepController _swap_forloop_headers steps={k.as_list()}")
659  steps[i - 1] = self._step_step
660  steps[i] = previous_step._step
661  self.parentparent.set_raw_steps(steps)
662 
663  def move_down(self):
664  next_step = self.stepstep(self._index_index() + 1)
665  next_step.move_up()
666  if len(self._step_step.steps) == 0:
667  self._recreate_complete_for_loop_header_recreate_complete_for_loop_header(cells=self.as_listas_list())
668 
669  def insert_after(self, new_step):
670  self.get_raw_stepsget_raw_steps().insert(0, new_step)
671 
672  def step(self, index):
673  return self.parentparent.step(index)
674 
676  return False
677 
678  def get_raw_steps(self):
679  return self._step_step.steps
680 
681  def set_raw_steps(self, steps):
682  self._step_step.steps = steps
683 
684  def _get_cell_position(self, col):
685  until_range = len(self._step_step.vars) + 1
686  flavor = self._step_step.flavor
687  if col == self._keyword_column_keyword_column_keyword_column:
688  return CellPosition(CellType.KEYWORD, None)
689  if col < self._keyword_column_keyword_column_keyword_column + until_range:
690  return CellPosition(CellType.ASSIGN, self._step_step.vars[:])
691  if col == self._keyword_column_keyword_column_keyword_column + until_range:
692  return CellPosition(CellType.MANDATORY, None)
693  if 'IN RANGE' not in flavor:
694  return CellPosition(CellType.OPTIONAL, None)
695  if col <= self._keyword_column_keyword_column_keyword_column + until_range + 1:
696  return CellPosition(CellType.MANDATORY, None)
697  if col <= self._keyword_column_keyword_column_keyword_column + until_range + 3:
698  return CellPosition(CellType.OPTIONAL, None)
699  return CellPosition(CellType.MUST_BE_EMPTY, None)
700 
701  def get_cell_info(self, col):
702  position = self._get_cell_position_get_cell_position_get_cell_position(col)
703  content = self._get_content_with_type_get_content_with_type(col, position)
704  return self._build_cell_info_build_cell_info_build_cell_info(content, position)
705 
706  def _build_cell_info(self, content, position):
707  return CellInfo(content, position, for_loop=True)
708 
709  @property
710  steps = property
711 
712  def steps(self):
713  return [IntendedStepController(self, sub_step)
714  for sub_step in self.get_raw_stepsget_raw_steps()]
715 
716  def index_of_step(self, step):
717  index_in_for_loop = self.get_raw_stepsget_raw_steps().index(step)
718  return self._index_index() + index_in_for_loop + 1
719 
720  def _get_comment(self, cells):
721  return None
722 
723  def comment(self):
724  print(f"\nDEBUG: ForLoopStepController RAW STEPS: {self.get_raw_steps()}")
725  for i in self.get_raw_stepsget_raw_steps():
726  print(f"\nDEBUG: ForLoopStepController PRINT STEPS: {i.as_list()}")
727  col = self._step_step.inner_kw_pos
728  header = self.as_listas_list()
729  if col > 0:
730  self._replace_with_new_cells_replace_with_new_cells(header[0:col-1] + ['Comment'] + header[col:])
731  else:
732  self._replace_with_new_cells_replace_with_new_cells(['Comment'] + header)
733 
734  """
735  def uncomment(self):
736  if self.as_list()[self._keyword_column] == 'Comment':
737  kw_column = self._keyword_column
738  self.shift_right(kw_column)
739  self.change(kw_column, '')
740  self.shift_left(self._keyword_column)
741  """
742 
743  def contains_keyword(self, name):
744  return False
745 
746  def add_step(self, step):
747  print(f"\nDEBUG: ForLoopStepController enter add_step step={step.as_list()}")
748  self.get_raw_stepsget_raw_steps().append(step)
749 
750  def _recreate(self, cells, comment=None, delete=False):
751  # print(f"\nDEBUG: ForLoopStepController enter recreate: self._step.inner_kw_pos={self._step.inner_kw_pos} "
752  # f"self.cells={cells[:]}")
753  kw_index = None
754  for idx in range(0, len(cells)):
755  if cells[idx] == '':
756  continue
757  if cells[idx] == 'FOR':
758  kw_index = idx
759  break
760  if kw_index and not delete: # Avoid IndentedStep when DeleteCells
761  print(f"\nDEBUG: ForLoopStepController returning recreate_complete_for_loop_header")
762  if comment:
763  self._recreate_complete_for_loop_header_recreate_complete_for_loop_header(['', cells[:], comment[:]])
764  else:
765  self._recreate_complete_for_loop_header_recreate_complete_for_loop_header([''] + cells)
766  else:
767  new_cells = cells[:]
768  index = self._index_index()
769  print(f"\nDEBUG: ForLoopStepController RAW STEPS: {self.get_raw_steps()}")
770  for i in self.get_raw_stepsget_raw_steps():
771  print(f"\nDEBUG: ForLoopStepController PRINT STEPS: {i.as_list()}")
772  self.parentparent.replace_step(index, robotapi.Step(new_cells, comment))
773  print(f"\nDEBUG: ForLoopStepController returning STEP recreate: index={index}")
774  self.recalculate_keyword_columnrecalculate_keyword_column()
775 
777  self._step_step.__init__(self.parentparent, cells[:])
778 
779  """
780  def _recreate_partial_for_loop_header(self, cells, comment):
781  if not cells or (cells[self._keyword_column].replace(' ', '').upper() != ':FOR'
782  and cells[self._keyword_column].replace(' ', '') != 'FOR'):
783  self._replace_with_new_cells(cells)
784  else:
785  steps = self.get_raw_steps()
786  i = self._index()
787  StepController._recreate_as_partial_for_loop(self, cells, comment)
788  self.parent.step(i).set_raw_steps(steps)
789  """
790 
791  def remove(self):
792  steps = self.parentparent.data.steps
793  index = steps.index(self._step_step)
794  steps.remove(self._step_step)
795  self.parentparent.data.steps = \
796  steps[:index] + self.get_raw_stepsget_raw_steps() + steps[index:]
797  self._step_step.steps = []
798 
800  if not cells:
801  return False
802  if cells[0] != self.as_listas_list()[0]:
803  return False
804  in_token_index = len(self.varsvarsvars) + 1
805  if len(cells) <= in_token_index:
806  return False
807  if len(self.as_listas_list()) <= in_token_index:
808  return False
809  if cells[in_token_index] != self.as_listas_list()[in_token_index]:
810  return False
811  return True
812 
813  def _replace_with_new_cells(self, cells):
814  index = self.parentparent.index_of_step(self._step_step)
815  self.parentparent.replace_step(index, robotapi.Step(cells))
816  self.get_raw_stepsget_raw_steps().reverse()
817  for substep in self.stepsstepsstepsstepssteps:
818  self.parentparent.add_step(index + 1, robotapi.Step(substep.as_list()))
819 
821  self.notify_value_changednotify_value_changed()
822 
823  def has_template(self):
824  return self.parentparent.has_template()
825 
826 
828 
829 
832  _invalid = False
833 
834  """
835  def _first_non_empty_cell(self):
836  cells = self.as_list()
837  index = 0
838  indent = []
839  while index < len(cells) and cells[index] == '':
840  indent.append('')
841  index += 1
842  self.indent = indent
843  return index
844  """
845 
846  """
847  @property
848  def _keyword_column(self):
849  return self._first_non_empty_cell()
850  """
851  """
852  def as_list(self):
853  row = self._step.as_list()
854  if not row:
855  return []
856  return [''] + row
857  """
858 
859  def _get_cell_position(self, col):
860  if col < self._keyword_column_keyword_column_keyword_column:
861  return CellPosition(CellType.MUST_BE_EMPTY, None)
862  return StepController._get_cell_position(self, col)
863 
865  p = self.parentparent.parent
866  index = p.index_of_step(self._step_step)
867  return LocalNamespace(p, self.datafile_controllerdatafile_controllerdatafile_controller._namespace, index)
868 
869  def _get_content_with_type(self, col, position):
870  if col < self._keyword_column_keyword_column_keyword_column:
871  return CellContent(ContentType.EMPTY, None)
872  return StepController._get_content_with_type(self, col, position)
873 
874  """
875  def comment(self):
876  col = self._keyword_column
877  print(f"DEBUG: IntendedStepController comment ENTER self._keyword_column={col}")
878  self.shift_right(0)
879  self.change(col+1, 'Comment')
880  """
881 
882  """
883  def uncomment(self):
884  if self._step.name == 'Comment':
885  kw_column = self._keyword_column
886  self.shift_right(kw_column)
887  self.change(kw_column, '')
888  self.shift_left(self._keyword_column)
889  """
890 
891  def _recreate(self, cells, comment=None, delete=False):
892  # print(f"DEBUG: IntendedStepController _recreate ENTER cells: {cells} comment: {comment}")
893  # idx = 1
894  if (cells == [] or cells[0] == '') and not delete: # Avoid IndentedStep when DeleteCells
895  """"
896  if len(cells) > 1 and cells[1] != '':
897  for idx in range(0, len(cells)):
898  if cells[idx] != '':
899  break
900  """
901  self._step_step.__init__(cells[:], comment=comment)
902  if self._step_step not in self.parentparent.get_raw_steps():
903  self.parentparent.add_step(self._step_step)
904  # print(f"DEBUG: IntendedStepController _recreated: steps={self._step.as_list()}")
905  else:
906  self._step_step.__init__(cells[:], comment=comment)
907  if self._step_step not in self.parentparent.get_raw_steps():
908  self.parentparent.add_step(self._step_step)
909  # print(f"DEBUG: IntendedStepController _recreated and will be NORMAL step: steps={self._step.as_list()}")
910  if not delete:
911  self._recreate_as_normal_step_recreate_as_normal_step(cells, comment)
912  self.recalculate_keyword_columnrecalculate_keyword_column()
913 
914  def _recreate_as_normal_step(self, cells, comment=None):
915  steps = self.parentparent.steps
916  index = [s._step for s in steps].index(self._step_step)
917  for i, step in reversed(list(enumerate(steps))):
918  if i == index:
919  break
920  step._replace_with_normal_step(i, step.as_list())
921  self._replace_with_normal_step_replace_with_normal_step(index, cells, comment)
922 
923  def _replace_with_normal_step(self, index, cells=None, comment=None):
924  index_of_parent = self.parentparent.parent.index_of_step(self.parentparent._step)
925  self.parentparent.parent.add_step(
926  index_of_parent + index + 2,
927  robotapi.Step(cells or self.as_listas_list(), comment=comment))
928  self.parentparent.get_raw_steps().pop(index)
929 
930  def remove(self):
931  self.parentparent.get_raw_steps().remove(self._step_step)
932 
933  # @utils.overrides(StepController)
934  def remove_empty_columns_from_end(self, delete=True):
935  if self._invalid_invalid:
936  return
937  StepController.remove_empty_columns_from_end(self, delete)
def _recreate(self, cells, comment=None, delete=False)
def _recreate(self, cells, comment=None, delete=False)
def _replace_with_normal_step(self, index, cells=None, comment=None)
def _kw_name_replace(self, old_value, new_match, old_match)
def _recreate(self, cells, comment=None, delete=False)
def shift_right(self, from_column, delete=False)
def shift_left(self, from_column, delete=False)
def _number_of_mandatory_arguments(self, args, args_amount)
def _recreate_as_intended_step(self, for_loop_step, cells, comment, index)
def change(self, col, new_value, delete=False)
def LocalNamespace(controller, namespace, row=None)