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

« back to all changes in this revision

Viewing changes to scripts/python-console

  • Committer: mattgiuca
  • Date: 2008-03-15 13:16:00 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:709
Added "tiny" versions of tutorial complete/incomplete balls for
    side panel use.

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
from threading import Thread
 
15
from functools import partial
 
16
 
 
17
import common.chat
 
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
class StdinFromWeb(object):
 
41
    def __init__(self, cmdQ, lineQ):
 
42
        self.cmdQ = cmdQ
 
43
        self.lineQ = lineQ
 
44
 
 
45
    def readline(self):
 
46
        self.cmdQ.put({"input":None})
 
47
        expiry.ping()
 
48
        ln = self.lineQ.get()
 
49
        if 'chat' in ln:
 
50
            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 PythonRunner(Thread):
 
100
    def __init__(self, cmdQ, lineQ):
 
101
        self.cmdQ = cmdQ
 
102
        self.lineQ = lineQ
 
103
        self.stdout = StdoutToWeb(self.cmdQ, self.lineQ)
 
104
        Thread.__init__(self)
 
105
 
 
106
    def execCmd(self, cmd):
 
107
        try:
 
108
            sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
 
109
            sys.stdout = self.stdout
 
110
            sys.stderr = self.stdout
 
111
            res = eval(cmd, self.globs)
 
112
            self.stdout.flush()
 
113
            self.cmdQ.put({"okay":res})
 
114
            self.curr_cmd = ''
 
115
        except Exception, exc:
 
116
            self.stdout.flush()
 
117
            self.cmdQ.put({"exc":str(exc)})
 
118
            self.curr_cmd = ''
 
119
 
 
120
    def run(self):
 
121
        self.globs = {}
 
122
        self.globs['__builtins__'] = globals()['__builtins__']
 
123
        self.curr_cmd = ''
 
124
        compiler = codeop.CommandCompiler()
 
125
 
 
126
        while True:
 
127
            ln = self.lineQ.get()
 
128
            if 'chat' in ln:
 
129
                if self.curr_cmd == '':
 
130
                    self.curr_cmd = ln['chat']
 
131
                else:
 
132
                    self.curr_cmd = self.curr_cmd + '\n' + ln['chat']
 
133
                try:
 
134
                    cmd = compiler(self.curr_cmd)
 
135
                    if cmd is None:
 
136
                        # The command was incomplete,
 
137
                        # so send back a None, so the
 
138
                        # client can print a '...'
 
139
                        self.cmdQ.put({"more":None})
 
140
                    else:
 
141
                        self.execCmd(cmd)
 
142
                except Exception, exc:
 
143
                    self.stdout.flush()
 
144
                    self.cmdQ.put({"exc":str(exc)})
 
145
                    self.curr_cmd = ''
 
146
            if 'block' in ln:
 
147
                # throw away a partial command.
 
148
                try:
 
149
                    cmd = compile(ln['block'], "<web session>", 'exec');
 
150
                    self.execCmd(cmd)
 
151
                except Exception, exc:
 
152
                    self.stdout.flush()
 
153
                    self.cmdQ.put({"exc":str(exc)})
 
154
                    self.curr_cmd = ''
 
155
 
 
156
def daemonize():
 
157
    if os.fork():   # launch child and...
 
158
        os._exit(0) # kill off parent
 
159
    os.setsid()
 
160
    if os.fork():   # launch child and...
 
161
        os._exit(0) # kill off parent again.
 
162
    os.umask(077)
 
163
 
 
164
# The global 'magic' is the secret that the client and server share
 
165
# which is used to create and md5 digest to authenticate requests.
 
166
# It is assigned a real value at startup.
 
167
magic = ''
 
168
 
 
169
cmdQ = Queue.Queue()
 
170
lineQ = Queue.Queue()
 
171
interpThread = PythonRunner(cmdQ, lineQ)
 
172
 
 
173
# Default expiry time of 15 minutes
 
174
expiry = ExpiryTimer(15 * 60)
 
175
 
 
176
def initializer():
 
177
    interpThread.setDaemon(True)
 
178
    interpThread.start()
 
179
    expiry.ping()
 
180
 
 
181
def dispatch_msg(msg):
 
182
    expiry.ping()
 
183
    lineQ.put({msg['cmd']:msg['text']})
 
184
    return cmdQ.get()
 
185
 
 
186
if __name__ == "__main__":
 
187
    port = int(sys.argv[1])
 
188
    magic = sys.argv[2]
 
189
    if len(sys.argv) >= 4:
 
190
        # working_dir
 
191
        os.chdir(sys.argv[3])
 
192
        os.environ['HOME'] = sys.argv[3]
 
193
 
 
194
    common.chat.start_server(port, magic, True, dispatch_msg, initializer)