commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r9962 - trunk/gnue-common/src/base


From: reinhard
Subject: [gnue] r9962 - trunk/gnue-common/src/base
Date: Mon, 12 Oct 2009 15:32:31 -0500 (CDT)

Author: reinhard
Date: 2009-10-12 15:32:31 -0500 (Mon, 12 Oct 2009)
New Revision: 9962

Modified:
   trunk/gnue-common/src/base/tree.py
Log:
Added option to allow/disallow None values for attribs.


Modified: trunk/gnue-common/src/base/tree.py
===================================================================
--- trunk/gnue-common/src/base/tree.py  2009-10-12 19:38:44 UTC (rev 9961)
+++ trunk/gnue-common/src/base/tree.py  2009-10-12 20:32:31 UTC (rev 9962)
@@ -668,11 +668,13 @@
             _node_attribs_['color'] = {
                 'type': str,
                 'allowed_values': ['white', 'blue', 'red', 'green'],
+                'required': False,
                 'default': 'white',
                 'label': u_("Background Color"),
                 'description': u_("Color on the screen")}
             _node_attribs_['speed'] = {
                 'type': int,
+                'required': True,
                 'default': 0,
                 'label': u_("Speed"),
                 'description': u_("Speed in km per hour")}
@@ -688,6 +690,11 @@
     allowed_values: Limited value set for this attribute. If not included in
     the dictionary, all possible values of the defined type are valid.
 
+    required: False means that the attribute may also be set to None, True
+    means that this is not allowed. If not included in the dictionary, it
+    defaults to False. Required attributes must be set at object initialization
+    unless a default value exists.
+
     label: Short name for the attribute to present to users (e.g. in
     gnue-designer).
 
@@ -765,10 +772,17 @@
         if name is not None:
             self.name = name
 
+        # Set attributes given in object constructor.
         for (attrib, value) in kwargs.items():
             self.__set_attrib__(attrib, value)
 
+        # Check whether all required attribs have been initialized.
+        for (attrib, definition) in self._node_attribs_.items():
+            if definition.get('required', False):
+                if self.__get_attrib__(attrib) is None:
+                    raise AttribRequiredError(self, attrib)
 
+
     # -------------------------------------------------------------------------
     # Access attribs as object attributes
     # -------------------------------------------------------------------------
@@ -826,7 +840,7 @@
         if issubclass(target_type, NamedNode) and value is not None:
             return self.__root__.__get_node_dict__(target_type)[value]
         else:
-            value
+            return value
 
     # -------------------------------------------------------------------------
 
@@ -844,11 +858,13 @@
 
         definition = self._node_attribs_[name]
 
-        # TODO: Add option to allow/disallow setting to None.
+        # Check if setting to None is allowed.
+        if value is None and definition.get('required', False):
+            raise AttribRequiredError(self, name)
 
         target_type = definition['type']
 
-        # If this is a reference to another node, we need to store the name
+        # If this is a reference to another node, we need to store the name.
         if issubclass(target_type, NamedNode):
             target_type = unicode
 
@@ -856,15 +872,18 @@
         if not isinstance(value, target_type):
             value = target_type(value)
 
+        # Check if value is allowed.
         if definition.has_key('allowed_values'):
             if value not in definition['allowed_values']:
                 raise ValueError
 
+        # Call _change_foo_ method of the object.
         if '_change_' + name + '_' in dir(self):
             getattr(self, '_change_' + name + '_')(value)
 
         self.__attribs[name] = value
 
+        # The attrib 'name' doubles as the node name.
         if name == 'name':
             self.__node_name__ = value
 
@@ -995,6 +1014,25 @@
 
 
 # =============================================================================
+
+class AttribRequiredError(errors.ApplicationError):
+    """
+    The attribute is required.
+
+    A required attribute is missing at object creation or attempt to set
+    required attribute to None.
+    """
+    def __init__(self, node, attrib_name):
+        message = u_(
+                "Attribute '%(attrib_name)s' is required for node "
+                "'%(node_name)s' of of class '%(node_class)s'")
+        errors.ApplicationError.__init__(self, message % {
+            'attrib_name': attrib_name,
+            'node_name': unicode(node),
+            'node_class': node.__class__.__name__})
+
+
+# =============================================================================
 # Self test code
 # =============================================================================
 
@@ -1212,10 +1250,10 @@
         _allowed_children_ = {}
         def _change_supervisor_(self, value):
             print "Hey, %s's supervisor has changed to %s" % (self, value)
-    Member._node_attribs_ = AttribNode._node_attribs_
+    Member._node_attribs_ = AttribNode._node_attribs_.copy()
     Member._node_attribs_.update({
-            'rank': {'type': str},
-            'supervisor': {'type': Member}})
+        'rank': {'type': str, 'required': True},
+        'supervisor': {'type': Member}})
     class Crew(AttribNode):
         _allowed_children_ = {Member: {}}
         _node_dicts_ = [Member]
@@ -1239,6 +1277,16 @@
                 name="Nyota Uhura",
                 rank="Communication Officer")])
 
+    # Test check of required attributes.
+    try:
+        Member(parent=crew, name='Guest')
+    except AttribRequiredError, error:
+        print "Correctly got an exception:", error
+    try:
+        crew.Spock.rank = None
+    except AttribRequiredError, error:
+        print "Correctly got an exception:", error
+
     # Test attribute access for children.
     print "Spock can be directly accessed:",
     print crew.Spock





reply via email to

[Prev in Thread] Current Thread [Next in Thread]