diff options
author | Tal Einat <532281+taleinat@users.noreply.github.com> | 2021-04-28 22:27:55 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-28 22:27:55 (GMT) |
commit | 15d386185659683fc044ccaa300aa8cd7d49cc1a (patch) | |
tree | 6fac7df4ac125b39648d8f0d7fbb008212dc6ba8 /Lib/idlelib/idle_test/tkinter_testing_utils.py | |
parent | 103d5e420dd90489933ad9da8bb1d6008773384d (diff) | |
download | cpython-15d386185659683fc044ccaa300aa8cd7d49cc1a.zip cpython-15d386185659683fc044ccaa300aa8cd7d49cc1a.tar.gz cpython-15d386185659683fc044ccaa300aa8cd7d49cc1a.tar.bz2 |
bpo-37903: IDLE: Shell sidebar with prompts (GH-22682)
The first followup will change shell indents to spaces.
More are expected.
Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
Diffstat (limited to 'Lib/idlelib/idle_test/tkinter_testing_utils.py')
-rw-r--r-- | Lib/idlelib/idle_test/tkinter_testing_utils.py | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/Lib/idlelib/idle_test/tkinter_testing_utils.py b/Lib/idlelib/idle_test/tkinter_testing_utils.py new file mode 100644 index 0000000..a9f8386 --- /dev/null +++ b/Lib/idlelib/idle_test/tkinter_testing_utils.py @@ -0,0 +1,56 @@ +"""Utilities for testing with Tkinter""" +import functools + + +def run_in_tk_mainloop(test_method): + """Decorator for running a test method with a real Tk mainloop. + + This starts a Tk mainloop before running the test, and stops it + at the end. This is faster and more robust than the common + alternative method of calling .update() and/or .update_idletasks(). + + Test methods using this must be written as generator functions, + using "yield" to allow the mainloop to process events and "after" + callbacks, and then continue the test from that point. + + This also assumes that the test class has a .root attribute, + which is a tkinter.Tk object. + + For example (from test_sidebar.py): + + @run_test_with_tk_mainloop + def test_single_empty_input(self): + self.do_input('\n') + yield + self.assert_sidebar_lines_end_with(['>>>', '>>>']) + """ + @functools.wraps(test_method) + def new_test_method(self): + test_generator = test_method(self) + root = self.root + # Exceptions raised by self.assert...() need to be raised + # outside of the after() callback in order for the test + # harness to capture them. + exception = None + def after_callback(): + nonlocal exception + try: + next(test_generator) + except StopIteration: + root.quit() + except Exception as exc: + exception = exc + root.quit() + else: + # Schedule the Tk mainloop to call this function again, + # using a robust method of ensuring that it gets a + # chance to process queued events before doing so. + # See: https://stackoverflow.com/q/18499082#comment65004099_38817470 + root.after(1, root.after_idle, after_callback) + root.after(0, root.after_idle, after_callback) + root.mainloop() + + if exception: + raise exception + + return new_test_method |