[Python-checkins] python/dist/src/Lib/idlelib NEWS.txt, 1.28, 1.29 PyShell.py, 1.83, 1.84 ScriptBinding.py, 1.25, 1.26 run.py, 1.27, 1.28

kbk at users.sourceforge.net kbk at users.sourceforge.net
Wed Jan 21 13:54:32 EST 2004


Update of /cvsroot/python/python/dist/src/Lib/idlelib
In directory sc8-pr-cvs1:/tmp/cvs-serv15527

Modified Files:
	NEWS.txt PyShell.py ScriptBinding.py run.py 
Log Message:
Added a Tk error dialog to run.py inform the user if the subprocess can't
connect to the user GUI process.  Added a timeout to the GUI's listening
socket.  Added Tk error dialogs to PyShell.py to announce a failure to bind
the port or connect to the subprocess.  Clean up error handling during
connection initiation phase.  This is an update of Python Patch 778323.

M NEWS.txt
M PyShell.py
M ScriptBinding.py
M run.py

Backport candidate.



Index: NEWS.txt
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/NEWS.txt,v
retrieving revision 1.28
retrieving revision 1.29
diff -C2 -d -r1.28 -r1.29
*** NEWS.txt	2 Jan 2004 04:04:04 -0000	1.28
--- NEWS.txt	21 Jan 2004 18:54:30 -0000	1.29
***************
*** 4,7 ****
--- 4,13 ----
  *Release date: XX-XXX-2004*
  
+ - Added a Tk error dialog to run.py inform the user if the subprocess can't
+   connect to the user GUI process.  Added a timeout to the GUI's listening
+   socket.  Added Tk error dialogs to PyShell.py to announce a failure to bind
+   the port or connect to the subprocess.  Clean up error handling during
+   connection initiation phase.  This is an update of Python Patch 778323.
+ 
  - Print correct exception even if source file changed since shell was 
    restarted.  IDLEfork Patch 869012 Noam Raphael

Index: PyShell.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/PyShell.py,v
retrieving revision 1.83
retrieving revision 1.84
diff -C2 -d -r1.83 -r1.84
*** PyShell.py	24 Nov 2003 05:26:16 -0000	1.83
--- PyShell.py	21 Jan 2004 18:54:30 -0000	1.84
***************
*** 252,256 ****
          else:
              self.pyshell = PyShell(self)
!             self.pyshell.begin()
          return self.pyshell
  
--- 252,258 ----
          else:
              self.pyshell = PyShell(self)
!             if self.pyshell:
!                 if not self.pyshell.begin():
!                     return None
          return self.pyshell
  
***************
*** 345,348 ****
--- 347,353 ----
  
      def start_subprocess(self):
+         # spawning first avoids passing a listening socket to the subprocess
+         self.spawn_subprocess()
+         #time.sleep(20) # test to simulate GUI not accepting connection
          addr = (LOCALHOST, self.port)
          # Idle starts listening for connection on localhost
***************
*** 353,364 ****
                  break
              except socket.error, err:
!                 print>>sys.__stderr__,"IDLE socket error: " + err[1]\
!                                                     + ", retrying..."
          else:
!             display_port_binding_error()
!             sys.exit()
!         self.spawn_subprocess()
          # Accept the connection from the Python execution server
!         self.rpcclt.accept()
          self.rpcclt.register("stdin", self.tkconsole)
          self.rpcclt.register("stdout", self.tkconsole.stdout)
--- 358,372 ----
                  break
              except socket.error, err:
!                 pass
          else:
!             self.display_port_binding_error()
!             return None
          # Accept the connection from the Python execution server
!         self.rpcclt.listening_sock.settimeout(10)
!         try:
!             self.rpcclt.accept()
!         except socket.timeout, err:
!             self.display_no_subprocess_error()
!             return None
          self.rpcclt.register("stdin", self.tkconsole)
          self.rpcclt.register("stdout", self.tkconsole.stdout)
***************
*** 369,376 ****
          self.transfer_path()
          self.poll_subprocess()
  
      def restart_subprocess(self):
          if self.restarting:
!             return
          self.restarting = True
          # close only the subprocess debugger
--- 377,385 ----
          self.transfer_path()
          self.poll_subprocess()
+         return self.rpcclt
  
      def restart_subprocess(self):
          if self.restarting:
!             return self.rpcclt
          self.restarting = True
          # close only the subprocess debugger
***************
*** 389,393 ****
          console.executing = False
          self.spawn_subprocess()
