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

« back to all changes in this revision

Viewing changes to scripts/python-console

  • Committer: Matt Giuca
  • Date: 2009-02-24 02:02:03 UTC
  • mto: This revision was merged to the branch mainline in revision 1119.
  • Revision ID: matt.giuca@gmail.com-20090224020203-aqdcjnsj6y7wl32o
Added a new look to the IVLE header bar. Mmmm... Web 2.0.
Added top-level directory image-source, containing SVG and script files for
    generating the images.
ivle/webapp/coremedia/images: Added 'chrome' directory containing the rendered
    images.
Modified ivle/webapp/base/ivle-headings.html and
    ivle/webapp/coremedia/ivle.css to support the new images.
    Note that the H1 and H2 at the top of the page are no longer displayed
    (and their custom styles have been removed). There is a heading image
    instead.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
 
3
 
# usage:
4
 
#   python-console <port> <magic> [<working-dir>]
5
 
 
6
 
import cjson
7
 
import codeop
8
 
import md5
9
 
import os
10
 
import Queue
11
 
import signal
12
 
import socket
13
 
import sys
14
 
import traceback
15
 
from threading import Thread
16
 
from functools import partial
17
 
 
18
 
import common.chat
19
 
 
20
 
class Interrupt(Exception):
21
 
    def __init__(self):
22
 
        Exception.__init__(self, "Interrupted!")
23
 
 
24
 
class ExpiryTimer(object):
25
 
    def __init__(self, idle):
26
 
        self.idle = idle
27
 
        signal.signal(signal.SIGALRM, partial(self.timeout))
28
 
 
29
 
    def ping(self):
30
 
        signal.alarm(self.idle)
31
 
 
32
 
    def start(self, time):
33
 
        signal.alarm(time)
34
 
 
35
 
    def stop(self):
36
 
        self.ping()
37
 
 
38
 
    def timeout(self, signum, frame):
39
 
        sys.exit(1)
40
 
        
41
 
class StdinFromWeb(object):
42
 
    def __init__(self, cmdQ, lineQ):
43
 
        self.cmdQ = cmdQ
44
 
        self.lineQ = lineQ
45
 
 
46
 
    def readline(self):
47
 
        self.cmdQ.put({"input":None})
48
 
        expiry.ping()
49
 
        ln = self.lineQ.get()
50
 
        if 'chat' in ln:
51
 
            return ln['chat']
52
 
        if 'interrupt' in ln:
53
 
            raise Interrupt()
54
 
        if 'terminate' in ln:
55
 
            sys.exit(0)
56
 
            
57
 
 
58
 
class StdoutToWeb(object):
59
 
    def __init__(self, cmdQ, lineQ):
60
 
        self.cmdQ = cmdQ
61
 
        self.lineQ = lineQ
62
 
        self.remainder = ''
63
 
 
64
 
    def write(self, stuff):
65
 
        self.remainder = self.remainder + stuff
66
 
 
67
 
        # if there's less than 128 bytes, buffer
68
 
        if len(self.remainder) < 128:
69
 
            return
70
 
 
71
 
        # if there's lots, then send it in 1/2K blocks
72
 
        while len(self.remainder) > 512:
73
 
            blk = self.remainder[0:512]
74
 
            self.cmdQ.put({"output":blk})
75
 
            expiry.ping()
76
 
            ln = self.lineQ.get()
77
 
            self.remainder = self.remainder[512:]
78
 
 
79
 
        # Finally, split the remainder up into lines, and ship all the
80
 
        # completed lines off to the server.
81
 
        lines = self.remainder.split("\n")
82
 
        self.remainder = lines[-1]
83
 
        del lines[-1]
84
 
 
85
 
        if len(lines) > 0:
86
 
            lines.append('')
87
 
            text = "\n".join(lines)
88
 
            self.cmdQ.put({"output":text})
89
 
            expiry.ping()
90
 
            ln = self.lineQ.get()
91
 
            if 'interrupt' in ln:
92
 
                raise Interrupt()
93
 
 
94
 
    def flush(self):
95
 
        if len(self.remainder) > 0:
96
 
            self.cmdQ.put({"output":self.remainder})
97
 
            expiry.ping()
98
 
            ln = self.lineQ.get()
99
 
            self.remainder = ''
100
 
            if 'interrupt' in ln:
101
 
                raise Interrupt()
102
 
 
103
 
class WebIO(object):
104
 
    """Provides a file like interface to the Web front end of the console.
105
 
    You may print text to the console using write(), flush any buffered output 
106
 
    using flush(), or request text from the console using readline()"""
107
 
    
108
 
    def __init__(self, cmdQ, lineQ):
109
 
        self.cmdQ = cmdQ
110
 
        self.lineQ = lineQ
111
 
        self.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
112
 
        self.stdout = StdoutToWeb(self.cmdQ, self.lineQ)
113
 
 
114
 
    def write(self, stuff):
