Robot Framework Integrated Development Environment (RIDE)
librarykeywordrunner.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 robotide.lib.robot.errors import DataError
17 from robotide.lib.robot.model import Keywords
18 from robotide.lib.robot.output import LOGGER
19 from robotide.lib.robot.result import Keyword as KeywordResult
20 from robotide.lib.robot.utils import prepr, unic
21 from robotide.lib.robot.variables import VariableAssignment, contains_var, is_list_var
22 
23 from .steprunner import StepRunner
24 from .model import Keyword
25 from .outputcapture import OutputCapturer
26 from .signalhandler import STOP_SIGNAL_MONITOR
27 from .statusreporter import StatusReporter
28 
29 
31 
34  _executed_in_dry_run = ('BuiltIn.Import Library',
35  'BuiltIn.Set Library Search Order')
36 
37  def __init__(self, handler, name=None):
38  self._handler_handler = handler
39  self.namename = name or handler.name
40  self.pre_run_messagespre_run_messages = None
41 
42  @property
43  library = property
44 
45  def library(self):
46  return self._handler_handler.library
47 
48  @property
49  libname = property
50 
51  def libname(self):
52  return self._handler_handler.library.name
53 
54  @property
55  longname = property
56 
57  def longname(self):
58  return '%s.%s' % (self.librarylibrarylibrary.name, self.namename)
59 
60  def run(self, kw, context):
61  assignment = VariableAssignment(kw.assign)
62  with StatusReporter(context, self._get_result_get_result(kw, assignment)):
63  with assignment.assigner(context) as assigner:
64  return_value = self._run_run(context, kw.args)
65  assigner.assign(return_value)
66  return return_value
67 
68  def _get_result(self, kw, assignment):
69  handler = self._handler_handler
70  return KeywordResult(kwname=self.namename,
71  libname=handler.libname,
72  doc=handler.shortdoc,
73  args=kw.args,
74  assign=tuple(assignment),
75  tags=handler.tags,
76  type=kw.type)
77 
78  def _run(self, context, args):
79  if self.pre_run_messagespre_run_messages:
80  for message in self.pre_run_messagespre_run_messages:
81  context.output.message(message)
82  positional, named = \
83  self._handler_handler.resolve_arguments(args, context.variables)
84  context.output.trace(lambda: self._trace_log_args_trace_log_args(positional, named))
85  runner = self._runner_for_runner_for(context, self._handler_handler.current_handler(),
86  positional, dict(named))
87  return self._run_with_output_captured_and_signal_monitor_run_with_output_captured_and_signal_monitor(runner, context)
88 
89  def _trace_log_args(self, positional, named):
90  args = [prepr(arg) for arg in positional]
91  args += ['%s=%s' % (unic(n), prepr(v)) for n, v in named]
92  return 'Arguments: [ %s ]' % ' | '.join(args)
93 
94  def _runner_for(self, context, handler, positional, named):
95  timeout = self._get_timeout_get_timeout(context)
96  if timeout and timeout.active:
97  def runner():
98  with LOGGER.delayed_logging:
99  context.output.debug(timeout.get_message)
100  return timeout.run(handler, args=positional, kwargs=named)
101  return runner
102  return lambda: handler(*positional, **named)
103 
104  def _get_timeout(self, context):
105  return min(context.timeouts) if context.timeouts else None
106 
108  with OutputCapturer():
109  return self._run_with_signal_monitoring_run_with_signal_monitoring(runner, context)
110 
111  def _run_with_signal_monitoring(self, runner, context):
112  try:
113  STOP_SIGNAL_MONITOR.start_running_keyword(context.in_teardown)
114  return runner()
115  finally:
116  STOP_SIGNAL_MONITOR.stop_running_keyword()
117 
118  def dry_run(self, kw, context):
119  assignment = VariableAssignment(kw.assign)
120  result = self._get_result_get_result(kw, assignment)
121  with StatusReporter(context, result, dry_run_lib_kw=True):
122  assignment.validate_assignment()
123  self._dry_run_dry_run(context, kw.args)
124 
125  def _dry_run(self, context, args):
126  if self._handler_handler.longname in self._executed_in_dry_run_executed_in_dry_run:
127  self._run_run(context, args)
128  else:
129  self._handler_handler.resolve_arguments(args)
130 
131 
133 
134  def __init__(self, handler, name):
135  LibraryKeywordRunner.__init__(self, handler, name)
136  self._embedded_args_embedded_args = handler.name_regexp.match(name).groups()
137 
138  def _run(self, context, args):
139  if args:
140  raise DataError("Positional arguments are not allowed when using "
141  "embedded arguments.")
142  return LibraryKeywordRunner._run(self, context, self._embedded_args_embedded_args)
143 
144  def _dry_run(self, context, args):
145  return LibraryKeywordRunner._dry_run(self, context, self._embedded_args_embedded_args)
146 
147 
149 
150  def __init__(self, handler, default_dry_run_keywords=False):
151  LibraryKeywordRunner.__init__(self, handler)
152  self._default_dry_run_keywords_default_dry_run_keywords = default_dry_run_keywords
153 
154  # TODO: Should this be removed altogether?
155  # - Doesn't seem to be really needed.
156  # - Not used with dynamic run kws in the new design (at least currently)
157  def _get_timeout(self, namespace):
158  return None
159 
161  return self._run_with_signal_monitoring_run_with_signal_monitoring(runner, context)
162 
163  def _dry_run(self, context, args):
164  LibraryKeywordRunner._dry_run(self, context, args)
165  keywords = self._get_runnable_dry_run_keywords_get_runnable_dry_run_keywords(args)
166  StepRunner(context).run_steps(keywords)
167 
169  keywords = Keywords()
170  for keyword in self._get_dry_run_keywords_get_dry_run_keywords(args):
171  if contains_var(keyword.name):
172  continue
173  keywords.append(keyword)
174  return keywords
175 
176  def _get_dry_run_keywords(self, args):
177  name = self._handler_handler.name
178  if name == 'Run Keyword If':
179  return list(self._get_run_kw_if_keywords_get_run_kw_if_keywords(args))
180  if name == 'Run Keywords':
181  return list(self._get_run_kws_keywords_get_run_kws_keywords(args))
182  if self._default_dry_run_keywords_default_dry_run_keywords:
183  return self._get_default_run_kw_keywords_get_default_run_kw_keywords(args)
184  return []
185 
186  def _get_run_kw_if_keywords(self, given_args):
187  for kw_call in self._get_run_kw_if_calls_get_run_kw_if_calls(given_args):
188  if kw_call:
189  yield Keyword(name=kw_call[0], args=kw_call[1:])
190 
191  def _get_run_kw_if_calls(self, given_args):
192  while 'ELSE IF' in given_args:
193  kw_call, given_args = self._split_run_kw_if_args_split_run_kw_if_args(given_args, 'ELSE IF', 2)
194  yield kw_call
195  if 'ELSE' in given_args:
196  kw_call, else_call = self._split_run_kw_if_args_split_run_kw_if_args(given_args, 'ELSE', 1)
197  yield kw_call
198  yield else_call
199  elif self._validate_kw_call_validate_kw_call(given_args):
200  expr, kw_call = given_args[0], given_args[1:]
201  if not is_list_var(expr):
202  yield kw_call
203 
204  def _split_run_kw_if_args(self, given_args, control_word, required_after):
205  index = list(given_args).index(control_word)
206  expr_and_call = given_args[:index]
207  remaining = given_args[index+1:]
208  if not (self._validate_kw_call_validate_kw_call(expr_and_call) and
209  self._validate_kw_call_validate_kw_call(remaining, required_after)):
210  raise DataError("Invalid 'Run Keyword If' usage.")
211  if is_list_var(expr_and_call[0]):
212  return (), remaining
213  return expr_and_call[1:], remaining
214 
215  def _validate_kw_call(self, kw_call, min_length=2):
216  if len(kw_call) >= min_length:
217  return True
218  return any(is_list_var(item) for item in kw_call)
219 
220  def _get_run_kws_keywords(self, given_args):
221  for kw_call in self._get_run_kws_calls_get_run_kws_calls(given_args):
222  yield Keyword(name=kw_call[0], args=kw_call[1:])
223 
224  def _get_run_kws_calls(self, given_args):
225  if 'AND' not in given_args:
226  for kw_call in given_args:
227  yield [kw_call,]
228  else:
229  while 'AND' in given_args:
230  index = list(given_args).index('AND')
231  kw_call, given_args = given_args[:index], given_args[index + 1:]
232  yield kw_call
233  if given_args:
234  yield given_args
235 
236  def _get_default_run_kw_keywords(self, given_args):
237  index = list(self._handler_handler.arguments.positional).index('name')
238  return [Keyword(name=given_args[index], args=given_args[index+1:])]
Used when variable does not exist.
Definition: errors.py:67
A list-like object representing keywords in a suite, a test or a keyword.
Definition: keyword.py:135
Represents results of a single keyword.
Definition: model.py:63
def __init__(self, handler, default_dry_run_keywords=False)
def _split_run_kw_if_args(self, given_args, control_word, required_after)
def prepr(item, width=80)
Definition: unic.py:69
def contains_var(string, identifiers='$@&')
Definition: isvar.py:46