vlc wireless hybrid experiment example added
[nepi.git] / src / nepi / core / attributes.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 class Attribute(object):
5     ### Attribute types
6     STRING  = "STRING"
7     BOOL    = "BOOL"
8     ENUM    = "ENUM"
9     DOUBLE  = "DOUBLE"
10     INTEGER = "INTEGER"
11
12     types = [
13         STRING, 
14         BOOL, 
15         ENUM, 
16         DOUBLE, 
17         INTEGER
18     ]
19
20     ### Attribute Flags
21     NoFlags     = 0x00
22     # Attribute is only modifiable during experiment design
23     DesignOnly  = 0x01
24     # Attribute is read only and can't be modified by the user
25     # Note: ReadOnly implies DesignOnly
26     ReadOnly    = 0x03
27     # Attribute is invisible to the user but can be modified
28     Invisible   = 0x04
29     # Attribute has no default value in the testbed instance. 
30     # So it needs to be set explicitely
31     HasNoDefaultValue = 0x08
32
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)
37         self._name = name
38         self._type = type
39         self._help = help
40         self._value = value
41         self._flags = flags
42         # range: max and min possible values
43         self._range = range
44         # list of possible values
45         self._allowed = allowed
46         self._validation_function = validation_function
47         self._modified = False
48
49     @property
50     def name(self):
51         return self._name
52
53     @property
54     def type(self):
55         return self._type
56
57     @property
58     def help(self):
59         return self._help
60
61     @property
62     def flags(self):
63         return self._flags
64
65     @property
66     def invisible(self):
67         return (self._flags & Attribute.Invisible) == Attribute.Invisible
68
69     @property
70     def read_only(self):
71         return (self._flags & Attribute.ReadOnly) == Attribute.ReadOnly
72
73     @property
74     def has_no_default_value(self):
75         return (self._flags & Attribute.HasNoDefaultValue) == \
76                 Attribute.HasNoDefaultValue
77
78     @property
79     def design_only(self):
80         return (self._flags & Attribute.DesignOnly) == Attribute.DesignOnly
81
82     @property
83     def modified(self):
84         return self._modified
85
86     @property
87     def range(self):
88         return self._range
89
90     @property
91     def allowed(self):
92         return self._allowed
93
94     @property
95     def validation_function(self):
96         return self._validation_function
97
98     def get_value(self):
99         return self._value
100
101     def set_value(self, value):
102         if self.is_valid_value(value):
103             self._value = value
104             self._modified = True
105         else:
106             raise RuntimeError("Invalid value %s for attribute %s" %
107                     (str(value), self.name))
108
109     value = property(get_value, set_value)
110
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)    
115
116     def _is_in_range(self, value):
117         return not self.range or \
118                 (value >= self.range[0] and value <= self.range[1])
119
120     def _is_in_allowed_values(self, value):
121         return not self._allowed or value in self._allowed
122
123     def _is_valid(self, value):
124         return not self._validation_function or \
125                 self._validation_function(self, value)
126
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.
130     """
131     def __init__(self):
132         self._attributes = dict()
133
134     @property
135     def attributes(self):
136         return self._attributes.values()
137
138     @property
139     def attributes_list(self):
140         return self._attributes.keys()
141
142     def set_attribute_value(self, name, value):
143         self._attributes[name].value = value
144
145     def get_attribute_value(self, name):
146         return self._attributes[name].value
147
148     def get_attribute_help(self, name):
149         return self._attributes[name].help
150
151     def get_attribute_type(self, name):
152         return self._attributes[name].type
153
154     def get_attribute_range(self, name):
155         if not self._attributes[name].range:
156             return (None, None)
157         return self._attributes[name].range
158
159     def get_attribute_allowed(self, name):
160         return self._attributes[name].allowed
161
162     def is_attribute_read_only(self, name):
163         return self._attributes[name].read_only
164
165     def is_attribute_invisible(self, name):
166         return self._attributes[name].invisible
167
168     def is_attribute_design_only(self, name):
169         return self._attributes[name].design_only
170
171     def has_attribute_no_default_value(self, name):
172         return self._attributes[name].has_no_default_value
173
174     def is_attribute_modified(self, name):
175         return self._attributes[name].modified
176
177     def is_attribute_value_valid(self, name, value):
178         return self._attributes[name].is_valid_value(value)
179
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,
185                 validation_function)
186         self._attributes[name] = attribute
187
188     def del_attribute(self, name):
189         del self._attributes[name]
190
191     def has_attribute(self, name):
192         return name in self._attributes    
193     
194     def destroy(self):
195         self._attributes = dict()
196