Commit 861fbed9 authored by Seblu's avatar Seblu
Browse files

fix traceback on empty line in parser

fix traceback when typing enter with history disable (method Printer().ask())
clean quit on server disconnect
prompt in color
add login in prompt
new cli exceptions class
proper handle auth failure
parent 9d535ecb
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -128,11 +128,13 @@ try:
except BadArgument as e:
    printer.error("Bad Argument: %s"%str(e))
    oparser.print_help()
except cliError as e:
    printer.error(str(e))
except KeyboardInterrupt:
    exit(1)
except Exception as e:
    if cccli.debug:
        printer.fatal(str(e), exitcode=-1)
        printer.fatal(str(e), quit=False)
        raise
    printer.warn("This is a not expected error, please report it!")
    printer.fatal(str(e))
+30 −27
Original line number Diff line number Diff line
@@ -12,9 +12,9 @@ import subprocess
import shlex
import StringIO

from cccli import version, debug
import cccli
from cccli.command import Command, Alias
from cccli.printer import Printer
from cccli.printer import Printer, color
from cccli.exception import *

from sjrpc.client import SimpleRpcClient
@@ -70,29 +70,37 @@ class Cli(object):
    def _auth(self):
        '''Handle server authentification'''
        self.printer.debug("Authenticating...")
        if self.rpc.authentify(self.settings["login"], self.settings["pass"]):
        try:
            self.rpc.authentify(self.settings["login"], self.settings["pass"])
        except Exception:
            raise cliError("Autentification failed!")
        self.printer.debug("Authenticated.")
        else:
            self.printer.fatal("Autentification failed!")

    def _parse(self):
        '''Parse a line'''
        prompt = "> " if self.interactive else ""
        if self.interactive:
            prompt = "%s%s>%s "%(color["lwhite"],self.settings["login"],color["reset"])
        else:
            prompt = ""
        while True:
            try:
                argv = shlex.split(self.printer.getline(prompt), comments=True)
                # alias subsitution
                if argv[0] in self.alias:
                    argv[0] = self.alias[argv[0]]
            except ValueError as e:
                print type(e)
                self.printer.error("Lexer: %s"%str(e))
                continue
            except KeyboardInterrupt:
                self.printer.out("")
                continue
            except EOFError:
                break
            except SystemExit:
                break
            except KeyboardInterrupt:
                self.printer.out("")
            if len(argv) == 0:
                continue
            # alias subsitution
            if argv[0] in self.alias:
                argv[0] = self.alias[argv[0]]
            self._exec_command(argv)
        if self.interactive:
            self.printer.out("tcho!")
@@ -121,12 +129,15 @@ class Cli(object):
                self.printer.error("command: %s."%str(e))
            else:
                self.printer.error("No command: %s."%argv[0])
        except RpcError as e:
            if debug: raise
            self.printer.error("sjRPC: %s"%str(e))
        except cmdWarning as e:
            self.printer.warn("%s: %s"%(argv[0], str(e)))
        except cmdError as e:
            self.printer.error("%s: %s"%(argv[0], str(e)))
        except Exception as e:
            if debug: raise
            self.printer.error("%s: %s."%(argv[0], str(e)))
            if cccli.debug:
                raise
            self.printer.error(str(e))
            self.printer.warn("This is a not expected error, please report it!")

class CliHandler(RpcHandler):
    '''Handle RPC incoming request'''
@@ -134,16 +145,8 @@ class CliHandler(RpcHandler):
    @pure
    def get_tags(self, tags=()):
        if "version" in tags:
            return { "version": version }
            return { "version": cccli.version }

    @pure
    def quit(self, rpc=None):
        self.printer.fatal("Disconnected from server!")

class CliLexer(object):

    def __init__(self, fd):
        self.fd = fd

    def get_next_token(self):
        pass
        Printer().fatal("Disconnected from server!")
+3 −3
Original line number Diff line number Diff line
@@ -164,7 +164,7 @@ class Command(object):
    def cmd_history(self, argv):
        '''Show history of commands'''
        if not self.cli.history:
            raise Exception("History is disabled")
            raise cmdError("History is not available")
        for l in self.cli.history:
            self.printer.out(l)
    cmd_history.usage = "history"
@@ -196,10 +196,10 @@ class Command(object):
            self.printer.out("%s"%item["id"])
        self.printer.out("Count: %s"%len(items))
        if self.printer.ask("Are you sure to %s? (yes/NO) "%argv[0]) != "yes":
            raise Exception("Aborted")
            raise cmdWarning("Aborted")
        if len(items) > 5:
            if self.printer.ask("You request is on more than 5 objets. Are you really sure to %s its? (Yes, I am) "%argv[0]) != "Yes, I am":
                raise Exception("Aborted")
                raise cmdWarning("Aborted")
        self.cli.rpc[argv[0]](tql)


+13 −3
Original line number Diff line number Diff line
@@ -6,14 +6,24 @@ CloudControl CLI Exceptions Module
'''

################################################################################
class cliError(Exception):
class cliException(Exception):
    pass

class cliError(cliException):
    pass

class BadCommand(cliError):
    pass

class BadArgument(cliError):
################################################################################
class cmdException(cliException):
    pass

class BadArgument(cmdException):
    pass

class cmdWarning(cmdException):
    pass

class cliWarning(Exception):
class cmdError(cmdException):
    pass
+18 −11
Original line number Diff line number Diff line
@@ -62,12 +62,12 @@ class Printer(object):
    def err(self, message, fd=sys.stderr, nl=os.linesep):
        self.out(message, fd, nl)

    def fatal(self, message, exitcode=42, fd=sys.stderr, nl=os.linesep):
    def fatal(self, message, quit=True, fd=sys.stderr, nl=os.linesep):
        self.out("%sFatal%s: %s%s"%(color["lred"],color["red"],message, color["reset"]),
            fd,
            nl)
        if exitcode >= 0:
            os._exit(exitcode)
        if quit:
            os.kill(0, 15)

    def error(self, message, fd=sys.stderr, nl=os.linesep):
        self.out("%sError%s: %s%s"%(color["lred"],color["red"],message,color["reset"]),
@@ -83,19 +83,26 @@ class Printer(object):
        if cccli.debug:
            self.out(message, fd, nl)

    def getline(self, msg, history=True):
        s = raw_input(msg)
        if not history:
    def getline(self, prompt, history=True):
        try:
            s = raw_input(prompt)
        except EOFError:
            raise
        except KeyboardInterrupt:
            raise
        except:
            raise cliError
        if not history and s:
            self.history.removelast()
        return s

    def getpass(self, msg):
    def getpass(self, prompt):
        '''Ask for a password. No echo. Not in history'''
        return getpass.getpass(msg)
        return getpass.getpass(prompt)

    def ask(self, msg):
    def ask(self, prompt):
        '''Used to ask a question. Default answer not saved to history'''
        return self.getline(msg, history=False)
        return self.getline(prompt, history=False)


class History(object):
@@ -145,7 +152,7 @@ class History(object):

    def removelast(self):
        '''Remove last history line'''
        self.readline.remove_history_item(self.cli.readline.get_current_history_length())
        self.readline.remove_history_item(self.readline.get_current_history_length())

    def clear(self):
        '''Clear history'''