183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""Support for remote Python debugging. 283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehSome ASCII art to describe the structure: 483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh IN PYTHON SUBPROCESS # IN IDLE PROCESS 683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # oid='gui_adapter' 883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh +----------+ # +------------+ +-----+ 983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh | GUIProxy |--remote#call-->| GUIAdapter |--calls-->| GUI | 1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh+-----+--calls-->+----------+ # +------------+ +-----+ 1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh| Idb | # / 1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh+-----+<-calls--+------------+ # +----------+<--calls-/ 1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh | IdbAdapter |<--remote#call--| IdbProxy | 1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh +------------+ # +----------+ 1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh oid='idb_adapter' # 1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThe purpose of the Proxy and Adapter classes is to translate certain 1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieharguments and return values that cannot be transported through the RPC 1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehbarrier, in particular frame and traceback objects. 2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh""" 2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport types 2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib import rpc 2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib import Debugger 2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdebugging = 0 2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehidb_adap_oid = "idb_adapter" 3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehgui_adap_oid = "gui_adapter" 3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#======================================= 3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# In the PYTHON subprocess: 3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehframetable = {} 3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdicttable = {} 3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehcodetable = {} 3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehtracebacktable = {} 4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef wrap_frame(frame): 4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh fid = id(frame) 4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh frametable[fid] = frame 4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return fid 4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef wrap_info(info): 4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "replace info[2], a traceback instance, by its ID" 4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if info is None: 4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return None 5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh traceback = info[2] 5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh assert isinstance(traceback, types.TracebackType) 5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh traceback_id = id(traceback) 5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh tracebacktable[traceback_id] = traceback 5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh modified_info = (info[0], info[1], traceback_id) 5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return modified_info 5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass GUIProxy: 5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, conn, gui_adap_oid): 6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.conn = conn 6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.oid = gui_adap_oid 6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def interaction(self, message, frame, info=None): 6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # calls rpc.SocketIO.remotecall() via run.MyHandler instance 6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # pass frame and traceback object IDs instead of the objects themselves 6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.conn.remotecall(self.oid, "interaction", 6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (message, wrap_frame(frame), wrap_info(info)), 6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh {}) 7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass IdbAdapter: 7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, idb): 7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.idb = idb 7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh #----------called by an IdbProxy---------- 7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_step(self): 7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.idb.set_step() 8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_quit(self): 8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.idb.set_quit() 8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_continue(self): 8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.idb.set_continue() 8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_next(self, fid): 8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh frame = frametable[fid] 8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.idb.set_next(frame) 9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_return(self, fid): 9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh frame = frametable[fid] 9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.idb.set_return(frame) 9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def get_stack(self, fid, tbid): 9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ##print >>sys.__stderr__, "get_stack(%r, %r)" % (fid, tbid) 9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh frame = frametable[fid] 9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if tbid is None: 9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh tb = None 10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh tb = tracebacktable[tbid] 10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh stack, i = self.idb.get_stack(frame, tb) 10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ##print >>sys.__stderr__, "get_stack() ->", stack 10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh stack = [(wrap_frame(frame), k) for frame, k in stack] 10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ##print >>sys.__stderr__, "get_stack() ->", stack 10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return stack, i 10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def run(self, cmd): 10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import __main__ 11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.idb.run(cmd, __main__.__dict__) 11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_break(self, filename, lineno): 11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh msg = self.idb.set_break(filename, lineno) 11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return msg 11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def clear_break(self, filename, lineno): 11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh msg = self.idb.clear_break(filename, lineno) 11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return msg 11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def clear_all_file_breaks(self, filename): 12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh msg = self.idb.clear_all_file_breaks(filename) 12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return msg 12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh #----------called by a FrameProxy---------- 12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def frame_attr(self, fid, name): 12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh frame = frametable[fid] 12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return getattr(frame, name) 12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def frame_globals(self, fid): 13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh frame = frametable[fid] 13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dict = frame.f_globals 13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh did = id(dict) 13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dicttable[did] = dict 13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return did 13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def frame_locals(self, fid): 13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh frame = frametable[fid] 13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dict = frame.f_locals 14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh did = id(dict) 14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dicttable[did] = dict 14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return did 14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 14483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def frame_code(self, fid): 14583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh frame = frametable[fid] 14683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh code = frame.f_code 14783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cid = id(code) 14883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh codetable[cid] = code 14983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return cid 15083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 15183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh #----------called by a CodeProxy---------- 15283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 15383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def code_name(self, cid): 15483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh code = codetable[cid] 15583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return code.co_name 15683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 15783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def code_filename(self, cid): 15883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh code = codetable[cid] 15983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return code.co_filename 16083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 16183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh #----------called by a DictProxy---------- 16283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 16383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def dict_keys(self, did): 16483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dict = dicttable[did] 16583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return dict.keys() 16683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 16783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def dict_item(self, did, key): 16883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dict = dicttable[did] 16983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh value = dict[key] 17083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh value = repr(value) 17183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return value 17283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 17383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#----------end class IdbAdapter---------- 17483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 17583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 17683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef start_debugger(rpchandler, gui_adap_oid): 17783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Start the debugger and its RPC link in the Python subprocess 17883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 17983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Start the subprocess side of the split debugger and set up that side of the 18083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh RPC link by instantiating the GUIProxy, Idb debugger, and IdbAdapter 18183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh objects and linking them together. Register the IdbAdapter with the 18283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh RPCServer to handle RPC requests from the split debugger GUI via the 18383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh IdbProxy. 18483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 18583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 18683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh gui_proxy = GUIProxy(rpchandler, gui_adap_oid) 18783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh idb = Debugger.Idb(gui_proxy) 18883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh idb_adap = IdbAdapter(idb) 18983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh rpchandler.register(idb_adap_oid, idb_adap) 19083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return idb_adap_oid 19183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 19283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 19383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh#======================================= 19483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 19583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# In the IDLE process: 19683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 19783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 19883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass FrameProxy: 19983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 20083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, conn, fid): 20183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._conn = conn 20283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._fid = fid 20383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._oid = "idb_adapter" 20483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._dictcache = {} 20583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 20683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __getattr__(self, name): 20783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if name[:1] == "_": 20883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise AttributeError, name 20983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if name == "f_code": 21083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._get_f_code() 21183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if name == "f_globals": 21283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._get_f_globals() 21383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if name == "f_locals": 21483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._get_f_locals() 21583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._conn.remotecall(self._oid, "frame_attr", 21683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (self._fid, name), {}) 21783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 21883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _get_f_code(self): 21983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cid = self._conn.remotecall(self._oid, "frame_code", (self._fid,), {}) 22083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return CodeProxy(self._conn, self._oid, cid) 22183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 22283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _get_f_globals(self): 22383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh did = self._conn.remotecall(self._oid, "frame_globals", 22483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (self._fid,), {}) 22583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._get_dict_proxy(did) 22683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 22783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _get_f_locals(self): 22883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh did = self._conn.remotecall(self._oid, "frame_locals", 22983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (self._fid,), {}) 23083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._get_dict_proxy(did) 23183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 23283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _get_dict_proxy(self, did): 23383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if did in self._dictcache: 23483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._dictcache[did] 23583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dp = DictProxy(self._conn, self._oid, did) 23683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._dictcache[did] = dp 23783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return dp 23883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 23983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 24083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass CodeProxy: 24183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 24283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, conn, oid, cid): 24383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._conn = conn 24483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._oid = oid 24583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._cid = cid 24683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 24783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __getattr__(self, name): 24883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if name == "co_name": 24983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._conn.remotecall(self._oid, "code_name", 25083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (self._cid,), {}) 25183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if name == "co_filename": 25283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._conn.remotecall(self._oid, "code_filename", 25383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (self._cid,), {}) 25483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 25583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 25683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass DictProxy: 25783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 25883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, conn, oid, did): 25983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._conn = conn 26083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._oid = oid 26183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._did = did 26283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 26383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def keys(self): 26483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._conn.remotecall(self._oid, "dict_keys", (self._did,), {}) 26583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 26683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __getitem__(self, key): 26783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._conn.remotecall(self._oid, "dict_item", 26883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (self._did, key), {}) 26983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 27083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __getattr__(self, name): 27183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ##print >>sys.__stderr__, "failed DictProxy.__getattr__:", name 27283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise AttributeError, name 27383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 27483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 27583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass GUIAdapter: 27683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 27783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, conn, gui): 27883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.conn = conn 27983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.gui = gui 28083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 28183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def interaction(self, message, fid, modified_info): 28283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ##print "interaction: (%s, %s, %s)" % (message, fid, modified_info) 28383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh frame = FrameProxy(self.conn, fid) 28483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.gui.interaction(message, frame, modified_info) 28583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 28683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 28783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass IdbProxy: 28883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 28983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, conn, shell, oid): 29083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.oid = oid 29183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.conn = conn 29283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.shell = shell 29383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 29483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def call(self, methodname, *args, **kwargs): 29583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ##print "**IdbProxy.call %s %s %s" % (methodname, args, kwargs) 29683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh value = self.conn.remotecall(self.oid, methodname, args, kwargs) 29783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ##print "**IdbProxy.call %s returns %r" % (methodname, value) 29883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return value 29983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 30083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def run(self, cmd, locals): 30183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Ignores locals on purpose! 30283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh seq = self.conn.asyncqueue(self.oid, "run", (cmd,), {}) 30383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.shell.interp.active_seq = seq 30483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 30583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def get_stack(self, frame, tbid): 30683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # passing frame and traceback IDs, not the objects themselves 30783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh stack, i = self.call("get_stack", frame._fid, tbid) 30883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh stack = [(FrameProxy(self.conn, fid), k) for fid, k in stack] 30983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return stack, i 31083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 31183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_continue(self): 31283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.call("set_continue") 31383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 31483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_step(self): 31583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.call("set_step") 31683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 31783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_next(self, frame): 31883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.call("set_next", frame._fid) 31983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 32083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_return(self, frame): 32183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.call("set_return", frame._fid) 32283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 32383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_quit(self): 32483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.call("set_quit") 32583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 32683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def set_break(self, filename, lineno): 32783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh msg = self.call("set_break", filename, lineno) 32883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return msg 32983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 33083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def clear_break(self, filename, lineno): 33183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh msg = self.call("clear_break", filename, lineno) 33283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return msg 33383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 33483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def clear_all_file_breaks(self, filename): 33583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh msg = self.call("clear_all_file_breaks", filename) 33683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return msg 33783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 33883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef start_remote_debugger(rpcclt, pyshell): 33983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Start the subprocess debugger, initialize the debugger GUI and RPC link 34083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 34183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Request the RPCServer start the Python subprocess debugger and link. Set 34283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh up the Idle side of the split debugger by instantiating the IdbProxy, 34383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh debugger GUI, and debugger GUIAdapter objects and linking them together. 34483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 34583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Register the GUIAdapter with the RPCClient to handle debugger GUI 34683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh interaction requests coming from the subprocess debugger via the GUIProxy. 34783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 34883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh The IdbAdapter will pass execution and environment requests coming from the 34983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Idle debugger GUI to the subprocess debugger via the IdbProxy. 35083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 35183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 35283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh global idb_adap_oid 35383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 35483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh idb_adap_oid = rpcclt.remotecall("exec", "start_the_debugger",\ 35583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (gui_adap_oid,), {}) 35683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh idb_proxy = IdbProxy(rpcclt, pyshell, idb_adap_oid) 35783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh gui = Debugger.Debugger(pyshell, idb_proxy) 35883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh gui_adap = GUIAdapter(rpcclt, gui) 35983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh rpcclt.register(gui_adap_oid, gui_adap) 36083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return gui 36183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 36283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef close_remote_debugger(rpcclt): 36383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Shut down subprocess debugger and Idle side of debugger RPC link 36483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 36583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Request that the RPCServer shut down the subprocess debugger and link. 36683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Unregister the GUIAdapter, which will cause a GC on the Idle process 36783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh debugger and RPC link objects. (The second reference to the debugger GUI 36883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh is deleted in PyShell.close_remote_debugger().) 36983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 37083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 37183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh close_subprocess_debugger(rpcclt) 37283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh rpcclt.unregister(gui_adap_oid) 37383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 37483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef close_subprocess_debugger(rpcclt): 37583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh rpcclt.remotecall("exec", "stop_the_debugger", (idb_adap_oid,), {}) 37683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 37783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef restart_subprocess_debugger(rpcclt): 37883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh idb_adap_oid_ret = rpcclt.remotecall("exec", "start_the_debugger",\ 37983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (gui_adap_oid,), {}) 38083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh assert idb_adap_oid_ret == idb_adap_oid, 'Idb restarted with different oid' 381