Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / command_tree.py @ 5eae854d

History | View | Annotate | Download (7.8 kB)

1 00af4193 Stavros Sachtouris
# Copyright 2011 GRNET S.A. All rights reserved.
2 00af4193 Stavros Sachtouris
#
3 00af4193 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 00af4193 Stavros Sachtouris
# without modification, are permitted provided that the following
5 00af4193 Stavros Sachtouris
# conditions are met:
6 00af4193 Stavros Sachtouris
#
7 00af4193 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 00af4193 Stavros Sachtouris
#          copyright notice, this list of conditions and the following
9 00af4193 Stavros Sachtouris
#          disclaimer.
10 00af4193 Stavros Sachtouris
#
11 00af4193 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 00af4193 Stavros Sachtouris
#          copyright notice, this list of conditions and the following
13 00af4193 Stavros Sachtouris
#          disclaimer in the documentation and/or other materials
14 00af4193 Stavros Sachtouris
#          provided with the distribution.
15 00af4193 Stavros Sachtouris
#
16 00af4193 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 00af4193 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 00af4193 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 00af4193 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 00af4193 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 00af4193 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 00af4193 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 00af4193 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 00af4193 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 00af4193 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 00af4193 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 00af4193 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 00af4193 Stavros Sachtouris
#
29 00af4193 Stavros Sachtouris
# The views and conclusions contained in the software and
30 00af4193 Stavros Sachtouris
# documentation are those of the authors and should not be
31 00af4193 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 00af4193 Stavros Sachtouris
# or implied, of GRNET S.A.
33 00af4193 Stavros Sachtouris
34 00af4193 Stavros Sachtouris
import cmd
35 d9325478 Stavros Sachtouris
#from .errors import CLIUnknownCommand, CLICmdIncompleteError, CLICmdSpecError, CLIError
36 00af4193 Stavros Sachtouris
37 00af4193 Stavros Sachtouris
class Command(object):
38 00af4193 Stavros Sachtouris
        """Store a command and the next-level commands as well - no deep tree here"""
39 00af4193 Stavros Sachtouris
        _name = None
40 00af4193 Stavros Sachtouris
        path = None
41 00af4193 Stavros Sachtouris
        cmd_class = None
42 00af4193 Stavros Sachtouris
        subcommands = {}
43 00af4193 Stavros Sachtouris
        help = ' '
44 00af4193 Stavros Sachtouris
45 00af4193 Stavros Sachtouris
        def __init__(self, path, help = ' ', subcommands={}, cmd_class=None):
46 00af4193 Stavros Sachtouris
                self.path = path
47 00af4193 Stavros Sachtouris
                self.help = help
48 00af4193 Stavros Sachtouris
                self.subcommands =dict(subcommands)
49 00af4193 Stavros Sachtouris
                self.cmd_class = cmd_class
50 00af4193 Stavros Sachtouris
51 00af4193 Stavros Sachtouris
        @property 
52 00af4193 Stavros Sachtouris
        def name(self):
53 00af4193 Stavros Sachtouris
                if self._name is None:
54 00af4193 Stavros Sachtouris
                        self._name = self.path.split('_')[-1]
55 00af4193 Stavros Sachtouris
                return str(self._name)
56 00af4193 Stavros Sachtouris
57 00af4193 Stavros Sachtouris
        def add_subcmd(self, subcmd):
58 00af4193 Stavros Sachtouris
                if subcmd.path == self.path+'_'+subcmd.name:
59 00af4193 Stavros Sachtouris
                        self.subcommands[subcmd.name] = subcmd
60 00af4193 Stavros Sachtouris
                        return True
61 00af4193 Stavros Sachtouris
                return False
62 00af4193 Stavros Sachtouris
        def get_subcmd(self, name):
63 00af4193 Stavros Sachtouris
                try:
64 00af4193 Stavros Sachtouris
                        return self.subcommands[name]
65 00af4193 Stavros Sachtouris
                except KeyError:
66 00af4193 Stavros Sachtouris
                        return None
67 00af4193 Stavros Sachtouris
68 00af4193 Stavros Sachtouris
        def contains(self, name):
69 00af4193 Stavros Sachtouris
                """Check if a name is a direct child of self"""
70 00af4193 Stavros Sachtouris
                return self.subcommands.has_key(name)
71 00af4193 Stavros Sachtouris
72 d9325478 Stavros Sachtouris
        @property 
73 00af4193 Stavros Sachtouris
        def is_command(self):
74 00af4193 Stavros Sachtouris
                return self.cmd_class is not None
75 d9325478 Stavros Sachtouris
        @property 
76 d9325478 Stavros Sachtouris
        def has_description(self):
77 d9325478 Stavros Sachtouris
                return len(self.help.strip()) > 0
