~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to scripts/python-console

  • Committer: stevenbird
  • Date: 2008-02-19 21:17:21 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:512
Renaming of problems to exercises (initial commit).
Fix up module naming (exercises sometimes called tutorials).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/python
2
2
 
3
3
# usage:
4
 
#   python-console <port> <magic> [<working-dir>]
 
4
#   python-console <port> <magic>
5
5
 
6
6
import cjson
7
7
import codeop
 
8
import cStringIO
8
9
import md5
9
10
import os
10
11
import Queue
12
13
import socket
13
14
import sys
14
15
from threading import Thread
15
 
from functools import partial
16
16
 
17
17
import common.chat
18
18
 
19
 
class Interrupt(Exception):
20
 
    def __init__(self):
21
 
        Exception.__init__(self, "Interrupted!")
22
 
 
23
 
class ExpiryTimer(object):
24
 
    def __init__(self, idle):
25
 
        self.idle = idle
26
 
        signal.signal(signal.SIGALRM, partial(self.timeout))
27
 
 
28
 
    def ping(self):
29
 
        signal.alarm(self.idle)
30
 
 
31
 
    def start(self, time):
32
 
        signal.alarm(time)
33
 
 
34
 
    def stop(self):
35
 
        self.ping()
36
 
 
37
 
    def timeout(self, signum, frame):
38
 
        sys.exit(1)
39
 
        
40
19
class StdinFromWeb(object):
41
20
    def __init__(self, cmdQ, lineQ):
42
21
        self.cmdQ = cmdQ
43
22
        self.lineQ = lineQ
44
23
 
45
24
    def readline(self):
 
25
        # stop the clock!
 
26
        signal.alarm(0)
46
27
        self.cmdQ.put({"input":None})
47
 
        expiry.ping()
48
28
        ln = self.lineQ.get()
49
29
        if 'chat' in ln:
 
30
            # restart the clock:
 
31
            # Some of our 5 seconds may have elapsed, but never mind.
 
32
            signal.alarm(5)
50
33
            return ln['chat']
51
 
        if 'interrupt' in ln:
52
 
            raise Interrupt()
53
 
 
54
 
class StdoutToWeb(object):
55
 
    def __init__(self, cmdQ, lineQ):
56
 
        self.cmdQ = cmdQ
57
 
        self.lineQ = lineQ
58
 
        self.remainder = ''
59
 
 
60
 
    def write(self, stuff):
61
 
        self.remainder = self.remainder + stuff
62
 
 
63
 
        # if there's less than 128 bytes, buffer
64
 
        if len(self.remainder) < 128:
65
 
            return
66
 
 
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})
71
 
            expiry.ping()
72
 
            ln = self.lineQ.get()
73
 
            self.remainder = self.remainder[512:]
74
 
 
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]
79
 
        del lines[-1]
80
 
 
81
 
        if len(lines) > 0:
82
 
            lines.append('')
83
 
            text = "\n".join(lines)
84
 
            self.cmdQ.put({"output":text})
85
 
            expiry.ping()
86
 
            ln = self.lineQ.get()
87
 
            if 'interrupt' in ln:
88
 
                raise Interrupt()
89
 
 
90
 
    def flush(self):
91
 
        if len(self.remainder) > 0:
92
 
            self.cmdQ.put({"output":self.remainder})
93
 
            expiry.ping()
94
 
            ln = self.lineQ.get()
95
 
            self.remainder = ''
96
 
            if 'interrupt' in ln:
97
 
                raise Interrupt()
98
 
 
99
 
