mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Polish RemoteDebugger code.
Use a repr() on the subprocess side when fetching dict values for stack. The various dict entities are not needed by the debugger GUI, only their representation.
This commit is contained in:
parent
0444302710
commit
0e3a57731b
6 changed files with 69 additions and 46 deletions
|
@ -52,7 +52,7 @@ class Idb(bdb.Bdb):
|
||||||
|
|
||||||
class Debugger:
|
class Debugger:
|
||||||
|
|
||||||
interacting = 0
|
# interacting = 0 # XXX KBK 14Jun02 move to __init__
|
||||||
vstack = vsource = vlocals = vglobals = None
|
vstack = vsource = vlocals = vglobals = None
|
||||||
|
|
||||||
def __init__(self, pyshell, idb=None):
|
def __init__(self, pyshell, idb=None):
|
||||||
|
@ -60,8 +60,10 @@ class Debugger:
|
||||||
idb = Idb(self)
|
idb = Idb(self)
|
||||||
self.pyshell = pyshell
|
self.pyshell = pyshell
|
||||||
self.idb = idb
|
self.idb = idb
|
||||||
|
self.frame = None
|
||||||
self.make_gui()
|
self.make_gui()
|
||||||
|
self.interacting = 0
|
||||||
|
|
||||||
def run(self, *args):
|
def run(self, *args):
|
||||||
try:
|
try:
|
||||||
self.interacting = 1
|
self.interacting = 1
|
||||||
|
@ -155,7 +157,7 @@ class Debugger:
|
||||||
if self.vglobals.get():
|
if self.vglobals.get():
|
||||||
self.show_globals()
|
self.show_globals()
|
||||||
|
|
||||||
frame = None
|
# frame = None # XXX KBK 14Jun02 Move to __init__
|
||||||
|
|
||||||
def interaction(self, message, frame, info=None):
|
def interaction(self, message, frame, info=None):
|
||||||
self.frame = frame
|
self.frame = frame
|
||||||
|
@ -300,10 +302,11 @@ class Debugger:
|
||||||
gdict = frame.f_globals
|
gdict = frame.f_globals
|
||||||
if lv and gv and ldict is gdict:
|
if lv and gv and ldict is gdict:
|
||||||
ldict = None
|
ldict = None
|
||||||
|
# Calls OldStackviewer.NamespaceViewer.load_dict():
|
||||||
if lv:
|
if lv:
|
||||||
lv.load_dict(ldict, force)
|
lv.load_dict(ldict, force, self.pyshell.interp.rpcclt)
|
||||||
if gv:
|
if gv:
|
||||||
gv.load_dict(gdict, force)
|
gv.load_dict(gdict, force, self.pyshell.interp.rpcclt)
|
||||||
|
|
||||||
def set_breakpoint_here(self, edit):
|
def set_breakpoint_here(self, edit):
|
||||||
text = edit.text
|
text = edit.text
|
||||||
|
@ -312,7 +315,7 @@ class Debugger:
|
||||||
text.bell()
|
text.bell()
|
||||||
return
|
return
|
||||||
lineno = int(float(text.index("insert")))
|
lineno = int(float(text.index("insert")))
|
||||||
msg = self.set_break(filename, lineno)
|
msg = self.idb.set_break(filename, lineno)
|
||||||
if msg:
|
if msg:
|
||||||
text.bell()
|
text.bell()
|
||||||
return
|
return
|
||||||
|
|
|
@ -232,7 +232,7 @@ class NamespaceViewer:
|
||||||
|
|
||||||
dict = -1
|
dict = -1
|
||||||
|
|
||||||
def load_dict(self, dict, force=0):
|
def load_dict(self, dict, force=0, rpc_client=None):
|
||||||
if dict is self.dict and not force:
|
if dict is self.dict and not force:
|
||||||
return
|
return
|
||||||
subframe = self.subframe
|
subframe = self.subframe
|
||||||
|
@ -250,6 +250,10 @@ class NamespaceViewer:
|
||||||
for name in names:
|
for name in names:
|
||||||
value = dict[name]
|
value = dict[name]
|
||||||
svalue = self.repr.repr(value) # repr(value)
|
svalue = self.repr.repr(value) # repr(value)
|
||||||
|
# Strip extra quotes caused by calling repr on the (already)
|
||||||
|
# repr'd value sent across the RPC interface:
|
||||||
|
if rpc_client:
|
||||||
|
svalue = svalue[1:-1]
|
||||||
l = Label(subframe, text=name)
|
l = Label(subframe, text=name)
|
||||||
l.grid(row=row, column=0, sticky="nw")
|
l.grid(row=row, column=0, sticky="nw")
|
||||||
## l = Label(subframe, text=svalue, justify="l", wraplength=300)
|
## l = Label(subframe, text=svalue, justify="l", wraplength=300)
|
||||||
|
|
|
@ -529,6 +529,9 @@ class PyShell(OutputWindow):
|
||||||
self.set_debugger_indicator()
|
self.set_debugger_indicator()
|
||||||
|
|
||||||
def open_debugger(self):
|
def open_debugger(self):
|
||||||
|
# XXX KBK 13Jun02 An RPC client always exists now? Open remote
|
||||||
|
# debugger and return...dike the rest of this fcn and combine
|
||||||
|
# with open_remote_debugger?
|
||||||
if self.interp.rpcclt:
|
if self.interp.rpcclt:
|
||||||
return self.open_remote_debugger()
|
return self.open_remote_debugger()
|
||||||
import Debugger
|
import Debugger
|
||||||
|
|
|
@ -24,6 +24,8 @@ import sys
|
||||||
import rpc
|
import rpc
|
||||||
import Debugger
|
import Debugger
|
||||||
|
|
||||||
|
debugging = 0
|
||||||
|
|
||||||
# In the PYTHON subprocess
|
# In the PYTHON subprocess
|
||||||
|
|
||||||
frametable = {}
|
frametable = {}
|
||||||
|
@ -43,9 +45,9 @@ def wrap_info(info):
|
||||||
|
|
||||||
class GUIProxy:
|
class GUIProxy:
|
||||||
|
|
||||||
def __init__(self, conn, oid):
|
def __init__(self, conn, gui_adap_oid):
|
||||||
self.conn = conn
|
self.conn = conn
|
||||||
self.oid = oid
|
self.oid = gui_adap_oid
|
||||||
|
|
||||||
def interaction(self, message, frame, info=None):
|
def interaction(self, message, frame, info=None):
|
||||||
self.conn.remotecall(self.oid, "interaction",
|
self.conn.remotecall(self.oid, "interaction",
|
||||||
|
@ -128,24 +130,25 @@ class IdbAdapter:
|
||||||
def dict_item(self, did, key):
|
def dict_item(self, did, key):
|
||||||
dict = dicttable[did]
|
dict = dicttable[did]
|
||||||
value = dict[key]
|
value = dict[key]
|
||||||
try:
|
value = repr(value)
|
||||||
# Test for picklability
|
# try:
|
||||||
import cPickle
|
# # Test for picklability
|
||||||
cPickle.dumps(value)
|
# import cPickle
|
||||||
except:
|
# pklstr = cPickle.dumps(value)
|
||||||
value = None
|
# except:
|
||||||
|
# print >>sys.__stderr__, "** dict_item pickle failed: ", value
|
||||||
|
# raise
|
||||||
|
# #value = None
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def start_debugger(conn, gui_oid):
|
def start_debugger(conn, gui_adap_oid):
|
||||||
#
|
"Launch debugger in the remote python subprocess"
|
||||||
# launched in the python subprocess
|
gui_proxy = GUIProxy(conn, gui_adap_oid)
|
||||||
#
|
idb = Debugger.Idb(gui_proxy)
|
||||||
gui = GUIProxy(conn, gui_oid)
|
idb_adap = IdbAdapter(idb)
|
||||||
idb = Debugger.Idb(gui)
|
idb_adap_oid = "idb_adapter"
|
||||||
ada = IdbAdapter(idb)
|
conn.register(idb_adap_oid, idb_adap)
|
||||||
ada_oid = "idb_adapter"
|
return idb_adap_oid
|
||||||
conn.register(ada_oid, ada)
|
|
||||||
return ada_oid
|
|
||||||
|
|
||||||
# In the IDLE process
|
# In the IDLE process
|
||||||
|
|
||||||
|
@ -223,14 +226,14 @@ class DictProxy:
|
||||||
##print >>sys.__stderr__, "failed DictProxy.__getattr__:", name
|
##print >>sys.__stderr__, "failed DictProxy.__getattr__:", name
|
||||||
raise AttributeError, name
|
raise AttributeError, name
|
||||||
|
|
||||||
class GUIAdaper:
|
class GUIAdapter:
|
||||||
|
|
||||||
def __init__(self, conn, gui):
|
def __init__(self, conn, gui):
|
||||||
self.conn = conn
|
self.conn = conn
|
||||||
self.gui = gui
|
self.gui = gui
|
||||||
|
|
||||||
def interaction(self, message, fid, iid):
|
def interaction(self, message, fid, iid):
|
||||||
print "interaction(%s, %s, %s)" % (`message`, `fid`, `iid`)
|
##print "interaction: (%s, %s, %s)" % (`message`,`fid`, `iid`)
|
||||||
frame = FrameProxy(self.conn, fid)
|
frame = FrameProxy(self.conn, fid)
|
||||||
info = None # XXX for now
|
info = None # XXX for now
|
||||||
self.gui.interaction(message, frame, info)
|
self.gui.interaction(message, frame, info)
|
||||||
|
@ -272,16 +275,23 @@ class IdbProxy:
|
||||||
self.call("set_quit")
|
self.call("set_quit")
|
||||||
|
|
||||||
def start_remote_debugger(conn, pyshell):
|
def start_remote_debugger(conn, pyshell):
|
||||||
#
|
"""Start the subprocess debugger, initialize the debugger GUI and RPC link
|
||||||
# instruct the (remote) subprocess to create
|
|
||||||
# a debugger instance, and lets it know that
|
Start the debugger in the remote Python process. Instantiate IdbProxy,
|
||||||
# the local GUIAdapter called "gui_adapter"
|
Debugger GUI, and Debugger GUIAdapter objects, and link them together.
|
||||||
# is waiting notification of debugging events
|
|
||||||
#
|
The GUIAdapter will handle debugger GUI interaction requests coming from
|
||||||
ada_oid = "gui_adapter"
|
the subprocess debugger via the GUIProxy.
|
||||||
idb_oid = conn.remotecall("exec", "start_debugger", (ada_oid,), {})
|
|
||||||
idb = IdbProxy(conn, idb_oid)
|
The IdbAdapter will pass execution and environment requests coming from the
|
||||||
gui = Debugger.Debugger(pyshell, idb)
|
Idle debugger GUI to the subprocess debugger via the IdbProxy.
|
||||||
ada = GUIAdaper(conn, gui)
|
|
||||||
conn.register(ada_oid, ada)
|
"""
|
||||||
|
gui_adap_oid = "gui_adapter"
|
||||||
|
idb_adap_oid = conn.remotecall("exec", "start_the_debugger",\
|
||||||
|
(gui_adap_oid,), {})
|
||||||
|
idb_proxy = IdbProxy(conn, idb_adap_oid)
|
||||||
|
gui = Debugger.Debugger(pyshell, idb_proxy)
|
||||||
|
gui_adap = GUIAdapter(conn, gui)
|
||||||
|
conn.register(gui_adap_oid, gui_adap)
|
||||||
return gui
|
return gui
|
||||||
|
|
|
@ -119,7 +119,7 @@ class SocketIO:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def localcall(self, request):
|
def localcall(self, request):
|
||||||
##self.debug("localcall:", request)
|
self.debug("localcall:", request)
|
||||||
try:
|
try:
|
||||||
how, (oid, methodname, args, kwargs) = request
|
how, (oid, methodname, args, kwargs) = request
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -165,6 +165,7 @@ class SocketIO:
|
||||||
return ("EXCEPTION", (mod, name, args, tb))
|
return ("EXCEPTION", (mod, name, args, tb))
|
||||||
|
|
||||||
def remotecall(self, oid, methodname, args, kwargs):
|
def remotecall(self, oid, methodname, args, kwargs):
|
||||||
|
self.debug("remotecall:", oid, methodname, args, kwargs)
|
||||||
seq = self.asynccall(oid, methodname, args, kwargs)
|
seq = self.asynccall(oid, methodname, args, kwargs)
|
||||||
return self.asyncreturn(seq)
|
return self.asyncreturn(seq)
|
||||||
|
|
||||||
|
@ -197,10 +198,12 @@ class SocketIO:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise getattr(__import__(mod), name)(*args)
|
raise getattr(__import__(mod), name)(*args)
|
||||||
else:
|
# XXX KBK 15Jun02 mod is False here, also want to raise remaining exceptions
|
||||||
if mod:
|
# else:
|
||||||
name = mod + "." + name
|
# if mod:
|
||||||
raise name, args
|
# name = mod + "." + name
|
||||||
|
# raise name, args
|
||||||
|
raise name, args
|
||||||
if how == "ERROR":
|
if how == "ERROR":
|
||||||
raise RuntimeError, what
|
raise RuntimeError, what
|
||||||
raise SystemError, (how, what)
|
raise SystemError, (how, what)
|
||||||
|
|
|
@ -30,9 +30,9 @@ class Executive:
|
||||||
def runcode(self, code):
|
def runcode(self, code):
|
||||||
exec code in self.locals
|
exec code in self.locals
|
||||||
|
|
||||||
def start_debugger(self, gui_oid):
|
def start_the_debugger(self, gui_adap_oid):
|
||||||
import RemoteDebugger
|
import RemoteDebugger
|
||||||
return RemoteDebugger.start_debugger(self.conn, gui_oid)
|
return RemoteDebugger.start_debugger(self.conn, gui_adap_oid)
|
||||||
|
|
||||||
def stackviewer(self, flist_oid=None):
|
def stackviewer(self, flist_oid=None):
|
||||||
if not hasattr(sys, "last_traceback"):
|
if not hasattr(sys, "last_traceback"):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue