3d46edc405d972a7af86038bc256c5c52474c684
[nepi.git] / src / nepi / execution / attribute.py
1 #
2 #    NEPI, a framework to manage network experiments
3 #    Copyright (C) 2013 INRIA
4 #
5 #    This program is free software: you can redistribute it and/or modify
6 #    it under the terms of the GNU General Public License as published by
7 #    the Free Software Foundation, either version 3 of the License, or
8 #    (at your option) any later version.
9 #
10 #    This program is distributed in the hope that it will be useful,
11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #    GNU General Public License for more details.
14 #
15 #    You should have received a copy of the GNU General Public License
16 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19
20 ### Attribute Types
21 class Types:
22     String  = "STRING"
23     Bool    = "BOOL"
24     Enumerate    = "ENUM"
25     Double  = "DOUBLE"
26     Integer = "INTEGER"
27
28 ### Attribute Flags
29 class Flags:
30     """ Differents flags to characterize an attribute
31
32     """
33     # Attribute can be modified by the user 
34     NoFlags         = 0x00
35     # Attribute is not modifiable by the user
36     ReadOnly        = 0x01
37     # Attribute is not modifiable by the user during runtime
38     ExecReadOnly        = 0x02
39     # Attribute is an access credential
40     Credential      = 0x04
41     # Attribute is a filter used to discover resources
42     Filter      = 0x08
43
44 class Attribute(object):
45     """
46     .. class:: Class Args :
47       
48         :param name: Name of the attribute
49         :type name: str
50         :param help: Help about the attribute
51         :type help: str
52         :param type: type of the attribute
53         :type type: str
54         :param flags: Help about the attribute
55         :type flags: str
56         :param default: Default value of the attribute
57         :type default: str
58         :param allowed: Allowed value for this attribute
59         :type allowed: str
60         :param range: Range of the attribute
61         :type range: str
62         :param set_hook: hook that is related with this attribute
63         :type set_hook: str
64
65     """
66     def __init__(self, name, help, type = Types.String,
67             flags = Flags.NoFlags, default = None, allowed = None,
68             range = None, set_hook = None):
69         self._name = name
70         self._help = help
71         self._type = type
72         self._flags = flags
73         self._allowed = allowed
74         self._range = range
75         self._default = self._value = default
76         # callback to be invoked upon changing the 
77         # attribute value
78         self.set_hook = set_hook
79
80     @property
81     def name(self):
82     """ Returns the name of the attribute """
83         return self._name
84
85     @property
86     def default(self):
87     """ Returns the default value of the attribute """
88         return self._default
89
90     @property
91     def type(self):
92     """ Returns the type of the attribute """
93         return self._type
94
95     @property
96     def help(self):
97     """ Returns the help of the attribute """
98         return self._help
99
100     @property
101     def flags(self):
102     """ Returns the flags of the attribute """
103         return self._flags
104
105     @property
106     def allowed(self):
107     """ Returns the allowed value for this attribute """
108         return self._allowed
109
110     @property
111     def range(self):
112     """ Returns the range of the attribute """
113         return self._range
114
115     def has_flag(self, flag):
116     """ Returns true if the attribute has the flag 'flag'
117
118         :param flag: Flag that need to be ckecked
119         :type flag: Flags
120     """
121         return (self._flags & flag) == flag
122
123     def get_value(self):
124     """ Returns the value of the attribute """
125         return self._value
126
127     def set_value(self, value):
128     """ Change the value of the attribute after checking the type """
129         valid = True
130
131         if self.type == Types.Enumerate:
132             valid = value in self._allowed
133
134         if self.type in [Types.Double, Types.Integer] and self.range:
135             (min, max) = self.range
136             valid = (value >= min and value <= max) 
137         
138         valid = valid and self.is_valid_value(value)
139
140         if valid: 
141             if self.set_hook:
142                 # Hook receives old value, new value
143                 value = self.set_hook(self._value, value)
144
145             self._value = value
146         else:
147             raise ValueError("Invalid value %s for attribute %s" %
148                     (str(value), self.name))
149
150     value = property(get_value, set_value)
151
152     def is_valid_value(self, value):
153         """ Attribute subclasses will override this method to add 
154         adequate validation"""
155         return True
156