[Idle-dev] CVS: idle Debugger.py,1.13,1.14 EditorWindow.py,1.34,1.35 PyShell.py,1.29,1.30

Kurt B. Kaiser kbk@users.sourceforge.net
Tue, 22 Oct 2002 21:48:10 -0700


Update of /cvsroot/idlefork/idle
In directory usw-pr-cvs1:/tmp/cvs-serv24387

Modified Files:
	Debugger.py EditorWindow.py PyShell.py 
Log Message:
Implement Restoring Breakpoints in Subprocess Debugger

M Debugger.py
M EditorWindow.py
M PyShell.py

0. Polish PyShell.linecache_checkcache()
1. Move break clearing code to PyShell.PyShellEditorWindow from 
   EditorWindow.
2. Add PyShellEditorWindow.breakpoints attribute to __init__, a list of
   line numbers which are breakpoints for that edit window.
3. Remove the code in Debugger which removes all module breakpoints when
   debugger is closed.  Want to be able to reload into debugger when
   restarted.
4. Moved the code which sets EditorWindow.text breakpoints from Debugger
   to PyShell.PyShellEditorWindow and refactored.
5. Implement reloading subprocess debugger with breakpoints from all open
   PyShellEditorWindows when debugger is opened or subprocess restarted.
6. Eliminate the break_set attribute, use the breakpoint list instead.



Index: Debugger.py
===================================================================
RCS file: /cvsroot/idlefork/idle/Debugger.py,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -r1.13 -r1.14
*** Debugger.py	16 Sep 2002 01:06:52 -0000	1.13
--- Debugger.py	23 Oct 2002 04:48:08 -0000	1.14
***************
*** 78,86 ****
          if self.stackviewer:
              self.stackviewer.close(); self.stackviewer = None
-         # Remove all EditWindow BREAK tags when closing debugger:
-         edit_windows = self.pyshell.flist.inversedict.keys()
-         for window in edit_windows:
-             window.text.tag_remove("BREAK", 1.0, END)
-             window.break_set = False
          # Clean up pyshell if user clicked debugger control close widget.
          # (Causes a harmless extra cycle through close_debugger() if user
--- 78,81 ----
***************
*** 312,357 ****
              gv.load_dict(gdict, force, self.pyshell.interp.rpcclt)
  
!     def set_breakpoint_here(self, edit):
!         text = edit.text
!         filename = edit.io.filename
!         if not filename:
!             text.bell()
!             return
!         lineno = int(float(text.index("insert")))
          msg = self.idb.set_break(filename, lineno)
          if msg:
              text.bell()
              return
-         text.tag_add("BREAK", "insert linestart", "insert lineend +1char")
-         edit.break_set = True
  
!     def clear_breakpoint_here(self, edit):
!         text = edit.text
!         filename = edit.io.filename
!         if not filename:
!             text.bell()
!             return
!         lineno = int(float(text.index("insert")))
          msg = self.idb.clear_break(filename, lineno)
          if msg:
              text.bell()
              return
!         text.tag_remove("BREAK", "insert linestart",\
!                         "insert lineend +1char")
!         # Don't bother to track break_set status
! 
!     def clear_file_breaks(self, edit):
!         text = edit.text
!         filename = edit.io.filename
!         if not filename:
!             text.bell()
!             return
          msg = self.idb.clear_all_file_breaks(filename)
          if msg:
              text.bell()
              return
-         text.tag_remove("BREAK", "1.0", END)
-         edit.break_set = False
  
  
  class StackViewer(ScrolledList):
--- 307,338 ----
              gv.load_dict(gdict, force, self.pyshell.interp.rpcclt)
  
!     def set_breakpoint_here(self, filename, lineno):
          msg = self.idb.set_break(filename, lineno)
          if msg:
              text.bell()
              return
  
!     def clear_breakpoint_here(self, filename, lineno):
          msg = self.idb.clear_break(filename, lineno)
          if msg:
              text.bell()
              return
! 
!     def clear_file_breaks(self, filename):
          msg = self.idb.clear_all_file_breaks(filename)
          if msg:
              text.bell()
              return
  
+     def load_breakpoints(self):
+         "Load PyShellEditorWindow breakpoints into subprocess debugger"
+         pyshell_edit_windows = self.pyshell.flist.inversedict.keys()
+         for editwin in pyshell_edit_windows:
+             filename = editwin.io.filename
+             try:
+                 for lineno in editwin.breakpoints:
+                     self.set_breakpoint_here(filename, lineno)
+             except AttributeError:
+                 continue
  
  class StackViewer(ScrolledList):

