17 ExitForLoop, ContinueForLoop, DataError)
20 is_list_like, is_number, plural_or_not
as s, type_name)
23 from .statusreporter
import StatusReporter
37 except ExecutionPassed
as exception:
38 exception.set_earlier_failures(errors)
40 except ExecutionFailed
as exception:
41 errors.extend(exception.get_errors())
42 if not exception.can_continue(self.
_context_context.in_teardown,
51 if step.type == step.FOR_LOOP_TYPE:
53 return runner.run(step)
54 runner = context.get_runner(name
or step.name)
56 return runner.dry_run(step, context)
57 return runner.run(step, context)
60 def ForRunner(context, templated=False, flavor='IN'):
61 runners = {
'IN': ForInRunner,
62 'IN RANGE': ForInRangeRunner,
63 'IN ZIP': ForInZipRunner,
64 'IN ENUMERATE': ForInEnumerateRunner}
66 runner = runners[flavor]
69 return runner(context, templated)
78 def run(self, data, name=None):
79 result = KeywordResult(kwname=self.
_get_name_get_name(data),
80 type=data.FOR_LOOP_TYPE)
86 return '%s %s [ %s ]' % (
' | '.join(data.variables),
88 ' | '.join(data.values))
94 if not data.variables:
95 raise DataError(
'FOR loop has no loop variables.')
96 for var
in data.variables:
98 raise DataError(
"Invalid FOR loop variable '%s'." % var)
100 raise DataError(
'FOR loop has no loop values.')
101 if not data.keywords:
102 raise DataError(
'FOR loop contains no keywords.')
109 except ExitForLoop
as exception:
110 if exception.earlier_failures:
111 errors.extend(exception.earlier_failures.get_errors())
113 except ContinueForLoop
as exception:
114 if exception.earlier_failures:
115 errors.extend(exception.earlier_failures.get_errors())
117 except ExecutionPassed
as exception:
118 exception.set_earlier_failures(errors)
120 except ExecutionFailed
as exception:
121 errors.extend(exception.get_errors())
122 if not exception.can_continue(self.
_context_context.in_teardown,
130 if not self.
_context_context.dry_run:
133 for i
in range(0, len(values), var_count):
134 yield values[i:i+var_count]
139 values = self.
_context_context.variables.replace_list(data.values)
142 if len(values) % values_per_iteration == 0:
147 raise DataError(
'Number of FOR loop values should be multiple of '
148 'its variables. Got %d variables but %d value%s.'
149 % (variables, values, s(values)))
153 for var, item
in zip(data.variables, values))
154 result = KeywordResult(kwname=name,
155 type=data.FOR_ITEM_TYPE)
156 for var, value
in zip(data.variables, values):
157 self.
_context_context.variables[var] = value
160 runner.run_steps(data.keywords)
175 return len(variables)
181 super(ForInRangeRunner, self).
__init__(context, templated)
190 raise DataError(
'Converting argument of FOR IN RANGE failed: %s.'
192 if not 1 <= len(items) <= 3:
193 raise DataError(
'FOR IN RANGE expected 1-3 arguments, got %d.'
200 number = eval(str(item), {})
202 raise TypeError(
"Expected number, got %s." %
type_name(item))
209 super(ForInZipRunner, self).
__init__(context, templated)
216 if len(data.variables) == len(data.values):
218 raise DataError(
'FOR IN ZIP expects an equal number of variables and '
219 'iterables. Got %d variable%s and %d iterable%s.'
220 % (len(data.variables), s(data.variables),
221 len(data.values), s(data.values)))
227 raise DataError(
'FOR IN ZIP items must all be list-like, '
229 for zipped_item
in zip(*[list(item)
for item
in items]):
230 answer.extend(zipped_item)
237 super(ForInEnumerateRunner, self).
__init__(context, templated)
240 return 'IN ENUMERATE'
243 if len(variables) < 2:
244 raise DataError(
'FOR IN ENUMERATE expected 2 or more loop '
245 'variables, got %d.' % len(variables))
246 return len(variables) - 1
249 parent = super(ForInEnumerateRunner, self)
250 for index, values
in enumerate(parent._get_values_for_one_round(data)):
251 yield [index] + values
254 raise DataError(
'Number of FOR IN ENUMERATE loop values should be '
255 'multiple of its variables (excluding the index). '
256 'Got %d variable%s but %d value%s.'
257 % (variables, s(variables), values, s(values)))
268 super(InvalidForRunner, self).
__init__(context,
False)
271 def _run(self, data, *args, **kwargs):
272 raise DataError(
"Invalid FOR loop type '%s'. Expected 'IN', "
273 "'IN RANGE', 'IN ZIP', or 'IN ENUMERATE'."
Used when variable does not exist.
def __init__(self, context, templated=False)
def _get_values_for_one_round(self, data)
def _values_per_iteration(self, variables)
def _raise_wrong_variable_count(self, variables, values)
def _transform_items(self, items)
def _to_number_with_arithmetics(self, item)
def __init__(self, context, templated=False)
def __init__(self, context, templated=False)
def _validate(self, data)
def _get_values_for_one_round(self, data)
def run(self, data, name=None)
def _values_per_iteration(self, variables)
def _raise_wrong_variable_count(self, variables, values)
def _run_one_round(self, data, values)
def _transform_items(self, items)
def _get_name(self, data)
def _replace_variables(self, data)
def _replace_variables(self, data)
def _transform_items(self, items)
def __init__(self, context, templated=False)
Used to send an error from ForRunner() if it sees an unexpected error.
def _run(self, data, *args, **kwargs)
def __init__(self, context, flavor)
def run_steps(self, steps)
def run_step(self, step, name=None)
def __init__(self, context, templated=False)
def ForRunner(context, templated=False, flavor='IN')
def get_error_message()
Returns error message of the last occurred exception.
def frange(*args)
Like range() but accepts float arguments.
def format_assign_message(variable, value, cut_long=True)
def is_scalar_var(string)