class WebIO(object):
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()"""
103
 
    
104
 
    def __init__(self, cmdQ, lineQ):
105
 
        self.cmdQ = cmdQ
106
 
        self.lineQ = lineQ
107
 
        self.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
108
 
        self.stdout = StdoutToWeb(self.cmdQ, self.lineQ)
109
 
 
110
 
    def write(self, stuff):
111
 
        self.stdout.write(stuff)
112
 
 
113
 
    def flush(self):
114
 
        self.stdout.flush()
115
 
 
116
 
    def readline(self):
117
 
        self.stdout.flush()
118
 
        return self.stdin.readline()
119
34
 
120
35
class PythonRunner(Thread):
121
36
    def __init__(self, cmdQ, lineQ):
122
37
        self.cmdQ = cmdQ
123
38
        self.lineQ = lineQ
124
 
        self.webio = WebIO(self.cmdQ, self.lineQ)
 
39
        self.out = cStringIO.StringIO()
125
40
        Thread.__init__(self)
126
41
 
127
42
    def execCmd(self, cmd):
128
43
        try:
129
 
            sys.stdin = self.webio
130
 
            sys.stdout = self.webio
131
 
            sys.stderr = self.webio
132
 
            res = eval(cmd, self.globs)
133
 
            self.webio.flush()
134
 
            self.cmdQ.put({"okay":res})
 
44
            sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
 
45
            sys.stdout = self.out
 
46
            sys.stderr = self.out
 
47
            signal.alarm(5)
 
48
            res = eval(cmd, self.globs, self.locls)
 
49
            signal.alarm(0)
 
50
            self.cmdQ.put({"okay":(self.out.getvalue(),res)})
135
51
            self.curr_cmd = ''
 
52
            self.out = cStringIO.StringIO()
136
53
        except Exception, exc:
137
 
            self.webio.flush()
138
 
            exc_classname = exc.__class__.__name__
139
 
            self.cmdQ.put({"exc": exc_classname + ": " + str(exc)})
 
54
            signal.alarm(0)
 
55
            self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
140
56
            self.curr_cmd = ''
 
57
            self.out = cStringIO.StringIO()
141
58
 
142
59
    def run(self):
143
 
        self.globs = {}
144
 
        self.globs['__builtins__'] = globals()['__builtins__']
145
 
        self.curr_cmd = ''
 
60
        self.init_state()
146
61
        compiler = codeop.CommandCompiler()
147
62
 
148
63
        while True:
162
77
                    else:
163
78
                        self.execCmd(cmd)
164
79
                except Exception, exc:
165
 
                    self.webio.flush()
166
 
                    self.cmdQ.put({"exc":str(exc)})
 
80
                    signal.alarm(0)
 
81
                    self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
167
82
                    self.curr_cmd = ''
 
83
                    self.out = cStringIO.StringIO()
168
84
            if 'block' in ln:
169
85
                # throw away a partial command.
170
86
                try:
171
87
                    cmd = compile(ln['block'], "<web session>", 'exec');
172
88
                    self.execCmd(cmd)
173
89
                except Exception, exc:
174
 
                    self.webio.flush()
175
 
                    self.cmdQ.put({"exc":str(exc)})
 
90
                    signal.alarm(0)
 
91
                    self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
176
92
                    self.curr_cmd = ''
 
93
                    self.out = cStringIO.StringIO()
 
94
 
 
95
    def init_state(self):
 
96
        self.globs = {}
 
97
        self.globs['__builtins__'] = globals()['__builtins__']
 
98
        self.locls = {}
 
99
        self.curr_cmd = ''
177
100
 
178
101
def daemonize():
179
102
    if os.fork():   # launch child and...
192
115
lineQ = Queue.Queue()
193
116
interpThread = PythonRunner(cmdQ, lineQ)
194
117
 
195
 
# Default expiry time of 15 minutes
196
 
expiry = ExpiryTimer(15 * 60)
197
 
 
198
118
def initializer():
199
119
    interpThread.setDaemon(True)
200
120
    interpThread.start()
201
 
    expiry.ping()
202
121
 
203
122
def dispatch_msg(msg):
204
 
    expiry.ping()
205
123
    lineQ.put({msg['cmd']:msg['text']})
206
124
    return cmdQ.get()
207
125
 
208
126
if __name__ == "__main__":
209
127
    port = int(sys.argv[1])
210
128
    magic = sys.argv[2]
211
 
    if len(sys.argv) >= 4:
212
 
        # working_dir
213
 
        os.chdir(sys.argv[3])
214
 
        # Make python's search path follow the cwd
215
 
        sys.path[0] = ''
216
 
        os.environ['HOME'] = sys.argv[3]
217
129
 
218
130
    common.chat.start_server(port, magic, True, dispatch_msg, initializer)