1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2010-2013 CEA/DEN, EDF R&D, OPEN CASCADE
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 __date__ ="$15 avr. 2010 19:44:17$"
24 from uiexception import DevelException
26 # Most usable class types
27 TypeString= "".__class__
29 TypeInteger = __ref_integer.__class__
31 TypeDouble = __ref_double.__class__
33 TypeList = __ref_list.__class__
35 TypeDictionnary = __ref_dict.__class__
37 # There is no control to do for these attributes. They are attributes for the
38 # class management and not data of the model.
39 UNCHECKED_ATTRIBUTES = [
48 This class is a placeholder for modeling data. An object based on this class
49 (particular instance or specialized derived class) can defined attributes with
50 the following properties:
52 - a type : the class or the type of the attribute. Setting an attribute to
53 a value whose type is not the specified type raises an exception.
54 - a range : a list of the possible values for the attribute. Setting an
55 attribute to a value not in the range raises an exception
56 - a default: the default value of an attribute when an instance is created
57 - a void flag: the attribute can be authorized to be None or not using this
58 flag. Setting an attribute to a None value while the flag is not set to
59 True raises an exception. By default, a None value is not allowed.
61 These properties are dictionnaries mapping the attribute name to its
62 associated value for the property.
64 A typical usage is to derived this class in a specialized form where the
65 attributes names and there properties are defined in the constructor. See
66 use cases at the end of this file.
69 def __init__(self, typemap=None, rangemap=None, defaultmap=None, voidmap=None):
71 self._rangemap = {} # possible values
72 self._defaultmap = {} # defaults values
73 self._voidmap = {} # None values are allowed
75 if typemap is not None:
76 self._typemap.update(typemap)
77 if rangemap is not None:
78 self._rangemap.update(rangemap)
79 if voidmap is not None:
80 self._voidmap.update(voidmap)
82 # Default initialization (if any)
83 if defaultmap is not None:
84 self._defaultmap.update(defaultmap)
85 for name in self._defaultmap.keys():
86 self.__setattr__(name,self._defaultmap[name])
88 def addAttribute(self, name, type=None, range=None, default=None, void=None):
90 A None argument means that no entry is created in the associated maps.
92 self._typemap[name] = type
95 self._rangemap[name] = range
98 self._voidmap[name] = void
100 if (not void) and (default is None):
103 self.__setattr__(name,default)
105 def __setattr__(self, name, val):
106 if name in UNCHECKED_ATTRIBUTES:
107 self.__dict__[name] = val
111 if name == "_typemap":
112 print "WARNING WARNING WARNING : changing value of _typemap by ",val
114 if name not in self._typemap.keys():
115 raise DevelException("The class "+str(self.__class__)+" has no attribute "+str(name))
118 if not self.__isVoidAllowed(name):
119 raise DevelException("The attribute "+str(name)+" can't be None")
121 # We can stop here and set the value to None
122 self.__dict__[name] = None
125 if self.__isNotValidType(name,val):
126 raise DevelException("The attribute "+str(name)+" must be an instance of "+str(self._typemap[name]))
128 if self.__isNotValidRange(name,val):
129 raise DevelException("The attribute "+str(name)+" must be a value in :"+str(self._rangemap[name]))
131 self.__dict__[name] = val
133 def __getattribute__(self, name):
134 if name in UNCHECKED_ATTRIBUTES:
135 return self.__dict__[name]
137 if name not in self._typemap.keys():
138 raise DevelException("The class "+str(self.__class__)+" has no attribute "+str(name))
139 # The attribute coulb be requested while it has not been created yet (for
140 # example if we did't call the setter before).
141 if not self.__dict__.has_key(name):
144 return self.__dict__[name]
146 def __isNotValidType(self, name, val):
148 ( self._typemap[name] is not None) and
149 ( not isinstance(val,self._typemap[name]) ) )
153 def __isNotValidRange(self, name, val):
155 ( self._rangemap is not None) and
156 ( self._rangemap.has_key(name) ) and
157 ( self._rangemap[name] is not None ) and
158 ( val not in self._rangemap[name] ) )
162 def __isVoidAllowed(self,name):
164 ( self._voidmap is not None) and
165 ( self._voidmap.has_key(name) ) and
166 ( self._voidmap[name] is True ) )
171 print "DATAMODELER ["+str(self.__class__)+"]: self._typemap.keys() = "+str(self._typemap.keys())
177 # ==============================================================================
178 # Basic use cases and unit tests
179 # ==============================================================================
183 typemap["stringdata"] = TypeString
184 typemap["integerdata"] = TypeInteger
185 typemap["anydata"] = None # can be anything
187 data = DataModeler(typemap)
191 data.stringdata = sdata
192 data.integerdata = idata
195 data.anydata = "any value"
198 print data.integerdata
201 def TEST_addAttribute():
203 typemap["stringdata"] = TypeString
204 typemap["integerdata"] = TypeInteger
205 data = DataModeler(typemap)
206 data.stringdata = "a string value"
217 if data.myAttr != ref_value:
226 data.myAttr = "bad type value"
232 def TEST_badAttributeName():
234 map["stringdata"] = TypeString
235 map["integerdata"] = TypeInteger
237 data = DataModeler(map)
239 # this should raise an exception
247 def TEST_badAttributeType():
249 map["stringdata"] = TypeString
250 map["integerdata"] = TypeInteger
252 data = DataModeler(map)
253 # this should raise an exception
261 def TEST_badAttributeRange():
263 map["stringdata"] = TypeString
264 map["integerdata"] = TypeInteger
268 range["integerdata"] = [1,ref_integervalue,7]
270 data = DataModeler(map,range)
271 # this should not raise an exception
273 data.integerdata = ref_integervalue
274 data.stringdata = "anything (no restriction has been defined)"
279 # this should raise an exception
281 data.integerdata = 9999 # a value not in the range
287 def TEST_voidAttributeAllowed():
289 map["stringdata"] = TypeString
290 map["integerdata"] = TypeInteger
293 voidmap["stringdata"] = True
295 data = DataModeler(typemap=map,voidmap=voidmap)
297 # this should not raise an exception
298 data.stringdata = None
299 print data.stringdata
305 # this should raise an exception
306 data.integerdata = None
312 def TEST_defaultValues():
314 typemap["stringdata"] = TypeString
315 typemap["integerdata"] = TypeInteger
317 ref_value = "my initial value"
319 defaultmap["stringdata"] = ref_value
321 data = DataModeler(typemap=typemap,defaultmap=defaultmap)
322 print data.stringdata
323 if data.stringdata != ref_value:
328 if __name__ == "__main__":
329 from unittester import run
330 run("salome/kernel/datamodeler","TEST_usecase")
331 run("salome/kernel/datamodeler","TEST_addAttribute")
332 run("salome/kernel/datamodeler","TEST_badAttributeName")
333 run("salome/kernel/datamodeler","TEST_badAttributeType")
334 run("salome/kernel/datamodeler","TEST_badAttributeRange")
335 run("salome/kernel/datamodeler","TEST_voidAttributeAllowed")
336 run("salome/kernel/datamodeler","TEST_defaultValues")