blob: e2594dd32faa44f44845a070bca15abf1658bc3a [file] [log] [blame]
Chui Tey5d2af632002-05-26 13:36:41 +00001import sys
Kurt B. Kaiserb4179362002-07-26 00:06:42 +00002import time
3import socket
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +00004import traceback
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +00005
Tony Lowndsf53dec22002-12-20 04:24:43 +00006import boolcheck
7
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +00008import CallTips
9import RemoteDebugger
10import RemoteObjectBrowser
11import StackViewer
Chui Tey5d2af632002-05-26 13:36:41 +000012import rpc
13
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000014import __main__
15
Chui Tey5d2af632002-05-26 13:36:41 +000016def main():
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000017 """Start the Python execution server in a subprocess
18
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000019 In the Python subprocess, RPCServer is instantiated with handlerclass
20 MyHandler, which inherits register/unregister methods from RPCHandler via
21 the mix-in class SocketIO.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000022
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000023 When the RPCServer svr is instantiated, the TCPServer initialization
24 creates an instance of run.MyHandler and calls its handle() method.
25 handle() instantiates a run.Executive object, passing it a reference to the
26 MyHandler object. That reference is saved as attribute rpchandler of the
27 Executive instance. The Executive methods have access to the reference and
28 can pass it on to entities that they command
29 (e.g. RemoteDebugger.Debugger.start_debugger()). The latter, in turn, can
30 call MyHandler(SocketIO) register/unregister methods via the reference to
31 register and unregister themselves.
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000032
33 """
Chui Tey5d2af632002-05-26 13:36:41 +000034 port = 8833
35 if sys.argv[1:]:
36 port = int(sys.argv[1])
37 sys.argv[:] = [""]
38 addr = ("localhost", port)
Kurt B. Kaiser8dcdb772002-08-05 03:52:10 +000039 for i in range(6):
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000040 time.sleep(i)
41 try:
42 svr = rpc.RPCServer(addr, MyHandler)
43 break
44 except socket.error, err:
Kurt B. Kaiser8dcdb772002-08-05 03:52:10 +000045 if i < 3:
Kurt B. Kaiserb4179362002-07-26 00:06:42 +000046 print>>sys.__stderr__, ".. ",
47 else:
48 print>>sys.__stderr__,"\nPython subprocess socket error: "\
49 + err[1] + ", retrying...."
50 else:
51 print>>sys.__stderr__, "\nConnection to Idle failed, exiting."
52 sys.exit()
Chui Tey5d2af632002-05-26 13:36:41 +000053 svr.handle_request() # A single request only
54
55class MyHandler(rpc.RPCHandler):
56
57 def handle(self):
58 executive = Executive(self)
59 self.register("exec", executive)
60 sys.stdin = self.get_remote_proxy("stdin")
61 sys.stdout = self.get_remote_proxy("stdout")
62 sys.stderr = self.get_remote_proxy("stderr")
63 rpc.RPCHandler.handle(self)
64
65class Executive:
66
67 def __init__(self, rpchandler):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +000068 self.rpchandler = rpchandler
Kurt B. Kaiseradc63842002-08-25 14:08:07 +000069 self.locals = __main__.__dict__
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +000070 self.calltip = CallTips.CallTips()
Chui Tey5d2af632002-05-26 13:36:41 +000071
72 def runcode(self, code):
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +000073 try:
74 exec code in self.locals
75 except:
76 efile = sys.stderr
77 typ, val, tb = info = sys.exc_info()
78 sys.last_type, sys.last_value, sys.last_traceback = info
79 tbe = traceback.extract_tb(tb)
80 print >>efile, '\nTraceback (most recent call last):'
81 exclude = ("run.py", "rpc.py", "RemoteDebugger.py", "bdb.py")
82 self.cleanup_traceback(tbe, exclude)
83 traceback.print_list(tbe, file=efile)
84 lines = traceback.format_exception_only(typ, val)
85 for line in lines:
86 print>>efile, line,
87
88 def cleanup_traceback(self, tb, exclude):
89 "Remove excluded traces from beginning/end of tb; get cached lines"
90 orig_tb = tb[:]
91 while tb:
92 for rpcfile in exclude:
93 if tb[0][0].count(rpcfile):
94 break # found an exclude, break for: and delete tb[0]
95 else:
96 break # no excludes, have left RPC code, break while:
97 del tb[0]
98 while tb:
99 for rpcfile in exclude:
100 if tb[-1][0].count(rpcfile):
101 break
102 else:
103 break
104 del tb[-1]
105 if len(tb) == 0:
106 # exception was in IDLE internals, don't prune!
107 tb[:] = orig_tb[:]
108 print>>sys.stderr, "** IDLE Internal Exception: "
109 for i in range(len(tb)):
110 fn, ln, nm, line = tb[i]
111 if nm == '?':
112 nm = "-toplevel-"
113 if not line and fn.startswith("<pyshell#"):
114 line = self.rpchandler.remotecall('linecache', 'getline',
115 (fn, ln), {})
116 tb[i] = fn, ln, nm, line
Chui Tey5d2af632002-05-26 13:36:41 +0000117
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000118 def interrupt_the_server(self):
119 # XXX KBK 05Feb03 Windows requires this be done with messages and
120 # threads....
121 self.rpchandler.interrupted = True
122
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000123 def start_the_debugger(self, gui_adap_oid):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000124 return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid)
125
126 def stop_the_debugger(self, idb_adap_oid):
127 "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
128 self.rpchandler.unregister(idb_adap_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000129
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000130 def get_the_calltip(self, name):
131 return self.calltip.fetch_tip(name)
132
Chui Tey5d2af632002-05-26 13:36:41 +0000133 def stackviewer(self, flist_oid=None):
134 if not hasattr(sys, "last_traceback"):
135 return None
136 flist = None
137 if flist_oid is not None:
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000138 flist = self.rpchandler.get_remote_proxy(flist_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000139 tb = sys.last_traceback
140 while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
141 tb = tb.tb_next
142 item = StackViewer.StackTreeItem(flist, tb)
143 return RemoteObjectBrowser.remote_object_tree_item(item)