14
15
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):
40
19
class StdinFromWeb(object):
41
20
def __init__(self, cmdQ, lineQ):
45
24
def readline(self):
46
27
self.cmdQ.put({"input":None})
48
28
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()
120
35
class PythonRunner(Thread):
121
36
def __init__(self, cmdQ, lineQ):
123
38
self.lineQ = lineQ
124
self.webio = WebIO(self.cmdQ, self.lineQ)
39
self.out = cStringIO.StringIO()
125
40
Thread.__init__(self)
127
42
def execCmd(self, cmd):
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})
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)})
135
51
self.curr_cmd = ''
52
self.out = cStringIO.StringIO()
136
53
except Exception, exc:
138
exc_classname = exc.__class__.__name__
139
self.cmdQ.put({"exc": exc_classname + ": " + str(exc)})
55
self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
140
56
self.curr_cmd = ''
57
self.out = cStringIO.StringIO()
144
self.globs['__builtins__'] = globals()['__builtins__']
146
61
compiler = codeop.CommandCompiler()
164
79
except Exception, exc:
166
self.cmdQ.put({"exc":str(exc)})
81
self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
167
82
self.curr_cmd = ''
83
self.out = cStringIO.StringIO()
169
85
# throw away a partial command.
171
87
cmd = compile(ln['block'], "<web session>", 'exec');
173
89
except Exception, exc:
175
self.cmdQ.put({"exc":str(exc)})
91
self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
176
92
self.curr_cmd = ''
93
self.out = cStringIO.StringIO()
97
self.globs['__builtins__'] = globals()['__builtins__']
179
102
if os.fork(): # launch child and...
192
115
lineQ = Queue.Queue()
193
116
interpThread = PythonRunner(cmdQ, lineQ)
195
# Default expiry time of 15 minutes
196
expiry = ExpiryTimer(15 * 60)
198
118
def initializer():
199
119
interpThread.setDaemon(True)
200
120
interpThread.start()
203
122
def dispatch_msg(msg):
205
123
lineQ.put({msg['cmd']:msg['text']})
206
124
return cmdQ.get()
208
126
if __name__ == "__main__":
209
127
port = int(sys.argv[1])
210
128
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]
218
130
common.chat.start_server(port, magic, True, dispatch_msg, initializer)