Source code for robot.running.arguments.argumentmapper
# Copyright 2008-2015 Nokia Networks
# Copyright 2016- Robot Framework Foundation
#
# 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 typing import TYPE_CHECKING
from robot.errors import DataError
if TYPE_CHECKING:
from .argumentspec import ArgumentSpec
[docs]
class ArgumentMapper:
def __init__(self, arg_spec: 'ArgumentSpec'):
self.arg_spec = arg_spec
[docs]
def map(self, positional, named, replace_defaults=True):
template = KeywordCallTemplate(self.arg_spec)
template.fill_positional(positional)
template.fill_named(named)
if replace_defaults:
template.replace_defaults()
return template.positional, template.named
[docs]
class KeywordCallTemplate:
def __init__(self, spec: 'ArgumentSpec'):
self.spec = spec
self.positional = [DefaultValue(spec.defaults[arg])
if arg in spec.defaults else None
for arg in spec.positional]
self.named = []
[docs]
def fill_positional(self, positional):
self.positional[:len(positional)] = positional
[docs]
def fill_named(self, named):
spec = self.spec
for name, value in named:
if name in spec.positional_or_named:
index = spec.positional_or_named.index(name)
self.positional[index] = value
elif spec.var_named or name in spec.named_only:
self.named.append((name, value))
else:
raise DataError(f"Non-existing named argument '{name}'.")
named_names = {name for name, _ in named}
for name in spec.named_only:
if name not in named_names:
value = DefaultValue(spec.defaults[name])
self.named.append((name, value))
[docs]
def replace_defaults(self):
is_default = lambda arg: isinstance(arg, DefaultValue)
while self.positional and is_default(self.positional[-1]):
self.positional.pop()
self.positional = [a if not is_default(a) else a.value for a in self.positional]
self.named = [(n, v) for n, v in self.named if not is_default(v)]
[docs]
class DefaultValue:
def __init__(self, value):
self.value = value
[docs]
def resolve(self, variables):
try:
return variables.replace_scalar(self.value)
except DataError as err:
raise DataError(f'Resolving argument default values failed: {err}')