Robot Framework Integrated Development Environment (RIDE)
finders.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 re
17 
18 try:
19  from java.lang.System import (getProperty as get_java_property,
20  getProperties as get_java_properties)
21 except ImportError:
22  get_java_property = lambda name: None
23  get_java_properties = lambda: {}
24 
25 from robotide.lib.robot.errors import DataError, VariableError
26 from robotide.lib.robot.utils import (get_env_var, get_env_vars, get_error_message,
27  is_dict_like, is_list_like, normalize, DotDict,
28  NormalizedDict)
29 
30 from .isvar import validate_var
31 from .notfound import variable_not_found
32 
33 
35 
36  def __init__(self, variable_store):
37  self._finders_finders = (StoredFinder(variable_store),
38  NumberFinder(),
39  EmptyFinder(),
41  ExtendedFinder(self))
42  self._store_store = variable_store
43 
44  def find(self, name):
45  validate_var(name, '$@&%')
46  identifier = name[0]
47  for finder in self._finders_finders:
48  if identifier in finder.identifiers:
49  try:
50  value = finder.find(name)
51  except (KeyError, ValueError):
52  continue
53  try:
54  return self._validate_value_validate_value(value, identifier, name)
55  except VariableError:
56  raise
57  except:
58  raise VariableError("Resolving variable '%s' failed: %s"
59  % (name, get_error_message()))
60  variable_not_found(name, self._store_store.data)
61 
62  def _validate_value(self, value, identifier, name):
63  if identifier == '@':
64  if not is_list_like(value):
65  raise VariableError("Value of variable '%s' is not list or "
66  "list-like." % name)
67  # TODO: Is converting to list needed or would checking be enough?
68  # TODO: Check this and DotDict usage below in RF 3.1.
69  return list(value)
70  if identifier == '&':
71  if not is_dict_like(value):
72  raise VariableError("Value of variable '%s' is not dictionary "
73  "or dictionary-like." % name)
74  # TODO: Is converting to DotDict needed? Check in RF 3.1.
75  return DotDict(value)
76  return value
77 
78 
79 class StoredFinder():
80  identifiers = '$@&'
81 
82  def __init__(self, store):
83  self._store_store = store
84 
85  def find(self, name):
86  return self._store_store[name[2:-1]]
87 
88 
89 class NumberFinder():
90  identifiers = '$'
91 
92  def find(self, name):
93  number = normalize(name)[2:-1]
94  try:
95  return self._get_int_get_int(number)
96  except ValueError:
97  return float(number)
98 
99  def _get_int(self, number):
100  bases = {'0b': 2, '0o': 8, '0x': 16}
101  if number.startswith(tuple(bases)):
102  return int(number[2:], bases[number[:2]])
103  return int(number)
104 
105 
106 class EmptyFinder():
107  identifiers = '$@&'
108  find = NormalizedDict({'${EMPTY}': u'', '@{EMPTY}': (), '&{EMPTY}': {}},
109  ignore='_').__getitem__
110 
111 
113  identifiers = '$@&'
114 
117  _match_extended = re.compile(r'''
118  (.+?) # base name (group 1)
119  ([^\s\w].+) # extended part (group 2)
120  ''', re.UNICODE|re.VERBOSE).match
121 
122  def __init__(self, finder):
123  self._find_variable_find_variable = finder.find
124 
125  def find(self, name):
126  match = self._match_extended_match_extended(name[2:-1])
127  if match is None:
128  raise ValueError
129  base_name, extended = match.groups()
130  try:
131  variable = self._find_variable_find_variable('${%s}' % base_name)
132  except DataError as err:
133  raise VariableError("Resolving variable '%s' failed: %s"
134  % (name, err.message))
135  try:
136  return eval('_BASE_VAR_' + extended, {'_BASE_VAR_': variable})
137  except:
138  raise VariableError("Resolving variable '%s' failed: %s"
139  % (name, get_error_message()))
140 
141 
143  identifiers = '%'
144 
145  def find(self, name):
146  for getter in get_env_var, get_java_property:
147  value = getter(name[2:-1])
148  if value is not None:
149  return value
150  variable_not_found(name, self._get_candidates_get_candidates(),
151  "Environment variable '%s' not found." % name)
152 
153  def _get_candidates(self):
154  candidates = dict(get_java_properties())
155  candidates.update(get_env_vars())
156  return candidates
Used when no keyword is found or there is more than one match.
Definition: errors.py:75
Custom dictionary implementation automatically normalizing keys.
Definition: normalizing.py:58
def _validate_value(self, value, identifier, name)
Definition: finders.py:62
def get_error_message()
Returns error message of the last occurred exception.
Definition: error.py:41
def normalize(string, ignore=(), caseless=True, spaceless=True)
Normalizes given string according to given spec.
Definition: normalizing.py:30
def get_env_vars(upper=os.sep !='/')
Definition: robotenv.py:41
def validate_var(string, identifiers='$@&')
Definition: isvar.py:53
def variable_not_found(name, candidates, msg=None, deco_braces=True)
Raise DataError for missing variable name.
Definition: notfound.py:27