78 d9325478 Stavros Sachtouris
        @property 
79 d9325478 Stavros Sachtouris
        def description(self):
80 d9325478 Stavros Sachtouris
                return self.help
81 00af4193 Stavros Sachtouris
82 00af4193 Stavros Sachtouris
        def set_class(self, cmd_class):
83 00af4193 Stavros Sachtouris
                self.cmd_class = cmd_class
84 00af4193 Stavros Sachtouris
        def get_class(self):
85 00af4193 Stavros Sachtouris
                return self.cmd_class
86 00af4193 Stavros Sachtouris
87 629adab4 Stavros Sachtouris
        def has_subname(self, subname):
88 629adab4 Stavros Sachtouris
                return self.subcommands.has_key(subname)        
89 00af4193 Stavros Sachtouris
        def get_subnames(self):
90 00af4193 Stavros Sachtouris
                return self.subcommands.keys()
91 00af4193 Stavros Sachtouris
        def get_subcommands(self):
92 00af4193 Stavros Sachtouris
                return self.subcommands.values()
93 00af4193 Stavros Sachtouris
        def sublen(self):
94 00af4193 Stavros Sachtouris
                return len(self.subcommands)
95 00af4193 Stavros Sachtouris
96 629adab4 Stavros Sachtouris
        def parse_out(self, args):
97 629adab4 Stavros Sachtouris
                cmd = self
98 629adab4 Stavros Sachtouris
                index = 0
99 629adab4 Stavros Sachtouris
                for term in args:
100 629adab4 Stavros Sachtouris
                        try:
101 629adab4 Stavros Sachtouris
                                cmd = cmd.subcommands[term]
102 629adab4 Stavros Sachtouris
                        except KeyError:
103 629adab4 Stavros Sachtouris
                                break
104 629adab4 Stavros Sachtouris
                        index += 1
105 629adab4 Stavros Sachtouris
                return cmd, args[index:]
106 629adab4 Stavros Sachtouris
107 00af4193 Stavros Sachtouris
        def pretty_print(self, recursive=False):
108 00af4193 Stavros Sachtouris
                print('Path: %s (Name: %s) is_cmd: %s\n\thelp: %s'%(self.path, self.name,
109 d9325478 Stavros Sachtouris
                        self.is_command, self.help))
110 00af4193 Stavros Sachtouris
                for cmd in self.get_subcommands():
111 00af4193 Stavros Sachtouris
                        cmd.pretty_print(recursive)
112 00af4193 Stavros Sachtouris
113 00af4193 Stavros Sachtouris
def test_Command():
114 00af4193 Stavros Sachtouris
        cmd = Command('store', 'A store thingy')
115 00af4193 Stavros Sachtouris
        cmd.add_subcmd(Command('store_list'))
116 00af4193 Stavros Sachtouris
        tmp = cmd.get_subcmd('list')
117 00af4193 Stavros Sachtouris
        tmp.add_subcmd(Command('store_list_all', 'List everything'))
118 00af4193 Stavros Sachtouris
        tmp.add_subcmd(Command('store_list_one', 'List just one stuff'))
119 00af4193 Stavros Sachtouris
        cmd.pretty_print(True)
120 00af4193 Stavros Sachtouris
121 d9325478 Stavros Sachtouris
class CommandTree(object):
122 d9325478 Stavros Sachtouris
123 d9325478 Stavros Sachtouris
        groups = {}
124 d9325478 Stavros Sachtouris
        _all_commands = {}
125 d9325478 Stavros Sachtouris
        name = None
126 d9325478 Stavros Sachtouris
        description = None
127 d9325478 Stavros Sachtouris
128 d9325478 Stavros Sachtouris
        def __init__(self, name, description=''):
129 d9325478 Stavros Sachtouris
                self.name = name
130 d9325478 Stavros Sachtouris
                self.description = description
131 d9325478 Stavros Sachtouris
132 d9325478 Stavros Sachtouris
        def add_command(self, command_path, description=None, cmd_class=None):
133 d9325478 Stavros Sachtouris
                terms = command_path.split('_')
134 d9325478 Stavros Sachtouris
                try:
135 d9325478 Stavros Sachtouris
                        cmd = self.groups[terms[0]]
136 d9325478 Stavros Sachtouris
                except KeyError:
137 d9325478 Stavros Sachtouris
                        cmd = Command(terms[0])
138 d9325478 Stavros Sachtouris
                        self.groups[terms[0]] = cmd
139 d9325478 Stavros Sachtouris
                        self._all_commands[terms[0]] = cmd
140 d9325478 Stavros Sachtouris
                path = terms[0]
141 d9325478 Stavros Sachtouris
                for term in terms[1:]:
142 d9325478 Stavros Sachtouris
                        path += '_'+term
143 d9325478 Stavros Sachtouris
                        try:
144 d9325478 Stavros Sachtouris
                                cmd = cmd.subcommands[term]
145 d9325478 Stavros Sachtouris
                        except KeyError:
146 d9325478 Stavros Sachtouris
                                new_cmd = Command(path)
147 d9325478 Stavros Sachtouris
                                self._all_commands[path] = new_cmd
148 d9325478 Stavros Sachtouris
                                cmd.add_subcmd(new_cmd)
149 d9325478 Stavros Sachtouris
                                cmd = new_cmd
150 d9325478 Stavros Sachtouris
                if cmd_class is not None:
151 d9325478 Stavros Sachtouris
                        cmd.set_class(cmd_class)
152 d9325478 Stavros Sachtouris
                if description is not None:
153 d9325478 Stavros Sachtouris
                        cmd.help = description
154 d9325478 Stavros Sachtouris
        def get_command(self, path):
155 d9325478 Stavros Sachtouris
                return self._all_commands[path]
156 d9325478 Stavros Sachtouris
        def get_groups(self):
157 d9325478 Stavros Sachtouris
                return self.groups.values()
158 d9325478 Stavros Sachtouris
        def get_group_names(self):
159 d9325478 Stavros Sachtouris
                return self.groups.keys()
160 d9325478 Stavros Sachtouris
161 d9325478 Stavros Sachtouris
        def set_description(self, path, description):
162 d9325478 Stavros Sachtouris
                self._all_commands[path].help = description
163 d9325478 Stavros Sachtouris
        def get_descitpion(self, path):
164 d9325478 Stavros Sachtouris
                return self._all_commands[path].help
165 d9325478 Stavros Sachtouris
        def set_class(self, path, cmd_class):
166 d9325478 Stavros Sachtouris
                self._all_commands[path].set_class(cmd_class)
167 d9325478 Stavros Sachtouris
        def get_class(self, path):
168 d9325478 Stavros Sachtouris
                return self._all_commands[path].get_class()
169 d9325478 Stavros Sachtouris
170 73e0914d Stavros Sachtouris
        def get_subnames(self, path=None):
171 73e0914d Stavros Sachtouris
                return self.get_group_names() if path in (None, '') \
172 73e0914d Stavros Sachtouris
                else self._all_commands[path].get_subnames()
173 73e0914d Stavros Sachtouris
        def get_subcommands(self, path=None):
174 73e0914d Stavros Sachtouris
                return self.get_groups() if path in (None, '') \
175 73e0914d Stavros Sachtouris
                else self._all_commands[path].get_subcommands()
176 d9325478 Stavros Sachtouris
        def get_parent(self, path):
177 d9325478 Stavros Sachtouris
                if '_' not in path:
178 d9325478 Stavros Sachtouris
                        return None
179 d9325478 Stavros Sachtouris
                terms = path.split('_')
180 d9325478 Stavros Sachtouris
                parent_path = '_'.join(terms[:-1])
181 d9325478 Stavros Sachtouris
                return self._all_commands[parent_path]
182 d9325478 Stavros Sachtouris
        def get_closest_ancestor_command(self, path):
183 d9325478 Stavros Sachtouris
                path, sep, name = path.rpartition('_')
184 d9325478 Stavros Sachtouris
                while len(path) > 0:
185 d9325478 Stavros Sachtouris
                        cmd = self._all_commands[path]
186 d9325478 Stavros Sachtouris
                        if cmd.is_command:
187 d9325478 Stavros Sachtouris
                                return cmd
188 d9325478 Stavros Sachtouris
                        path, sep, name = path.rpartition('_')
189 d9325478 Stavros Sachtouris
                return None
190 d9325478 Stavros Sachtouris
191 d9325478 Stavros Sachtouris
                if '_' not in path:
192 d9325478 Stavros Sachtouris
                        return None
193 d9325478 Stavros Sachtouris
                terms = terms[:-1]
194 d9325478 Stavros Sachtouris
                while len(terms) > 0:
195 d9325478 Stavros Sachtouris
                        tmp_path = '_'.join(terms)
196 d9325478 Stavros Sachtouris
                        cmd = self._all_commands[tmp_path]
197 d9325478 Stavros Sachtouris
                        if cmd.is_command:
198 d9325478 Stavros Sachtouris
                                return cmd
199 d9325478 Stavros Sachtouris
                        terms = terms[:-1]
200 d9325478 Stavros Sachtouris
                raise KeyError('No ancestor commands')
201 d9325478 Stavros Sachtouris
202 d9325478 Stavros Sachtouris
        def pretty_print(self, group=None):
203 d9325478 Stavros Sachtouris
                if group is None:
204 d9325478 Stavros Sachtouris
                        for group in self.groups:
205 d9325478 Stavros Sachtouris
                                self.pretty_print(group)
