https://github.com/python/cpython/commit/108a2adbc7a98e6adf4cef6ef70e8b7bca328e32
commit: 108a2adbc7a98e6adf4cef6ef70e8b7bca328e32
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-06-30T06:34:26Z
summary:

[3.15] Use tkinter wrapper methods instead of raw Tcl calls in turtle and IDLE 
(GH-152414) (GH-152648)

Use tkinter wrapper methods instead of raw Tcl calls in turtle and IDLE 
(GH-152414)

* turtle: wm_attributes(topmost=...);
* idlelib.macosx: winfo_server();
* idlelib tests: after_info().
(cherry picked from commit fc866dc84ec430ab22d60609520f7ab27267baef)

Co-authored-by: Serhiy Storchaka <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>

files:
M Lib/idlelib/idle_test/template.py
M Lib/idlelib/idle_test/test_codecontext.py
M Lib/idlelib/idle_test/test_colorizer.py
M Lib/idlelib/idle_test/test_editor.py
M Lib/idlelib/idle_test/test_filelist.py
M Lib/idlelib/idle_test/test_iomenu.py
M Lib/idlelib/idle_test/test_multicall.py
M Lib/idlelib/idle_test/test_pyshell.py
M Lib/idlelib/idle_test/test_runscript.py
M Lib/idlelib/idle_test/test_stackviewer.py
M Lib/idlelib/idle_test/test_window.py
M Lib/idlelib/idle_test/test_zoomheight.py
M Lib/idlelib/idle_test/test_zzdummy.py
M Lib/idlelib/idle_test/test_zzdummy_user.py
M Lib/idlelib/macosx.py
M Lib/turtle.py

diff --git a/Lib/idlelib/idle_test/template.py 
b/Lib/idlelib/idle_test/template.py
index 725a55b9c47230c..69a2af22efa149a 100644
--- a/Lib/idlelib/idle_test/template.py
+++ b/Lib/idlelib/idle_test/template.py
@@ -17,7 +17,7 @@ def setUpClass(cls):
     @classmethod
     def tearDownClass(cls):
         cls.root.update_idletasks()
-##        for id in cls.root.tk.call('after', 'info'):
+##        for id in cls.root.after_info():
 ##            cls.root.after_cancel(id)  # Need for EditorWindow.
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/idle_test/test_codecontext.py 
b/Lib/idlelib/idle_test/test_codecontext.py
index 6969ad73b01a81a..3f070da022384ec 100644
--- a/Lib/idlelib/idle_test/test_codecontext.py
+++ b/Lib/idlelib/idle_test/test_codecontext.py
@@ -127,7 +127,7 @@ def test_del_with_timer(self):
         timer = self.cc.t1 = self.text.after(10000, lambda: None)
         self.cc.__del__()
         with self.assertRaises(TclError) as cm:
-            self.root.tk.call('after', 'info', timer)
+            self.root.after_info(timer)
         self.assertIn("doesn't exist", str(cm.exception))
 
     def test_reload(self):
@@ -151,7 +151,7 @@ def test_toggle_code_context_event(self):
         eq(cc.context['bg'], self.highlight_cfg['background'])
         eq(cc.context.get('1.0', 'end-1c'), '')
         eq(cc.editwin.label, 'Hide Code Context')
-        eq(self.root.tk.call('after', 'info', self.cc.t1)[1], 'timer')
+        eq(self.root.after_info(self.cc.t1)[1], 'timer')
 
         # Toggle off.
         toggle()
diff --git a/Lib/idlelib/idle_test/test_colorizer.py 
b/Lib/idlelib/idle_test/test_colorizer.py
index fb6ee8250867502..4d9e6bd887c5b87 100644
--- a/Lib/idlelib/idle_test/test_colorizer.py
+++ b/Lib/idlelib/idle_test/test_colorizer.py
@@ -260,7 +260,7 @@ def test_notify_range(self):
 
         # Colorizing already scheduled.
         save_id = color.after_id
-        eq(self.root.tk.call('after', 'info', save_id)[1], 'timer')
+        eq(self.root.after_info(save_id)[1], 'timer')
         self.assertFalse(color.colorizing)
         self.assertFalse(color.stop_colorizing)
         self.assertTrue(color.allow_colorizing)
@@ -277,7 +277,7 @@ def test_notify_range(self):
         color.notify_range('1.0', '1.0+3c')
         self.assertTrue(color.stop_colorizing)
         self.assertIsNotNone(color.after_id)
-        eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
+        eq(self.root.after_info(color.after_id)[1], 'timer')
         # New event scheduled.
         self.assertNotEqual(color.after_id, save_id)
 
@@ -297,7 +297,7 @@ def test_toggle_colorize_event(self):
         self.assertFalse(color.colorizing)
         self.assertFalse(color.stop_colorizing)
         self.assertTrue(color.allow_colorizing)
-        eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
+        eq(self.root.after_info(color.after_id)[1], 'timer')
 
         # Toggle colorizing off.
         color.toggle_colorize_event()
