import tabulate
[docs]class ConsoleConnection(object):
def __init__(self, cid, master, stream_in, stream_out):
super(ConsoleConnection, self).__init__()
self.cid = cid
self.master = master
self.stream_in = stream_in
self.stream_out = stream_out
self.history = []
self.history_index = 0
self.buff = []
self.history.insert(0, self.buff)
self.default_core = None
[docs] def write(self, buff, *args):
if isinstance(buff, list):
buff = ''.join([chr(c) for c in buff])
if args:
buff = buff % args
self.stream_out.write(buff)
self.stream_out.flush()
[docs] def writeln(self, buff, *args):
if isinstance(buff, list):
buff = ''.join([chr(c) for c in buff])
self.write(buff + '\n', *args)
[docs] def prompt(self):
self.write('#> ')
[docs] def table(self, table, **kwargs):
for line in tabulate.tabulate(table, headers = 'firstrow', tablefmt = 'simple', numalign = 'right', **kwargs).split('\n'):
self.write(line + '\n')
[docs] def log(self, logger, msg, *args):
self.writeln(msg, *args)
logger('[console %i] ' + msg, *((self.cid,) + args))
[docs] def execute(self, cmd):
if cmd[0] not in self.master.commands:
self.writeln('Unknown command: cmd="%s"', cmd)
return
cmd_desc = self.master.commands[cmd[0]]
try:
cmd_desc[0](self, cmd, *cmd_desc[1], **cmd_desc[2])
except Exception as exc:
self.master.machine.EXCEPTION(exc)
[docs] def boot(self):
self.prompt()
self.master.machine.reactor.add_fd(self.stream_in.get_selectee(), on_read = self.read_input, on_error = self.halt)
[docs] def halt(self):
self.master.machine.reactor.remove_fd(self.stream_in.fileno())
[docs] def die(self, exc):
self.master.machine.EXCEPTION(exc)
self.halt()
[docs]class TerminalConsoleConnection(ConsoleConnection):
def __init__(self, cid, master):
import sys
import termios
import tty
self.old_term_settings = termios.tcgetattr(sys.stdin)
tty.setcbreak(sys.stdin.fileno())
super(TerminalConsoleConnection, self).__init__(cid, master, sys.stdin, sys.stdout)
[docs] def halt(self):
super(TerminalConsoleConnection, self).halt()
import termios
termios.tcsetattr(self.stream_in, termios.TCSADRAIN, self.old_term_settings)
[docs]class ConsoleMaster(object):
console_id = 0
def __init__(self, machine):
super(ConsoleMaster, self).__init__()
self.machine = machine
self.connections = []
self.commands = {}
[docs] def register_command(self, name, callback, *args, **kwargs):
self.commands[name] = (callback, args, kwargs)
[docs] def is_registered_command(self, name):
return name in self.commands
[docs] def unregister_command(self, name):
if name in self.commands:
del self.commands[name]
[docs] def register_commands(self, commands, *args, **kwargs):
for name, handler in commands:
if self.is_registered_command(name):
continue
self.register_command(name, handler, *args, **kwargs)
[docs] def connect(self, slave):
self.connections.append(slave)
[docs] def boot(self):
self.register_command('?', cmd_help)
[docs] def halt(self):
self.unregister_command('?')
for slave in self.connections:
slave.halt()
[docs]def cmd_help(console, cmd):
"""
List all available command and their descriptions
"""
table = [
['Command', 'Description']
]
for cmd_name in sorted(console.master.commands.keys()):
table.append([cmd_name, console.master.commands[cmd_name][0].__doc__])
console.table(table)