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