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:
Kurt B. Kaiser 2002-06-16 03:32:24 +00:00
parent 0444302710
commit 0e3a57731b
6 changed files with 69 additions and 46 deletions

View File

@ -52,7 +52,7 @@ class Idb(bdb.Bdb):
class Debugger:
interacting = 0
# interacting = 0 # XXX KBK 14Jun02 move to __init__
vstack = vsource = vlocals = vglobals = None
def __init__(self, pyshell, idb=None):
@ -60,7 +60,9 @@ class Debugger:
idb = Idb(self)
self.pyshell = pyshell
self.idb = idb
self.frame = None
self.make_gui()
self.interacting = 0
def run(self, *args):
try:
@ -155,7 +157,7 @@ class Debugger:
if self.vglobals.get():
self.show_globals()
frame = None
# frame = None # XXX KBK 14Jun02 Move to __init__
def interaction(self, message, frame, info=None):
self.frame = frame
@ -300,10 +302,11 @@ class Debugger:
gdict = frame.f_globals
if lv and gv and ldict is gdict:
ldict = None
# Calls OldStackviewer.NamespaceViewer.load_dict():
if lv:
lv.load_dict(ldict, force)
lv.load_dict(ldict, force, self.pyshell.interp.rpcclt)
if gv:
gv.load_dict(gdict, force)
gv.load_dict(gdict, force, self.pyshell.interp.rpcclt)
def set_breakpoint_here(self, edit):
text = edit.text
@ -312,7 +315,7 @@ class Debugger:
text.bell()
return
lineno = int(float(text.index("insert")))
msg = self.set_break(filename, lineno)
msg = self.idb.set_break(filename, lineno)
if msg:
text.bell()
return

View File

@ -232,7 +232,7 @@ class NamespaceViewer:
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:
return
subframe = self.subframe
@ -250,6 +250,10 @@ class NamespaceViewer:
for name in names:
value = dict[name]
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.grid(row=row, column=0, sticky="nw")
## l = Label(subframe, text=svalue, justify="l", wraplength=300)

View File

@ -529,6 +529,9 @@ class PyShell(OutputWindow):
self.set_debugger_indicator()
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:
return self.open_remote_debugger()
import Debugger

View File

@ -24,6 +24,8 @@ import sys
import rpc
import Debugger
debugging = 0
# In the PYTHON subprocess
frametable = {}
@ -43,9 +45,9 @@ def wrap_info(info):
class GUIProxy:
def __init__(self, conn, oid):
def __init__(self, conn, gui_adap_oid):
self.conn = conn
self.oid = oid
self.oid = gui_adap_oid
def interaction(self, message, frame, info=None):
self.conn.remotecall(self.oid, "interaction",
@ -128,24 +130,25 @@ class IdbAdapter:
def dict_item(self, did, key):
dict = dicttable[did]
value = dict[key]
try:
# Test for picklability
import cPickle
cPickle.dumps(value)
except:
value = None
value = repr(value)
# try:
# # Test for picklability
# import cPickle
# pklstr = cPickle.dumps(value)
# except:
# print >>sys.__stderr__, "** dict_item pickle failed: ", value
# raise
# #value = None
return value
def start_debugger(conn, gui_oid):
#
# launched in the python subprocess
#
gui = GUIProxy(conn, gui_oid)
idb = Debugger.Idb(gui)
ada = IdbAdapter(idb)
ada_oid = "idb_adapter"
conn.register(ada_oid, ada)
return ada_oid
def start_debugger(conn, gui_adap_oid):
"Launch debugger in the remote python subprocess"
gui_proxy = GUIProxy(conn, gui_adap_oid)
idb = Debugger.Idb(gui_proxy)
idb_adap = IdbAdapter(idb)
idb_adap_oid = "idb_adapter"
conn.register(idb_adap_oid, idb_adap)
return idb_adap_oid
# In the IDLE process
@ -223,14 +226,14 @@ class DictProxy:
##print >>sys.__stderr__, "failed DictProxy.__getattr__:", name
raise AttributeError, name
class GUIAdaper:
class GUIAdapter:
def __init__(self, conn, gui):
self.conn = conn
self.gui = gui
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)
info = None # XXX for now
self.gui.interaction(message, frame, info)
@ -272,16 +275,23 @@ class IdbProxy:
self.call("set_quit")
def start_remote_debugger(conn, pyshell):
#
# instruct the (remote) subprocess to create
# a debugger instance, and lets it know that
# the local GUIAdapter called "gui_adapter"
# is waiting notification of debugging events
#
ada_oid = "gui_adapter"
idb_oid = conn.remotecall("exec", "start_debugger", (ada_oid,), {})
idb = IdbProxy(conn, idb_oid)
gui = Debugger.Debugger(pyshell, idb)
ada = GUIAdaper(conn, gui)
conn.register(ada_oid, ada)
"""Start the subprocess debugger, initialize the debugger GUI and RPC link
Start the debugger in the remote Python process. Instantiate IdbProxy,
Debugger GUI, and Debugger GUIAdapter objects, and link them together.
The GUIAdapter will 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.
"""
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

View File

@ -119,7 +119,7 @@ class SocketIO:
pass
def localcall(self, request):
##self.debug("localcall:", request)
self.debug("localcall:", request)
try:
how, (oid, methodname, args, kwargs) = request
except TypeError:
@ -165,6 +165,7 @@ class SocketIO:
return ("EXCEPTION", (mod, name, args, tb))
def remotecall(self, oid, methodname, args, kwargs):
self.debug("remotecall:", oid, methodname, args, kwargs)
seq = self.asynccall(oid, methodname, args, kwargs)
return self.asyncreturn(seq)
@ -197,10 +198,12 @@ class SocketIO:
pass
else:
raise getattr(__import__(mod), name)(*args)
else:
if mod:
name = mod + "." + name
raise name, args
# XXX KBK 15Jun02 mod is False here, also want to raise remaining exceptions
# else:
# if mod:
# name = mod + "." + name
# raise name, args
raise name, args
if how == "ERROR":
raise RuntimeError, what
raise SystemError, (how, what)

View File

@ -30,9 +30,9 @@ class Executive:
def runcode(self, code):
exec code in self.locals
def start_debugger(self, gui_oid):
def start_the_debugger(self, gui_adap_oid):
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):
if not hasattr(sys, "last_traceback"):