Lib.robot.running.userkeywordrunner.py Maven / Gradle / Ivy
# Copyright 2008-2015 Nokia Solutions and Networks
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from robot.errors import (ExecutionFailed, ReturnFromKeyword, ExecutionPassed,
UserKeywordExecutionFailed, DataError, VariableError,
PassExecution)
from robot.result import Keyword as KeywordResult
from robot.utils import DotDict, prepr, split_tags_from_doc
from robot.variables import is_list_var, VariableAssignment
from .arguments import DefaultValue
from .statusreporter import StatusReporter
from .steprunner import StepRunner
from .timeouts import KeywordTimeout
class UserKeywordRunner(object):
def __init__(self, handler, name=None):
self._handler = handler
self.name = name or handler.name
@property
def longname(self):
libname = self._handler.libname
return '%s.%s' % (libname, self.name) if libname else self.name
@property
def libname(self):
return self._handler.libname
@property
def arguments(self):
return self._handler.arguments
def run(self, kw, context):
assignment = VariableAssignment(kw.assign)
result = self._get_result(kw, assignment, context.variables)
with StatusReporter(context, result):
with assignment.assigner(context) as assigner:
return_value = self._run(context, kw.args, result)
assigner.assign(return_value)
return return_value
def _get_result(self, kw, assignment, variables):
handler = self._handler
doc = variables.replace_string(handler.doc, ignore_errors=True)
doc, tags = split_tags_from_doc(doc)
tags = variables.replace_list(handler.tags, ignore_errors=True) + tags
return KeywordResult(kwname=self.name,
libname=handler.libname,
doc=doc.splitlines()[0] if doc else '',
args=kw.args,
assign=tuple(assignment),
tags=tags,
type=kw.type)
def _run(self, context, args, result):
variables = context.variables
args = self._resolve_arguments(args, variables)
with context.user_keyword:
self._set_arguments(args, context)
timeout = self._get_timeout(variables)
if timeout is not None:
result.timeout = str(timeout)
with context.timeout(timeout):
error, return_ = self._execute(context)
if error and not error.can_continue(context.in_teardown):
raise error
return_value = self._get_return_value(variables, return_)
if error:
error.return_value = return_value
raise error
return return_value
def _get_timeout(self, variables=None):
timeout = self._handler.timeout
if not timeout:
return None
timeout = KeywordTimeout(timeout.value, timeout.message, variables)
return timeout
def _resolve_arguments(self, arguments, variables=None):
return self.arguments.resolve(arguments, variables)
def _set_arguments(self, arguments, context):
positional, named = arguments
variables = context.variables
args, kwargs = self.arguments.map(positional, named,
replace_defaults=False)
self._set_variables(args, kwargs, variables)
context.output.trace(lambda: self._trace_log_args_message(variables))
def _set_variables(self, positional, kwargs, variables):
before_varargs, varargs = self._split_args_and_varargs(positional)
for name, value in zip(self.arguments.positional, before_varargs):
if isinstance(value, DefaultValue):
value = value.resolve(variables)
variables['${%s}' % name] = value
if self.arguments.varargs:
variables['@{%s}' % self.arguments.varargs] = varargs
if self.arguments.kwargs:
variables['&{%s}' % self.arguments.kwargs] = DotDict(kwargs)
def _split_args_and_varargs(self, args):
if not self.arguments.varargs:
return args, []
positional = len(self.arguments.positional)
return args[:positional], args[positional:]
def _trace_log_args_message(self, variables):
args = ['${%s}' % arg for arg in self.arguments.positional]
if self.arguments.varargs:
args.append('@{%s}' % self.arguments.varargs)
if self.arguments.kwargs:
args.append('&{%s}' % self.arguments.kwargs)
return self._format_trace_log_args_message(args, variables)
def _format_trace_log_args_message(self, args, variables):
args = ['%s=%s' % (name, prepr(variables[name])) for name in args]
return 'Arguments: [ %s ]' % ' | '.join(args)
def _execute(self, context):
if not (self._handler.keywords or self._handler.return_value):
raise DataError("User keyword '%s' contains no keywords." % self.name)
error = return_ = pass_ = None
try:
StepRunner(context).run_steps(self._handler.keywords)
except ReturnFromKeyword as exception:
return_ = exception
error = exception.earlier_failures
except ExecutionPassed as exception:
pass_ = exception
error = exception.earlier_failures
except ExecutionFailed as exception:
error = exception
with context.keyword_teardown(error):
td_error = self._run_teardown(context)
if error or td_error:
error = UserKeywordExecutionFailed(error, td_error)
return error or pass_, return_
def _get_return_value(self, variables, return_):
ret = self._handler.return_value if not return_ else return_.return_value
if not ret:
return None
contains_list_var = any(is_list_var(item) for item in ret)
try:
ret = variables.replace_list(ret)
except DataError as err:
raise VariableError('Replacing variables from keyword return value '
'failed: %s' % err.message)
if len(ret) != 1 or contains_list_var:
return ret
return ret[0]
def _run_teardown(self, context):
if not self._handler.teardown:
return None
try:
name = context.variables.replace_string(self._handler.teardown.name)
except DataError as err:
return ExecutionFailed(err.message, syntax=True)
if name.upper() in ('', 'NONE'):
return None
try:
StepRunner(context).run_step(self._handler.teardown, name)
except PassExecution:
return None
except ExecutionFailed as err:
return err
return None
def dry_run(self, kw, context):
assignment = VariableAssignment(kw.assign)
result = self._get_result(kw, assignment, context.variables)
with StatusReporter(context, result):
assignment.validate_assignment()
self._dry_run(context, kw.args, result)
def _dry_run(self, context, args, result):
self._resolve_arguments(args)
with context.user_keyword:
timeout = self._get_timeout()
if timeout:
result.timeout = str(timeout)
error, _ = self._execute(context)
if error:
raise error
class EmbeddedArgumentsRunner(UserKeywordRunner):
def __init__(self, handler, name):
UserKeywordRunner.__init__(self, handler, name)
match = handler.embedded_name.match(name)
if not match:
raise ValueError('Does not match given name')
self.embedded_args = list(zip(handler.embedded_args, match.groups()))
def _resolve_arguments(self, args, variables=None):
# Validates that no arguments given.
self.arguments.resolve(args, variables)
if not variables:
return []
return [(n, variables.replace_scalar(v)) for n, v in self.embedded_args]
def _set_arguments(self, embedded_args, context):
variables = context.variables
for name, value in embedded_args:
variables['${%s}' % name] = value
context.output.trace(lambda: self._trace_log_args_message(variables))
def _trace_log_args_message(self, variables):
args = ['${%s}' % arg for arg, _ in self.embedded_args]
return self._format_trace_log_args_message(args, variables)
© 2015 - 2025 Weber Informatics LLC | Privacy Policy