@@ -0,0 +1,2163 @@
+%22%22%22A repl across hosts.%22%22%22%0Aimport ast%0Aimport sys%0Aimport readline%0Aimport traceback%0Afrom io import StringIO%0A%0A%0Adef read_stmt():%0A    stmt = ''%0A    prompt = '%3E%3E%3E '%0A    indented = False%0A    while True:%0A        try:%0A            line = input(prompt)%0A        except EOFError:%0A            print()%0A            sys.exit(0)%0A        stmt += line + '%5Cn'%0A        try:%0A            ast.parse(stmt)%0A        except SyntaxError as e:%0A            msg = e.args%5B0%5D%0A            if msg == 'unexpected EOF while parsing':%0A                prompt = '... '%0A                continue%0A            raise%0A        else:%0A            if line.startswith((' ', '%5Ct')) and prompt == '... ':%0A                continue%0A            return stmt%0A%0A%0Anamespace = %7B%7D%0A%0Adef runit(stmt):%0A    code = compile(stmt, '%3Cstdin%3E', 'single', dont_inherit=True)%0A    sys.stdout = StringIO()%0A    try:%0A        result = exec(code, namespace)%0A    except Exception:%0A        return False, traceback.format_exc()%0A    return True, sys.stdout.getvalue()%0A%0A%0Adef dorepl(group):%0A    from chopsticks.tunnel import ErrorResult%0A    try:%0A        stmt = read_stmt()%0A    except Exception:%0A        traceback.print_exc()%0A        return%0A    results = group.call(runit, stmt)%0A    vals = list(results.values())%0A    if all(vals%5B0%5D == v for v in vals%5B1:%5D):%0A        results = %7B'all %25d' %25 len(vals): vals%5B0%5D%7D%0A    for host, result in sorted(results.items()):%0A        if isinstance(result, ErrorResult):%0A            success = False%0A            result = result.msg%0A        else:%0A            success, result = result%0A        color = '32' if success else '31'%0A        if sys.stderr.isatty():%0A            fmt = '%5Cx1b%5B%7Bcolor%7Dm%5B%7Bhost%7D%5D%5Cx1b%5B0m %7Bl%7D'%0A        else:%0A            fmt = '%5B%7Bhost%7D%5D %7Bl%7D'%0A%0A        for l in result.splitlines():%0A            print(fmt.format(host=host, color=color, l=l))%0A%0A%0Aif __name__ == '__main__':%0A    from chopsticks.tunnel import Docker%0A    from chopsticks.group import Group%0A    group = Group(%5B%0A        Docker('python3.4', image='python:3.4'),%0A        Docker('python3.5', image='python:3.5'),%0A        Docker('python3.6', image='python:3.6'),%0A    %5D)%0A%0A    try:%0A        while True:%0A            dorepl(group)%0A    finally:%0A        del group%0A

Add REPL that evaluates code on various Python versions