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