#!/usr/bin/env python #coding=utf8 ''' CloudControl CLI Printer module ''' import sys import os import getpass import cccli from cccli.exception import * color = { # regular "red": "\033[0;31m", "green": "\033[0;32m", "yellow": "\033[0;33m", "blue": "\033[0;34m", "purple": "\033[0;35m", "cyan": "\033[0;36m", "white": "\033[0;37m", # lighted "lred": "\033[1;31m", "lgreen": "\033[1;32m", "lyellow": "\033[1;33m", "lblue": "\033[1;34m", "lpurple": "\033[1;35m", "lcyan": "\033[1;36m", "lwhite": "\033[1;37m", # underline "ured": "\033[4;31m", "ugreen": "\033[4;32m", "uyellow": "\033[4;33m", "ublue": "\033[4;34m", "upurple": "\033[4;35m", "ucyan": "\033[4;36m", # others "light": "\033[1m", "reset": "\033[m", } class Printer(object): '''Print relative class''' def __init__(self, interactive=False, forceyes=False, historyfile=None, historysize=None): self.readline = None self.history = History() self.historyfile = historyfile self.historysize = historysize self.forceyes = forceyes if interactive: self.setinteractive() def isinteractive(self): '''Return if printer is in interactive mode''' return self.readline is not None def setinteractive(self): if self.readline is not None: return import readline self.readline = readline if self.history is None: self.history = History(self.readline) else: self.history.readline = readline self.history.load(self.historyfile) self.history.maxsize(self.historysize) def out(self, message="", fd=sys.stdout, nl=os.linesep, flush=True): '''Print a message in fd ended by nl''' fd.write("%s%s"%(message, nl)) if flush: fd.flush() def err(self, message, fd=sys.stderr, nl=os.linesep): self.out(message, fd, nl) 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 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"]), fd, nl) def warn(self, message, fd=sys.stderr, nl=os.linesep): self.out("%sWarning%s: %s%s"%(color["lyellow"],color["yellow"],message,color["reset"]), fd, nl) def debug(self, message, fd=sys.stderr, nl=os.linesep): if cccli.debug: self.out(message, fd, nl) 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, prompt): '''Ask for a password. No echo. Not in history''' if self.readline is None: raise cliError("Unable to ask a password in non-interactive mode") return getpass.getpass(prompt) def ask(self, prompt, goodans=None): '''Used to ask a question. Default answer not saved to history''' if self.forceyes and goodans is not None: return goodans if self.readline is None: raise cliError("Unable to ask question in non-interactive mode") return self.getline(prompt, history=False) class History(object): '''History class''' def __init__(self): self.readline = None def __nonzero__(self): return self.readline is not None def __getattribute__(self, name): r = object.__getattribute__(self, "readline") if name == "readline": return r if r is None: return lambda *a,**k: None return object.__getattribute__(self, name) def __iter__(self): for i in range(1, len(self)): yield self.readline.get_history_item(i) def __len__(self): if self.readline is None: return 0 return self.readline.get_current_history_length() def load(self, path): '''Load history from a file''' try: self.readline.read_history_file(path) except IOError: pass def save(self, path): '''Save history into path''' try: self.readline.write_history_file(path) except IOError: pass def maxsize(self, size=None): '''Set or return max history size''' if size is not None: self.readline.set_history_length(size) return self.readline.get_history_length() def removelast(self): '''Remove last history line''' self.readline.remove_history_item(self.readline.get_current_history_length() - 1) def clear(self): '''Clear history''' self.readline.clear_history()