https://github.com/python/cpython/commit/eac1dcfda3ad738ae3d480b16e8422b33c8c455d
commit: eac1dcfda3ad738ae3d480b16e8422b33c8c455d
branch: 3.14
author: Serhiy Storchaka <[email protected]>
committer: terryjreedy <[email protected]>
date: 2026-09-04T17:08:16-04:00
summary:

[3.14] gh-156896: Stop scrubbing tkinter submodules upon idlelib.run import 
(GH-156915) (#156959)

gh-156896: Stop scrubbing tkinter submodules upon idlelib.run import (#156915)

Instead, invoke the scrubbing within run.main, which is called after
the import when starting the IDLE user process.

To manually test that scrub_tkinter_submodules
is called when proper, start (or restart) Shell, enter
`import tkinter; dir(tkinter), and check that that font,
messagebox, ttk, and the dialog modules are missing.

It is obvious from the code that the function is not otherwise
called.  To test anyway, continue with `import tkinter.ttk;
import idlelib.run; tkinter.ttk` and check for proper output.

(cherry picked from commit e50d23389be07bf702bde74c3cda794c6febb53e)

Co-authored-by: Terry Jan Reedy <[email protected]>

files:
A Misc/NEWS.d/next/IDLE/2026-09-03-17-16-26.gh-issue-156896.XTQJlq.rst
M Lib/idlelib/run.py

diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py
index f5564ccf90f7f46..2725043b4ed9253 100644
--- a/Lib/idlelib/run.py
+++ b/Lib/idlelib/run.py
@@ -1,6 +1,6 @@
 """ idlelib.run
 
-Simplified, pyshell.ModifiedInterpreter spawns a subprocess with
+Simplified: pyshell.ModifiedInterpreter spawns a subprocess with
 f'''{sys.executable} -c "__import__('idlelib.run').run.main()"'''
 '.run' is needed because __import__ returns idlelib, not idlelib.run.
 """
@@ -26,18 +26,23 @@
 from idlelib import rpc  # multiple objects
 from idlelib import stackviewer  # StackTreeItem
 from idlelib import util  # fix_scaling
-import __main__
+import __main__  # self.locals in Executive.__init__.
 
 import tkinter  # Use tcl and, if startup fails, messagebox.
-if not hasattr(sys.modules['idlelib.run'], 'firstrun'):
-    # Undo modifications of tkinter by idlelib imports; see bpo-25507.
+
+def scrub_tkinter_submodules():  # Call in main when starting user process.
+    # Undo modifications of tkinter by idlelib imports; see gh-69693.
+    # Which of these submodules got imported (and thus added as a tkinter
+    # attribute) depends on what idlelib pulled in, so tolerate missing
+    # ones rather than assuming a fixed set; see gh-59396.
     for mod in ('simpledialog', 'messagebox', 'font',
                 'dialog', 'filedialog', 'commondialog',
                 'ttk'):
-        delattr(tkinter, mod)
-        del sys.modules['tkinter.' + mod]
-    # Avoid AttributeError if run again; see bpo-37038.
-    sys.modules['idlelib.run'].firstrun = False
+        try:
+            delattr(tkinter, mod)
+            del sys.modules['tkinter.' + mod]
+        except (AttributeError, KeyError):
+            pass
 
 LOCALHOST = '127.0.0.1'
 
@@ -133,6 +138,9 @@ def main(del_exitfunc=False):
     register and unregister themselves.
 
     """
+
+    scrub_tkinter_submodules()
+
     global exit_now
     global quitting
     global no_exitfunc
@@ -699,8 +707,7 @@ def stackviewer(self, flist_oid=None):
         item = stackviewer.StackTreeItem(exc, flist)
         return debugobj_r.remote_object_tree_item(item)
 
-
-if __name__ == '__main__':
+if __name__ == '__main__':  # __name__ is 'idlelib.run' in user subprocess.
     from unittest import main
     main('idlelib.idle_test.test_run', verbosity=2)
 
diff --git 
a/Misc/NEWS.d/next/IDLE/2026-09-03-17-16-26.gh-issue-156896.XTQJlq.rst 
b/Misc/NEWS.d/next/IDLE/2026-09-03-17-16-26.gh-issue-156896.XTQJlq.rst
new file mode 100644
index 000000000000000..fd759cdbe92c2ff
--- /dev/null
+++ b/Misc/NEWS.d/next/IDLE/2026-09-03-17-16-26.gh-issue-156896.XTQJlq.rst
@@ -0,0 +1 @@
+Stop deleting tkinter submodules when idlelib.run is imported.

_______________________________________________
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