14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao"""Support for remote Python debugging. 24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 34adfde8bc82dd39f59e0445588c3e599ada477dJosh GaoSome ASCII art to describe the structure: 44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao IN PYTHON SUBPROCESS # IN IDLE PROCESS 64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # 74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # oid='gui_adapter' 84adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao +----------+ # +------------+ +-----+ 94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao | GUIProxy |--remote#call-->| GUIAdapter |--calls-->| GUI | 104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao+-----+--calls-->+----------+ # +------------+ +-----+ 114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao| Idb | # / 124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao+-----+<-calls--+------------+ # +----------+<--calls-/ 134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao | IdbAdapter |<--remote#call--| IdbProxy | 144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao +------------+ # +----------+ 154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao oid='idb_adapter' # 164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 174adfde8bc82dd39f59e0445588c3e599ada477dJosh GaoThe purpose of the Proxy and Adapter classes is to translate certain 184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoarguments and return values that cannot be transported through the RPC 194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaobarrier, in particular frame and traceback objects. 204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao""" 224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport types 244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom idlelib import rpc 254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom idlelib import Debugger 264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodebugging = 0 284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoidb_adap_oid = "idb_adapter" 304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaogui_adap_oid = "gui_adapter" 314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#======================================= 334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# In the PYTHON subprocess: 354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoframetable = {} 374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodicttable = {} 384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaocodetable = {} 394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaotracebacktable = {} 404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef wrap_frame(frame): 424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao fid = id(frame) 434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao frametable[fid] = frame 444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return fid 454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef wrap_info(info): 474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "replace info[2], a traceback instance, by its ID" 484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if info is None: 494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return None 504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao traceback = info[2] 524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao assert isinstance(traceback, types.TracebackType) 534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao traceback_id = id(traceback) 544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao tracebacktable[traceback_id] = traceback 554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao modified_info = (info[0], info[1], traceback_id) 564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return modified_info 574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass GUIProxy: 594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, conn, gui_adap_oid): 614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.conn = conn 624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.oid = gui_adap_oid 634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def interaction(self, message, frame, info=None): 654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # calls rpc.SocketIO.remotecall() via run.MyHandler instance 664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # pass frame and traceback object IDs instead of the objects themselves 674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.conn.remotecall(self.oid, "interaction", 684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (message, wrap_frame(frame), wrap_info(info)), 694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao {}) 704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass IdbAdapter: 724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, idb): 744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.idb = idb 754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao #----------called by an IdbProxy---------- 774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_step(self): 794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.idb.set_step() 804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_quit(self): 824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.idb.set_quit() 834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_continue(self): 854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.idb.set_continue() 864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_next(self, fid): 884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao frame = frametable[fid] 894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.idb.set_next(frame) 904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_return(self, fid): 924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao frame = frametable[fid] 934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.idb.set_return(frame) 944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def get_stack(self, fid, tbid): 964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ##print >>sys.__stderr__, "get_stack(%r, %r)" % (fid, tbid) 974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao frame = frametable[fid] 984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if tbid is None: 994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao tb = None 1004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 1014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao tb = tracebacktable[tbid] 1024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao stack, i = self.idb.get_stack(frame, tb) 1034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ##print >>sys.__stderr__, "get_stack() ->", stack 1044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao stack = [(wrap_frame(frame), k) for frame, k in stack] 1054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ##print >>sys.__stderr__, "get_stack() ->", stack 1064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return stack, i 1074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def run(self, cmd): 1094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao import __main__ 1104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.idb.run(cmd, __main__.__dict__) 1114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_break(self, filename, lineno): 1134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao msg = self.idb.set_break(filename, lineno) 1144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return msg 1154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def clear_break(self, filename, lineno): 1174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao msg = self.idb.clear_break(filename, lineno) 1184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return msg 1194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def clear_all_file_breaks(self, filename): 1214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao msg = self.idb.clear_all_file_breaks(filename) 1224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return msg 1234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao #----------called by a FrameProxy---------- 1254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def frame_attr(self, fid, name): 1274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao frame = frametable[fid] 1284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return getattr(frame, name) 1294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def frame_globals(self, fid): 1314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao frame = frametable[fid] 1324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao dict = frame.f_globals 1334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao did = id(dict) 1344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao dicttable[did] = dict 1354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return did 1364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def frame_locals(self, fid): 1384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao frame = frametable[fid] 1394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao dict = frame.f_locals 1404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao did = id(dict) 1414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao dicttable[did] = dict 1424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return did 1434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def frame_code(self, fid): 1454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao frame = frametable[fid] 1464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao code = frame.f_code 1474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao cid = id(code) 1484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao codetable[cid] = code 1494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return cid 1504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao #----------called by a CodeProxy---------- 1524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def code_name(self, cid): 1544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao code = codetable[cid] 1554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return code.co_name 1564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def code_filename(self, cid): 1584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao code = codetable[cid] 1594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return code.co_filename 1604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao #----------called by a DictProxy---------- 1624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def dict_keys(self, did): 1644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao dict = dicttable[did] 1654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return dict.keys() 1664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def dict_item(self, did, key): 1684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao dict = dicttable[did] 1694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao value = dict[key] 1704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao value = repr(value) 1714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return value 1724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#----------end class IdbAdapter---------- 1744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef start_debugger(rpchandler, gui_adap_oid): 1774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Start the debugger and its RPC link in the Python subprocess 1784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Start the subprocess side of the split debugger and set up that side of the 1804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao RPC link by instantiating the GUIProxy, Idb debugger, and IdbAdapter 1814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao objects and linking them together. Register the IdbAdapter with the 1824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao RPCServer to handle RPC requests from the split debugger GUI via the 1834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao IdbProxy. 1844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """ 1864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao gui_proxy = GUIProxy(rpchandler, gui_adap_oid) 1874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao idb = Debugger.Idb(gui_proxy) 1884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao idb_adap = IdbAdapter(idb) 1894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao rpchandler.register(idb_adap_oid, idb_adap) 1904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return idb_adap_oid 1914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#======================================= 1944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 1954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# In the IDLE process: 1964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass FrameProxy: 1994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, conn, fid): 2014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._conn = conn 2024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._fid = fid 2034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._oid = "idb_adapter" 2044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._dictcache = {} 2054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __getattr__(self, name): 2074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if name[:1] == "_": 2084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise AttributeError, name 2094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if name == "f_code": 2104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._get_f_code() 2114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if name == "f_globals": 2124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._get_f_globals() 2134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if name == "f_locals": 2144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._get_f_locals() 2154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._conn.remotecall(self._oid, "frame_attr", 2164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (self._fid, name), {}) 2174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def _get_f_code(self): 2194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao cid = self._conn.remotecall(self._oid, "frame_code", (self._fid,), {}) 2204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return CodeProxy(self._conn, self._oid, cid) 2214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def _get_f_globals(self): 2234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao did = self._conn.remotecall(self._oid, "frame_globals", 2244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (self._fid,), {}) 2254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._get_dict_proxy(did) 2264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def _get_f_locals(self): 2284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao did = self._conn.remotecall(self._oid, "frame_locals", 2294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (self._fid,), {}) 2304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._get_dict_proxy(did) 2314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def _get_dict_proxy(self, did): 2334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if did in self._dictcache: 2344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._dictcache[did] 2354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao dp = DictProxy(self._conn, self._oid, did) 2364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._dictcache[did] = dp 2374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return dp 2384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass CodeProxy: 2414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, conn, oid, cid): 2434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._conn = conn 2444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._oid = oid 2454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._cid = cid 2464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __getattr__(self, name): 2484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if name == "co_name": 2494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._conn.remotecall(self._oid, "code_name", 2504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (self._cid,), {}) 2514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if name == "co_filename": 2524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._conn.remotecall(self._oid, "code_filename", 2534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (self._cid,), {}) 2544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass DictProxy: 2574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, conn, oid, did): 2594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._conn = conn 2604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._oid = oid 2614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._did = did 2624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def keys(self): 2644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._conn.remotecall(self._oid, "dict_keys", (self._did,), {}) 2654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __getitem__(self, key): 2674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._conn.remotecall(self._oid, "dict_item", 2684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (self._did, key), {}) 2694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __getattr__(self, name): 2714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ##print >>sys.__stderr__, "failed DictProxy.__getattr__:", name 2724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise AttributeError, name 2734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass GUIAdapter: 2764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, conn, gui): 2784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.conn = conn 2794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.gui = gui 2804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def interaction(self, message, fid, modified_info): 2824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ##print "interaction: (%s, %s, %s)" % (message, fid, modified_info) 2834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao frame = FrameProxy(self.conn, fid) 2844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.gui.interaction(message, frame, modified_info) 2854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass IdbProxy: 2884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, conn, shell, oid): 2904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.oid = oid 2914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.conn = conn 2924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.shell = shell 2934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def call(self, methodname, *args, **kwargs): 2954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ##print "**IdbProxy.call %s %s %s" % (methodname, args, kwargs) 2964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao value = self.conn.remotecall(self.oid, methodname, args, kwargs) 2974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ##print "**IdbProxy.call %s returns %r" % (methodname, value) 2984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return value 2994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def run(self, cmd, locals): 3014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Ignores locals on purpose! 3024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao seq = self.conn.asyncqueue(self.oid, "run", (cmd,), {}) 3034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.shell.interp.active_seq = seq 3044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def get_stack(self, frame, tbid): 3064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # passing frame and traceback IDs, not the objects themselves 3074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao stack, i = self.call("get_stack", frame._fid, tbid) 3084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao stack = [(FrameProxy(self.conn, fid), k) for fid, k in stack] 3094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return stack, i 3104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_continue(self): 3124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.call("set_continue") 3134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_step(self): 3154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.call("set_step") 3164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_next(self, frame): 3184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.call("set_next", frame._fid) 3194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_return(self, frame): 3214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.call("set_return", frame._fid) 3224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_quit(self): 3244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.call("set_quit") 3254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_break(self, filename, lineno): 3274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao msg = self.call("set_break", filename, lineno) 3284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return msg 3294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def clear_break(self, filename, lineno): 3314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao msg = self.call("clear_break", filename, lineno) 3324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return msg 3334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def clear_all_file_breaks(self, filename): 3354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao msg = self.call("clear_all_file_breaks", filename) 3364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return msg 3374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef start_remote_debugger(rpcclt, pyshell): 3394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Start the subprocess debugger, initialize the debugger GUI and RPC link 3404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Request the RPCServer start the Python subprocess debugger and link. Set 3424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao up the Idle side of the split debugger by instantiating the IdbProxy, 3434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao debugger GUI, and debugger GUIAdapter objects and linking them together. 3444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Register the GUIAdapter with the RPCClient to handle debugger GUI 3464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao interaction requests coming from the subprocess debugger via the GUIProxy. 3474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao The IdbAdapter will pass execution and environment requests coming from the 3494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Idle debugger GUI to the subprocess debugger via the IdbProxy. 3504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """ 3524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao global idb_adap_oid 3534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao idb_adap_oid = rpcclt.remotecall("exec", "start_the_debugger",\ 3554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (gui_adap_oid,), {}) 3564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao idb_proxy = IdbProxy(rpcclt, pyshell, idb_adap_oid) 3574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao gui = Debugger.Debugger(pyshell, idb_proxy) 3584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao gui_adap = GUIAdapter(rpcclt, gui) 3594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao rpcclt.register(gui_adap_oid, gui_adap) 3604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return gui 3614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef close_remote_debugger(rpcclt): 3634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Shut down subprocess debugger and Idle side of debugger RPC link 3644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Request that the RPCServer shut down the subprocess debugger and link. 3664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Unregister the GUIAdapter, which will cause a GC on the Idle process 3674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao debugger and RPC link objects. (The second reference to the debugger GUI 3684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao is deleted in PyShell.close_remote_debugger().) 3694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """ 3714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao close_subprocess_debugger(rpcclt) 3724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao rpcclt.unregister(gui_adap_oid) 3734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef close_subprocess_debugger(rpcclt): 3754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao rpcclt.remotecall("exec", "stop_the_debugger", (idb_adap_oid,), {}) 3764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef restart_subprocess_debugger(rpcclt): 3784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao idb_adap_oid_ret = rpcclt.remotecall("exec", "start_the_debugger",\ 3794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (gui_adap_oid,), {}) 3804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao assert idb_adap_oid_ret == idb_adap_oid, 'Idb restarted with different oid' 381