Source code for robot.parsing.settings

#  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 robot.utils import is_string, py2to3, unicode

from .comments import Comment


[docs]@py2to3 class Setting(object): def __init__(self, setting_name, parent=None, comment=None): self.setting_name = setting_name self.parent = parent self._set_initial_value() self._set_comment(comment) self._populated = False def _set_initial_value(self): self.value = [] def _set_comment(self, comment): self.comment = Comment(comment)
[docs] def reset(self): self.__init__(self.setting_name, self.parent)
@property def source(self): return self.parent.source if self.parent is not None else None @property def directory(self): return self.parent.directory if self.parent is not None else None
[docs] def populate(self, value, comment=None): """Mainly used at parsing time, later attributes can be set directly.""" if not self._populated: self._populate(value) self._set_comment(comment) self._populated = True else: self._set_initial_value() self._set_comment(None) self.report_invalid_syntax("Setting '%s' used multiple times." % self.setting_name, 'ERROR')
def _populate(self, value): self.value = value
[docs] def is_set(self): return bool(self.value)
[docs] def is_for_loop(self): return False
[docs] def report_invalid_syntax(self, message, level='ERROR'): self.parent.report_invalid_syntax(message, level)
def _string_value(self, value): return value if is_string(value) else ' '.join(value) def _concat_string_with_value(self, string, value): if string: return string + ' ' + self._string_value(value) return self._string_value(value)
[docs] def as_list(self): return self._data_as_list() + self.comment.as_list()
def _data_as_list(self): ret = [self.setting_name] if self.value: ret.extend(self.value) return ret def __nonzero__(self): return self.is_set() def __iter__(self): return iter(self.value or ()) def __unicode__(self): return unicode(self.value or '')
[docs]class StringValueJoiner(object): def __init__(self, separator): self._separator = separator
[docs] def join_string_with_value(self, string, value): if string: return string + self._separator + self.string_value(value) return self.string_value(value)
[docs] def string_value(self, value): if is_string(value): return value return self._separator.join(value)
[docs]class Documentation(Setting): def _set_initial_value(self): self.value = '' def _populate(self, value): self.value = self._concat_string_with_value(self.value, value) def _string_value(self, value): return value if is_string(value) else ''.join(value) def _data_as_list(self): return [self.setting_name, self.value]
[docs]class Template(Setting): def _set_initial_value(self): self.value = None def _populate(self, value): self.value = self._concat_string_with_value(self.value, value)
[docs] def is_set(self): return self.value is not None
[docs] def is_active(self): return self.value and self.value.upper() != 'NONE'
def _data_as_list(self): ret = [self.setting_name] if self.value: ret.append(self.value) return ret
[docs]class Fixture(Setting): # `keyword`, `is_comment` and `assign` make the API compatible with Step. @property def keyword(self): return self.name or ''
[docs] def is_comment(self): return False
def _set_initial_value(self): self.name = None self.args = [] self.assign = () def _populate(self, value): if not self.name: self.name = value[0] if value else '' value = value[1:] self.args.extend(value)
[docs] def is_set(self): return self.name is not None
[docs] def is_active(self): return self.name and self.name.upper() != 'NONE'
def _data_as_list(self): ret = [self.setting_name] if self.name or self.args: ret.append(self.name or '') if self.args: ret.extend(self.args) return ret
[docs]class Timeout(Setting): def _set_initial_value(self): self.value = None self.message = '' def _populate(self, value): if not self.value: self.value = value[0] if value else '' value = value[1:] self.message = self._concat_string_with_value(self.message, value) # TODO: Remove custom timeout message support in RF 3.2. if value and self.parent: self.parent.report_invalid_syntax( 'Using custom timeout messages is deprecated since Robot ' 'Framework 3.0.1 and will be removed in future versions. ' "Message that was used is '%s'." % self.message, level='WARN')
[docs] def is_set(self): return self.value is not None
def _data_as_list(self): ret = [self.setting_name] if self.value or self.message: ret.append(self.value or '') if self.message: ret.append(self.message) return ret
[docs]class Tags(Setting): def _set_initial_value(self): self.value = None def _populate(self, value): self.value = (self.value or []) + value
[docs] def is_set(self): return self.value is not None
def __add__(self, other): if not isinstance(other, Tags): raise TypeError('Tags can only be added with tags') tags = Tags('Tags') tags.value = (self.value or []) + (other.value or []) return tags
[docs]class Arguments(Setting): pass
[docs]class Return(Setting): pass
[docs]class Metadata(Setting): setting_name = 'Metadata' def __init__(self, parent, name, value, comment=None, joined=False): self.parent = parent self.name = name joiner = StringValueJoiner('' if joined else ' ') self.value = joiner.join_string_with_value('', value) self._set_comment(comment)
[docs] def reset(self): pass
[docs] def is_set(self): return True
def _data_as_list(self): return [self.setting_name, self.name, self.value]
class _Import(Setting): def __init__(self, parent, name, args=None, alias=None, comment=None): self.parent = parent self.name = name self.args = args or [] self.alias = alias self._set_comment(comment) def reset(self): pass @property def type(self): return type(self).__name__ def is_set(self): return True def _data_as_list(self): return [self.type, self.name] + self.args def report_invalid_syntax(self, message, level='ERROR', parent=None): parent = parent or getattr(self, 'parent', None) if parent: parent.report_invalid_syntax(message, level) else: from robot.api import logger logger.write(message, level)
[docs]class Library(_Import): def __init__(self, parent, name, args=None, alias=None, comment=None): if args and not alias: args, alias = self._split_possible_alias(args) _Import.__init__(self, parent, name, args, alias, comment) def _split_possible_alias(self, args): if len(args) > 1 and args[-2] == 'WITH NAME': return args[:-2], args[-1] return args, None def _data_as_list(self): data = ['Library', self.name] + self.args if self.alias: data += ['WITH NAME', self.alias] return data
[docs]class Resource(_Import): def __init__(self, parent, name, invalid_args=None, comment=None): if invalid_args: name += ' ' + ' '.join(invalid_args) _Import.__init__(self, parent, name, comment=comment)
[docs]class Variables(_Import): def __init__(self, parent, name, args=None, comment=None): _Import.__init__(self, parent, name, args, comment=comment)
class _DataList(object): def __init__(self, parent): self._parent = parent self.data = [] def add(self, meta): self._add(meta) def _add(self, meta): self.data.append(meta) def _parse_name_and_value(self, value): name = value[0] if value else '' return name, value[1:] def __getitem__(self, index): return self.data[index] def __setitem__(self, index, item): self.data[index] = item def __len__(self): return len(self.data) def __iter__(self): return iter(self.data)
[docs]class ImportList(_DataList):
[docs] def populate_library(self, data, comment): self._populate(Library, data, comment)
[docs] def populate_resource(self, data, comment): self._populate(Resource, data, comment)
[docs] def populate_variables(self, data, comment): self._populate(Variables, data, comment)
def _populate(self, item_class, data, comment): name, value = self._parse_name_and_value(data) self._add(item_class(self._parent, name, value, comment=comment))
[docs]class MetadataList(_DataList):
[docs] def populate(self, name, value, comment): self._add(Metadata(self._parent, name, value, comment, joined=True))