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

« back to all changes in this revision

Viewing changes to scripts/python-console

  • Committer: dcoles
  • Date: 2008-07-14 01:08:59 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:850
Console: Moved console up into dispatch. Now any application can, in theory, 
have it's own console just by adding 'useconsole = True' to the app settings.
Note: There are some cases where this may not be a good idea - ie. The full 
console app, public applications, etc. Removed the old single instances of 
console and made apps init functions use the new scripts_init section.

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>
 
4
#   python-console <port> <magic> [<working-dir>]
5
5
 
6
6
import cjson
7
7
import codeop
8
 
import cStringIO
9
8
import md5
10
9
import os
11
10
import Queue
12
11
import signal
13
12
import socket
14
13
import sys
 
14
import traceback
15
15
from threading import Thread
16
16
from functools import partial
17
17
 
18
18
import common.chat
19
19
 
 
20
class Interrupt(Exception):
 
21
    def __init__(self):
 
22
        Exception.__init__(self, "Interrupted!")
 
23
 
20
24
class ExpiryTimer(object):
21
25
    def __init__(self, idle):
22
26
        self.idle = idle
23
 
        signal.signal(signal.SIGALRM, partial(self.timeout,self))
 
27
        signal.signal(signal.SIGALRM, partial(self.timeout))
24
28
 
25
29
    def ping(self):
26
30
        signal.alarm(self.idle)
40
44
        self.lineQ = lineQ
41
45
 
42
46
    def readline(self):
43
 
        # stop the clock!
44
47
        self.cmdQ.put({"input":None})
45
48
        expiry.ping()
46
49
        ln = self.lineQ.get()
47
50
        if 'chat' in ln:
48
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()
49
120
 
50
121
class PythonRunner(Thread):
51
122
    def __init__(self, cmdQ, lineQ):
52
123
        self.cmdQ = cmdQ
53
124
        self.lineQ = lineQ
54
 
        self.out = cStringIO.StringIO()
 
125
        self.webio = WebIO(self.cmdQ, self.lineQ)
55
126
        Thread.__init__(self)
56
127
 
57
128
    def execCmd(self, cmd):
58
129
        try:
59
 
            sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
60
 
            sys.stdout = self.out
61
 
            sys.stderr = self.out
62
 
            res = eval(cmd, self.globs, self.locls)
63
 
            self.cmdQ.put({"okay":(self.out.getvalue(),res)})
64
 
            self.curr_cmd = ''
65
 
            self.out = cStringIO.StringIO()
66
 
        except Exception, exc:
67
 
            self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
68
 
            self.curr_cmd = ''
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)
 
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 = ''
70
142
 
71
143
    def run(self):
72
 
        self.init_state()
 
144
        self.globs = {}
 
145
        self.globs['__builtins__'] = globals()['__builtins__']
 
146
        self.curr_cmd = ''
73
147
        compiler = codeop.CommandCompiler()
74
148
 
75
149
        while True:
88
162
                        self.cmdQ.put({"more":None})
89
163
                    else:
90
164
                        self.execCmd(cmd)
91
 
                except Exception, exc:
92
 
                    self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
 
165
                except:
 
166
                    tb = format_exc_start(start=3)
 
167
                    self.cmdQ.put({"exc": ''.join(tb)})
 
168
                    self.webio.flush()
93
169
                    self.curr_cmd = ''
94
 
                    self.out = cStringIO.StringIO()
95
170
            if 'block' in ln:
96
171
                # throw away a partial command.
97
172
                try:
98
173
                    cmd = compile(ln['block'], "<web session>", 'exec');
99
174
                    self.execCmd(cmd)
100
 
                except Exception, exc:
101
 
                    self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
 
175
                except:
 
176
                    tb = format_exc_start()
 
177
                    self.webio.flush()
 
178
                    self.cmdQ.put({"exc": ''.join(tb)})
102
179
                    self.curr_cmd = ''
103
 
                    self.out = cStringIO.StringIO()
104
 
 
105
 
    def init_state(self):
106
 
        self.globs = {}
107
 
        self.globs['__builtins__'] = globals()['__builtins__']
108
 
        self.locls = {}
109
 
        self.curr_cmd = ''
110
180
 
111
181
def daemonize():
112
182
    if os.fork():   # launch child and...
138
208
    lineQ.put({msg['cmd']:msg['text']})
139
209
    return cmdQ.get()
140
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
 
141
219
if __name__ == "__main__":
142
220
    port = int(sys.argv[1])
143
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]
144
228
 
145
229
    common.chat.start_server(port, magic, True, dispatch_msg, initializer)