From 861fbed9b72589cd4d868cdee3544592e3d2ebad Mon Sep 17 00:00:00 2001 From: Seblu <sebastien.luttringer@smartjog.com> Date: Wed, 29 Dec 2010 16:48:47 +0100 Subject: [PATCH] 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 --- bin/cc-cli | 4 +++- cccli/cli.py | 57 ++++++++++++++++++++++++---------------------- cccli/command.py | 6 ++--- cccli/exception.py | 16 ++++++++++--- cccli/printer.py | 29 ++++++++++++++--------- 5 files changed, 67 insertions(+), 45 deletions(-) diff --git a/bin/cc-cli b/bin/cc-cli index cd80251..f2fc917 100755 --- a/bin/cc-cli +++ b/bin/cc-cli @@ -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)) diff --git a/cccli/cli.py b/cccli/cli.py index fc80e91..6607a0b 100644 --- a/cccli/cli.py +++ b/cccli/cli.py @@ -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"]): - self.printer.debug("Authenticated.") - else: - self.printer.fatal("Autentification failed!") + try: + self.rpc.authentify(self.settings["login"], self.settings["pass"]) + except Exception: + raise cliError("Autentification failed!") + self.printer.debug("Authenticated.") 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!") diff --git a/cccli/command.py b/cccli/command.py index 7cee183..1aedffe 100644 --- a/cccli/command.py +++ b/cccli/command.py @@ -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) diff --git a/cccli/exception.py b/cccli/exception.py index 4c55997..446e39e 100644 --- a/cccli/exception.py +++ b/cccli/exception.py @@ -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 diff --git a/cccli/printer.py b/cccli/printer.py index 93b95f0..c7ffe69 100644 --- a/cccli/printer.py +++ b/cccli/printer.py @@ -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''' -- GitLab