15
14
from threading import Thread
15
from functools import partial
19
class Interrupt(Exception):
21
Exception.__init__(self, "Interrupted!")
23
class ExpiryTimer(object):
24
def __init__(self, idle):
26
signal.signal(signal.SIGALRM, partial(self.timeout))
29
signal.alarm(self.idle)
31
def start(self, time):
37
def timeout(self, signum, frame):
19
40
class StdinFromWeb(object):
20
41
def __init__(self, cmdQ, lineQ):
24
45
def readline(self):
27
46
self.cmdQ.put({"input":None})
28
48
ln = self.lineQ.get()
31
# Some of our 5 seconds may have elapsed, but never mind.
54
class StdoutToWeb(object):
55
def __init__(self, cmdQ, lineQ):
60
def write(self, stuff):
61
self.remainder = self.remainder + stuff
63
# if there's less than 128 bytes, buffer
64
if len(self.remainder) < 128:
67
# if there's lots, then send it in 1/2K blocks
68
while len(self.remainder) > 512:
69
blk = self.remainder[0:512]
70
self.cmdQ.put({"output":blk})
73
self.remainder = self.remainder[512:]
75
# Finally, split the remainder up into lines, and ship all the
76
# completed lines off to the server.
77
lines = self.remainder.split("\n")
78
self.remainder = lines[-1]
83
text = "\n".join(lines)
84
self.cmdQ.put({"output":text})
91
if len(self.remainder) > 0:
92
self.cmdQ.put({"output":self.remainder})
100
"""Provides a file like interface to the Web front end of the console.
101
You may print text to the console using write(), flush any buffered output
102
using flush(), or request text from the console using readline()"""
104
def __init__(self, cmdQ, lineQ):
107
self.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
108
self.stdout = StdoutToWeb(self.cmdQ, self.lineQ)
110
def write(self, stuff):
111
self.stdout.write(stuff)
118
return self.stdin.readline()
35
120
class PythonRunner(Thread):
36
121
def __init__(self, cmdQ, lineQ):
38
123
self.lineQ = lineQ
39
self.out = cStringIO.StringIO()
124
self.webio = WebIO(self.cmdQ, self.lineQ)
40
125
Thread.__init__(self)
42
127
def execCmd(self, cmd):
44
sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
48
res = eval(cmd, self.globs, self.locls)
50
self.cmdQ.put({"okay":(self.out.getvalue(),res)})
129
sys.stdin = self.webio
130
sys.stdout = self.webio
131
sys.stderr = self.webio
132
res = eval(cmd, self.globs)
134
self.cmdQ.put({"okay":res})
51
135
self.curr_cmd = ''
52
self.out = cStringIO.StringIO()
53
136
except Exception, exc:
55
self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
138
exc_classname = exc.__class__.__name__
139
self.cmdQ.put({"exc": exc_classname + ": " + str(exc)})
56
140
self.curr_cmd = ''
57
self.out = cStringIO.StringIO()
144
self.globs['__builtins__'] = globals()['__builtins__']
61
146
compiler = codeop.CommandCompiler()
79
164
except Exception, exc:
81
self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
166
self.cmdQ.put({"exc":str(exc)})
82
167
self.curr_cmd = ''
83
self.out = cStringIO.StringIO()
85
169
# throw away a partial command.
87
171
cmd = compile(ln['block'], "<web session>", 'exec');
89
173
except Exception, exc:
91
self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
175
self.cmdQ.put({"exc":str(exc)})
92
176
self.curr_cmd = ''
93
self.out = cStringIO.StringIO()
97
self.globs['__builtins__'] = globals()['__builtins__']
102
179
if os.fork(): # launch child and...
115
192
lineQ = Queue.Queue()
116
193
interpThread = PythonRunner(cmdQ, lineQ)
195
# Default expiry time of 15 minutes
196
expiry = ExpiryTimer(15 * 60)
118
198
def initializer():
119
199
interpThread.setDaemon(True)
120
200
interpThread.start()
122
203
def dispatch_msg(msg):
123
205
lineQ.put({msg['cmd']:msg['text']})
124
206
return cmdQ.get()
126
208
if __name__ == "__main__":
127
209
port = int(sys.argv[1])
128
210
magic = sys.argv[2]
211
if len(sys.argv) >= 4:
213
os.chdir(sys.argv[3])
214
# Make python's search path follow the cwd
216
os.environ['HOME'] = sys.argv[3]
130
218
common.chat.start_server(port, magic, True, dispatch_msg, initializer)