moduleinfo.py 6.93 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
# Copyright (C) 2009  Internet Systems Consortium.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.


try:
    from collections import OrderedDict
except ImportError:
    from mycollections import OrderedDict

# Define value type
STRING_TYPE = "string"
LIST_TYPE = "list"
INT_TYPE = "int"

MODULE_NODE_NAME = 'module'
COMMAND_NODE_NAME = 'command'
PARAM_NODE_NAME = 'param'


class ParamInfo:
    """The parameter of one command
    each command parameter have four attributes, 
    parameter name, parameter type, parameter value, and parameter description
    """
    def __init__(self, name, desc = '', type = STRING_TYPE, 
                 optional = False, value = '', default_value = ''):
        self.name = name
        self.type = type
        self.value = value
        self.default_value = default_value                           
        self.desc = desc
        self.is_optional = optional
    
    def __str__(self):        
        return str("\t%s <type: %s> \t(%s)" % (self.name, self.type, self.desc))

class CommandInfo:
    """One command which provide by one bind10 module, it has zero or 
    more parameters
    """

54
    def __init__(self, name, desc = ""):
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
        self.name = name
        self.desc = desc
        self.params = OrderedDict()        
        # Set default parameter "help"
        self.add_param(ParamInfo("help", 
                                  desc = "Get help for command",
                                  optional = True))
                
    def __str__(self):
        return str("%s \t(%s)" % (self.name, self.desc))
        

    def add_param(self, paraminfo):
        self.params[paraminfo.name] = paraminfo
        

    def has_param_with_name(self, param_name):
        return param_name in self.params
        

    def get_param_with_name(self, param_name):
        return self.params[param_name]
        

    def get_params(self):
        return list(self.params.values())
        

    def get_param_names(self):
        return list(self.params.keys())
        
        
    def get_mandatory_param_names(self):
        all_names = self.params.keys()
        return [name for name in all_names 
                if not self.params[name].is_optional]        
        
92
    def get_param_name_by_position(self, pos, param_count):
93 94 95 96 97 98 99 100 101
        # 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")
102 103 104
        if type(pos) != int:
            raise KeyError(str(pos) + " is not an integer")
        else:
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
            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")


136
    def command_help(self):
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
        print("Command ", self)
        print("\t\thelp (Get help for command)")
                
        params = self.params.copy()
        del params["help"]

        if len(params) == 0:
            print("\tNo parameters for the command")
            return
        
        print("\n\tMandatory parameters:")
        mandatory_infos = []
        for info in params.values():            
            if not info.is_optional:
                print("\t", info)
                mandatory_infos.append(info)

        optional_infos = [info for info in params.values() 
                          if info not in mandatory_infos]
        if len(optional_infos) > 0:
            print("\n\tOptional parameters:")      
            for info in optional_infos:
                    print("\t", info)


class ModuleInfo:
    """Define the information of one module, include module name, 
164
    module supporting commands.
165 166
    """    
    
167
    def __init__(self, name, desc = ""):
168 169 170 171
        self.name = name
        self.desc = desc
        self.commands = OrderedDict()         
        self.add_command(CommandInfo(name = "help", 
172
                                     desc = "Get help for module"))
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
        
    def __str__(self):
        return str("%s \t%s" % (self.name, self.desc))
        
    def add_command(self, command_info):        
        self.commands[command_info.name] = command_info
        
    def has_command_with_name(self, command_name):
        return command_name in self.commands
        
    def get_command_with_name(self, command_name):
        return self.commands[command_name]
        
    def get_commands(self):
        return list(self.commands.values())
        
    def get_command_names(self):
        return list(self.commands.keys())

    def module_help(self):
        print("Module ", self, "\nAvailable commands:")
        for k in self.commands.keys():
            print("\t", self.commands[k])
            
    def command_help(self, command):
198
        self.commands[command].command_help()    
199