1""" 2Wrapper around the eventloop that gives some time to the Tkinter GUI to process 3events when it's loaded and while we are waiting for input at the REPL. This 4way we don't block the UI of for instance ``turtle`` and other Tk libraries. 5 6(Normally Tkinter registers it's callbacks in ``PyOS_InputHook`` to integrate 7in readline. ``prompt-toolkit`` doesn't understand that input hook, but this 8will fix it for Tk.) 9""" 10import sys 11import time 12 13__all__ = ["inputhook"] 14 15 16def _inputhook_tk(inputhook_context): 17 """ 18 Inputhook for Tk. 19 Run the Tk eventloop until prompt-toolkit needs to process the next input. 20 """ 21 # Get the current TK application. 22 import tkinter 23 24 import _tkinter # Keep this imports inline! 25 26 root = tkinter._default_root 27 28 def wait_using_filehandler(): 29 """ 30 Run the TK eventloop until the file handler that we got from the 31 inputhook becomes readable. 32 """ 33 # Add a handler that sets the stop flag when `prompt-toolkit` has input 34 # to process. 35 stop = [False] 36 37 def done(*a): 38 stop[0] = True 39 40 root.createfilehandler(inputhook_context.fileno(), _tkinter.READABLE, done) 41 42 # Run the TK event loop as long as we don't receive input. 43 while root.dooneevent(_tkinter.ALL_EVENTS): 44 if stop[0]: 45 break 46 47 root.deletefilehandler(inputhook_context.fileno()) 48 49 def wait_using_polling(): 50 """ 51 Windows TK doesn't support 'createfilehandler'. 52 So, run the TK eventloop and poll until input is ready. 53 """ 54 while not inputhook_context.input_is_ready(): 55 while root.dooneevent(_tkinter.ALL_EVENTS | _tkinter.DONT_WAIT): 56 pass 57 # Sleep to make the CPU idle, but not too long, so that the UI 58 # stays responsive. 59 time.sleep(0.01) 60 61 if root is not None: 62 if hasattr(root, "createfilehandler"): 63 wait_using_filehandler() 64 else: 65 wait_using_polling() 66 67 68def inputhook(inputhook_context): 69 # Only call the real input hook when the 'Tkinter' library was loaded. 70 if "Tkinter" in sys.modules or "tkinter" in sys.modules: 71 _inputhook_tk(inputhook_context) 72