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

« back to all changes in this revision

Viewing changes to scripts/python-console

  • Committer: wagrant
  • Date: 2008-07-14 03:19:15 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:859
browser: Remove some redundant CSS. There's no need to set things that
         are already inherited.

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
 
 
55
class StdoutToWeb(object):
 
56
    def __init__(self, cmdQ, lineQ):
 
57
        self.cmdQ = cmdQ
 
58
        self.lineQ = lineQ
 
59
        self.remainder = ''
 
60
 
 
61
    def write(self, stuff):
 
62
        self.remainder = self.remainder + stuff
 
63
 
 
64
        # if there's less than 128 bytes, buffer
 
65
        if len(self.remainder) < 128:
 
66
            return
 
67
 
 
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})
 
72
            expiry.ping()
 
73
            ln = self.lineQ.get()
 
74
            self.remainder = self.remainder[512:]
 
75
 
 
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]
 
80
        del lines[-1]
 
81
 
 
82
        if len(lines) > 0:
 
83
            lines.append('')
 
84
            text = "\n".join(lines)
 
85
            self.cmdQ.put({"output":text})
 
86
            expiry.ping()
 
87
            ln = self.lineQ.get()
 
88
            if 'interrupt' in ln:
 
89
                raise Interrupt()
 
90
 
 
91
    def flush(self):
 
92
        if len(self.remainder) > 0:
 
93
            self.cmdQ.put({"output":self.remainder})
 
94
            expiry.ping()
 
95
            ln = self.lineQ.get()
 
96
            self.remainder = ''
 
97
            if 'interrupt' in ln:
 
98
                raise Interrupt()
 
99
 
 
100
class WebIO(object):
 
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()"""
 
104
    
 
105
    def __init__(self, cmdQ, lineQ):
 
106
        self.cmdQ = cmdQ
 
107
        self.lineQ = lineQ
 
108
        self.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
 
109
        self.stdout = StdoutToWeb(self.cmdQ, self.lineQ)
 
110
 
 
111
    def write(self, stuff):
 
112
        self.stdout.write(stuff)
 
113
 
 
114
    def flush(self):
 
115
        self.stdout.flush()
 
116
 
 
117
    def readline(self):
 
118
        self.stdout.flush()
 
119
        return self.stdin.readline()
 
120
 
 
121
class PythonRunner(Thread):
 
122
    def __init__(self, cmdQ, lineQ):
 
123
        self.cmdQ = cmdQ
 
124
        self.lineQ = lineQ
 
125
        self.webio = WebIO(self.cmdQ, self.lineQ)
 
126
        Thread.__init__(self)
 
127
 
 
128
    def execCmd(self, cmd):
 
129
        try:
 
130
            sys.stdin = self.webio
 
131
            sys.stdout = self.webio
 
132
            sys.stderr = self.webio
 
133
            res = eval(cmd, self.globs)
 
134
            self.webio.flush()
 
135
            self.cmdQ.put({"okay":res})
 
136
            self.curr_cmd = ''
 
137
        except:
 
138
            tb = format_exc_start(start=1)
 
139
            self.webio.flush()
 
140
            self.cmdQ.put({"exc": ''.join(tb)})
 
141
            self.curr_cmd = ''
 
142
 
 
143
    def run(self):
 
144
        self.globs = {}
 
145
        self.globs['__builtins__'] = globals()['__builtins__']
 
146
        self.curr_cmd = ''
 
147
        compiler = codeop.CommandCompiler()
 
148
 
 
149
        while True:
 
150
            ln = self.lineQ.get()
 
151
            if 'chat' in ln:
 
152
                if self.curr_cmd == '':
 
153
                    self.curr_cmd = ln['chat']
 
154
                else:
 
155
                    self.curr_cmd = self.curr_cmd + '\n' + ln['chat']
 
156
                try:
 
157
                    cmd = compiler(self.curr_cmd)
 
158
                    if cmd is None:
 
159
                        # The command was incomplete,
 
160
                        # so send back a None, so the
 
161
                        # client can print a '...'
 
162
                        self.cmdQ.put({"more":None})
 
163
                    else:
 
164
                        self.execCmd(cmd)
 
165
                except:
 
166
                    tb = format_exc_start(start=3)
 
167
                    self.cmdQ.put({"exc": ''.join(tb)})
 
168
                    self.webio.flush()
 
169
                    self.curr_cmd = ''
 
170
            if 'block' in ln:
 
171
                # throw away a partial command.
 
172
                try:
 
173
                    cmd = compile(ln['block'], "<web session>", 'exec');
 
174
                    self.execCmd(cmd)
 
175
                except:
 
176
                    tb = format_exc_start()
 
177
                    self.webio.flush()
 
178
                    self.cmdQ.put({"exc": ''.join(tb)})
 
179
                    self.curr_cmd = ''
 
180
 
 
181
def daemonize():
 
182
    if os.fork():   # launch child and...
 
183
        os._exit(0) # kill off parent
 
184
    os.setsid()
 
185
    if os.fork():   # launch child and...
 
186
        os._exit(0) # kill off parent again.
 
187
    os.umask(077)
 
188
 
 
189
# The global 'magic' is the secret that the client and server share
 
190
# which is used to create and md5 digest to authenticate requests.
 
191
# It is assigned a real value at startup.
 
192
magic = ''
 
193
 
 
194
cmdQ = Queue.Queue()
 
195
lineQ = Queue.Queue()
 
196
interpThread = PythonRunner(cmdQ, lineQ)
 
197
 
 
198
# Default expiry time of 15 minutes
 
199
expiry = ExpiryTimer(15 * 60)
 
200
 
 
201
def initializer():
 
202
    interpThread.setDaemon(True)
 
203
    interpThread.start()
 
204
    expiry.ping()
 
205
 
 
206
def dispatch_msg(msg):
 
207
    expiry.ping()
 
208
    lineQ.put({msg['cmd']:msg['text']})
 
209
    return cmdQ.get()
 
210
 
 
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)
 
217
    return ''.join(list)
 
218
 
 
219
if __name__ == "__main__":
 
220
    port = int(sys.argv[1])
 
221
    magic = sys.argv[2]
 
222
    if len(sys.argv) >= 4:
 
223
        # working_dir
 
224
        os.chdir(sys.argv[3])
 
225
        # Make python's search path follow the cwd
 
226
        sys.path[0] = ''
 
227
        os.environ['HOME'] = sys.argv[3]
 
228
 
 
229
    common.chat.start_server(port, magic, True, dispatch_msg, initializer)