Robot Framework Integrated Development Environment (RIDE)
tablecontrollers.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 from .. import utils
17 from ..publish import (RideTestCaseRemoved, RideVariableAdded, RideVariableRemoved, RideVariableMovedUp,
18  RideVariableMovedDown, RideUserKeywordRemoved, RideUserKeywordAdded, RideTestCaseAdded)
19 from ..publish.messages import RideItemMovedUp, RideItemMovedDown
20 from ..robotapi import is_list_var, is_scalar_var, is_dict_var
21 from ..utils import overrides, variablematcher
22 from .basecontroller import ControllerWithParent
23 from . import macrocontrollers # TestCaseController, UserKeywordController
24 from .settingcontrollers import MetadataController, ImportController, VariableController
25 
26 
28 
29  def move_up(self, index):
30  if index > 0:
31  self._swap_swap(index - 1, index)
32 
33  def move_down(self, index):
34  if index < len(self._items_items_items) - 1:
35  self._swap_swap(index, index + 1)
36 
37  def _swap(self, ind1, ind2):
38  self._items_items_items[ind1], self._items_items_items[ind2] = self._items_items_items[ind2], self._items_items_items[ind1]
39  self.mark_dirtymark_dirty()
40 
41  def delete(self, index):
42  if isinstance(self._items_items_items, list):
43  self._items_items_items.pop(index)
44  else:
45  self._items_items_items.data.pop(index)
46  self.mark_dirtymark_dirty()
47 
48  @property
49  _items = property
50 
51  def _items(self):
52  raise NotImplementedError(self.__class__)
53 
54  def mark_dirty(self):
55  raise NotImplementedError(self.__class__)
56 
57 
59 
60  def __init__(self, parent_controller, table):
61  self._parent_parent_parent = parent_controller
62  self._table_table = table
63 
64 
67  def _index_difference(self, original_list, sorted_list):
68  index_difference = []
69  for item in original_list:
70  counter = 0
71  for item2 in sorted_list:
72  if item.name == item2.name:
73  index_difference.append(counter)
74  break
75  counter += 1
76  return index_difference
77 
78 
80 
81  def __init__(self, parent_controller, table):
82  _TableController.__init__(self, parent_controller, table)
83  self._variable_cache_variable_cache = {}
84 
85  def _get(self, variable):
86  if variable not in self._variable_cache_variable_cache:
87  self._variable_cache_variable_cache[variable] = VariableController(self, variable)
88  return self._variable_cache_variable_cache[variable]
89 
90  def __iter__(self):
91  return iter(self._get_get(v) for v in self._table_table)
92 
93  def __getitem__(self, index):
94  return self._get_get(self._items_items_items_items_items[index])
95 
96  def index(self, ctrl):
97  return [v for v in self].index(ctrl)
98 
99  @property
100  _items = property
101 
102  def _items(self):
103  return self._table_table.variables
104 
105  def move_up(self, index):
106  if index == 0:
107  return False
108  ctrl = self[index]
109  _WithListOperations.move_up(self, index)
110  other = self[index]
111  self.mark_dirtymark_dirtymark_dirty()
112  RideVariableMovedUp(item=ctrl, other=other).publish()
113 
114  def move_down(self, index):
115  if index + 1 == len(self._items_items_items_items_items):
116  return False
117  ctrl = self[index]
118  _WithListOperations.move_down(self, index)
119  other = self[index]
120  self.mark_dirtymark_dirtymark_dirty()
121  RideVariableMovedDown(item=ctrl, other=other).publish()
122 
123  def add_variable(self, name, value, comment=None):
124  self._table_table.add(name, value, comment)
125  self.mark_dirtymark_dirtymark_dirty()
126  var_controller = self[-1]
127  self.notify_variable_addednotify_variable_added(var_controller)
128  return var_controller
129 
130  def validate_scalar_variable_name(self, name, item=None):
131  return self._validate_name_validate_name(_ScalarVarValidator(), name, item)
132 
133  def validate_list_variable_name(self, name, item=None):
134  return self._validate_name_validate_name(_ListVarValidator(), name, item)
135 
136  def validate_dict_variable_name(self, name, item=None):
137  return self._validate_name_validate_name(_DictVarValidator(), name, item)
138 
139  def _validate_name(self, validator, name, item=None):
140  return VariableNameValidation(self, validator, name, item)
141 
142  def delete(self, index):
143  self.remove_varremove_var(self[index])
144 
145  def remove_var(self, var_controller):
146  self._items_items_items_items_items.remove(var_controller.data)
147  del self._variable_cache_variable_cache[var_controller.data]
148  self.mark_dirtymark_dirtymark_dirty()
149  self.notify_variable_removednotify_variable_removed(var_controller)
150 
151  def notify_variable_added(self, ctrl):
152  self.datafile_controllerdatafile_controllerdatafile_controller.update_namespace()
153  RideVariableAdded(datafile=self.datafiledatafiledatafile,
154  name=ctrl.name, item=ctrl,
155  index=ctrl.index).publish()
156 
157  def notify_variable_removed(self, ctrl):
158  self.datafile_controllerdatafile_controllerdatafile_controller.update_namespace()
159  RideVariableRemoved(datafile=self.datafiledatafiledatafile,
160  name=ctrl.name, item=ctrl).publish()
161 
162  def contains_variable(self, name):
163  vars_as_list = []
164  for var in self._items_items_items_items_items:
165  vars_as_list += var.as_list()
166  return any(variablematcher.value_contains_variable(string, name)
167  for string in vars_as_list)
168 
169 
170  def sort(self):
171  variables_sorted = sorted(self._table_table.variables, key=lambda variable: variable.name)
172  index_difference = self._index_difference_index_difference(self._table_table.variables, variables_sorted)
173  self._table_table.variables = variables_sorted
174  return index_difference
175 
176 
177  def restore_variable_order(self, list):
178  variables_temp = []
179  for i in list:
180  variables_temp.append(self._table_table.variables[i])
181  self._table_table.variables = variables_temp
182 
183 
185  __call__ = lambda self, name: is_scalar_var(name)
186  name = 'Scalar'
187  prefix = '$'
188 
189 
191  __call__ = lambda self, name: is_list_var(name)
192  name = 'List'
193  prefix = '@'
194 
195 
197  __call__ = lambda self, name: is_dict_var(name)
198  name = 'Dictionary'
199  prefix = '&'
200 
201 
203 
204  def __init__(self, table, name, named_ctrl=None):
205  self._table_table = table
206  self.error_messageerror_message = ''
207  self._named_ctrl_named_ctrl = named_ctrl
208  self._validate(name.strip())
209 
210  def _name_taken(self, name):
211  return any(utils.eq(name, item.name, ignore=['_'])
212  for item in self._table_table if item != self._named_ctrl_named_ctrl)
213 
214 
216 
217  def __init__(self, table, validator, name, named_ctrl=None):
218  self._validator_validator = validator
219  _NameValidation.__init__(self, table, name, named_ctrl)
220 
221  def _validate(self, name):
222  if not self._validator_validator(name):
223  self.error_messageerror_messageerror_message = '%s variable name must be in format %s{name}' % \
224  (self._validator_validator.name, self._validator_validator.prefix)
225  if self._name_taken_name_taken(name):
226  self.error_messageerror_messageerror_message = 'Variable with this name already exists.'
227 
228 
230 
231  def _validate(self, name):
232  if not name:
233  self.error_messageerror_messageerror_message = '%s name cannot be empty.' % \
234  self._table_table.item_type
235  if self._name_taken_name_taken(name):
236  self.error_messageerror_messageerror_message = '%s with this name already exists.' % \
237  self._table_table.item_type
238  if "\n" in name:
239  self.error_messageerror_messageerror_message = '%s name contains newlines' % \
240  self._table_table.item_type
241 
242 
244 
245  @property
246  _items = property
247 
248  def _items(self):
249  raise NotImplementedError(self.__class__)
250 
251  def __iter__(self):
252  return iter(self._create_controller_create_controller(item) for item in self._table_table)
253 
254  def _create_controller(self, item):
255  if item not in self._item_to_controller_item_to_controller_item_to_controller:
256  self._item_to_controller_item_to_controller_item_to_controller[item] = self._controller_class(self, item)
257  return self._item_to_controller_item_to_controller_item_to_controller[item]
258 
259  @property
260  _item_to_controller = property
261 
263  if not hasattr(self, '_item_to_controller_attribute'):
264  self._item_to_controller_attribute_item_to_controller_attribute = {}
265  return self._item_to_controller_attribute_item_to_controller_attribute
266 
267  def __len__(self):
268  return len(self._items_items_items)
269 
270  def __getitem__(self, index):
271  return self._create_controller_create_controller(self._items_items_items[index])
272 
273  def move_up(self, item):
274  items = self._items_items_items
275  idx = items.index(item)
276  if idx == 0:
277  return False
278  upper = idx - 1
279  items[upper], items[idx] = items[idx], items[upper]
280  self.mark_dirtymark_dirty()
281  RideItemMovedUp(item=self._create_controller_create_controller(item)).publish()
282  return True
283 
284  def move_down(self, item):
285  items = self._items_items_items
286  idx = items.index(item)
287  if idx + 1 == len(items):
288  return False
289  lower = idx + 1
290  items[idx], items[lower] = items[lower], items[idx]
291  self.mark_dirtymark_dirty()
292  RideItemMovedDown(item=self._create_controller_create_controller(item)).publish()
293  return True
294 
295  def validate_name(self, name, named_ctrl=None):
296  return MacroNameValidation(self, name, named_ctrl)
297 
298  def delete(self, ctrl):
299  self._items_items_items.remove(ctrl.data)
300  if ctrl.data in self._item_to_controller_item_to_controller_item_to_controller:
301  del self._item_to_controller_item_to_controller_item_to_controller[ctrl.data]
302  self.datafile_controllerdatafile_controllerdatafile_controller.update_namespace()
303  self.mark_dirtymark_dirty()
304  self._notify_removal(ctrl)
305 
306  def add(self, ctrl):
307  item = ctrl.data
308  item.parent = self._table_table
309  self._items_items_items.append(item)
310  new_controller = self._create_controller_create_controller(item)
311  self.datafile_controllerdatafile_controllerdatafile_controller.update_namespace()
312  self.mark_dirtymark_dirty()
313  self._notify_creation(new_controller.name, new_controller)
314 
315  def _create_new(self, name, config=None):
316  name = name.strip()
317  ctrl = self._create_controller_create_controller(self._table_table.add(name))
318  self._configure_controller_configure_controller(ctrl, config)
319  self.datafile_controllerdatafile_controllerdatafile_controller.update_namespace()
320  self.mark_dirtymark_dirty()
321  self._notify_creation(name, ctrl)
322  return ctrl
323 
324  def _configure_controller(self, ctrl, config):
325  pass
326 
327 
328 class TestCaseTableController(_MacroTable):
329  item_type = 'Test case'
330 
334 
335  @property
336  _items = property
337 
338  def _items(self):
339  return self._table_table.tests
340 
341  def _notify_creation(self, name, ctrl):
342  RideTestCaseAdded(datafile=self.datafiledatafiledatafile, name=name, item=ctrl).publish()
343 
344  def _notify_removal(self, item):
345  RideTestCaseRemoved(datafile=self.datafiledatafiledatafile, name=item.name, item=item).publish()
346 
347  def new(self, name):
348  return self._create_new_create_new(name)
349 
350 
351  def sort(self):
352  tests_sorted = sorted(self._table_table.tests, key=lambda testcase: testcase.name)
353  index_difference = self._index_difference_index_difference(self._table_table.tests, tests_sorted)
354  self._table_table.tests = tests_sorted
355  return index_difference
356 
357 
358  def restore_test_order(self, list):
359  tests_temp = []
360  for i in list:
361  tests_temp.append(self._table_table.tests[i])
362  self._table_table.tests = tests_temp
363 
364 
366  item_type = 'User keyword'
367 
371 
372  @property
373  _items = property
374 
375  def _items(self):
376  return self._table_table.keywords
377 
378  def _notify_creation(self, name, ctrl):
379  # print("DEBUG notify_creation %s" % name)
380  RideUserKeywordAdded(datafile=self.datafiledatafiledatafile, name=name, item=ctrl).publish()
381 
382  def _notify_removal(self, item):
383  # print("DEBUG notify_removal %s" % item.name)
384  RideUserKeywordRemoved(datafile=self.datafiledatafiledatafile, name=item.name, item=item).publish()
385 
386  def new(self, name, argstr=''):
387  return self._create_new_create_new(name, argstr)
388 
389  def _configure_controller(self, ctrl, config):
390  if config:
391  ctrl.arguments.set_value(config)
392 
393 
394  def sort(self):
395  keywords_sorted = sorted(self._table_table.keywords, key=lambda userkeyword: userkeyword.name)
396  index_difference = self._index_difference_index_difference(self._table_table.keywords, keywords_sorted)
397  self._table_table.keywords = keywords_sorted
398  return index_difference
399 
400 
401  def restore_keyword_order(self, list):
402  keywords_temp = []
403  for i in list:
404  keywords_temp.append(self._table_table.keywords[i])
405  self._table_table.keywords = keywords_temp
406 
407 
409 
410  def __init__(self, parent_controller, table, resource_file_controller_factory=None):
411  _TableController.__init__(self, parent_controller, table)
412  self._resource_file_controller_factory_resource_file_controller_factory = resource_file_controller_factory
413  self.__import_controllers__import_controllers = None
414 
415  def __iter__(self):
416  return iter(self._import_controllers_import_controllers_import_controllers)
417 
418  def __getitem__(self, index):
419  return self._import_controllers_import_controllers_import_controllers[index]
420 
421  @property
422  _import_controllers = property
423 
425  if self.__import_controllers__import_controllers is None:
426  self.__import_controllers__import_controllers = [self._import_controller_import_controller(imp) for imp in self._items_items_items_items_items]
427  return self.__import_controllers__import_controllers
428 
429  def _import_controller(self, import_):
430  return ImportController(self, import_)
431 
432  @property
433  _items = property
434 
435  def _items(self):
436  return self._table_table.imports
437 
438  @property
439  resource_file_controller_factory = property
440 
442  return self._resource_file_controller_factory_resource_file_controller_factory
443 
444  @overrides(_WithListOperations)
445  def _swap(self, ind1, ind2):
446  imps = self._import_controllers_import_controllers_import_controllers
447  imps[ind1], imps[ind2] = imps[ind2], imps[ind1]
448  _WithListOperations._swap(self, ind1, ind2)
449 
450  def remove_import_data(self, imp):
451  self.deletedeletedelete(self._items_items_items_items_items.data.index(imp))
452 
453  def delete(self, index):
454  item = self[index]
455  _WithListOperations.delete(self, index)
456  self._import_controllers_import_controllers_import_controllers.pop(index)
457  item.publish_removed()
458  self.notify_imports_modifiednotify_imports_modified()
459 
460  def add_library(self, name, argstr, alias, comment=None):
461  self._import_controllers_import_controllers_import_controllers # Call property since it has to exist before adding new
462  import_ = self._table_table.add_library(name, utils.split_value(argstr),
463  comment)
464  import_.alias = alias
465  self._parent_parent_parent.mark_dirty()
466  self._add_controller_add_controller(import_)
467  self.notify_imports_modifiednotify_imports_modified()
468  return self[-1]
469 
470  def _add_controller(self, import_):
471  ctrl = self._import_controller_import_controller(import_)
472  ctrl.publish_added()
473  self._import_controllers_import_controllers_import_controllers.append(ctrl)
474 
475  def add_resource(self, path, comment=None):
476  self._import_controllers_import_controllers_import_controllers # Have to exist before adding new
477  import_ = self._table_table.add_resource(path, comment)
478  self._parent_parent_parent.mark_dirty()
479  self.resource_import_modifiedresource_import_modified(path)
480  self._add_controller_add_controller(import_)
481  self.notify_imports_modifiednotify_imports_modified()
482  return self[-1]
483 
484  def add_variables(self, path, argstr, comment=None):
485  self._import_controllers_import_controllers_import_controllers # Have to exist before adding new
486  import_ = self._table_table.add_variables(path, utils.split_value(argstr), comment)
487  self._parent_parent_parent.mark_dirty()
488  self._add_controller_add_controller(import_)
489  return self[-1]
490 
492  self.datafile_controllerdatafile_controllerdatafile_controller.update_namespace()
493 
494  def resource_import_modified(self, path):
495  return self._parent_parent_parent.resource_import_modified(path)
496 
497 
499 
500  def __iter__(self):
501  return iter(MetadataController(self, m) for m in self._items_items_items_items_items)
502 
503  def __getitem__(self, index):
504  return MetadataController(self, self._items_items_items_items_items[index])
505 
506  @property
507  _items = property
508 
509  def _items(self):
510  return self._table_table.metadata
511 
512  def add_metadata(self, name, value, comment=None):
513  self._table_table.add_metadata(name, value, comment)
514  self._parent_parent_parent.mark_dirty()
515  return self[-1]
def __init__(self, parent_controller, table, resource_file_controller_factory=None)
def add_library(self, name, argstr, alias, comment=None)
def restore_keyword_order(self, list)
Restores the old order of the keyword list.
def sort(self)
Sorts the keywords of the controller by name.
def restore_test_order(self, list)
Restores the old order of the test list.
def sort(self)
Sorts the tests of the controller by name.
def __init__(self, table, validator, name, named_ctrl=None)
def sort(self)
Sorts the variables of the controller by name.
def restore_variable_order(self, list)
Restores the old order of the variable list.
def validate_name(self, name, named_ctrl=None)
def __init__(self, table, name, named_ctrl=None)
def _index_difference(self, original_list, sorted_list)
Determines the difference in sorting order for undo/redo.
def __init__(self, parent_controller, table)
Sent when an item (test, keyword, variable) is moved down.
Definition: messages.py:438
Sent when an item (test, keyword, variable) is moved up.
Definition: messages.py:433
Sent when a new test case is added to a suite.
Definition: messages.py:423
Sent when a test case is removed from a suite.
Definition: messages.py:428
Sent when a new user keyword is added to a suite or resource.
Definition: messages.py:393
Sent when a user keyword is removed from a suite or resource.
Definition: messages.py:398
Sent when a new variable is added to a suite.
Definition: messages.py:443
Sent when a variable is moved down item is the item that has been moved down other is the item that w...
Definition: messages.py:464
Sent when a variable is moved up item is the item that has been moved up other is the item that was s...
Definition: messages.py:456
Sent when a variable is removed from a suite.
Definition: messages.py:448