blob: 6ab80444de51e1395427973746233f46428728be [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:
Kurt B. Kaiserb6aff152003-03-03 20:06:48 +000076 self.flush_stdout()
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +000077 efile = sys.stderr
78 typ, val, tb = info = sys.exc_info()
79 sys.last_type, sys.last_value, sys.last_traceback = info
80 tbe = traceback.extract_tb(tb)
Kurt B. Kaiserb6aff152003-03-03 20:06:48 +000081 print >>efile, 'Traceback (most recent call last):'
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +000082 exclude = ("run.py", "rpc.py", "RemoteDebugger.py", "bdb.py")
83 self.cleanup_traceback(tbe, exclude)
84 traceback.print_list(tbe, file=efile)
85 lines = traceback.format_exception_only(typ, val)
86 for line in lines:
87 print>>efile, line,
Kurt B. Kaiserb6aff152003-03-03 20:06:48 +000088 self.flush_stdout()
89
90 def flush_stdout(self):
91 try:
92 if sys.stdout.softspace:
93 sys.stdout.softspace = 0
94 sys.stdout.write("\n")
95 except AttributeError:
96 pass
Kurt B. Kaiser86bc4642003-02-27 23:04:17 +000097
98 def cleanup_traceback(self, tb, exclude):
99 "Remove excluded traces from beginning/end of tb; get cached lines"
100 orig_tb = tb[:]
101 while tb:
102 for rpcfile in exclude:
103 if tb[0][0].count(rpcfile):
104 break # found an exclude, break for: and delete tb[0]
105 else:
106 break # no excludes, have left RPC code, break while:
107 del tb[0]
108 while tb:
109 for rpcfile in exclude:
110 if tb[-1][0].count(rpcfile):
111 break
112 else:
113 break
114 del tb[-1]
115 if len(tb) == 0:
116 # exception was in IDLE internals, don't prune!
117 tb[:] = orig_tb[:]
118 print>>sys.stderr, "** IDLE Internal Exception: "
119 for i in range(len(tb)):
120 fn, ln, nm, line = tb[i]
121 if nm == '?':
122 nm = "-toplevel-"
123 if not line and fn.startswith("<pyshell#"):
124 line = self.rpchandler.remotecall('linecache', 'getline',
125 (fn, ln), {})
126 tb[i] = fn, ln, nm, line
Chui Tey5d2af632002-05-26 13:36:41 +0000127
Kurt B. Kaiser003091c2003-02-17 18:57:16 +0000128 def interrupt_the_server(self):
129 # XXX KBK 05Feb03 Windows requires this be done with messages and
130 # threads....
131 self.rpchandler.interrupted = True
132
Kurt B. Kaiser0e3a5772002-06-16 03:32:24 +0000133 def start_the_debugger(self, gui_adap_oid):
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000134 return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid)
135
136 def stop_the_debugger(self, idb_adap_oid):
137 "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
138 self.rpchandler.unregister(idb_adap_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000139
Kurt B. Kaiser5afa1df2002-10-10 08:25:24 +0000140 def get_the_calltip(self, name):
141 return self.calltip.fetch_tip(name)
142
Chui Tey5d2af632002-05-26 13:36:41 +0000143 def stackviewer(self, flist_oid=None):
144 if not hasattr(sys, "last_traceback"):
145 return None
146 flist = None
147 if flist_oid is not None:
Kurt B. Kaiserffd3a422002-06-26 02:32:09 +0000148 flist = self.rpchandler.get_remote_proxy(flist_oid)
Chui Tey5d2af632002-05-26 13:36:41 +0000149 tb = sys.last_traceback
150 while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
151 tb = tb.tb_next
152 item = StackViewer.StackTreeItem(flist, tb)
153 return RemoteObjectBrowser.remote_object_tree_item(item)