115
 
        self.stdout.write(stuff)
116
 
 
117
 
    def flush(self):
118
 
        self.stdout.flush()
119
 
 
120
 
    def readline(self):
121
 
        self.stdout.flush()
122
 
        return self.stdin.readline()
123
 
 
124
 
class PythonRunner(Thread):
125
 
    def __init__(self, cmdQ, lineQ):
126
 
        self.cmdQ = cmdQ
127
 
        self.lineQ = lineQ
128
 
        self.webio = WebIO(self.cmdQ, self.lineQ)
129
 
        Thread.__init__(self)
130
 
 
131
 
    def execCmd(self, cmd):
132
 
        try:
133
 
            sys.stdin = self.webio
134
 
            sys.stdout = self.webio
135
 
            sys.stderr = self.webio
136
 
            res = eval(cmd, self.globs)
137
 
            self.webio.flush()
138
 
            self.cmdQ.put({"okay":res})
139
 
            self.curr_cmd = ''
140
 
        except:
141
 
            tb = format_exc_start(start=1)
142
 
            self.webio.flush()
143
 
            self.cmdQ.put({"exc": ''.join(tb)})
144
 
            self.curr_cmd = ''
145
 
 
146
 
    def run(self):
147
 
        self.globs = {}
148
 
        self.globs['__builtins__'] = globals()['__builtins__']
149
 
        self.curr_cmd = ''
150
 
        compiler = codeop.CommandCompiler()
151
 
 
152
 
        while True:
153
 
            ln = self.lineQ.get()
154
 
            if 'chat' in ln:
155
 
                if self.curr_cmd == '':
156
 
                    self.curr_cmd = ln['chat']
157
 
                else:
158
 
                    self.curr_cmd = self.curr_cmd + '\n' + ln['chat']
159
 
                try:
160
 
                    cmd = compiler(self.curr_cmd)
161
 
                    if cmd is None:
162
 
                        # The command was incomplete,
163
 
                        # so send back a None, so the
164
 
                        # client can print a '...'
165
 
                        self.cmdQ.put({"more":None})
166
 
                    else:
167
 
                        self.execCmd(cmd)
168
 
                except:
169
 
                    tb = format_exc_start(start=3)
170
 
                    self.cmdQ.put({"exc": ''.join(tb)})
171
 
                    self.webio.flush()
172
 
                    self.curr_cmd = ''
173
 
            if 'block' in ln:
174
 
                # throw away a partial command.
175
 
                try:
176
 
                    cmd = compile(ln['block'], "<web session>", 'exec');
177
 
                    self.execCmd(cmd)
178
 
                except:
179
 
                    tb = format_exc_start(start=1)
180
 
                    self.webio.flush()
181
 
                    self.cmdQ.put({"exc": ''.join(tb)})
182
 
                    self.curr_cmd = ''
183
 
 
184
 
def daemonize():
185
 
    if os.fork():   # launch child and...
186
 
        os._exit(0) # kill off parent
187
 
    os.setsid()
188
 
    if os.fork():   # launch child and...
189
 
        os._exit(0) # kill off parent again.
190
 
    os.umask(077)
191
 
 
192
 
# The global 'magic' is the secret that the client and server share
193
 
# which is used to create and md5 digest to authenticate requests.
194
 
# It is assigned a real value at startup.
195
 
magic = ''
196
 
 
197
 
cmdQ = Queue.Queue()
198
 
lineQ = Queue.Queue()
199
 
interpThread = PythonRunner(cmdQ, lineQ)
200
 
 
201
 
# Default expiry time of 15 minutes
202
 
expiry = ExpiryTimer(15 * 60)
203
 
 
204
 
def initializer():
205
 
    interpThread.setDaemon(True)
206
 
    interpThread.start()
207
 
    expiry.ping()
208
 
 
209
 
def dispatch_msg(msg):
210
 
    expiry.ping()
211
 
    lineQ.put({msg['cmd']:msg['text']})
212
 
    return cmdQ.get()
213
 
 
214
 
def format_exc_start(start=0):
215
 
    etype, value, tb = sys.exc_info()
216
 
    tbbits = traceback.extract_tb(tb)[start:]
217
 
    list = ['Traceback (most recent call last):\n']
218
 
    list = list + traceback.format_list(tbbits)
219
 
    list = list + traceback.format_exception_only(etype, value)
220
 
    return ''.join(list)
221
 
 
222
 
if __name__ == "__main__":
223
 
    port = int(sys.argv[1])
224
 
    magic = sys.argv[2]
225
 
    if len(sys.argv) >= 4:
226
 
        # working_dir
227
 
        os.chdir(sys.argv[3])
228
 
        # Make python's search path follow the cwd
229
 
        sys.path[0] = ''
230
 
        os.environ['HOME'] = sys.argv[3]
231
 
 
232
 
    common.chat.start_server(port, magic, True, dispatch_msg, initializer)