Skip to content
Snippets Groups Projects
printer.py 6.96 KiB
Newer Older
#!/usr/bin/env python
#coding=utf8

'''
Seblu's avatar
Seblu committed
CloudControl CLI Printer module
Seblu's avatar
Seblu committed
import os
import termios
import fcntl
import struct
Seblu's avatar
Seblu committed

Seblu's avatar
Seblu committed
import cccli
from cccli.exception import *
    "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",
    "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",
    "ured": "\033[4;31m",
    "ugreen": "\033[4;32m",
    "uyellow": "\033[4;33m",
    "ublue": "\033[4;34m",
    "upurple": "\033[4;35m",
    "ucyan": "\033[4;36m",
    "light": "\033[1m",
    "reset": "\033[m",
Seblu's avatar
Seblu committed
    "[": "\001",
    "]": "\002",
Seblu's avatar
Seblu committed

class Printer(object):
    '''Print relative class'''
    def __init__(self):
Seblu's avatar
Seblu committed
        self.readline = None
        self.history = History()
        self.completion = Completion()
Seblu's avatar
Seblu committed

    def set_interactive(self):
        '''Set interactive mode'''
        if self.readline is not None:
            return
Seblu's avatar
Seblu committed
        try:
            import readline
        except Exception as e:
            raise cliError("Unable to start readline")
        self.readline = readline
Seblu's avatar
Seblu committed
        # enable history
        self.history.readline = readline
        # enable completion
        self.completion.readline = readline
Seblu's avatar
Seblu committed
    def out(self, message="", fd=sys.stdout, nl=os.linesep, flush=True):
Seblu's avatar
Seblu committed
        '''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):
Seblu's avatar
Seblu committed
        self.out("%sFatal%s: %s%s"%(color["lred"],color["red"],message, color["reset"]),
            fd,
            nl)
        if quit:
            os.kill(0, 15)
Seblu's avatar
Seblu committed

    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):
Seblu's avatar
Seblu committed
        if cccli.debug:
Seblu's avatar
Seblu committed
            self.out(message, fd, nl)

    def interactive(self, message, fd=sys.stderr, nl=os.linesep):
        '''Print only in interactive mode'''
        if self.readline is not None:
            self.out(message, fd, nl)

    def getline(self, prompt, history=True):
Seblu's avatar
Seblu committed
        '''Read a line from stdin'''
        try:
            s = raw_input(prompt)
        except EOFError:
            raise
        except KeyboardInterrupt:
            raise
Seblu's avatar
Seblu committed
        except Exception as e:
            raise cliError(str(e))
        if not history and s:
Seblu's avatar
Seblu committed
            self.history.removelast()
        return s

    def getpass(self, prompt):
Seblu's avatar
Seblu committed
        '''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")
        fd = sys.stdin.fileno()
        old = termios.tcgetattr(fd)
        new = termios.tcgetattr(fd)
        new[3] = new[3] & ~termios.ECHO
        try:
            termios.tcsetattr(fd, termios.TCSADRAIN, new)
            passwd = raw_input(prompt)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old)
        return passwd
Seblu's avatar
Seblu committed

    def ask(self, prompt):
Seblu's avatar
Seblu committed
        '''Used to ask a question. Default answer not saved to history'''
        if self.readline is None:
            raise cliError("Unable to ask question in non-interactive mode")
Seblu's avatar
Seblu committed
        h = list(self.history)
        self.history.clear()
        try:
            r = self.getline(prompt, history=False)
        finally:
            self.history.load(h)
        return r
Seblu's avatar
Seblu committed

    def get_term_size(self):
        '''Return terminal size'''
        if self.readline is None:
            raise cliError("Unable to get term size in non-interactive mode")
        req = struct.pack("HHHH", 0, 0, 0, 0)
        resp = fcntl.ioctl(sys.stdin.fileno(), termios.TIOCGWINSZ, req)
        rows, cols, px_x, px_y = struct.unpack("HHHH", resp)
        return rows, cols

Seblu's avatar
Seblu committed

class History(object):
    '''History class'''
    def __init__(self):
        self.readline = None
Seblu's avatar
Seblu committed

    def __nonzero__(self):
        return self.readline is not None
Seblu's avatar
Seblu committed

    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)
Seblu's avatar
Seblu committed

    def __iter__(self):
Seblu's avatar
Seblu committed
        if self.readline is None:
            return
        for i in range(1, self.readline.get_current_history_length() + 1):
Seblu's avatar
Seblu committed
            yield self.readline.get_history_item(i)

    def __len__(self):
Seblu's avatar
Seblu committed
        if self.readline is None:
            return 0
Seblu's avatar
Seblu committed
        return self.readline.get_current_history_length()

Seblu's avatar
Seblu committed
    def load(self, items):
        '''Load history from a list'''
        self.clear()
        for l in items:
            self.readline.add_history(l)

    def read(self, path):
Seblu's avatar
Seblu committed
        '''Load history from a file'''
Seblu's avatar
Seblu committed
        self.clear()
Seblu's avatar
Seblu committed
        try:
            self.readline.read_history_file(path)
        except IOError:
            pass

Seblu's avatar
Seblu committed
    def write(self, path):
Seblu's avatar
Seblu committed
        '''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)
Seblu's avatar
Seblu committed

    def clear(self):
        '''Clear history'''
        self.readline.clear_history()

class Completion(object):
    '''Handle completion functions'''
    def __init__(self):
        self.readline = 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 get_buf(self):
        '''Return current readline buffer'''
        return self.readline.get_line_buffer()

    def get_begin(self):
        '''Get the beginning index of the readline tab-completion scope'''
        return self.readline.get_begidx()

    def get_end(self):
        '''Get the ending index of the readline tab-completion scope'''
        return self.readline.get_begidx()

    def set_completer(self, func):
        '''Set completer function'''
        self.readline.set_completer(func)
        self.readline.parse_and_bind("tab: complete")