!         self.rpcclt.accept()
          self.transfer_path()
          # annotate restart in shell window and mark it
--- 398,406 ----
          console.executing = False
          self.spawn_subprocess()
!         try:
!             self.rpcclt.accept()
!         except socket.timeout, err:
!             self.display_no_subprocess_error()
!             return None
          self.transfer_path()
          # annotate restart in shell window and mark it
***************
*** 408,411 ****
--- 421,425 ----
              debug.load_breakpoints()
          self.restarting = False
+         return self.rpcclt
  
      def __request_interrupt(self):
***************
*** 416,420 ****
  
      def kill_subprocess(self):
!         self.rpcclt.close()
          self.unix_terminate()
          self.tkconsole.executing = False
--- 430,437 ----
  
      def kill_subprocess(self):
!         try:
!             self.rpcclt.close()
!         except AttributeError:  # no socket
!             pass
          self.unix_terminate()
          self.tkconsole.executing = False
***************
*** 639,649 ****
                  del c[key]
  
-     def display_executing_dialog(self):
-         tkMessageBox.showerror(
-             "Already executing",
-             "The Python Shell window is already executing a command; "
-             "please wait until it is finished.",
-             master=self.tkconsole.text)
- 
      def runcommand(self, code):
          "Run the code without invoking the debugger"
--- 656,659 ----
***************
*** 696,699 ****
--- 706,737 ----
          self.tkconsole.stderr.write(s)
  
+     def display_port_binding_error(self):
+         tkMessageBox.showerror(
+             "Port Binding Error",
+             "IDLE can't bind TCP/IP port 8833, which is necessary to "
+             "communicate with its Python execution server.  Either "
+             "no networking is installed on this computer or another "
+             "process (another IDLE?) is using the port.  Run IDLE with the -n "
+             "command line switch to start without a subprocess and refer to "
+             "Help/IDLE Help 'Running without a subprocess' for further "
+             "details.",
+             master=self.tkconsole.text)
+ 
+     def display_no_subprocess_error(self):
+         tkMessageBox.showerror(
+             "Subprocess Startup Error",
+             "IDLE's subprocess didn't make connection.  Either IDLE can't "
+             "start a subprocess or personal firewall software is blocking "
+             "the connection.",
+             master=self.tkconsole.text)
+ 
+     def display_executing_dialog(self):
+         tkMessageBox.showerror(
+             "Already executing",
+             "The Python Shell window is already executing a command; "
+             "please wait until it is finished.",
+             master=self.tkconsole.text)
+ 
+ 
  class PyShell(OutputWindow):
  
***************
*** 766,771 ****
          #
          self.pollinterval = 50  # millisec
-         if use_subprocess:
-             self.interp.start_subprocess()
  
      reading = False
--- 804,807 ----
***************
*** 888,891 ****
--- 924,931 ----
          if use_subprocess:
              nosub = ''
+             client = self.interp.start_subprocess()
+             if not client:
+                 self.close()
+                 return None
          else:
              nosub = "==== No Subprocess ===="
***************
*** 895,903 ****
          self.showprompt()
          import Tkinter
!         Tkinter._default_root = None
! 
!     def interact(self):
!         self.begin()
!         self.top.mainloop()
  
      def readline(self):
--- 935,940 ----
          self.showprompt()
          import Tkinter
!         Tkinter._default_root = None # 03Jan04 KBK What's this?
!         return client
  
      def readline(self):
***************
*** 1282,1290 ****
              if not args:
                  flist.new()
!         if enable_shell:
!             flist.open_shell()
!     elif enable_shell:
!         flist.pyshell = PyShell(flist)
!         flist.pyshell.begin()
      shell = flist.pyshell
      # handle remaining options:
--- 1319,1325 ----
              if not args:
                  flist.new()
!     if enable_shell:
!         if not flist.open_shell():
!             return # couldn't open shell
      shell = flist.pyshell
      # handle remaining options:
***************
*** 1296,1300 ****
          if filename and os.path.isfile(filename):
              shell.interp.execfile(filename)
!     if cmd or script:
          shell.interp.runcommand("""if 1:
              import sys as _sys
--- 1331,1335 ----
          if filename and os.path.isfile(filename):
              shell.interp.execfile(filename)
!     if shell and cmd or script:
          shell.interp.runcommand("""if 1:
              import sys as _sys
***************
*** 1310,1331 ****
      root.destroy()
  
- 
- def display_port_binding_error():
-     print """\
- \nIDLE cannot run.
- 
- IDLE needs to use a specific TCP/IP port (8833) in order to communicate with
- its Python execution server.  IDLE is unable to bind to this port, and so
- cannot start. Here are some possible causes of this problem:
- 
-   1. TCP/IP networking is not installed or not working on this computer
-   2. Another program (another IDLE?) is running that uses this port
-   3. Personal firewall software is preventing IDLE from using this port
- 
- Run IDLE with the -n command line switch to start without a subprocess
- and refer to Help/IDLE Help "Running without a subprocess" for further
- details.
- """
- 
  if __name__ == "__main__":
      sys.modules['PyShell'] = sys.modules['__main__']
--- 1345,1348 ----

Index: ScriptBinding.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/ScriptBinding.py,v
retrieving revision 1.25
retrieving revision 1.26
diff -C2 -d -r1.25 -r1.26
*** ScriptBinding.py	5 Jun 2003 02:38:32 -0000	1.25
--- ScriptBinding.py	21 Jan 2004 18:54:30 -0000	1.26
***************
*** 138,141 ****
--- 138,143 ----
          flist = self.editwin.flist
          shell = flist.open_shell()
+         if not shell:
+             return  # couldn't open the shell
          interp = shell.interp
          if PyShell.use_subprocess:

Index: run.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/run.py,v
retrieving revision 1.27
retrieving revision 1.28
diff -C2 -d -r1.27 -r1.28
*** run.py	2 Jan 2004 04:04:04 -0000	1.27
--- run.py	21 Jan 2004 18:54:30 -0000	1.28
***************
*** 48,51 ****
--- 48,52 ----
      no_exitfunc = del_exitfunc
      port = 8833
+     #time.sleep(15) # test subprocess not responding
      if sys.argv[1:]:
          port = int(sys.argv[1])
***************
*** 91,95 ****
  
  def manage_socket(address):
!     for i in range(6):
          time.sleep(i)
          try:
--- 92,96 ----
  
  def manage_socket(address):
!     for i in range(3):
          time.sleep(i)
          try:
***************
*** 97,107 ****
              break
          except socket.error, err:
!             if i < 3:
!                 print>>sys.__stderr__, ".. ",
!             else:
!                 print>>sys.__stderr__,"\nPython subprocess socket error: "\
!                                               + err[1] + ", retrying...."
      else:
!         print>>sys.__stderr__, "\nConnection to Idle failed, exiting."
          global exit_now
          exit_now = True
--- 98,107 ----
              break
          except socket.error, err:
!             print>>sys.__stderr__,"IDLE Subprocess: socket error: "\
!                                         + err[1] + ", retrying...."
      else:
!         print>>sys.__stderr__, "IDLE Subprocess: Connection to "\
!                                "IDLE GUI failed, exiting."
!         show_socket_error(err, address)
          global exit_now
          exit_now = True
***************
*** 109,112 ****
--- 109,127 ----
      server.handle_request() # A single request only
  
+ def show_socket_error(err, address):
+     import Tkinter
+     import tkMessageBox
+     root = Tkinter.Tk()
+     root.withdraw()
+     if err[0] == 61: # connection refused
+         msg = "IDLE's subprocess can't connect to %s:%d.  This may be due "\
+               "to your personal firewall configuration.  It is safe to "\
+               "allow this internal connection because no data is visible on "\
+               "external ports." % address
+         tkMessageBox.showerror("IDLE Subprocess Error", msg, parent=root)
+     else:
+         tkMessageBox.showerror("IDLE Subprocess Error", "Socket Error: %s" % err[1])
+     root.destroy()
+ 
  def print_exception():
      import linecache
***************
*** 117,121 ****
      sys.last_type, sys.last_value, sys.last_traceback = excinfo
      tbe = traceback.extract_tb(tb)
!     print >>efile, '\nTraceback (most recent call last):'
      exclude = ("run.py", "rpc.py", "threading.py", "Queue.py",
                 "RemoteDebugger.py", "bdb.py")
--- 132,136 ----
      sys.last_type, sys.last_value, sys.last_traceback = excinfo
      tbe = traceback.extract_tb(tb)
!     print>>efile, '\nTraceback (most recent call last):'
      exclude = ("run.py", "rpc.py", "threading.py", "Queue.py",
                 "RemoteDebugger.py", "bdb.py")





More information about the Python-checkins mailing list