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 _______________________________________________ commit-gnue mailing list commit-gnue@gnu.org http://lists.gnu.org/mailman/listinfo/commit-gnue