[Python-checkins] bpo-44282: Fix occasional test_incremental_editing failures on buildbots (GH-26491) (GH-26499)

vstinner webhook-mailer at python.org
Wed Jun 2 20:14:50 EDT 2021


https://github.com/python/cpython/commit/9c89d62073fa0bcfe68e59add5b55fbcbf7672ab
commit: 9c89d62073fa0bcfe68e59add5b55fbcbf7672ab
branch: 3.10
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: vstinner <vstinner at python.org>
date: 2021-06-03T02:14:41+02:00
summary:

bpo-44282: Fix occasional test_incremental_editing failures on buildbots (GH-26491) (GH-26499)

Signed-off-by: Tal Einat <532281+taleinat at users.noreply.github.com>
(cherry picked from commit adef445dc34685648bd0ea1c125df2ef143912ed)

Co-authored-by: Tal Einat <532281+taleinat at users.noreply.github.com>

files:
M Lib/idlelib/idle_test/test_colorizer.py
M Lib/idlelib/idle_test/test_sidebar.py
M Lib/idlelib/idle_test/tkinter_testing_utils.py

diff --git a/Lib/idlelib/idle_test/test_colorizer.py b/Lib/idlelib/idle_test/test_colorizer.py
index 498480a74e3551..b0b120e75a1553 100644
--- a/Lib/idlelib/idle_test/test_colorizer.py
+++ b/Lib/idlelib/idle_test/test_colorizer.py
@@ -551,7 +551,7 @@ def test_long_multiline_string(self):
             ''')
         self._assert_highlighting(source, {'STRING': [('1.0', '5.4')]})
 
-    @run_in_tk_mainloop
+    @run_in_tk_mainloop(delay=50)
     def test_incremental_editing(self):
         text = self.text
         eq = self.assertEqual
diff --git a/Lib/idlelib/idle_test/test_sidebar.py b/Lib/idlelib/idle_test/test_sidebar.py
index 43e8137d7079c9..53ac3eb27335d7 100644
--- a/Lib/idlelib/idle_test/test_sidebar.py
+++ b/Lib/idlelib/idle_test/test_sidebar.py
@@ -510,19 +510,19 @@ def test_initial_state(self):
         )
         self.assert_sidebar_lines_synced()
 
-    @run_in_tk_mainloop
+    @run_in_tk_mainloop()
     def test_single_empty_input(self):
         self.do_input('\n')
         yield
         self.assert_sidebar_lines_end_with(['>>>', '>>>'])
 
-    @run_in_tk_mainloop
+    @run_in_tk_mainloop()
     def test_single_line_statement(self):
         self.do_input('1\n')
         yield
         self.assert_sidebar_lines_end_with(['>>>', None, '>>>'])
 
-    @run_in_tk_mainloop
+    @run_in_tk_mainloop()
     def test_multi_line_statement(self):
         # Block statements are not indented because IDLE auto-indents.
         self.do_input(dedent('''\
@@ -540,14 +540,14 @@ def test_multi_line_statement(self):
             '>>>',
         ])
 
-    @run_in_tk_mainloop
+    @run_in_tk_mainloop()
     def test_single_long_line_wraps(self):
         self.do_input('1' * 200 + '\n')
         yield
         self.assert_sidebar_lines_end_with(['>>>', None, '>>>'])
         self.assert_sidebar_lines_synced()
 
-    @run_in_tk_mainloop
+    @run_in_tk_mainloop()
     def test_squeeze_multi_line_output(self):
         shell = self.shell
         text = shell.text
@@ -567,7 +567,7 @@ def test_squeeze_multi_line_output(self):
         self.assert_sidebar_lines_end_with(['>>>', None, None, None, '>>>'])
         self.assert_sidebar_lines_synced()
 
-    @run_in_tk_mainloop
+    @run_in_tk_mainloop()
     def test_interrupt_recall_undo_redo(self):
         text = self.shell.text
         # Block statements are not indented because IDLE auto-indents.
@@ -613,7 +613,7 @@ def test_interrupt_recall_undo_redo(self):
             ['>>>', '...', '...', '...', None, '>>>']
         )
 
-    @run_in_tk_mainloop
+    @run_in_tk_mainloop()
     def test_very_long_wrapped_line(self):
         with swap_attr(self.shell, 'squeezer', None):
             self.do_input('x = ' + '1'*10_000 + '\n')
@@ -678,7 +678,7 @@ def get_sidebar_colors():
         sidebar.update_colors()
         self.assertEqual(get_sidebar_colors(), test_colors)
 
-    @run_in_tk_mainloop
+    @run_in_tk_mainloop()
     def test_mousewheel(self):
         sidebar = self.shell.shell_sidebar
         text = self.shell.text
@@ -703,7 +703,7 @@ def test_mousewheel(self):
         yield
         self.assertIsNotNone(text.dlineinfo(text.index(f'{last_lineno}.0')))
 
-    @run_in_tk_mainloop
+    @run_in_tk_mainloop()
     def test_copy(self):
         sidebar = self.shell.shell_sidebar
         text = self.shell.text
@@ -728,7 +728,7 @@ def test_copy(self):
         copied_text = text.clipboard_get()
         self.assertEqual(copied_text, selected_text)
 
-    @run_in_tk_mainloop
+    @run_in_tk_mainloop()
     def test_copy_with_prompts(self):
         sidebar = self.shell.shell_sidebar
         text = self.shell.text
diff --git a/Lib/idlelib/idle_test/tkinter_testing_utils.py b/Lib/idlelib/idle_test/tkinter_testing_utils.py
index a9f8386e2cd9f6..a89839bbe38add 100644
--- a/Lib/idlelib/idle_test/tkinter_testing_utils.py
+++ b/Lib/idlelib/idle_test/tkinter_testing_utils.py
@@ -2,7 +2,7 @@
 import functools
 
 
-def run_in_tk_mainloop(test_method):
+def run_in_tk_mainloop(delay=1):
     """Decorator for running a test method with a real Tk mainloop.
 
     This starts a Tk mainloop before running the test, and stops it
@@ -13,44 +13,50 @@ def run_in_tk_mainloop(test_method):
     using "yield" to allow the mainloop to process events and "after"
     callbacks, and then continue the test from that point.
 
+    The delay argument is passed into root.after(...) calls as the number
+    of ms to wait before passing execution back to the generator function.
+
     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
+    @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
+    def decorator(test_method):
+        @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(delay, root.after_idle, after_callback)
+            root.after(0, root.after_idle, after_callback)
+            root.mainloop()
+
+            if exception:
+                raise exception
+
+        return new_test_method
+
+    return decorator



More information about the Python-checkins mailing list