Revision d9325478 kamaki/cli/command.py

b/kamaki/cli/command.py
32 32
# or implied, of GRNET S.A.
33 33

  
34 34
import cmd
35
#from .errors import CLIUnknownCommand, CLICmdIncompleteError, CLICmdSpecError, CLIError
35 36

  
36 37
class Command(object):
37 38
	"""Store a command and the next-level commands as well - no deep tree here"""
......
68 69
		"""Check if a name is a direct child of self"""
69 70
		return self.subcommands.has_key(name)
70 71

  
72
	@property 
71 73
	def is_command(self):
72 74
		return self.cmd_class is not None
75
	@property 
76
	def has_description(self):
77
		return len(self.help.strip()) > 0
78
	@property 
79
	def description(self):
80
		return self.help
73 81

  
74 82
	def set_class(self, cmd_class):
75 83
		self.cmd_class = cmd_class
......
85 93

  
86 94
	def pretty_print(self, recursive=False):
87 95
		print('Path: %s (Name: %s) is_cmd: %s\n\thelp: %s'%(self.path, self.name,
88
			self.is_command(), self.help))
96
			self.is_command, self.help))
89 97
		for cmd in self.get_subcommands():
90 98
			cmd.pretty_print(recursive)
91 99

  
......
97 105
	tmp.add_subcmd(Command('store_list_one', 'List just one stuff'))
98 106
	cmd.pretty_print(True)
99 107

  
108
class CommandTree(object):
109

  
110
	groups = {}
111
	_all_commands = {}
112
	name = None
113
	description = None
114

  
115
	def __init__(self, name, description=''):
116
		self.name = name
117
		self.description = description
118

  
119
	def add_command(self, command_path, description=None, cmd_class=None):
120
		terms = command_path.split('_')
121
		try:
122
			cmd = self.groups[terms[0]]
123
		except KeyError:
124
			cmd = Command(terms[0])
125
			self.groups[terms[0]] = cmd
126
			self._all_commands[terms[0]] = cmd
127
		path = terms[0]
128
		for term in terms[1:]:
129
			path += '_'+term
130
			try:
131
				cmd = cmd.subcommands[term]
132
			except KeyError:
133
				new_cmd = Command(path)
134
				self._all_commands[path] = new_cmd
135
				cmd.add_subcmd(new_cmd)
136
				cmd = new_cmd
137
		if cmd_class is not None:
138
			cmd.set_class(cmd_class)
139
		if description is not None:
140
			cmd.help = description
141
	def get_command(self, path):
142
		return self._all_commands[path]
143
	def get_groups(self):
144
		return self.groups.values()
145
	def get_group_names(self):
146
		return self.groups.keys()
147

  
148
	def set_description(self, path, description):
149
		self._all_commands[path].help = description
150
	def get_descitpion(self, path):
151
		return self._all_commands[path].help
152
	def set_class(self, path, cmd_class):
153
		self._all_commands[path].set_class(cmd_class)
154
	def get_class(self, path):
155
		return self._all_commands[path].get_class()
156

  
157
	def get_subnames(self, path):
158
		return self._all_commands[path].get_subnames()
159
	def get_subcommands(self, path):
160
		return self._all_commands[path].get_subcommands()
161
	def get_parent(self, path):
162
		if '_' not in path:
163
			return None
164
		terms = path.split('_')
165
		parent_path = '_'.join(terms[:-1])
166
		return self._all_commands[parent_path]
167
	def get_closest_ancestor_command(self, path):
168
		path, sep, name = path.rpartition('_')
169
		while len(path) > 0:
170
			cmd = self._all_commands[path]
171
			if cmd.is_command:
172
				return cmd
173
			path, sep, name = path.rpartition('_')
174
		return None
175

  
176
		if '_' not in path:
177
			return None
178
		terms = terms[:-1]
179
		while len(terms) > 0:
180
			tmp_path = '_'.join(terms)
181
			cmd = self._all_commands[tmp_path]
182
			if cmd.is_command:
183
				return cmd
184
			terms = terms[:-1]
185
		raise KeyError('No ancestor commands')
186

  
187
	def pretty_print(self, group=None):
188
		if group is None:
189
			for group in self.groups:
190
				self.pretty_print(group)
191
		else:
192
			self.groups[group].pretty_print(recursive=True)
193

  
194
def test_CommandTree():
195
	tree = CommandTree('kamaki', 'the kamaki tools')
196
	tree.add_command('store', 'A storage thingy')
197
	tree.add_command('server_list_lala', description='A testing server list', cmd_class=Shell)
198
	tree.add_command('store_list_all', 'List all things', cmd_class=Command)
199
	tree.add_command('store_list', 'List smthing pls', cmd_class=Shell)
200
	tree.add_command('server_list', description='A server list subgrp')
201
	tree.add_command('server', description='A server is a SERVER', cmd_class=CommandTree)
202
	tree.set_class('server', None)
203
	tree.set_description('server_list', '')
204
	if tree.get_class('server_list_lala') is Shell:
205
		print('server_list_lala is Shell')
206
	else:
207
		print('server_list_lala is not Shell')
208
	tree.pretty_print()
209
	print('store_list_all closest parent command is %s'%tree.get_closest_ancestor_command('store_list_all').path)
210
	tree.set_class('store', tree.get_command('store_list').get_class())
211
	tree.set_class('store_list', None)
212
	print('store_list_all closest parent command is %s'%tree.get_closest_ancestor_command('store_list_all').path)
213
	try:
214
		print('nonexisting_list_command closest parent is %s'%tree.get_closest_ancestor_command('nonexisting_list_command').path)
215
	except KeyError:
216
		print('Aparrently nonexisting_list_command is nonexisting ')
217

  
100 218
class Shell(cmd.Cmd):
101 219
	"""Simple command processor example."""
102 220

  
......
125 243

  
126 244
#import sys
127 245
#sh.onecmd(' '.join(sys.argv[1:]))
128
test_Command()
246
#test_CommandTree()

Also available in: Unified diff