[Idle-dev] CVS: idle PyShell.py,1.61,1.62 RemoteDebugger.py,1.9,1.10 run.py,1.15,1.16

Kurt B. Kaiser kbk@users.sourceforge.net
Sun, 11 May 2003 19:33:50 -0700


Update of /cvsroot/idlefork/idle
In directory sc8-pr-cvs1:/tmp/cvs-serv2433

Modified Files:
	PyShell.py RemoteDebugger.py run.py 
Log Message:
1. RemoteDebugger now runs user code in subprocess MainThread
2. run.py: move exception printing to toplevel to allow access from main()
3. Clarification in PyShell.py: when the subprocess is restarted, the
   debugger GUI is reused with a fresh instance of the subprocess
   debugger.

M PyShell.py
M RemoteDebugger.py
M run.py


Index: PyShell.py
===================================================================
RCS file: /cvsroot/idlefork/idle/PyShell.py,v
retrieving revision 1.61
retrieving revision 1.62
diff -C2 -r1.61 -r1.62
*** PyShell.py	10 May 2003 00:09:52 -0000	1.61
--- PyShell.py	12 May 2003 02:33:47 -0000	1.62
***************
*** 369,372 ****
--- 369,373 ----
          if debug:
              try:
+                 # Only close subprocess debugger, don't unregister gui_adap!
                  RemoteDebugger.close_subprocess_debugger(self.rpcclt)
              except:
***************
*** 388,391 ****
--- 389,393 ----
          # restart subprocess debugger
          if debug:
+             # Restarted debugger connects to current instance of debug GUI
              gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
              # reload remote debugger breakpoints for all PyShellEditWindows

Index: RemoteDebugger.py
===================================================================
RCS file: /cvsroot/idlefork/idle/RemoteDebugger.py,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -r1.9 -r1.10
*** RemoteDebugger.py	25 Jan 2003 21:33:40 -0000	1.9
--- RemoteDebugger.py	12 May 2003 02:33:47 -0000	1.10
***************
*** 301,305 ****
      def run(self, cmd, locals):
          # Ignores locals on purpose!
!         seq = self.conn.asynccall(self.oid, "run", (cmd,), {})
          self.shell.interp.active_seq = seq
  
--- 301,305 ----
      def run(self, cmd, locals):
          # Ignores locals on purpose!
!         seq = self.conn.asyncqueue(self.oid, "run", (cmd,), {})
          self.shell.interp.active_seq = seq
  

Index: run.py
===================================================================
RCS file: /cvsroot/idlefork/idle/run.py,v
retrieving revision 1.15
retrieving revision 1.16
diff -C2 -r1.15 -r1.16
*** run.py	8 May 2003 20:26:55 -0000	1.15
--- run.py	12 May 2003 02:33:47 -0000	1.16
***************
*** 63,67 ****
              ret = method(*args, **kwargs)
              rpc.response_queue.put((seq, ret))
!         except KeyboardInterrupt:
              continue
  
--- 63,69 ----
              ret = method(*args, **kwargs)
              rpc.response_queue.put((seq, ret))
!         except:
!             print_exception()
!             rpc.response_queue.put((seq, None))
              continue
  
***************
*** 85,88 ****
--- 87,143 ----
      server.handle_request() # A single request only
  
