3 ^l/c@sdZddlZddlmZdZdadZiZiZiZ iZ ddZ dd Z Gd d d Z Gd d d ZddZGdddZGdddZGdddZGdddZGdddZddZddZddZd d!Zed"krdd#lmZed$d%d&d'dS)(aSupport for remote Python debugging. Some ASCII art to describe the structure: IN PYTHON SUBPROCESS # IN IDLE PROCESS # # oid='gui_adapter' +----------+ # +------------+ +-----+ | GUIProxy |--remote#call-->| GUIAdapter |--calls-->| GUI | +-----+--calls-->+----------+ # +------------+ +-----+ | Idb | # / +-----+<-calls--+------------+ # +----------+<--calls-/ | IdbAdapter |<--remote#call--| IdbProxy | +------------+ # +----------+ oid='idb_adapter' # The purpose of the Proxy and Adapter classes is to translate certain arguments and return values that cannot be transported through the RPC barrier, in particular frame and traceback objects. N)debugger idb_adapterZ gui_adaptercCst|}|t|<|SN)id frametable)framefidr*/usr/lib64/python3.6/idlelib/debugger_r.py wrap_frame(sr cCsN|dkr dS|d}t|tjs$tt|}|t|<|d|d|f}|SdS)z0replace info[2], a traceback instance, by its IDNr)Z isinstancetypesZ TracebackTypeAssertionErrorrtracebacktable)infoZ tracebackZ traceback_id modified_inforrr wrap_info-src@seZdZddZdddZdS)GUIProxycC||_||_dSr)connoid)selfr gui_adap_oidrrr __init__;zGUIProxy.__init__NcCs&|jj|jd|t|t|fidS)N interaction)r remotecallrr r)rmessagerrrrr r?s zGUIProxy.interactionr__name__ __module__ __qualname__rrrrrr r9rc@seZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ ddZ ddZ ddZddZddZddZdd Zd!d"Zd#d$Zd%d&Zd'd(Zd)S)* IdbAdaptercCs ||_dSr)idb)rr$rrr rHzIdbAdapter.__init__cC|jjdSr)r$set_steprrrr r'Mr%zIdbAdapter.set_stepcCr&r)r$set_quitr(rrr r)Pr%zIdbAdapter.set_quitcCr&r)r$ set_continuer(rrr r*Sr%zIdbAdapter.set_continuecCt|}|jj|dSr)rr$set_nextrrrrrr r,VzIdbAdapter.set_nextcCr+r)rr$ set_returnr-rrr r/Zr.zIdbAdapter.set_returncCsFt|}|dkrd}nt|}|jj||\}}dd|D}||fS)NcSsg|]\}}t||fqSr)r ).0Zframe2krrr ez(IdbAdapter.get_stack..)rrr$ get_stack)rrtbidrZtbstackirrr r4^szIdbAdapter.get_stackcCsddl}|jj||jdS)Nr)__main__r$runZ__dict__)rcmdr8rrr r9hr.zIdbAdapter.runcC|jj||}|Sr)r$ set_breakrfilenameZlinenomsgrrr r<lzIdbAdapter.set_breakcCr;r)r$ clear_breakr=rrr rApr@zIdbAdapter.clear_breakcCs|jj|}|Sr)r$clear_all_file_breaksrr>r?rrr rBt z IdbAdapter.clear_all_file_breakscCst|}t||Sr)rZgetattr)rrnamerrrr frame_attrzr.zIdbAdapter.frame_attrcC"t|}|j}t|}|t|<|Sr)r f_globalsr dicttablerrrdictdidrrr frame_globals~ zIdbAdapter.frame_globalscCrGr)rf_localsrrIrJrrr frame_localsrNzIdbAdapter.frame_localscCrGr)rf_coder codetable)rrrcodecidrrr frame_coderNzIdbAdapter.frame_codecCt|}|jSr)rRco_namerrTrSrrr code_namer.zIdbAdapter.code_namecCrVr)rR co_filenamerXrrr code_filenamer.zIdbAdapter.code_filenamecCs tddS)Nz"dict_keys not public or pickleable)ZNotImplementedErrorrrLrrr dict_keysr%zIdbAdapter.dict_keyscCst|}t|jSr)rIZlistkeys)rrLrKrrr dict_keys_listr.zIdbAdapter.dict_keys_listcCst|}||}t|}|Sr)rIZrepr)rrLkeyrKvaluerrr dict_itemszIdbAdapter.dict_itemN)rr r!rr'r)r*r,r/r4r9r<rArBrFrMrPrUrYr[r]r_rbrrrr r#Fs(  r#cCs,t||}tj|}t|}|jt|tS)a|Start the debugger and its RPC link in the Python subprocess Start the subprocess side of the split debugger and set up that side of the RPC link by instantiating the GUIProxy, Idb debugger, and IdbAdapter objects and linking them together. Register the IdbAdapter with the RPCServer to handle RPC requests from the split debugger GUI via the IdbProxy. )rrZIdbr#register idb_adap_oid)Z rpchandlerrZ gui_proxyr$Zidb_adaprrr start_debuggers   rec@s<eZdZddZddZddZddZd d Zd d Zd S) FrameProxycCs||_||_d|_i|_dS)Nr)_conn_fid_oid _dictcache)rrrrrr rszFrameProxy.__init__cCsb|dddkrt||dkr(|jS|dkr8|jS|dkrH|jS|jj|jd|j|fiS)Nr Z_rQrHrOrF)AttributeError _get_f_code_get_f_globals _get_f_localsrgrrirhrrErrr __getattr__s zFrameProxy.__getattr__cCs(|jj|jd|jfi}t|j|j|S)NrU)rgrrirh CodeProxy)rrTrrr rlszFrameProxy._get_f_codecC"|jj|jd|jfi}|j|S)NrMrgrrirh_get_dict_proxyr\rrr rm  zFrameProxy._get_f_globalscCrr)NrPrsr\rrr rnruzFrameProxy._get_f_localscCs2||jkr|j|St|j|j|}||j|<|Sr)rj DictProxyrgri)rrLZdprrr rts    zFrameProxy._get_dict_proxyN) rr r!rrprlrmrnrtrrrr rfs  rfc@eZdZddZddZdS)rqcC||_||_||_dSr)rgri_cid)rrrrTrrr rzCodeProxy.__init__cCsD|dkr |jj|jd|jfiS|dkr@|jj|jd|jfiSdS)NrWrYrZr[)rgrriryrorrr rps    zCodeProxy.__getattr__N)rr r!rrprrrr rqsrqc@s,eZdZddZddZddZddZd S) rvcCrxr)rgri_did)rrrrLrrr rrzzDictProxy.__init__cCs|jj|jd|jfiS)Nr_rgrrir{r(rrr r^s zDictProxy.keyscCs|jj|jd|j|fiS)Nrbr|)rr`rrr __getitem__rDzDictProxy.__getitem__cCs t|dSr)rkrorrr rpszDictProxy.__getattr__N)rr r!rr^r}rprrrr rvs rvc@rw) GUIAdaptercCrr)rgui)rrrrrr rrzGUIAdapter.__init__cCs t|j|}|jj|||dSr)rfrrr)rrrrrrrr r!s zGUIAdapter.interactionNrrrrr r~r"r~c@sleZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ ddZ ddZ ddZdS)IdbProxycCs||_||_||_dSr)rrshell)rrrrrrr r)rzzIdbProxy.__init__cOs|jj|j|||}|Sr)rrr)rZ methodnameZargsZkwargsrarrr call.sz IdbProxy.callcCs$|jj|jd|fi}||jj_dS)Nr9)rZ asyncqueuerrZinterpZ active_seq)rr:ZlocalsZseqrrr r94sz IdbProxy.runcs.jd|j|\}}fdd|D}||fS)Nr4cs g|]\}}tj||fqSr)rfr)r0rr1r(rr r2<r3z&IdbProxy.get_stack..rrh)rrr5r6r7rr(r r49szIdbProxy.get_stackcC|jddS)Nr*rr(rrr r*?r%zIdbProxy.set_continuecCr)Nr'rr(rrr r'Br%zIdbProxy.set_stepcC|jd|jdS)Nr,rrrrrr r,Er%zIdbProxy.set_nextcCr)Nr/rrrrr r/Hr%zIdbProxy.set_returncCr)Nr)rr(rrr r)Kr%zIdbProxy.set_quitcC|jd||}|S)Nr<rr=rrr r<Nr@zIdbProxy.set_breakcCr)NrArr=rrr rARr@zIdbProxy.clear_breakcCs|jd|}|S)NrBrrCrrr rBVrDzIdbProxy.clear_all_file_breaksN)rr r!rrr9r4r*r'r,r/r)r<rArBrrrr r'srcCsD|jddtfiat||t}tj||}t||}|jt||S)a]Start the subprocess debugger, initialize the debugger GUI and RPC link Request the RPCServer start the Python subprocess debugger and link. Set up the Idle side of the split debugger by instantiating the IdbProxy, debugger GUI, and debugger GUIAdapter objects and linking them together. Register the GUIAdapter with the RPCClient to handle debugger GUI interaction requests coming from the subprocess debugger via the GUIProxy. The IdbAdapter will pass execution and environment requests coming from the Idle debugger GUI to the subprocess debugger via the IdbProxy. execstart_the_debugger)rrrdrrZDebuggerr~rc)rpccltZpyshellZ idb_proxyrZgui_adaprrr start_remote_debuggerZs     rcCst||jtdS)a]Shut down subprocess debugger and Idle side of debugger RPC link Request that the RPCServer shut down the subprocess debugger and link. Unregister the GUIAdapter, which will cause a GC on the Idle process debugger and RPC link objects. (The second reference to the debugger GUI is deleted in pyshell.close_remote_debugger().) N)close_subprocess_debuggerZ unregisterrrrrr close_remote_debuggerrs rcCs|jddtfidS)NrZstop_the_debugger)rrdrrrr r~r%rcCs&|jddtfi}|tks"tddS)Nrrz Idb restarted with different oid)rrrdr)rZidb_adap_oid_retrrr restart_subprocess_debuggers rr8)mainzidlelib.idle_test.test_debuggerr F)Z verbosityZexit)Z__doc__r ZidlelibrZ debuggingrdrrrIrRrr rrr#rerfrqrvr~rrrrrrZunittestrrrrr Zs4   m* 3