Salome HOME
Merge branch 'vsr/26458'
[modules/kernel.git] / src / KERNEL_PY / kernel / datamodeler.py
index 2decc74ae891a8bc09a2343578cacf7e26b22ef2..a338eb2ea758698219fceba9294740dfe0a9d817 100644 (file)
@@ -1,10 +1,10 @@
 # -*- coding: iso-8859-1 -*-
-# Copyright (C) 2010-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2010-2021  CEA/DEN, EDF R&D, OPEN CASCADE
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
 # License as published by the Free Software Foundation; either
-# version 2.1 of the License.
+# version 2.1 of the License, or (at your option) any later version.
 #
 # This library is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 #
 
+## \defgroup datamodeler datamodeler
+#  \{ 
+#  \details Helper for modeling user data
+#  \}
+
 __author__="gboulant"
 __date__ ="$15 avr. 2010 19:44:17$"
 
-from uiexception import DevelException
+from .uiexception import DevelException
 
 # Most usable class types
 TypeString= "".__class__
@@ -40,9 +45,27 @@ UNCHECKED_ATTRIBUTES = [
     "_typemap",
     "_rangemap",
     "_defaultmap",
-    "_voidmap"
+    "_voidmap",
 ]
 
+## This class is a placeholder for modeling data. An object based on this class
+#  (particular instance or specialized derived class) can defined attributes with
+#  the following properties:
+#  - a type : the class or the type of the attribute. Setting an attribute to
+#    a value whose type is not the specified type raises an exception.
+#  - a range : a list of the possible values for the attribute. Setting an
+#    attribute to a value not in the range raises an exception
+#  - a default: the default value of an attribute when an instance is created
+#  - a void flag: the attribute can be authorized to be None or not using this
+#    flag. Setting an attribute to a None value while the flag is not set to
+#    True raises an exception. By default, a None value is not allowed.
+#
+#  These properties are dictionnaries mapping the attribute name to its
+#  associated value for the property.
+#  \n A typical usage is to derived this class in a specialized form where the
+#  attributes names and there properties are defined in the constructor. See
+#  use cases at the end of this file.
+#  \ingroup datamodeler
 class DataModeler:
     """
     This class is a placeholder for modeling data. An object based on this class
@@ -82,17 +105,18 @@ class DataModeler:
         # Default initialization (if any)
         if defaultmap is not None:
             self._defaultmap.update(defaultmap)
-            for name in self._defaultmap.keys():
+            for name in self._defaultmap:
                 self.__setattr__(name,self._defaultmap[name])
 
-    def addAttribute(self, name, type=None, range=None, default=None, void=None):
+    ## %A None argument means that no entry is created in the associated maps.
+    def addAttribute(self, name, a_type=None, a_range=None, default=None, void=None):
         """
         A None argument means that no entry is created in the associated maps.
         """
-        self._typemap[name] = type
+        self._typemap[name] = a_type
 
-        if range is not None:
-            self._rangemap[name] = range
+        if a_range is not None:
+            self._rangemap[name] = a_range
 
         if void is not None:
             self._voidmap[name] = void
@@ -104,14 +128,14 @@ class DataModeler:
 
     def __setattr__(self, name, val):
         if name in UNCHECKED_ATTRIBUTES:
-            self.__dict__[name] = val
+            object.__setattr__(self, name, val)
             return
 
         #__GBO_DEBUG_
         if name == "_typemap":
-            print "WARNING WARNING WARNING : changing value of _typemap by ",val
+            print("WARNING WARNING WARNING : changing value of _typemap by ",val)
 
-        if name not in self._typemap.keys():
+        if name not in self._typemap:
             raise DevelException("The class "+str(self.__class__)+" has no attribute "+str(name))
 
         if val is None:
@@ -132,16 +156,19 @@ class DataModeler:
     
     def __getattribute__(self, name):
         if name in UNCHECKED_ATTRIBUTES:
-            return self.__dict__[name]
+            return object.__getattribute__(self, name)
 
-        if name not in self._typemap.keys():
-            raise DevelException("The class "+str(self.__class__)+" has no attribute "+str(name))
+        if name in DataModeler.__dict__:
+            return object.__getattribute__(self, name)
+
+        if name not in self._typemap:
+            raise DevelException("The class  has no attribute "+str(name))
         # The attribute coulb be requested while it has not been created yet (for
         # example if we did't call the setter before).
-        if not self.__dict__.has_key(name):
+        if name not in self.__dict__.keys():
             return None
-        
-        return self.__dict__[name]
+
+        return object.__getattribute__(self, name)
 
     def __isNotValidType(self, name, val):
         isNotValid = (
@@ -153,7 +180,7 @@ class DataModeler:
     def __isNotValidRange(self, name, val):
         isNotValid = (
             ( self._rangemap is not None) and
-            ( self._rangemap.has_key(name) ) and
+            ( name in self._rangemap ) and
             ( self._rangemap[name] is not None ) and
             ( val not in self._rangemap[name] ) )
 
@@ -162,13 +189,13 @@ class DataModeler:
     def __isVoidAllowed(self,name):
         isVoidAllowed = (
             ( self._voidmap is not None) and
-            ( self._voidmap.has_key(name) ) and
+            ( name in self._voidmap ) and
             ( self._voidmap[name] is True ) )
             
         return isVoidAllowed
 
     def log(self):
-        print "DATAMODELER ["+str(self.__class__)+"]: self._typemap.keys() = "+str(self._typemap.keys())
+        print("DATAMODELER ["+str(self.__class__)+"]: self._typemap.keys() = "+str(list(self._typemap.keys())))
 
 
 
@@ -195,7 +222,7 @@ def TEST_usecase():
     data.anydata = "any value"
     data.anydata = True
 
-    print data.integerdata
+    print(data.integerdata)
     return True
 
 def TEST_addAttribute():
@@ -208,8 +235,8 @@ def TEST_addAttribute():
     ref_value = 1.3
     data.addAttribute(
         name    = "myAttr",
-        type    = TypeDouble,
-        range   = None,
+        a_type    = TypeDouble,
+        a_range   = None,
         default = ref_value,
         void    = False)
 
@@ -218,15 +245,15 @@ def TEST_addAttribute():
             return False
         data.myAttr = 5.3
         #data.myAttr = 5
-    except Exception, e:
-        print e
+    except Exception as e:
+        print(e)
         return False
 
     try:
         data.myAttr = "bad type value"
         return False
-    except Exception, e:
-        print e
+    except Exception as e:
+        print(e)
         return True
 
 def TEST_badAttributeName():
@@ -240,8 +267,8 @@ def TEST_badAttributeName():
     try:
         data.myatt = 3
         return False
-    except Exception, e:
-        print "OK : "+str(e)
+    except Exception as e:
+        print("OK : "+str(e))
         return True
 
 def TEST_badAttributeType():
@@ -254,8 +281,8 @@ def TEST_badAttributeType():
     try:
         data.stringdata = 2
         return False
-    except Exception, e:
-        print "OK : "+str(e)
+    except Exception as e:
+        print("OK : "+str(e))
         return True
 
 def TEST_badAttributeRange():
@@ -272,16 +299,16 @@ def TEST_badAttributeRange():
     try:
         data.integerdata = ref_integervalue
         data.stringdata = "anything (no restriction has been defined)"
-    except Exception, e:
-        print e
+    except Exception as e:
+        print(e)
         return False
 
     # this should raise an exception
     try:
         data.integerdata = 9999 # a value not in the range
         return False
-    except Exception, e:
-        print e
+    except Exception as e:
+        print(e)
         return True
 
 def TEST_voidAttributeAllowed():
@@ -296,17 +323,17 @@ def TEST_voidAttributeAllowed():
     try:
         # this should not raise an exception
         data.stringdata = None
-        print data.stringdata
-    except Exception, e:
-        print e
+        print(data.stringdata)
+    except Exception as e:
+        print(e)
         return False
     
     try:
         # this should raise an exception
         data.integerdata = None
         return False
-    except Exception, e:
-        print e
+    except Exception as e:
+        print(e)
         return True
 
 def TEST_defaultValues():
@@ -319,14 +346,14 @@ def TEST_defaultValues():
     defaultmap["stringdata"] = ref_value
 
     data = DataModeler(typemap=typemap,defaultmap=defaultmap)
-    print data.stringdata
+    print(data.stringdata)
     if data.stringdata != ref_value:
         return False
     else:
         return True
 
 if __name__ == "__main__":
-    from unittester import run
+    from .unittester import run
     run("salome/kernel/datamodeler","TEST_usecase")
     run("salome/kernel/datamodeler","TEST_addAttribute")
     run("salome/kernel/datamodeler","TEST_badAttributeName")