+ def print_exception():
+     flush_stdout()
+     efile = sys.stderr
+     typ, val, tb = info = sys.exc_info()
+     tbe = traceback.extract_tb(tb)
+     print >>efile, 'Traceback (most recent call last):'
+     exclude = ("run.py", "rpc.py", "threading.py", "Queue.py",
+                "RemoteDebugger.py", "bdb.py")
+     cleanup_traceback(tbe, exclude)
+     traceback.print_list(tbe, file=efile)
+     lines = traceback.format_exception_only(typ, val)
+     for line in lines:
+         print>>efile, line,
+ 
+ def cleanup_traceback(tb, exclude):
+     "Remove excluded traces from beginning/end of tb; get cached lines"
+     orig_tb = tb[:]
+     while tb:
+         for rpcfile in exclude:
+             if tb[0][0].count(rpcfile):
+                 break    # found an exclude, break for: and delete tb[0]
+         else:
+             break        # no excludes, have left RPC code, break while:
+         del tb[0]
+     while tb:
+         for rpcfile in exclude:
+             if tb[-1][0].count(rpcfile):
+                 break
+         else:
+             break
+         del tb[-1]
+     if len(tb) == 0:
+         # exception was in IDLE internals, don't prune!
+         tb[:] = orig_tb[:]
+         print>>sys.stderr, "** IDLE Internal Exception: "
+     rpchandler = rpc.objecttable['exec'].rpchandler
+     for i in range(len(tb)):
+         fn, ln, nm, line = tb[i]
+         if nm == '?':
+             nm = "-toplevel-"
+         if not line and fn.startswith("<pyshell#"):
+             line = rpchandler.remotecall('linecache', 'getline',
+                                               (fn, ln), {})
+         tb[i] = fn, ln, nm, line
+ 
+ def flush_stdout():
+     try:
+         if sys.stdout.softspace:
+             sys.stdout.softspace = 0
+             sys.stdout.write("\n")
+     except (AttributeError, EOFError):
+         pass
+ 
  
  class MyRPCServer(rpc.RPCServer):
***************
*** 154,213 ****
                  if exit_requested:
                      os._exit(0)
!                 self.flush_stdout()
!                 efile = sys.stderr
!                 typ, val, tb = info = sys.exc_info()
!                 sys.last_type, sys.last_value, sys.last_traceback = info
!                 tbe = traceback.extract_tb(tb)
!                 print >>efile, 'Traceback (most recent call last):'
!                 exclude = ("run.py", "rpc.py", "threading.py",
!                            "RemoteDebugger.py", "bdb.py")
!                 self.cleanup_traceback(tbe, exclude)
!                 traceback.print_list(tbe, file=efile)
!                 lines = traceback.format_exception_only(typ, val)
!                 for line in lines:
!                     print>>efile, line,
              except:
                  sys.stderr = sys.__stderr__
                  raise
          else:
!             self.flush_stdout()
! 
!     def flush_stdout(self):
!         try:
!             if sys.stdout.softspace:
!                 sys.stdout.softspace = 0
!                 sys.stdout.write("\n")
!         except (AttributeError, EOFError):
!             pass
! 
!     def cleanup_traceback(self, tb, exclude):
!         "Remove excluded traces from beginning/end of tb; get cached lines"
!         orig_tb = tb[:]
!         while tb:
!             for rpcfile in exclude:
!                 if tb[0][0].count(rpcfile):
!                     break    # found an exclude, break for: and delete tb[0]
!             else:
!                 break        # no excludes, have left RPC code, break while:
!             del tb[0]
!         while tb:
!             for rpcfile in exclude:
!                 if tb[-1][0].count(rpcfile):
!                     break
!             else:
!                 break
!             del tb[-1]
!         if len(tb) == 0:
!             # exception was in IDLE internals, don't prune!
!             tb[:] = orig_tb[:]
!             print>>sys.stderr, "** IDLE Internal Exception: "
!         for i in range(len(tb)):
!             fn, ln, nm, line = tb[i]
!             if nm == '?':
!                 nm = "-toplevel-"
!             if not line and fn.startswith("<pyshell#"):
!                 line = self.rpchandler.remotecall('linecache', 'getline',
!                                                   (fn, ln), {})
!             tb[i] = fn, ln, nm, line
  
      def interrupt_the_server(self):
--- 209,218 ----
                  if exit_requested:
                      os._exit(0)
!                 print_exception()
              except:
                  sys.stderr = sys.__stderr__
                  raise
          else:
!             flush_stdout()
  
      def interrupt_the_server(self):