Index: EditorWindow.py
===================================================================
RCS file: /cvsroot/idlefork/idle/EditorWindow.py,v
retrieving revision 1.34
retrieving revision 1.35
diff -C2 -r1.34 -r1.35
*** EditorWindow.py	6 Oct 2002 01:57:45 -0000	1.34
--- EditorWindow.py	23 Oct 2002 04:48:08 -0000	1.35
***************
*** 59,63 ****
          self.recentFilesPath=os.path.join(idleConf.GetUserCfgDir(),
                  'recent-files.lst')
-         self.break_set = False
          self.vbar = vbar = Scrollbar(top, name='vbar')
          self.text_frame = text_frame = Frame(top)
--- 59,62 ----
***************
*** 626,632 ****
              title = "*%s*" % title
              icon = "*%s" % icon
-             if self.break_set:
-                 shell = self.flist.pyshell 
-                 shell.interp.debugger.clear_file_breaks(self)
          self.top.wm_title(title)
          self.top.wm_iconname(icon)
--- 625,628 ----
***************
*** 697,703 ****
          if self.io.filename:
              self.UpdateRecentFilesList(newFile=self.io.filename)
-         if self.break_set:
-             shell = self.flist.pyshell
-             shell.interp.debugger.clear_file_breaks(self)
          WindowList.unregister_callback(self.postwindowsmenu)
          if self.close_hook:
--- 693,696 ----

Index: PyShell.py
===================================================================
RCS file: /cvsroot/idlefork/idle/PyShell.py,v
retrieving revision 1.29
retrieving revision 1.30
diff -C2 -r1.29 -r1.30
*** PyShell.py	10 Oct 2002 08:25:24 -0000	1.29
--- PyShell.py	23 Oct 2002 04:48:08 -0000	1.30
***************
*** 45,53 ****
      warnings.showwarning = idle_showwarning
  
! # We need to patch linecache.checkcache, because we don't want it
! # to throw away our <pyshell#...> entries.
! # Rather than repeating its code here, we save those entries,
! # then call the original function, and then restore the saved entries.
! def linecache_checkcache(orig_checkcache=linecache.checkcache):
      cache = linecache.cache
      save = {}
--- 45,57 ----
      warnings.showwarning = idle_showwarning
  
! def linecache_checkcache():
!     """Extend linecache.checkcache to preserve the <pyshell#...> entries
! 
!     Rather than repeating the linecache code, patch it by saving the pyshell#
!     entries, call linecache.checkcache(), and then restore the saved
!     entries.
! 
!     """
!     orig_checkcache=linecache.checkcache
      cache = linecache.cache
      save = {}
***************
*** 57,90 ****
      orig_checkcache()
      cache.update(save)
  linecache.checkcache = linecache_checkcache
  
  class PyShellEditorWindow(EditorWindow):
      "Regular text edit window when a shell is present"
!     # XXX ought to merge with regular editor window
  
      def __init__(self, *args):
          apply(EditorWindow.__init__, (self,) + args)
          self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
!         self.text.bind("<<clear-breakpoint-here>>",
!                        self.clear_breakpoint_here)
          self.text.bind("<<open-python-shell>>", self.flist.open_shell)
  
!     rmenu_specs = [
!         ("Set Breakpoint", "<<set-breakpoint-here>>"),
!         ("Clear Breakpoint", "<<clear-breakpoint-here>>")
!     ]
  
      def set_breakpoint_here(self, event=None):
!         if not self.flist.pyshell or not self.flist.pyshell.interp.debugger:
!             self.text.bell()
              return
!         self.flist.pyshell.interp.debugger.set_breakpoint_here(self)
  
      def clear_breakpoint_here(self, event=None):
!         if not self.flist.pyshell or not self.flist.pyshell.interp.debugger:
!             self.text.bell()
              return
!         self.flist.pyshell.interp.debugger.clear_breakpoint_here(self)
!                                     
  
  class PyShellFileList(FileList):
--- 61,149 ----
      orig_checkcache()
      cache.update(save)
+     
  linecache.checkcache = linecache_checkcache
  
+ 
  class PyShellEditorWindow(EditorWindow):
      "Regular text edit window when a shell is present"
! 
!     # XXX KBK 19Oct02 Breakpoints are currently removed if module is
!     # changed or closed.  Future plans include saving breakpoints in a
!     # project file and possibly preserving breakpoints by changing their
!     # line numbers as a module is modified.
  
      def __init__(self, *args):
+         self.breakpoints = []
          apply(EditorWindow.__init__, (self,) + args)
          self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