@@ -324,7 +324,7 @@ def test_toggle_colorize_event(self):
         # Toggle on while colorizing not in progress.
         color.colorizing = False
         color.toggle_colorize_event()
-        eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
+        eq(self.root.after_info(color.after_id)[1], 'timer')
         self.assertFalse(color.colorizing)
         self.assertTrue(color.stop_colorizing)
         self.assertTrue(color.allow_colorizing)
@@ -363,7 +363,7 @@ def test_recolorize(self, mock_recmain):
         mock_recmain.assert_called()
         eq(mock_recmain.call_count, 1)
         # Rescheduled when TODO tag still exists.
-        eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
+        eq(self.root.after_info(color.after_id)[1], 'timer')
 
         # No changes to text, so no scheduling added.
         text.tag_remove('TODO', '1.0', 'end')
diff --git a/Lib/idlelib/idle_test/test_editor.py 
b/Lib/idlelib/idle_test/test_editor.py
index 0dfe2f3c58befad..e28ee549f180aa0 100644
--- a/Lib/idlelib/idle_test/test_editor.py
+++ b/Lib/idlelib/idle_test/test_editor.py
@@ -20,7 +20,7 @@ def setUpClass(cls):
     @classmethod
     def tearDownClass(cls):
         cls.root.update_idletasks()
-        for id in cls.root.tk.call('after', 'info'):
+        for id in cls.root.after_info():
             cls.root.after_cancel(id)
         cls.root.destroy()
         del cls.root
@@ -114,7 +114,7 @@ def tearDownClass(cls):
         cls.window._close()
         del cls.window
         cls.root.update_idletasks()
-        for id in cls.root.tk.call('after', 'info'):
+        for id in cls.root.after_info():
             cls.root.after_cancel(id)
         cls.root.destroy()
         del cls.root
@@ -225,7 +225,7 @@ def tearDownClass(cls):
         cls.window._close()
         del cls.window
         cls.root.update_idletasks()
-        for id in cls.root.tk.call('after', 'info'):
+        for id in cls.root.after_info():
             cls.root.after_cancel(id)
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/idle_test/test_filelist.py 
b/Lib/idlelib/idle_test/test_filelist.py
index 731f1975e50e239..e22cc3eced30822 100644
--- a/Lib/idlelib/idle_test/test_filelist.py
+++ b/Lib/idlelib/idle_test/test_filelist.py
@@ -16,7 +16,7 @@ def setUpClass(cls):
     @classmethod
     def tearDownClass(cls):
         cls.root.update_idletasks()
-        for id in cls.root.tk.call('after', 'info'):
+        for id in cls.root.after_info():
             cls.root.after_cancel(id)
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/idle_test/test_iomenu.py 
b/Lib/idlelib/idle_test/test_iomenu.py
index 80f72bdfe5ff0ef..90a23620354f313 100644
--- a/Lib/idlelib/idle_test/test_iomenu.py
+++ b/Lib/idlelib/idle_test/test_iomenu.py
@@ -30,7 +30,7 @@ def tearDownClass(cls):
         cls.editwin._close()
         del cls.editwin
         cls.root.update_idletasks()
-        for id in cls.root.tk.call('after', 'info'):
+        for id in cls.root.after_info():
             cls.root.after_cancel(id)  # Need for EditorWindow.
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/idle_test/test_multicall.py 
b/Lib/idlelib/idle_test/test_multicall.py
index 67f28db6b0875cf..7d73761cfdfee82 100644
--- a/Lib/idlelib/idle_test/test_multicall.py
+++ b/Lib/idlelib/idle_test/test_multicall.py
@@ -19,7 +19,7 @@ def setUpClass(cls):
     def tearDownClass(cls):
         del cls.mc
         cls.root.update_idletasks()
-##        for id in cls.root.tk.call('after', 'info'):
+##        for id in cls.root.after_info():
 ##            cls.root.after_cancel(id)  # Need for EditorWindow.
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/idle_test/test_pyshell.py 
b/Lib/idlelib/idle_test/test_pyshell.py
index 706703965bffd6f..51f7691eefe9d5d 100644
--- a/Lib/idlelib/idle_test/test_pyshell.py
+++ b/Lib/idlelib/idle_test/test_pyshell.py
@@ -40,7 +40,7 @@ def setUpClass(cls):
     @classmethod
     def tearDownClass(cls):
         #cls.root.update_idletasks()
-##        for id in cls.root.tk.call('after', 'info'):
+##        for id in cls.root.after_info():
 ##            cls.root.after_cancel(id)  # Need for EditorWindow.
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/idle_test/test_runscript.py 
b/Lib/idlelib/idle_test/test_runscript.py
index 5fc60185a663e8f..63086bfa4a404e9 100644
--- a/Lib/idlelib/idle_test/test_runscript.py
+++ b/Lib/idlelib/idle_test/test_runscript.py
@@ -18,7 +18,7 @@ def setUpClass(cls):
     @classmethod
     def tearDownClass(cls):
         cls.root.update_idletasks()
