Browse Source

smarter handling of optional and mandatories in positional parameter handling

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jelte-datadef@386 e5f2f494-b856-4b98-b285-d166d9295462
Jelte Jansen 15 years ago
parent
commit
1af07bbec7

+ 3 - 3
src/bin/bigtool/run_bigtool.py

@@ -34,19 +34,19 @@ def prepare_config_commands(bigtool):
     cmd = CommandInfo(name = "remove", desc = "Remove entry from configuration list", need_inst_param = False)
     param = ParamInfo(name = "identifier", type = "string", optional=True)
     cmd.add_param(param)
-    param = ParamInfo(name = "value", type = "string", optional=True)
+    param = ParamInfo(name = "value", type = "string", optional=False)
     cmd.add_param(param)
     module.add_command(cmd)
 
     cmd = CommandInfo(name = "set", desc = "Set a configuration value", need_inst_param = False)
     param = ParamInfo(name = "identifier", type = "string", optional=True)
     cmd.add_param(param)
-    param = ParamInfo(name = "value", type = "string", optional=True)
+    param = ParamInfo(name = "value", type = "string", optional=False)
     cmd.add_param(param)
     module.add_command(cmd)
 
     cmd = CommandInfo(name = "unset", desc = "Unset a configuration value", need_inst_param = False)
-    param = ParamInfo(name = "identifier", type = "string", optional=True)
+    param = ParamInfo(name = "identifier", type = "string", optional=False)
     cmd.add_param(param)
     module.add_command(cmd)
 

+ 11 - 1
src/lib/bigtool/bigtool.py

@@ -67,6 +67,8 @@ class BigTool(Cmd):
                                              list(params.keys())[0])
         elif params:
             param_name = None
+            index = 0
+            param_count = len(params)
             for name in params:
                 # either the name of the parameter must be known, or
                 # the 'name' must be an integer (ie. the position of
@@ -81,7 +83,14 @@ class BigTool(Cmd):
                             raise CmdUnknownParamSyntaxError(cmd.module, cmd.command, cmd.params[name])
                     else:
                         # replace the numbered items by named items
-                        param_name = command_info.get_param_name_by_position(name+1)
+                        # if a parameter is optional, and subsequent ones
+                        # are not, we have to mix and match a little;
+                        # 1: optional
+                        # 2: mandatory
+                        # 3: optional
+                        # 3 given: 1,2,3. 2 given: 1 and 2. 1 given: 2
+                        #param_name = command_info.get_param_name_by_position(name+1)
+                        param_name = command_info.get_param_name_by_position2(name+1, index, param_count)
                         cmd.params[param_name] = cmd.params[name]
                         del cmd.params[name]
                         
@@ -327,6 +336,7 @@ class BigTool(Cmd):
             print("Error: " + identifier + " not found")
         except KeyError as ke:
             print("Error: missing " + str(ke))
+            raise ke
 
     def go(self, identifier):
         # just to see if it exists

+ 44 - 1
src/lib/bigtool/moduleinfo.py

@@ -34,7 +34,7 @@ class ParamInfo:
         node = xmldoc.createElement(PARAM_NODE_NAME)
         node.setAttribute('name', name)
         node.setAttribute('value', value)                             
-        return node                                              
+        return node
 
 class CommandInfo:
     """One command which provide by one bind10 module, it has zero or 
@@ -81,6 +81,49 @@ class CommandInfo:
         return [name for name in all_names 
                 if not self.params[name].is_optional]        
         
+    def get_param_name_by_position2(self, pos, index, param_count):
+        # count mandatories back from the last
+        # from the last mandatory; see the number of mandatories before it
+        # and compare that to the number of positional arguments left to do
+        # if the number of lefts is higher than the number of mandatories,
+        # use the first optional. Otherwise, use the first unhandled mandatory
+        # (and update the location accordingly?)
+        # (can this be done in all cases? this is certainly not the most efficient method;
+        # one way to make the whole of this more consistent is to always set mandatories first, but
+        # that would make some commands less nice to use ("config set value location" instead of "config set location value")
+        if type(pos) == int:
+            if param_count == len(self.params) - 1:
+                i = 0
+                for k in self.params.keys():
+                    if i == pos:
+                        return k
+                    i += 1
+                raise KeyError(str(pos) + " out of range")
+            elif param_count <= len(self.params):
+                mandatory_count = 0
+                for k in self.params.keys():
+                    if not self.params[k].is_optional:
+                        mandatory_count += 1
+                if param_count == mandatory_count:
+                    # return the first mandatory from pos
+                    i = 0
+                    for k in self.params.keys():
+                        if i >= pos and not self.params[k].is_optional:
+                            return k
+                        i += 1
+                    raise KeyError(str(pos) + " out of range")
+                else:
+                    i = 0
+                    for k in self.params.keys():
+                        if i == pos:
+                            return k
+                        i += 1
+                    raise KeyError(str(pos) + " out of range")
+            else:
+                raise KeyError("Too many parameters")
+        else:
+            raise KeyError(str(pos) + " is not an integer")
+    
     def get_param_name_by_position(self, pos):
         if type(pos) == int:
             i = 0

+ 16 - 1
src/lib/cc/python/ISC/CC/data.py

@@ -239,7 +239,22 @@ class UIConfigData():
             return value, default, False
         return None, False, False
 
+    def get_value_map_single(self, identifier, entry):
+        """Returns a single entry for a value_map, where the value is
+           not a part of a bigger map"""
+        result_part = {}
+        result_part['name'] = entry['item_name']
+        result_part['type'] = entry['item_type']
+        value, default, modified = self.get_value(identifier)
+        # should we check type and only set int, double, bool and string here?
+        result_part['value'] = value
+        result_part['default'] = default
+        result_part['modified'] = modified
+        return result_part
+
     def get_value_map(self, identifier, entry):
+        """Returns a single entry for a value_map, where the value is
+           a part of a bigger map"""
         result_part = {}
         result_part['name'] = entry['item_name']
         result_part['type'] = entry['item_type']
@@ -264,7 +279,7 @@ class UIConfigData():
         if type(spec) == dict:
             # either the top-level list of modules or a spec map
             if 'item_name' in spec:
-                result_part = self.get_value_map(identifier, spec)
+                result_part = self.get_value_map_single(identifier, spec)
                 if result_part['type'] == "list":
                     values = self.get_value(identifier)[0]
                     if values: