blob: 74c1b8947a0d0b157505fa4208b8f83d3b96a18c [file] [log] [blame]
Chui Tey5d2af632002-05-26 13:36:41 +00001import sys
Martin v. Löwis9ae3f7a2012-07-09 20:46:11 +02002import io
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +00003import linecache
Kurt B. Kaiserb4179362002-07-26 00:06:42 +00004import time
5import socket
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +00006import traceback
Georg Brandl2067bfd2008-05-25 13:05:15 +00007import _thread as thread
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +00008import threading
Alexandre Vassalottif260e442008-05-11 19:59:59 +00009import queue
Andrew Svetlov753445a2012-03-26 21:56:44 +030010import tkinter
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000011
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000012from idlelib import CallTips
13from idlelib import AutoComplete
Kurt B. Kaiserb1754452005-11-18 22:05:48 +000014
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +000015from idlelib import RemoteDebugger
16from idlelib import RemoteObjectBrowser
17from idlelib import StackViewer
18from idlelib import rpc
Serhiy Storchaka39e70a42013-01-25 15:30:58 +020019from idlelib import PyShell
20from idlelib import IOBinding
Chui Tey5d2af632002-05-26 13:36:41 +000021
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000022import __main__
23
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000024LOCALHOST = '127.0.0.1'
25
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000026try:
27 import warnings
28except ImportError:
29 pass
30else:
Benjamin Peterson206e3072008-10-19 14:07:49 +000031 def idle_formatwarning_subproc(message, category, filename, lineno,
Guilherme Polo1fff0082009-08-14 15:05:30 +000032 line=None):
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000033 """Format warnings the IDLE way"""
34 s = "\nWarning (from warnings module):\n"
35 s += ' File \"%s\", line %s\n' % (filename, lineno)
Guilherme Polo1fff0082009-08-14 15:05:30 +000036 if line is None:
37 line = linecache.getline(filename, lineno)
38 line = line.strip()
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000039 if line:
40 s += " %s\n" % line
41 s += "%s: %s\n" % (category.__name__, message)
42 return s
Kurt B. Kaiser49a5fe12004-07-04 01:25:56 +000043
Andrew Svetlova2251aa2012-03-13 18:36:13 -070044
Andrew Svetlov753445a2012-03-26 21:56:44 +030045tcl = tkinter.Tcl()
46
47
48def handle_tk_events(tcl=tcl):
Andrew Svetlova2251aa2012-03-13 18:36:13 -070049 """Process any tk events that are ready to be dispatched if tkinter
50 has been imported, a tcl interpreter has been created and tk has been
51 loaded."""
Andrew Svetlov753445a2012-03-26 21:56:44 +030052 tcl.eval("update")
Andrew Svetlova2251aa2012-03-13 18:36:13 -070053
54
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000055# Thread shared globals: Establish a queue between a subthread (which handles
56# the socket) and the main thread (which runs user code), plus global
Guido van Rossum8ce8a782007-11-01 19:42:39 +000057# completion, exit and interruptable (the main thread) flags:
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000058
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +000059exit_now = False
60quitting = False
Guido van Rossum8ce8a782007-11-01 19:42:39 +000061interruptable = False
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000062
Kurt B. Kaiser62df0442003-05-28 01:47:46 +000063def main(del_exitfunc=False):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000064 """Start the Python execution server in a subprocess
65
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000066 In the Python subprocess, RPCServer is instantiated with handlerclass
67 MyHandler, which inherits register/unregister methods from RPCHandler via
68 the mix-in class SocketIO.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000069
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000070 When the RPCServer 'server' is instantiated, the TCPServer initialization
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000071 creates an instance of run.MyHandler and calls its handle() method.
72 handle() instantiates a run.Executive object, passing it a reference to the
73 MyHandler object. That reference is saved as attribute rpchandler of the
74 Executive instance. The Executive methods have access to the reference and
75 can pass it on to entities that they command
76 (e.g. RemoteDebugger.Debugger.start_debugger()). The latter, in turn, can
77 call MyHandler(SocketIO) register/unregister methods via the reference to
78 register and unregister themselves.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000079
80 """
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +000081 global exit_now
82 global quitting
Kurt B. Kaiser62df0442003-05-28 01:47:46 +000083 global no_exitfunc
Victor Stinnerb28a3752013-06-25 00:17:37 +020084
85 warnings.formatwarning = idle_formatwarning_subproc
86
Kurt B. Kaiser62df0442003-05-28 01:47:46 +000087 no_exitfunc = del_exitfunc
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +000088 #time.sleep(15) # test subprocess not responding
Kurt B. Kaisere67842a2009-04-04 20:13:23 +000089 try:
90 assert(len(sys.argv) > 1)
91 port = int(sys.argv[-1])
92 except:
Kurt B. Kaiser8fc98c32009-04-04 20:20:29 +000093 print("IDLE Subprocess: no IP port passed in sys.argv.",
94 file=sys.__stderr__)
Kurt B. Kaisere67842a2009-04-04 20:13:23 +000095 return
Chui Tey5d2af632002-05-26 13:36:41 +000096 sys.argv[:] = [""]
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +000097 sockthread = threading.Thread(target=manage_socket,
98 name='SockThread',
Kurt B. Kaiser24d7e0c2003-06-05 23:51:29 +000099 args=((LOCALHOST, port),))
Benjamin Peterson71088cc2008-09-19 21:49:37 +0000100 sockthread.daemon = True
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000101 sockthread.start()
102 while 1:
103 try:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000104 if exit_now:
105 try:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000106 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000107 except KeyboardInterrupt:
108 # exiting but got an extra KBI? Try again!
109 continue
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000110 try:
Kurt B. Kaiser20345fb2005-05-05 23:29:54 +0000111 seq, request = rpc.request_queue.get(block=True, timeout=0.05)
Alexandre Vassalottif260e442008-05-11 19:59:59 +0000112 except queue.Empty:
Andrew Svetlova2251aa2012-03-13 18:36:13 -0700113 handle_tk_events()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000114 continue
115 method, args, kwargs = request
116 ret = method(*args, **kwargs)
117 rpc.response_queue.put((seq, ret))
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000118 except KeyboardInterrupt:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000119 if quitting:
120 exit_now = True
Kurt B. Kaiseraa6b8562003-05-14 18:15:40 +0000121 continue
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000122 except SystemExit:
123 raise
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000124 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000125 type, value, tb = sys.exc_info()
Kurt B. Kaisera2792be2003-05-17 21:04:10 +0000126 try:
127 print_exception()
128 rpc.response_queue.put((seq, None))
129 except:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000130 # Link didn't work, print same exception to __stderr__
131 traceback.print_exception(type, value, tb, file=sys.__stderr__)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000132 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000133 else:
134 continue
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000135
136def manage_socket(address):
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000137 for i in range(3):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000138 time.sleep(i)
139 try:
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000140 server = MyRPCServer(address, MyHandler)
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000141 break
Andrew Svetlov0832af62012-12-18 23:10:48 +0200142 except OSError as err:
143 print("IDLE Subprocess: OSError: " + err.args[1] +
Georg Brandl6464d472007-10-22 16:16:13 +0000144 ", retrying....", file=sys.__stderr__)
Amaury Forgeot d'Arcefae8c42008-11-21 23:08:09 +0000145 socket_error = err
Kurt B. Kaiserb4179362002-07-26 00:06:42 +0000146 else:
Amaury Forgeot d'Arcefae8c42008-11-21 23:08:09 +0000147 print("IDLE Subprocess: Connection to "
148 "IDLE GUI failed, exiting.", file=sys.__stderr__)
149 show_socket_error(socket_error, address)
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000150 global exit_now
151 exit_now = True
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000152 return
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000153 server.handle_request() # A single request only
154
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000155def show_socket_error(err, address):
Georg Brandl14fc4272008-05-17 18:39:55 +0000156 import tkinter
157 import tkinter.messagebox as tkMessageBox
158 root = tkinter.Tk()
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000159 root.withdraw()
Georg Brandl6464d472007-10-22 16:16:13 +0000160 if err.args[0] == 61: # connection refused
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000161 msg = "IDLE's subprocess can't connect to %s:%d. This may be due "\
162 "to your personal firewall configuration. It is safe to "\
163 "allow this internal connection because no data is visible on "\
164 "external ports." % address
165 tkMessageBox.showerror("IDLE Subprocess Error", msg, parent=root)
166 else:
Georg Brandl6464d472007-10-22 16:16:13 +0000167 tkMessageBox.showerror("IDLE Subprocess Error",
168 "Socket Error: %s" % err.args[1])
Kurt B. Kaiseraf3eb872004-01-21 18:54:30 +0000169 root.destroy()
170
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000171def print_exception():
Kurt B. Kaisere9802a32004-01-02 04:04:04 +0000172 import linecache
173 linecache.checkcache()
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000174 flush_stdout()
175 efile = sys.stderr
Kurt B. Kaiser924f6162003-11-19 04:52:32 +0000176 typ, val, tb = excinfo = sys.exc_info()
177 sys.last_type, sys.last_value, sys.last_traceback = excinfo
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200178 seen = set()
179
180 def print_exc(typ, exc, tb):
181 seen.add(exc)
182 context = exc.__context__
183 cause = exc.__cause__
184 if cause is not None and cause not in seen:
185 print_exc(type(cause), cause, cause.__traceback__)
186 print("\nThe above exception was the direct cause "
187 "of the following exception:\n", file=efile)
Serhiy Storchaka71317492013-01-09 12:24:48 +0200188 elif (context is not None and
189 not exc.__suppress_context__ and
190 context not in seen):
Serhiy Storchaka78470b42013-01-09 12:21:57 +0200191 print_exc(type(context), context, context.__traceback__)
192 print("\nDuring handling of the above exception, "
193 "another exception occurred:\n", file=efile)
194 if tb:
195 tbe = traceback.extract_tb(tb)
196 print('Traceback (most recent call last):', file=efile)
197 exclude = ("run.py", "rpc.py", "threading.py", "queue.py",
198 "RemoteDebugger.py", "bdb.py")
199 cleanup_traceback(tbe, exclude)
200 traceback.print_list(tbe, file=efile)
201 lines = traceback.format_exception_only(typ, exc)
202 for line in lines:
203 print(line, end='', file=efile)
204
205 print_exc(typ, val, tb)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000206
207def cleanup_traceback(tb, exclude):
208 "Remove excluded traces from beginning/end of tb; get cached lines"
209 orig_tb = tb[:]
210 while tb:
211 for rpcfile in exclude:
212 if tb[0][0].count(rpcfile):
213 break # found an exclude, break for: and delete tb[0]
214 else:
215 break # no excludes, have left RPC code, break while:
216 del tb[0]
217 while tb:
218 for rpcfile in exclude:
219 if tb[-1][0].count(rpcfile):
220 break
221 else:
222 break
223 del tb[-1]
224 if len(tb) == 0:
225 # exception was in IDLE internals, don't prune!
226 tb[:] = orig_tb[:]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000227 print("** IDLE Internal Exception: ", file=sys.stderr)
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000228 rpchandler = rpc.objecttable['exec'].rpchandler
229 for i in range(len(tb)):
230 fn, ln, nm, line = tb[i]
231 if nm == '?':
232 nm = "-toplevel-"
233 if not line and fn.startswith("<pyshell#"):
234 line = rpchandler.remotecall('linecache', 'getline',
235 (fn, ln), {})
236 tb[i] = fn, ln, nm, line
237
238def flush_stdout():
Guido van Rossum79139b22007-02-09 23:20:19 +0000239 """XXX How to do this now?"""
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000240
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000241def exit():
Guido van Rossumc76a2502007-08-09 14:26:58 +0000242 """Exit subprocess, possibly after first clearing exit functions.
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000243
244 If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
Guido van Rossumc76a2502007-08-09 14:26:58 +0000245 functions registered with atexit will be removed before exiting.
246 (VPython support)
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000247
248 """
249 if no_exitfunc:
Guido van Rossumc76a2502007-08-09 14:26:58 +0000250 import atexit
251 atexit._clear()
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000252 sys.exit(0)
Chui Tey5d2af632002-05-26 13:36:41 +0000253
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000254class MyRPCServer(rpc.RPCServer):
255
256 def handle_error(self, request, client_address):
257 """Override RPCServer method for IDLE
258
259 Interrupt the MainThread and exit server if link is dropped.
260
261 """
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000262 global quitting
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000263 try:
264 raise
265 except SystemExit:
266 raise
267 except EOFError:
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000268 global exit_now
269 exit_now = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000270 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000271 except:
272 erf = sys.__stderr__
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000273 print('\n' + '-'*40, file=erf)
274 print('Unhandled server exception!', file=erf)
Amaury Forgeot d'Arcbed17102008-11-29 01:48:47 +0000275 print('Thread: %s' % threading.current_thread().name, file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000276 print('Client Address: ', client_address, file=erf)
277 print('Request: ', repr(request), file=erf)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000278 traceback.print_exc(file=erf)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000279 print('\n*** Unrecoverable, server exiting!', file=erf)
280 print('-'*40, file=erf)
Kurt B. Kaisere9535112004-11-19 15:46:49 +0000281 quitting = True
282 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000283
Chui Tey5d2af632002-05-26 13:36:41 +0000284class MyHandler(rpc.RPCHandler):
285
286 def handle(self):
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000287 """Override base method"""
Chui Tey5d2af632002-05-26 13:36:41 +0000288 executive = Executive(self)
289 self.register("exec", executive)
Serhiy Storchaka39e70a42013-01-25 15:30:58 +0200290 self.console = self.get_remote_proxy("console")
291 sys.stdin = PyShell.PseudoInputFile(self.console, "stdin",
292 IOBinding.encoding)
293 sys.stdout = PyShell.PseudoOutputFile(self.console, "stdout",
294 IOBinding.encoding)
295 sys.stderr = PyShell.PseudoOutputFile(self.console, "stderr",
296 IOBinding.encoding)
297
Andrew Svetlovcd49d532012-03-25 11:43:02 +0300298 sys.displayhook = rpc.displayhook
Kurt B. Kaiserf609a342007-12-28 03:57:56 +0000299 # page help() text to shell.
300 import pydoc # import must be done here to capture i/o binding
301 pydoc.pager = pydoc.plainpager
Benjamin Peterson0d4931e2013-05-11 22:24:28 -0500302
303 # Keep a reference to stdin so that it won't try to exit IDLE if
304 # sys.stdin gets changed from within IDLE's shell. See issue17838.
305 self._keep_stdin = sys.stdin
306
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000307 self.interp = self.get_remote_proxy("interp")
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000308 rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
309
310 def exithook(self):
311 "override SocketIO method - wait for MainThread to shut us down"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000312 time.sleep(10)
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000313
314 def EOFhook(self):
315 "Override SocketIO method - terminate wait on callback and exit thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000316 global quitting
317 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000318 thread.interrupt_main()
Kurt B. Kaisera00050f2003-05-08 20:26:55 +0000319
320 def decode_interrupthook(self):
321 "interrupt awakened thread"
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000322 global quitting
323 quitting = True
Kurt B. Kaiser93e8e542003-06-13 22:03:43 +0000324 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000325
Chui Tey5d2af632002-05-26 13:36:41 +0000326
Kurt B. Kaiserdcba6622004-12-21 22:10:32 +0000327class Executive(object):
Chui Tey5d2af632002-05-26 13:36:41 +0000328
329 def __init__(self, rpchandler):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000330 self.rpchandler = rpchandler
Kurt B. Kaiseradc63842002-08-25 14:08:07 +0000331 self.locals = __main__.__dict__
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000332 self.calltip = CallTips.CallTips()
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000333 self.autocomplete = AutoComplete.AutoComplete()
Chui Tey5d2af632002-05-26 13:36:41 +0000334
335 def runcode(self, code):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000336 global interruptable
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000337 try:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000338 self.usr_exc_info = None
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000339 interruptable = True
340 try:
341 exec(code, self.locals)
342 finally:
343 interruptable = False
Roger Serwyf4675212013-06-11 22:25:14 -0500344 except SystemExit:
345 # Scripts that raise SystemExit should just
346 # return to the interactive prompt
347 pass
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +0000348 except:
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000349 self.usr_exc_info = sys.exc_info()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000350 if quitting:
Kurt B. Kaiser62df0442003-05-28 01:47:46 +0000351 exit()
Kurt B. Kaiser67fd0ea2003-05-24 20:59:15 +0000352 # even print a user code SystemExit exception, continue
353 print_exception()
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000354 jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
355 if jit:
356 self.rpchandler.interp.open_remote_stack_viewer()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000357 else:
Kurt B. Kaiser9ec454e2003-05-12 02:33:47 +0000358 flush_stdout()
Chui Tey5d2af632002-05-26 13:36:41 +0000359
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000360 def interrupt_the_server(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000361 if interruptable:
362 thread.interrupt_main()
Kurt B. Kaiser11c53e22003-03-22 19:40:19 +0000363
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000364 def start_the_debugger(self, gui_adap_oid):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000365 return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid)
366
367 def stop_the_debugger(self, idb_adap_oid):
368 "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
369 self.rpchandler.unregister(idb_adap_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000370
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000371 def get_the_calltip(self, name):
372 return self.calltip.fetch_tip(name)
373
Kurt B. Kaiserb1754452005-11-18 22:05:48 +0000374 def get_the_completion_list(self, what, mode):
375 return self.autocomplete.fetch_completions(what, mode)
376
Chui Tey5d2af632002-05-26 13:36:41 +0000377 def stackviewer(self, flist_oid=None):
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000378 if self.usr_exc_info:
379 typ, val, tb = self.usr_exc_info
380 else:
Chui Tey5d2af632002-05-26 13:36:41 +0000381 return None
382 flist = None
383 if flist_oid is not None:
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000384 flist = self.rpchandler.get_remote_proxy(flist_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000385 while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
386 tb = tb.tb_next
Kurt B. Kaiser9f366092003-06-02 01:50:19 +0000387 sys.last_type = typ
388 sys.last_value = val
Chui Tey5d2af632002-05-26 13:36:41 +0000389 item = StackViewer.StackTreeItem(flist, tb)
390 return RemoteObjectBrowser.remote_object_tree_item(item)