!         self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
          self.text.bind("<<open-python-shell>>", self.flist.open_shell)
  
!     rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
!                    ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
  
      def set_breakpoint_here(self, event=None):
!         text = self.text
!         filename = self.io.filename
!         if not filename:
!             text.bell()
              return
!         lineno = int(float(text.index("insert")))
!         try:
!             i = self.breakpoints.index(lineno)
!         except:  # only add if missing, i.e. do once
!             self.breakpoints.append(lineno)
!         text.tag_add("BREAK", "insert linestart", "insert lineend +1char")
!         try:    # update the subprocess debugger
!             debug = self.flist.pyshell.interp.debugger
!             debug.set_breakpoint_here(filename, lineno)
!         except: # but debugger may not be active right now....
!             pass
  
      def clear_breakpoint_here(self, event=None):
!         text = self.text
!         filename = self.io.filename
!         if not filename:
!             text.bell()
              return
!         lineno = int(float(text.index("insert")))
!         try:
!             self.breakpoints.remove(lineno)
!         except:
!             pass
!         text.tag_remove("BREAK", "insert linestart",\
!                         "insert lineend +1char")
!         try:
!             debug = self.flist.pyshell.interp.debugger
!             debug.clear_breakpoint_here(filename, lineno)
!         except:
!             pass
! 
!     def clear_file_breaks(self):
!         if self.breakpoints:
!             text = self.text
!             filename = self.io.filename
!             if not filename:
!                 text.bell()
!                 return
!             self.breakpoints = []
!             text.tag_remove("BREAK", "1.0", END)
!             try:
!                 debug = self.flist.pyshell.interp.debugger
!                 debug.clear_file_breaks(filename)
!             except:
!                 pass
! 
!     def saved_change_hook(self):
!         "Extend base method - clear breaks if module is modified"
!         if not self.get_saved():
!             self.clear_file_breaks()
!         EditorWindow.saved_change_hook(self)
! 
!     def _close(self):
!         "Extend base method - clear breaks when module is closed"
!         self.clear_file_breaks()
!         EditorWindow._close(self)
!                                 
  
  class PyShellFileList(FileList):
***************
*** 175,179 ****
              # sys.prefix.
              executable = os.path.join(sys.prefix, 'Resources', 
!                                 'Python.app', 'Contents', 'MacOS', 'python')
              return executable
          else:
--- 234,239 ----
              # sys.prefix.
              executable = os.path.join(sys.prefix, 'Resources', 
!                                       'Python.app', 'Contents',
!                                       'MacOS', 'python')
              return executable
          else:
***************
*** 208,213 ****
      def restart_subprocess(self):
          # close only the subprocess debugger
!         db = self.getdebugger()
!         if db:
              RemoteDebugger.close_subprocess_debugger(self.rpcclt)           
          # kill subprocess, spawn a new one, accept connection
--- 268,273 ----
      def restart_subprocess(self):
          # close only the subprocess debugger
!         debug = self.getdebugger()
!         if debug:
              RemoteDebugger.close_subprocess_debugger(self.rpcclt)           
          # kill subprocess, spawn a new one, accept connection
***************
*** 216,224 ****
          self.rpcclt.accept()
          # restart remote debugger
!         if db:
              gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
!             # reload remote debugger breakpoints
!             pass   # XXX KBK 04Sep02 TBD
!         
      active_seq = None
  
--- 276,284 ----
          self.rpcclt.accept()
          # restart remote debugger
!         if debug:
              gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
!             # reload remote debugger breakpoints for all PyShellEditWindows
!             debug.load_breakpoints()
! 
      active_seq = None
  
***************
*** 266,269 ****
--- 326,337 ----
              clt.close()
  
+     debugger = None
+ 
+     def setdebugger(self, debugger):
+         self.debugger = debugger
+ 
+     def getdebugger(self):
+         return self.debugger
+ 
      def remote_stack_viewer(self):
          import RemoteObjectBrowser
***************
*** 383,394 ****
                  del c[key]
  
-     debugger = None
- 
-     def setdebugger(self, debugger):
-         self.debugger = debugger
- 
-     def getdebugger(self):
-         return self.debugger
- 
      def display_executing_dialog(self):
          tkMessageBox.showerror(
--- 451,454 ----
***************
*** 568,571 ****
--- 628,633 ----
          gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt, self)
          self.interp.setdebugger(gui)
+         # Load all PyShellEditorWindow breakpoints:
+         gui.load_breakpoints()
          sys.ps1 = "[DEBUG ON]\n>>> "
          self.showprompt()