Commit 73e0914d authored by Stavros Sachtouris's avatar Stavros Sachtouris
Browse files

Initial shell functionality with 1st lvl cmds

parent 0f653327
......@@ -42,6 +42,7 @@ gevent.monkey.patch_all()
import logging
from inspect import getargspec
import new
from argparse import ArgumentParser, ArgumentError
from os.path import basename
from sys import exit, stdout, stderr, argv
......@@ -75,7 +76,6 @@ candidate_command_terms = []
allow_no_commands = False
allow_all_commands = False
allow_subclass_signatures = False
load2shell = False
def _allow_class_in_cmd_tree(cls):
global allow_all_commands
......@@ -128,20 +128,11 @@ def command():
#store each term, one by one, first
_commands.add_command(cls.__name__, cls.description, cls)
if load2shell:
global shell
name = cls.__name__.split()[-1]
def do_method(self, line):
cls.main(line.split())
do_method.__name__ = 'do_%s'%name
setattr(shell, do_method.__name__, do_method)
def help_method(self):
print(cls.description)
help_method.__name__ = 'help_'%name
setattr(shell, help_method.__name__, help_method)
return cls
return decorator
def _update_parser(parser, arguments):
for name, argument in arguments.items():
try:
......@@ -332,6 +323,9 @@ def one_command():
class Shell(cmd.Cmd):
"""Kamaki interactive shell"""
_prefix = '['
_suffix = ']:'
_defaultnames = []
def greet(self, version):
print('kamaki v%s - Interactive Shell\n\t(exit or ^D to exit)\n'%version)
......@@ -341,28 +335,70 @@ class Shell(cmd.Cmd):
def do_exit(self, line):
return True
shell = None
@classmethod
def _register_method(self, method, name):
self.__dict__[name] = method
#self._tmp_method = new.instancemethod(method, name, self)
#setattr(self, name, self._tmp_method)
#del self._tmp_method
def _register_command(self, command):
method_name = 'do_%s'%command.name
def do_method(self, line):
if command.is_command:
cls = command.get_class()
parsed, unparsed = parse_known_args(_init_parser(argv))
instance = cls(_arguments)
args = line.split()
instance.main(*unparsed)
else:
print('should go next level, man!')
self._register_method(do_method, method_name)
def kamaki_loop(self,command,prefix=''):
#setup prompt
if prefix in (None, ''):
self.prompt = '%s%s%s'%(self._prefix, command.name, self._suffix)
else:
cmd_str = ' '.join(command.path.split())
self.prompt = '%s%s%s'%(self._prefix, cmd_str, self._suffix)
self._defaultnames = command.get_subnames()
for cmd in command.get_subcommands():
self._register_command(cmd)
self.cmdloop()
def _start_shell():
global shell
shell = Shell()
shell.set_prompt(basename(argv[0]))
from kamaki import __version__ as version
shell.greet(version)
shell.do_EOF = shell.do_exit
return shell
def run_shell():
global shell
_start_shell()
shell = _start_shell()
_config = _arguments['config']
_config.value = None
for grp in _config.get_groups():
global load2shell
load2shell = True
global allow_all_commands
allow_all_commands = True
load_group_package(grp)
shell.do_store()
shell.cmdloop()
shell.kamaki_loop(_commands)
def main():
"""
def do_lala(self):
print('do lalalala')
_start_shell()
setattr(shell, 'do_lala_lele', do_lala)
shell.cmdloop()
return
"""
if len(argv) <= 1:
run_shell()
else:
......
......@@ -154,10 +154,12 @@ class CommandTree(object):
def get_class(self, path):
return self._all_commands[path].get_class()
def get_subnames(self, path):
return self._all_commands[path].get_subnames()
def get_subcommands(self, path):
return self._all_commands[path].get_subcommands()
def get_subnames(self, path=None):
return self.get_group_names() if path in (None, '') \
else self._all_commands[path].get_subnames()
def get_subcommands(self, path=None):
return self.get_groups() if path in (None, '') \
else self._all_commands[path].get_subcommands()
def get_parent(self, path):
if '_' not in path:
return None
......
#!/usr/bin/env python
# Copyright 2012 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
API_DESCRIPTION=dict(history='Command history')
from kamaki.cli.argument import IntArgument, ValueArgument, FlagArgument
from kamaki.cli.history import History
from kamaki.cli.utils import print_list
from kamaki.cli import command
class _init_history(object):
def __init__(self, arguments={}):
self.arguments=arguments
try:
self.config = self.get_argument('config')
except KeyError:
pass
def get_argument(self, argterm):
return self.arguments[argterm].value
def main(self):
self.history = History(self.config.get('history', 'file'))
@command()
class history(_init_history):
"""Show history [containing terms...]"""
def __init__(self, arguments={}):
super(history, self).__init__(arguments)
self.arguments['limit'] = IntArgument('number of lines to show', '-n', default=0)
self.arguments['match'] = ValueArgument('show lines that match all given terms', '--match')
def main(self):
super(history, self).main()
ret = self.history.get(match_terms = self.get_argument('match'),
limit=self.get_argument('limit'))
print(''.join(ret))
@command()
class history_clean(_init_history):
"""Clean up history"""
def main(self):
super(history_clean, self).main()
self.history.clean()
#!/usr/bin/env python
# Copyright 2012 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from os.path import exists
def order_free_contains(containing, contained):
superset = containing.split()
for term in contained.split():
if term not in superset:
return False
return True
class History(object):
def __init__(self, filepath):
self.filepath=filepath
@classmethod
def _match(self,line, match_terms):
if match_terms is None:
return True
for term in match_terms.split():
if term not in line:
return False
return True
def get(self, match_terms=None, limit=0):
f = open(self.filepath, 'r')
result = ['%s. \t%s'%(index+1,line) \
for index,line in enumerate(f.readlines()) \
if self._match(line, match_terms)]
offset = len(result)-limit if limit and len(result) > limit else 0
return result[offset:]
def add(self, line):
f = open(self.filepath, 'a+')
f.write(line+'\n')
f.close()
def clean(self):
f = open(self.filepath, 'w')
f.close()
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment