4
# python-console <port> <magic>
4
# python-console <port> <magic> [<working-dir>]
15
15
from threading import Thread
16
16
from functools import partial
20
class Interrupt(Exception):
22
Exception.__init__(self, "Interrupted!")
20
24
class ExpiryTimer(object):
21
25
def __init__(self, idle):
23
signal.signal(signal.SIGALRM, partial(self.timeout,self))
27
signal.signal(signal.SIGALRM, partial(self.timeout))
26
30
signal.alarm(self.idle)
42
46
def readline(self):
44
47
self.cmdQ.put({"input":None})
46
49
ln = self.lineQ.get()
55
class StdoutToWeb(object):
56
def __init__(self, cmdQ, lineQ):
61
def write(self, stuff):
62
self.remainder = self.remainder + stuff
64
# if there's less than 128 bytes, buffer
65
if len(self.remainder) < 128:
68
# if there's lots, then send it in 1/2K blocks
69
while len(self.remainder) > 512:
70
blk = self.remainder[0:512]
71
self.cmdQ.put({"output":blk})
74
self.remainder = self.remainder[512:]
76
# Finally, split the remainder up into lines, and ship all the
77
# completed lines off to the server.
78
lines = self.remainder.split("\n")
79
self.remainder = lines[-1]
84
text = "\n".join(lines)
85
self.cmdQ.put({"output":text})
92
if len(self.remainder) > 0:
93
self.cmdQ.put({"output":self.remainder})
101
"""Provides a file like interface to the Web front end of the console.
102
You may print text to the console using write(), flush any buffered output
103
using flush(), or request text from the console using readline()"""
105
def __init__(self, cmdQ, lineQ):
108
self.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
109
self.stdout = StdoutToWeb(self.cmdQ, self.lineQ)
111
def write(self, stuff):
112
self.stdout.write(stuff)
119
return self.stdin.readline()
50
121
class PythonRunner(Thread):
51
122
def __init__(self, cmdQ, lineQ):
53
124
self.lineQ = lineQ
54
self.out = cStringIO.StringIO()
125
self.webio = WebIO(self.cmdQ, self.lineQ)
55
126
Thread.__init__(self)
57
128
def execCmd(self, cmd):
59
sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
62
res = eval(cmd, self.globs, self.locls)
63
self.cmdQ.put({"okay":(self.out.getvalue(),res)})
65
self.out = cStringIO.StringIO()
66
except Exception, exc:
67
self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
69
self.out = cStringIO.StringIO()
130
sys.stdin = self.webio
131
sys.stdout = self.webio
132
sys.stderr = self.webio
133
res = eval(cmd, self.globs)
135
self.cmdQ.put({"okay":res})
138
tb = format_exc_start(start=1)
140
self.cmdQ.put({"exc": ''.join(tb)})
145
self.globs['__builtins__'] = globals()['__builtins__']
73
147
compiler = codeop.CommandCompiler()
88
162
self.cmdQ.put({"more":None})
91
except Exception, exc:
92
self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
166
tb = format_exc_start(start=3)
167
self.cmdQ.put({"exc": ''.join(tb)})
93
169
self.curr_cmd = ''
94
self.out = cStringIO.StringIO()
96
171
# throw away a partial command.
98
173
cmd = compile(ln['block'], "<web session>", 'exec');
100
except Exception, exc:
101
self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
176
tb = format_exc_start()
178
self.cmdQ.put({"exc": ''.join(tb)})
102
179
self.curr_cmd = ''
103
self.out = cStringIO.StringIO()
105
def init_state(self):
107
self.globs['__builtins__'] = globals()['__builtins__']
112
182
if os.fork(): # launch child and...
138
208
lineQ.put({msg['cmd']:msg['text']})
139
209
return cmdQ.get()
211
def format_exc_start(start=0):
212
etype, value, tb = sys.exc_info()
213
tbbits = traceback.extract_tb(tb)[start:]
214
list = ['Traceback (most recent call last):\n']
215
list = list + traceback.format_list(tbbits)
216
list = list + traceback.format_exception_only(etype, value)
141
219
if __name__ == "__main__":
142
220
port = int(sys.argv[1])
143
221
magic = sys.argv[2]
222
if len(sys.argv) >= 4:
224
os.chdir(sys.argv[3])
225
# Make python's search path follow the cwd
227
os.environ['HOME'] = sys.argv[3]
145
229
common.chat.start_server(port, magic, True, dispatch_msg, initializer)