-
Notifications
You must be signed in to change notification settings - Fork 16
/
repl.py
109 lines (91 loc) · 2.59 KB
/
repl.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"""A repl across hosts."""
from __future__ import print_function, unicode_literals
import ast
import sys
import traceback
PY2 = sys.version_info < (3,)
if PY2:
from cStringIO import StringIO
else:
from io import StringIO
if PY2:
input = raw_input # noqa
def exec_(code, namespace):
exec('exec code in namespace')
else:
exec_ = eval('exec')
def read_stmt():
stmt = ''
prompt = '>>> '
while True:
try:
line = input(prompt)
except EOFError:
print()
sys.exit(0)
stmt += line + '\n'
try:
ast.parse(stmt)
except SyntaxError as e:
msg = e.args[0]
if msg == 'unexpected EOF while parsing':
prompt = '... '
continue
raise
else:
if line.startswith((' ', '\t')) and prompt == '... ':
continue
return stmt
namespace = {}
def runit(stmt):
code = compile(stmt, '<stdin>', 'single', dont_inherit=True)
buf = sys.stdout = StringIO()
try:
exec_(code, namespace)
except Exception:
return False, traceback.format_exc()
return True, buf.getvalue()
def dorepl(group):
from chopsticks.tunnel import ErrorResult
from repl import runit
try:
stmt = read_stmt()
except Exception:
traceback.print_exc()
return
results = group.call(runit, stmt)
vals = list(results.values())
if all(vals[0] == v for v in vals[1:]):
results = {'all %d' % len(vals): vals[0]}
for host, result in sorted(results.items()):
if isinstance(result, ErrorResult):
success = False
result = result.msg
else:
success, result = result
color = '32' if success else '31'
if sys.stderr.isatty():
fmt = '\x1b[{color}m[{host}]\x1b[0m {l}'
else:
fmt = '[{host}] {l}'
for l in result.splitlines():
print(fmt.format(host=host, color=color, l=l))
if __name__ == '__main__':
from chopsticks.tunnel import Docker
from chopsticks.group import Group
import chopsticks.ioloop
chopsticks.tunnel.PICKLE_LEVEL = 2
class Py2Docker(Docker):
python3 = 'python2'
group = Group([
Py2Docker('python2.7', image='python:2.7'),
Docker('python3.3', image='python:3.3'),
Docker('python3.4', image='python:3.4'),
Docker('python3.5', image='python:3.5'),
Docker('python3.6', image='python:3.6'),
])
try:
while True:
dorepl(group)
finally:
del group