Robot Framework Integrated Development Environment (RIDE)
filesetter.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 import inspect
17 import io
18 try:
19  import yaml
20 except ImportError:
21  yaml = None
22 
23 from robotide.lib.robot.errors import DataError
24 from robotide.lib.robot.output import LOGGER
25 from robotide.lib.robot.utils import (get_error_message, is_dict_like, is_list_like,
26  is_string, seq2str2, type_name, DotDict, Importer)
27 
28 
30 
31  def __init__(self, store):
32  self._store_store = store
33 
34  def set(self, path_or_variables, args=None, overwrite=False):
35  variables = self._import_if_needed_import_if_needed(path_or_variables, args)
36  self._set_set(variables, overwrite)
37  return variables
38 
39  def _import_if_needed(self, path_or_variables, args=None):
40  if not is_string(path_or_variables):
41  return path_or_variables
42  LOGGER.info("Importing variable file '%s' with args %s"
43  % (path_or_variables, args))
44  if path_or_variables.lower().endswith('.yaml'):
45  importer = YamlImporter()
46  else:
47  importer = PythonImporter()
48  try:
49  return importer.import_variables(path_or_variables, args)
50  except:
51  args = 'with arguments %s ' % seq2str2(args) if args else ''
52  raise DataError("Processing variable file '%s' %sfailed: %s"
53  % (path_or_variables, args, get_error_message()))
54 
55  def _set(self, variables, overwrite=False):
56  for name, value in variables:
57  self._store_store.add(name, value, overwrite)
58 
59 
60 class YamlImporter():
61 
62  def import_variables(self, path, args=None):
63  if args:
64  raise DataError('YAML variable files do not accept arguments.')
65  variables = self._import_import(path)
66  return [('${%s}' % name, self._dot_dict_dot_dict(value))
67  for name, value in variables]
68 
69  def _import(self, path):
70  with io.open(path, encoding='UTF-8') as stream:
71  variables = self._load_yaml_load_yaml(stream)
72  if not is_dict_like(variables):
73  raise DataError('YAML variable file must be a mapping, got %s.'
74  % type_name(variables))
75  return variables.items()
76 
77  def _load_yaml(self, stream):
78  if not yaml:
79  raise DataError('Using YAML variable files requires PyYAML module '
80  'to be installed. Typically you can install it '
81  'by running `pip install pyyaml`.')
82  if yaml.__version__.split('.')[0] == '3':
83  return yaml.load(stream)
84  return yaml.full_load(stream)
85 
86 
87  def _dot_dict(self, value):
88  if is_dict_like(value):
89  value = DotDict((n, self._dot_dict_dot_dict(v)) for n, v in value.items())
90  return value
91 
92 
94 
95  def import_variables(self, path, args=None):
96  importer = Importer('variable file').import_class_or_module_by_path
97  var_file = importer(path, instantiate_with_args=())
98  return self._get_variables_get_variables(var_file, args)
99 
100  def _get_variables(self, var_file, args):
101  if self._is_dynamic_is_dynamic(var_file):
102  variables = self._get_dynamic_get_dynamic(var_file, args)
103  else:
104  variables = self._get_static_get_static(var_file)
105  return list(self._decorate_and_validate_decorate_and_validate(variables))
106 
107  def _is_dynamic(self, var_file):
108  return (hasattr(var_file, 'get_variables') or
109  hasattr(var_file, 'getVariables'))
110 
111  def _get_dynamic(self, var_file, args):
112  get_variables = (getattr(var_file, 'get_variables', None) or
113  getattr(var_file, 'getVariables'))
114  variables = get_variables(*args)
115  if is_dict_like(variables):
116  return variables.items()
117  raise DataError("Expected '%s' to return dict-like value, got %s."
118  % (get_variables.__name__, type_name(variables)))
119 
120  def _get_static(self, var_file):
121  names = [attr for attr in dir(var_file) if not attr.startswith('_')]
122  if hasattr(var_file, '__all__'):
123  names = [name for name in names if name in var_file.__all__]
124  variables = [(name, getattr(var_file, name)) for name in names]
125  if not inspect.ismodule(var_file):
126  variables = [(n, v) for n, v in variables if not callable(v)]
127  return variables
128 
129  def _decorate_and_validate(self, variables):
130  for name, value in variables:
131  name = self._decorate_decorate(name)
132  self._validate_validate(name, value)
133  yield name, value
134 
135  def _decorate(self, name):
136  if name.startswith('LIST__'):
137  return '@{%s}' % name[6:]
138  if name.startswith('DICT__'):
139  return '&{%s}' % name[6:]
140  return '${%s}' % name
141 
142  def _validate(self, name, value):
143  if name[0] == '@' and not is_list_like(value):
144  raise DataError("Invalid variable '%s': Expected list-like value, "
145  "got %s." % (name, type_name(value)))
146  if name[0] == '&' and not is_dict_like(value):
147  raise DataError("Invalid variable '%s': Expected dict-like value, "
148  "got %s." % (name, type_name(value)))
Used when variable does not exist.
Definition: errors.py:67
def _import_if_needed(self, path_or_variables, args=None)
Definition: filesetter.py:39
def _set(self, variables, overwrite=False)
Definition: filesetter.py:55
def set(self, path_or_variables, args=None, overwrite=False)
Definition: filesetter.py:34
def get_error_message()
Returns error message of the last occurred exception.
Definition: error.py:41
def seq2str2(sequence)
Returns sequence in format [ item 1 | item 2 | ...
Definition: misc.py:126