# Everything is done inside the loader function so that no other names # are placed in the global namespace. Before user code is executed, # even this name is unbound. def loader(): import sys, os, protocol, threading, time import Remote ## Use to debug the loading process itself: ## sys.stdout = open('c:\\windows\\desktop\\stdout.txt','a') ## sys.stderr = open('c:\\windows\\desktop\\stderr.txt','a') # Ensure that there is absolutely no pollution of the global # namespace by deleting the global name of this function. global loader del loader # Connect to IDLE try: client = protocol.Client() except protocol.connectionLost, cL: print 'loader: Unable to connect to IDLE', cL return # Connect to an ExecBinding object that needs our help. If # the user is starting multiple programs right now, we might get a # different one than the one that started us. Proving that's okay is # left as an exercise to the reader. (HINT: Twelve, by the pigeonhole # principle) ExecBinding = client.getobject('ExecBinding') if not ExecBinding: print "loader: IDLE does not need me." return # All of our input and output goes through ExecBinding. sys.stdin = Remote.pseudoIn( ExecBinding.readline ) sys.stdout = Remote.pseudoOut( ExecBinding.write.void, tag="stdout" ) sys.stderr = Remote.pseudoOut( ExecBinding.write.void, tag="stderr" ) # Create a Remote object and start it running. remote = Remote.Remote(globals(), ExecBinding) rthread = threading.Thread(target=remote.mainloop) rthread.setDaemon(1) rthread.start() # Block until either the client or the user program stops user = rthread.isAlive while user and client.isAlive(): time.sleep(0.025) if not user(): user = hasattr(sys, "ready_to_exit") and sys.ready_to_exit for t in threading.enumerate(): if not t.isDaemon() and t.isAlive() and t!=threading.currentThread(): user = t.isAlive break # We need to make sure we actually exit, so that the user doesn't get # stuck with an invisible process. We want to finalize C modules, so # we don't use os._exit(), but we don't call sys.exitfunc, which might # block forever. del sys.exitfunc sys.exit() loader()