-        for id in cls.root.tk.call('after', 'info'):
+        for id in cls.root.after_info():
             cls.root.after_cancel(id)  # Need for EditorWindow.
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/idle_test/test_stackviewer.py 
b/Lib/idlelib/idle_test/test_stackviewer.py
index 55f510382bf4c36..2434d38e4ffe83e 100644
--- a/Lib/idlelib/idle_test/test_stackviewer.py
+++ b/Lib/idlelib/idle_test/test_stackviewer.py
@@ -21,7 +21,7 @@ def setUpClass(cls):
     def tearDownClass(cls):
 
         cls.root.update_idletasks()
-##        for id in cls.root.tk.call('after', 'info'):
+##        for id in cls.root.after_info():
 ##            cls.root.after_cancel(id)  # Need for EditorWindow.
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/idle_test/test_window.py 
b/Lib/idlelib/idle_test/test_window.py
index 5a2645b9cc27dce..9b56d321a407d68 100644
--- a/Lib/idlelib/idle_test/test_window.py
+++ b/Lib/idlelib/idle_test/test_window.py
@@ -29,7 +29,7 @@ def setUpClass(cls):
     def tearDownClass(cls):
         window.registry = window.WindowList()
         cls.root.update_idletasks()
-##        for id in cls.root.tk.call('after', 'info'):
+##        for id in cls.root.after_info():
 ##            cls.root.after_cancel(id)  # Need for EditorWindow.
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/idle_test/test_zoomheight.py 
b/Lib/idlelib/idle_test/test_zoomheight.py
index aa5bdfb4fbd4c62..3b97c34d4ab29d6 100644
--- a/Lib/idlelib/idle_test/test_zoomheight.py
+++ b/Lib/idlelib/idle_test/test_zoomheight.py
@@ -21,7 +21,7 @@ def setUpClass(cls):
     def tearDownClass(cls):
         cls.editwin._close()
         cls.root.update_idletasks()
-        for id in cls.root.tk.call('after', 'info'):
+        for id in cls.root.after_info():
             cls.root.after_cancel(id)  # Need for EditorWindow.
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/idle_test/test_zzdummy.py 
b/Lib/idlelib/idle_test/test_zzdummy.py
index 14c343cf9b30872..c8e7dd6941b5899 100644
--- a/Lib/idlelib/idle_test/test_zzdummy.py
+++ b/Lib/idlelib/idle_test/test_zzdummy.py
@@ -135,7 +135,7 @@ def tearDownClass(cls):
         zzdummy.idleConf.userCfg = usercfg
         del cls.editor, cls.text
         cls.root.update_idletasks()
-        for id in cls.root.tk.call('after', 'info'):
+        for id in cls.root.after_info():
             cls.root.after_cancel(id)  # Need for EditorWindow.
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/idle_test/test_zzdummy_user.py 
b/Lib/idlelib/idle_test/test_zzdummy_user.py
index 1d3f2ac3096fb0e..a3476bf52bc5882 100644
--- a/Lib/idlelib/idle_test/test_zzdummy_user.py
+++ b/Lib/idlelib/idle_test/test_zzdummy_user.py
@@ -68,7 +68,7 @@ def tearDownClass(cls):
         zzdummy.idleConf.userCfg = real_usercfg
         del cls.editor, cls.text
         cls.root.update_idletasks()
-        for id in cls.root.tk.call('after', 'info'):
+        for id in cls.root.after_info():
             cls.root.after_cancel(id)  # Need for EditorWindow.
         cls.root.destroy()
         del cls.root
diff --git a/Lib/idlelib/macosx.py b/Lib/idlelib/macosx.py
index 332952f4572cbda..428e49f3eb7d8ec 100644
--- a/Lib/idlelib/macosx.py
+++ b/Lib/idlelib/macosx.py
@@ -39,7 +39,7 @@ def _init_tk_type():
             _tk_type = "xquartz"
         elif 'aqua' not in ws:
             _tk_type = "other"
-        elif 'AppKit' in root.tk.call('winfo', 'server', '.'):
+        elif 'AppKit' in root.winfo_server():
             _tk_type = "cocoa"
         else:
             _tk_type = "carbon"
diff --git a/Lib/turtle.py b/Lib/turtle.py
index b52d681b3af1c32..ae5be9fe7039d5e 100644
--- a/Lib/turtle.py
+++ b/Lib/turtle.py
@@ -989,8 +989,8 @@ def __init__(self, cv, mode=_CFG["mode"],
             # the Turtle window will show behind the Terminal window when you
             # start the demo from the command line.
             rootwindow = cv.winfo_toplevel()
-            rootwindow.call('wm', 'attributes', '.', '-topmost', '1')
-            rootwindow.call('wm', 'attributes', '.', '-topmost', '0')
+            rootwindow.wm_attributes(topmost=True)
+            rootwindow.wm_attributes(topmost=False)
 
     def clear(self):
         """Delete all drawings and all turtles from the TurtleScreen.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to