Robot Framework
store.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 from robot.errors import DataError, VariableError
17 from robot.utils import DotDict, is_dict_like, is_list_like, NormalizedDict, type_name
18 
19 from .notfound import variable_not_found
20 from .resolvable import GlobalVariableValue, Resolvable
21 from .search import is_assign
22 
23 
24 NOT_SET = object()
25 
26 
28 
29  def __init__(self, variables):
30  self.datadata = NormalizedDict(ignore='_')
31  self._variables_variables = variables
32 
33  def resolve_delayed(self, item=None):
34  if item:
35  return self._resolve_delayed_resolve_delayed(*item)
36  for name, value in list(self.datadata.items()):
37  try:
38  self._resolve_delayed_resolve_delayed(name, value)
39  except DataError:
40  pass
41 
42  def _resolve_delayed(self, name, value):
43  if not self._is_resolvable_is_resolvable(value):
44  return value
45  try:
46  self.datadata[name] = value.resolve(self._variables_variables)
47  except DataError as err:
48  # Recursive resolving may have already removed variable.
49  if name in self.datadata:
50  self.datadata.pop(name)
51  value.report_error(err)
52  variable_not_found('${%s}' % name, self.datadata)
53  return self.datadata[name]
54 
55  def _is_resolvable(self, value):
56  try:
57  return isinstance(value, Resolvable)
58  except Exception:
59  return False
60 
61  def __getitem__(self, name):
62  if name not in self.datadata:
63  variable_not_found('${%s}' % name, self.datadata)
64  return self._resolve_delayed_resolve_delayed(name, self.datadata[name])
65 
66  def get(self, name, default=NOT_SET, decorated=True):
67  try:
68  if decorated:
69  name = self._undecorate_undecorate(name)
70  return self[name]
71  except VariableError:
72  if default is NOT_SET:
73  raise
74  return default
75 
76  def update(self, store):
77  self.datadata.update(store.data)
78 
79  def clear(self):
80  self.datadata.clear()
81 
82  def add(self, name, value, overwrite=True, decorated=True):
83  if decorated:
84  name, value = self._undecorate_and_validate_undecorate_and_validate(name, value)
85  if (overwrite
86  or name not in self.datadata
87  or isinstance(self.datadata[name], GlobalVariableValue)):
88  self.datadata[name] = value
89 
90  def _undecorate(self, name):
91  if not is_assign(name):
92  raise VariableError("Invalid variable name '%s'." % name)
93  return name[2:-1]
94 
95  def _undecorate_and_validate(self, name, value):
96  undecorated = self._undecorate_undecorate(name)
97  if name[0] == '@':
98  if not is_list_like(value):
99  self._raise_cannot_set_type_raise_cannot_set_type(name, value, 'list')
100  value = list(value)
101  if name[0] == '&':
102  if not is_dict_like(value):
103  self._raise_cannot_set_type_raise_cannot_set_type(name, value, 'dictionary')
104  value = DotDict(value)
105  return undecorated, value
106 
107  def _raise_cannot_set_type(self, name, value, expected):
108  raise VariableError("Cannot set variable '%s': Expected %s-like value, got %s."
109  % (name, expected, type_name(value)))
110 
111  def __len__(self):
112  return len(self.datadata)
113 
114  def __iter__(self):
115  return iter(self.datadata)
116 
117  def __contains__(self, name):
118  return name in self.datadata
119 
120  def as_dict(self, decoration=True):
121  if decoration:
122  variables = (self._decorate_decorate(name, self[name]) for name in self)
123  else:
124  variables = self.datadata
125  return NormalizedDict(variables, ignore='_')
126 
127  def _decorate(self, name, value):
128  if is_dict_like(value):
129  name = '&{%s}' % name
130  elif is_list_like(value):
131  name = '@{%s}' % name
132  else:
133  name = '${%s}' % name
134  return name, value
Used when variable does not exist.
Definition: errors.py:72
Custom dictionary implementation automatically normalizing keys.
Definition: normalizing.py:50
def __contains__(self, name)
Definition: store.py:117
def add(self, name, value, overwrite=True, decorated=True)
Definition: store.py:82
def _decorate(self, name, value)
Definition: store.py:127
def resolve_delayed(self, item=None)
Definition: store.py:33
def _is_resolvable(self, value)
Definition: store.py:55
def as_dict(self, decoration=True)
Definition: store.py:120
def _raise_cannot_set_type(self, name, value, expected)
Definition: store.py:107
def _undecorate_and_validate(self, name, value)
Definition: store.py:95
def __init__(self, variables)
Definition: store.py:29
def __getitem__(self, name)
Definition: store.py:61
def _undecorate(self, name)
Definition: store.py:90
def get(self, name, default=NOT_SET, decorated=True)
Definition: store.py:66
def _resolve_delayed(self, name, value)
Definition: store.py:42
def is_dict_like(item)
Definition: robottypes.py:72
def type_name(item, capitalize=False)
Return "non-technical" type name for objects and types.
Definition: robottypes.py:86
def is_list_like(item)
Definition: robottypes.py:66
def variable_not_found(name, candidates, message=None, deco_braces=True)
Raise DataError for missing variable name.
Definition: notfound.py:26
def is_assign(string, identifiers='$@&', allow_assign_mark=False)
Definition: search.py:50