1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import __builtin__
21 import __main__
22 import codeop
23 import keyword
24 import re
25 import readline
26 import threading
27 import traceback
28 import sys
29 import string
30
31 import pygtk
32 pygtk.require("2.0")
33 import gobject
34 import gtk
35
36
37 __all__ = ['interact']
38
39
41
43 self.globals = globals
44 self.locals = lokals
45
46 self.completions = keyword.kwlist + \
47 __builtin__.__dict__.keys() + \
48 __main__.__dict__.keys()
49
61
62 - def update(self, globs, locs):
63 self.globals = globs
64 self.locals = locs
65
66 for key in self.locals.keys():
67 if not key in self.completions:
68 self.completions.append(key)
69 for key in self.globals.keys():
70 if not key in self.completions:
71 self.completions.append(key)
72
74 matches = []
75 n = len(text)
76 for word in self.completions:
77 if word[:n] == text:
78 matches.append(word)
79 return matches
80
82 m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
83 if not m:
84 return
85 expr, attr = m.group(1, 3)
86
87 obj = eval(expr, self.globals, self.locals)
88 words = dir(obj)
89
90 matches = []
91 n = len(attr)
92 for word in words:
93 if word[:n] == attr:
94 matches.append("%s.%s" % (expr, word))
95 return matches
96
97
99 """Run a gtk main() in a separate thread.
100 Python commands can be passed to the thread where they will be executed.
101 This is implemented by periodically checking for passed code using a
102 GTK timeout callback.
103 """
104 TIMEOUT = 100
105
106 - def __init__(self, globals=None, locals=None):
107 threading.Thread.__init__(self)
108 self.ready = threading.Condition()
109 self.globs = globals or {'__name__':
110 '__console__', 'gtk': gtk}
111 self.locs = locals or {}
112 self._has_quit = False
113 self.cmd = ''
114 self.new_cmd = None
115
116 self.completer = Completer(self.globs, self.locs)
117
119 print self.banner
120 readline.set_completer(self.completer.complete)
121 readline.parse_and_bind('tab: complete')
122 ps1 = getattr(self, 'ps1', '>>> ')
123 ps2 = getattr(self, 'ps1', '... ')
124 read = self.reader
125
126 prompt = ps1
127 try:
128 while True:
129 command = read(prompt) + '\n'
130 prompt = self.feed(command) and ps1 or ps2
131 except (EOFError, KeyboardInterrupt):
132 pass
133 print
134 self._has_quit = True
135
137 """Execute waiting code. Called every timeout period."""
138 self.ready.acquire()
139
140 if self._has_quit:
141 if self.main_loop:
142 self.main_loop.quit()
143 return False
144
145 if self.new_cmd != None:
146 self.ready.notify()
147 self.cmd = self.cmd + self.new_cmd
148 self.new_cmd = None
149 try:
150 code = codeop.compile_command(self.cmd[:-1])
151 if code:
152 self.cmd = ''
153 exec code in self.globs, self.locs
154 self.completer.update(self.globs, self.locs)
155 except Exception:
156 traceback.print_exc()
157 self.cmd = ''
158
159 self.ready.release()
160 return True
161
163 if (not code) or (code[-1]<>'\n'):
164 code = code +'\n'
165 self.ready.acquire()
166 self.completer.update(self.globs, self.locs)
167 self.new_cmd = code
168 self.code_exec()
169 self.ready.release()
170 return not self.cmd
171
172 - def feed(self, code):
173 """Feed a line of code to the thread.
174 This function will block until the code checked by the GTK thread.
175 Return true if executed the code.
176 Returns false if deferring execution until complete block available.
177 """
178
179 if (not code) or (code[-1]<>'\n'):
180 code = code +'\n'
181 self.completer.update(self.globs, self.locs)
182 self.ready.acquire()
183 self.new_cmd = code
184 self.ready.wait()
185 self.ready.release()
186
187 return not self.cmd
188
189 - def interact(self, banner=None, reader=None, block=False):
190 self.banner = banner or 'Interactive GTK Shell'
191 self.reader = reader or raw_input
192 gobject.timeout_add(self.TIMEOUT, self.code_exec)
193 gtk.gdk.threads_init()
194 self.start()
195 self.main_loop = block and gobject.MainLoop()
196 if self.main_loop:
197 self.main_loop.run()
198
199
200
201
202 -def interact(banner=None, reader=None, local=None):
205
206 if __name__=="__main__":
207 interpreter = GtkInterpreter()
208 interpreter.feed_sync("import sys")
209 interpreter.feed_sync("sys.path.append('.')")
210
211 if len(sys.argv) > 1:
212 for file in open(sys.argv[1]).readlines():
213 interpreter.feed_sync(file)
214
215 banner = 'Interactive GTK Shell'
216 py_version = string.join(map(str, sys.version_info[:3]), '.')
217 pygtk_version = string.join(map(str, gtk.pygtk_version), '.')
218 gtk_version = string.join(map(str, gtk.gtk_version), '.')
219 banner += '\nPython %s, Pygtk %s, GTK+ %s' % (py_version, pygtk_version,
220 gtk_version)
221
222 interpreter.interact(banner, block=True)
223