Commit 0e3a5773 authored by Kurt B. Kaiser's avatar Kurt B. Kaiser

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.
parent 04443027
...@@ -52,7 +52,7 @@ class Idb(bdb.Bdb): ...@@ -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,7 +60,9 @@ class Debugger: ...@@ -60,7 +60,9 @@ 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:
...@@ -155,7 +157,7 @@ class Debugger: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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): ...@@ -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 ...@@ -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): ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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,9 +198,11 @@ class SocketIO: ...@@ -197,9 +198,11 @@ 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:
# name = mod + "." + name
# raise name, args
raise name, args raise name, args
if how == "ERROR": if how == "ERROR":
raise RuntimeError, what raise RuntimeError, what
......
...@@ -30,9 +30,9 @@ class Executive: ...@@ -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"):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment