Mercurial > cpython-lru_cache-weakref
comparison Lib/idlelib/PyShell.py @ 52849:a014dc47b552
Merged revisions 71126 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r71126 | kurt.kaiser | 2009-04-04 03:03:48 -0400 (Sat, 04 Apr 2009) | 5 lines
Allow multiple IDLE GUI/subprocess pairs to exist
simultaneously. Thanks to David Scherer for suggesting
the use of an ephemeral port for the GUI.
Patch 1529142 Weeble.
........
| author | Kurt B. Kaiser <kbk@shore.net> |
|---|---|
| date | Sat, 04 Apr 2009 21:07:39 +0000 |
| parents | f138fbe2945e |
| children | e63d4678fca7 e4a83e91521a |
comparison
equal
deleted
inserted
replaced
| 52848:5bc8cf3d90b3 | 52849:a014dc47b552 |
|---|---|
| 32 from idlelib import rpc | 32 from idlelib import rpc |
| 33 from idlelib import Debugger | 33 from idlelib import Debugger |
| 34 from idlelib import RemoteDebugger | 34 from idlelib import RemoteDebugger |
| 35 from idlelib import macosxSupport | 35 from idlelib import macosxSupport |
| 36 | 36 |
| 37 LOCALHOST = '127.0.0.1' | 37 HOST = '127.0.0.1' # python execution server on localhost loopback |
| 38 PORT = 0 # someday pass in host, port for remote debug capability | |
| 38 | 39 |
| 39 try: | 40 try: |
| 40 from signal import SIGTERM | 41 from signal import SIGTERM |
| 41 except ImportError: | 42 except ImportError: |
| 42 SIGTERM = 15 | 43 SIGTERM = 15 |
| 337 self.tkconsole = tkconsole | 338 self.tkconsole = tkconsole |
| 338 locals = sys.modules['__main__'].__dict__ | 339 locals = sys.modules['__main__'].__dict__ |
| 339 InteractiveInterpreter.__init__(self, locals=locals) | 340 InteractiveInterpreter.__init__(self, locals=locals) |
| 340 self.save_warnings_filters = None | 341 self.save_warnings_filters = None |
| 341 self.restarting = False | 342 self.restarting = False |
| 342 self.subprocess_arglist = self.build_subprocess_arglist() | 343 self.subprocess_arglist = None |
| 343 | 344 self.port = PORT |
| 344 port = 8833 | 345 |
| 345 rpcclt = None | 346 rpcclt = None |
| 346 rpcpid = None | 347 rpcpid = None |
| 347 | 348 |
| 348 def spawn_subprocess(self): | 349 def spawn_subprocess(self): |
| 350 if self.subprocess_arglist == None: | |
| 351 self.subprocess_arglist = self.build_subprocess_arglist() | |
| 349 args = self.subprocess_arglist | 352 args = self.subprocess_arglist |
| 350 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args) | 353 self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args) |
| 351 | 354 |
| 352 def build_subprocess_arglist(self): | 355 def build_subprocess_arglist(self): |
| 356 assert (self.port!=0), ( | |
| 357 "Socket should have been assigned a port number.") | |
| 353 w = ['-W' + s for s in sys.warnoptions] | 358 w = ['-W' + s for s in sys.warnoptions] |
| 354 # Maybe IDLE is installed and is being accessed via sys.path, | 359 # Maybe IDLE is installed and is being accessed via sys.path, |
| 355 # or maybe it's not installed and the idle.py script is being | 360 # or maybe it's not installed and the idle.py script is being |
| 356 # run from the IDLE source directory. | 361 # run from the IDLE source directory. |
| 357 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc', | 362 del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc', |
| 366 else: | 371 else: |
| 367 decorated_exec = sys.executable | 372 decorated_exec = sys.executable |
| 368 return [decorated_exec] + w + ["-c", command, str(self.port)] | 373 return [decorated_exec] + w + ["-c", command, str(self.port)] |
| 369 | 374 |
| 370 def start_subprocess(self): | 375 def start_subprocess(self): |
| 371 # spawning first avoids passing a listening socket to the subprocess | 376 addr = (HOST, self.port) |
| 372 self.spawn_subprocess() | 377 # GUI makes several attempts to acquire socket, listens for connection |
| 373 #time.sleep(20) # test to simulate GUI not accepting connection | |
| 374 addr = (LOCALHOST, self.port) | |
| 375 # Idle starts listening for connection on localhost | |
| 376 for i in range(3): | 378 for i in range(3): |
| 377 time.sleep(i) | 379 time.sleep(i) |
| 378 try: | 380 try: |
| 379 self.rpcclt = MyRPCClient(addr) | 381 self.rpcclt = MyRPCClient(addr) |
| 380 break | 382 break |
| 381 except socket.error as err: | 383 except socket.error as err: |
| 382 pass | 384 pass |
| 383 else: | 385 else: |
| 384 self.display_port_binding_error() | 386 self.display_port_binding_error() |
| 385 return None | 387 return None |
| 388 # if PORT was 0, system will assign an 'ephemeral' port. Find it out: | |
| 389 self.port = self.rpcclt.listening_sock.getsockname()[1] | |
| 390 # if PORT was not 0, probably working with a remote execution server | |
| 391 if PORT != 0: | |
| 392 # To allow reconnection within the 2MSL wait (cf. Stevens TCP | |
| 393 # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic | |
| 394 # on Windows since the implementation allows two active sockets on | |
| 395 # the same address! | |
| 396 self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET, | |
| 397 socket.SO_REUSEADDR, 1) | |
| 398 self.spawn_subprocess() | |
| 399 #time.sleep(20) # test to simulate GUI not accepting connection | |
| 386 # Accept the connection from the Python execution server | 400 # Accept the connection from the Python execution server |
| 387 self.rpcclt.listening_sock.settimeout(10) | 401 self.rpcclt.listening_sock.settimeout(10) |
| 388 try: | 402 try: |
| 389 self.rpcclt.accept() | 403 self.rpcclt.accept() |
| 390 except socket.timeout as err: | 404 except socket.timeout as err: |
| 732 self.tkconsole.stderr.write(s) | 746 self.tkconsole.stderr.write(s) |
| 733 | 747 |
| 734 def display_port_binding_error(self): | 748 def display_port_binding_error(self): |
| 735 tkMessageBox.showerror( | 749 tkMessageBox.showerror( |
| 736 "Port Binding Error", | 750 "Port Binding Error", |
| 737 "IDLE can't bind TCP/IP port 8833, which is necessary to " | 751 "IDLE can't bind to a TCP/IP port, which is necessary to " |
| 738 "communicate with its Python execution server. Either " | 752 "communicate with its Python execution server. This might be " |
| 739 "no networking is installed on this computer or another " | 753 "because no networking is installed on this computer. " |
| 740 "process (another IDLE?) is using the port. Run IDLE with the -n " | 754 "Run IDLE with the -n command line switch to start without a " |
| 741 "command line switch to start without a subprocess and refer to " | 755 "subprocess and refer to Help/IDLE Help 'Running without a " |
| 742 "Help/IDLE Help 'Running without a subprocess' for further " | 756 "subprocess' for further details.", |
| 743 "details.", | |
| 744 master=self.tkconsole.text) | 757 master=self.tkconsole.text) |
| 745 | 758 |
| 746 def display_no_subprocess_error(self): | 759 def display_no_subprocess_error(self): |
| 747 tkMessageBox.showerror( | 760 tkMessageBox.showerror( |
| 748 "Subprocess Startup Error", | 761 "Subprocess Startup Error", |
| 1283 | 1296 |
| 1284 def main(): | 1297 def main(): |
| 1285 global flist, root, use_subprocess | 1298 global flist, root, use_subprocess |
| 1286 | 1299 |
| 1287 use_subprocess = True | 1300 use_subprocess = True |
| 1288 enable_shell = False | 1301 enable_shell = True |
| 1289 enable_edit = False | 1302 enable_edit = False |
| 1290 debug = False | 1303 debug = False |
| 1291 cmd = None | 1304 cmd = None |
| 1292 script = None | 1305 script = None |
| 1293 startup = False | 1306 startup = False |
| 1304 if o == '-d': | 1317 if o == '-d': |
| 1305 debug = True | 1318 debug = True |
| 1306 enable_shell = True | 1319 enable_shell = True |
| 1307 if o == '-e': | 1320 if o == '-e': |
| 1308 enable_edit = True | 1321 enable_edit = True |
| 1322 enable_shell = False | |
| 1309 if o == '-h': | 1323 if o == '-h': |
| 1310 sys.stdout.write(usage_msg) | 1324 sys.stdout.write(usage_msg) |
| 1311 sys.exit() | 1325 sys.exit() |
| 1312 if o == '-i': | 1326 if o == '-i': |
| 1313 enable_shell = True | 1327 enable_shell = True |
| 1354 sys.path.insert(0, dir) | 1368 sys.path.insert(0, dir) |
| 1355 # check the IDLE settings configuration (but command line overrides) | 1369 # check the IDLE settings configuration (but command line overrides) |
| 1356 edit_start = idleConf.GetOption('main', 'General', | 1370 edit_start = idleConf.GetOption('main', 'General', |
| 1357 'editor-on-startup', type='bool') | 1371 'editor-on-startup', type='bool') |
| 1358 enable_edit = enable_edit or edit_start | 1372 enable_edit = enable_edit or edit_start |
| 1359 enable_shell = enable_shell or not edit_start | |
| 1360 # start editor and/or shell windows: | 1373 # start editor and/or shell windows: |
| 1361 root = Tk(className="Idle") | 1374 root = Tk(className="Idle") |
| 1362 | 1375 |
| 1363 fixwordbreaks(root) | 1376 fixwordbreaks(root) |
| 1364 root.withdraw() | 1377 root.withdraw() |
