2 # -*- coding: utf-8 -*-
4 class Attribute(object):
22 # Attribute is only modifiable during experiment design
24 # Attribute is read only and can't be modified by the user
25 # Note: ReadOnly implies DesignOnly
27 # Attribute is invisible to the user but can be modified
29 # Attribute has no default value in the testbed instance.
30 # So it needs to be set explicitely
31 HasNoDefaultValue = 0x08
33 def __init__(self, name, help, type, value = None, range = None,
34 allowed = None, flags = NoFlags, validation_function = None):
35 if not type in Attribute.types:
36 raise AttributeError("invalid type %s " % type)
42 # range: max and min possible values
44 # list of possible values
45 self._allowed = allowed
46 self._validation_function = validation_function
47 self._modified = False
67 return (self._flags & Attribute.Invisible) == Attribute.Invisible
71 return (self._flags & Attribute.ReadOnly) == Attribute.ReadOnly
74 def has_no_default_value(self):
75 return (self._flags & Attribute.HasNoDefaultValue) == \
76 Attribute.HasNoDefaultValue
79 def design_only(self):
80 return (self._flags & Attribute.DesignOnly) == Attribute.DesignOnly
95 def validation_function(self):
96 return self._validation_function
101 def set_value(self, value):
102 if self.is_valid_value(value):
104 self._modified = True
106 raise RuntimeError("Invalid value %s for attribute %s" %
107 (str(value), self.name))
109 value = property(get_value, set_value)
111 def is_valid_value(self, value):
112 return self._is_in_range(value) and \
113 self._is_in_allowed_values(value) and \
114 self._is_valid(value)
116 def _is_in_range(self, value):
117 return not self.range or \
118 (value >= self.range[0] and value <= self.range[1])
120 def _is_in_allowed_values(self, value):
121 return not self._allowed or value in self._allowed
123 def _is_valid(self, value):
124 return not self._validation_function or \
125 self._validation_function(self, value)
127 class AttributesMap(object):
128 """AttributesMap is the base class for every object whose attributes
129 are going to be manipulated by the end-user in a script or GUI.
132 self._attributes = dict()
135 def attributes(self):
136 return self._attributes.values()
139 def attributes_list(self):
140 return self._attributes.keys()
142 def set_attribute_value(self, name, value):
143 self._attributes[name].value = value
145 def get_attribute_value(self, name):
146 return self._attributes[name].value
148 def get_attribute_help(self, name):
149 return self._attributes[name].help
151 def get_attribute_type(self, name):
152 return self._attributes[name].type
154 def get_attribute_range(self, name):
155 if not self._attributes[name].range:
157 return self._attributes[name].range
159 def get_attribute_allowed(self, name):
160 return self._attributes[name].allowed
162 def is_attribute_read_only(self, name):
163 return self._attributes[name].read_only
165 def is_attribute_invisible(self, name):
166 return self._attributes[name].invisible
168 def is_attribute_design_only(self, name):
169 return self._attributes[name].design_only
171 def has_attribute_no_default_value(self, name):
172 return self._attributes[name].has_no_default_value
174 def is_attribute_modified(self, name):
175 return self._attributes[name].modified
177 def is_attribute_value_valid(self, name, value):
178 return self._attributes[name].is_valid_value(value)
180 def add_attribute(self, name, help, type, value = None, range = None,
181 allowed = None, flags = Attribute.NoFlags, validation_function = None):
182 if name in self._attributes:
183 raise AttributeError("Attribute %s already exists" % name)
184 attribute = Attribute(name, help, type, value, range, allowed, flags,
186 self._attributes[name] = attribute
188 def del_attribute(self, name):
189 del self._attributes[name]
191 def has_attribute(self, name):
192 return name in self._attributes
195 self._attributes = dict()