206 d9325478 Stavros Sachtouris
                else:
207 d9325478 Stavros Sachtouris
                        self.groups[group].pretty_print(recursive=True)
208 d9325478 Stavros Sachtouris
209 d9325478 Stavros Sachtouris
def test_CommandTree():
210 d9325478 Stavros Sachtouris
        tree = CommandTree('kamaki', 'the kamaki tools')
211 d9325478 Stavros Sachtouris
        tree.add_command('store', 'A storage thingy')
212 d9325478 Stavros Sachtouris
        tree.add_command('server_list_lala', description='A testing server list', cmd_class=Shell)
213 d9325478 Stavros Sachtouris
        tree.add_command('store_list_all', 'List all things', cmd_class=Command)
214 d9325478 Stavros Sachtouris
        tree.add_command('store_list', 'List smthing pls', cmd_class=Shell)
215 d9325478 Stavros Sachtouris
        tree.add_command('server_list', description='A server list subgrp')
216 d9325478 Stavros Sachtouris
        tree.add_command('server', description='A server is a SERVER', cmd_class=CommandTree)
217 d9325478 Stavros Sachtouris
        tree.set_class('server', None)
218 d9325478 Stavros Sachtouris
        tree.set_description('server_list', '')
219 d9325478 Stavros Sachtouris
        if tree.get_class('server_list_lala') is Shell:
220 d9325478 Stavros Sachtouris
                print('server_list_lala is Shell')
221 d9325478 Stavros Sachtouris
        else:
222 d9325478 Stavros Sachtouris
                print('server_list_lala is not Shell')
223 d9325478 Stavros Sachtouris
        tree.pretty_print()
224 d9325478 Stavros Sachtouris
        print('store_list_all closest parent command is %s'%tree.get_closest_ancestor_command('store_list_all').path)
225 d9325478 Stavros Sachtouris
        tree.set_class('store', tree.get_command('store_list').get_class())
226 d9325478 Stavros Sachtouris
        tree.set_class('store_list', None)
227 d9325478 Stavros Sachtouris
        print('store_list_all closest parent command is %s'%tree.get_closest_ancestor_command('store_list_all').path)
228 d9325478 Stavros Sachtouris
        try:
229 d9325478 Stavros Sachtouris
                print('nonexisting_list_command closest parent is %s'%tree.get_closest_ancestor_command('nonexisting_list_command').path)
230 d9325478 Stavros Sachtouris
        except KeyError:
231 d9325478 Stavros Sachtouris
                print('Aparrently nonexisting_list_command is nonexisting ')
232 d9325478 Stavros Sachtouris
233 00af4193 Stavros Sachtouris
class Shell(cmd.Cmd):
234 00af4193 Stavros Sachtouris
        """Simple command processor example."""
235 00af4193 Stavros Sachtouris
236 00af4193 Stavros Sachtouris
        def do_greet(self, line):
237 00af4193 Stavros Sachtouris
                """Hello [cmd]
238 00af4193 Stavros Sachtouris
                        @line some line"""
239 00af4193 Stavros Sachtouris
                print "hello"
240 00af4193 Stavros Sachtouris
241 00af4193 Stavros Sachtouris
        def do_lala(self, lala):
242 00af4193 Stavros Sachtouris
                print('This is what I got: %s'%lala)
243 00af4193 Stavros Sachtouris
        def help_lala(self):
244 00af4193 Stavros Sachtouris
                print('This is SPAAARTAAAAAAA')
245 00af4193 Stavros Sachtouris
246 00af4193 Stavros Sachtouris
        def do_lalum(self, args):
247 00af4193 Stavros Sachtouris
                print('lalum')
248 00af4193 Stavros Sachtouris
        def complete_lalum(self, text, line, begidx, endidx):
249 00af4193 Stavros Sachtouris
                completions = ['lala']
250 00af4193 Stavros Sachtouris
                return completions
251 00af4193 Stavros Sachtouris
252 00af4193 Stavros Sachtouris
        def do_EOF(self, line):
253 00af4193 Stavros Sachtouris
                return True
254 00af4193 Stavros Sachtouris
255 1c1fd2fa Stavros Sachtouris
if __name__ == '__main__':
256 1c1fd2fa Stavros Sachtouris
        sh = Shell()
257 1c1fd2fa Stavros Sachtouris
        sh.prompt = 'lala_$ '
258 1c1fd2fa Stavros Sachtouris
        sh.cmdloop()
259 1c1fd2fa Stavros Sachtouris
260 1c1fd2fa Stavros Sachtouris
        #import sys
261 1c1fd2fa Stavros Sachtouris
        #sh.onecmd(' '.join(sys.argv[1:]))
262 1c1fd2fa Stavros Sachtouris
        #test_CommandTree()