| 413 | |
| 414 | |
| 415 | class ModifiedInterpreter(InteractiveInterpreter): |
| 416 | |
| 417 | def __init__(self, tkconsole): |
| 418 | self.tkconsole = tkconsole |
| 419 | locals = sys.modules['__main__'].__dict__ |
| 420 | InteractiveInterpreter.__init__(self, locals=locals) |
| 421 | self.restarting = False |
| 422 | self.subprocess_arglist = None |
| 423 | self.port = PORT |
| 424 | self.original_compiler_flags = self.compile.compiler.flags |
| 425 | |
| 426 | _afterid = None |
| 427 | rpcclt = None |
| 428 | rpcsubproc = None |
| 429 | |
| 430 | def spawn_subprocess(self): |
| 431 | if self.subprocess_arglist is None: |
| 432 | self.subprocess_arglist = self.build_subprocess_arglist() |
| 433 | self.rpcsubproc = subprocess.Popen(self.subprocess_arglist) |
| 434 | |
| 435 | def build_subprocess_arglist(self): |
| 436 | assert (self.port!=0), ( |
| 437 | "Socket should have been assigned a port number.") |
| 438 | w = ['-W' + s for s in sys.warnoptions] |
| 439 | # Maybe IDLE is installed and is being accessed via sys.path, |
| 440 | # or maybe it's not installed and the idle.py script is being |
| 441 | # run from the IDLE source directory. |
| 442 | del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc', |
| 443 | default=False, type='bool') |
| 444 | command = f"__import__('idlelib.run').run.main({del_exitf!r})" |
| 445 | return [sys.executable] + w + ["-c", command, str(self.port)] |
| 446 | |
| 447 | def start_subprocess(self): |
| 448 | addr = (HOST, self.port) |
| 449 | # GUI makes several attempts to acquire socket, listens for connection |
| 450 | for i in range(3): |
| 451 | time.sleep(i) |
| 452 | try: |
| 453 | self.rpcclt = MyRPCClient(addr) |
| 454 | break |
| 455 | except OSError: |
| 456 | pass |
| 457 | else: |
| 458 | self.display_port_binding_error() |
| 459 | return None |
| 460 | # if PORT was 0, system will assign an 'ephemeral' port. Find it out: |
| 461 | self.port = self.rpcclt.listening_sock.getsockname()[1] |
| 462 | # if PORT was not 0, probably working with a remote execution server |
| 463 | if PORT != 0: |
| 464 | # To allow reconnection within the 2MSL wait (cf. Stevens TCP |
| 465 | # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic |
| 466 | # on Windows since the implementation allows two active sockets on |
| 467 | # the same address! |
| 468 | self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET, |
| 469 | socket.SO_REUSEADDR, 1) |
| 470 | self.spawn_subprocess() |
| 471 | #time.sleep(20) # test to simulate GUI not accepting connection |
| 472 | # Accept the connection from the Python execution server |