]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-134300: Remove idlelib from the path of the IDLE user process (#152739)
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 1 Jul 2026 16:35:57 +0000 (19:35 +0300)
committerGitHub <noreply@github.com>
Wed, 1 Jul 2026 16:35:57 +0000 (12:35 -0400)
The idlelib directory ends up on sys.path when idle.py is run as a script,
and it was passed to the user process, where it let user code import
idlelib submodules as top-level modules, such as "import help".

Lib/idlelib/idle_test/test_pyshell.py
Lib/idlelib/pyshell.py
Misc/NEWS.d/next/IDLE/2026-07-01-15-00-00.gh-issue-134300.iDlPaT.rst [new file with mode: 0644]

index 51f7691eefe9d5dd01fde75918551e9445dc8a5c..dec81bdbbccd67e7cd25035917c40aa195ef7862 100644 (file)
@@ -2,6 +2,7 @@
 # Plus coverage of test_warning.  Was 20% with test_openshell.
 
 from idlelib import pyshell
+import os
 import unittest
 from test.support import requires
 from tkinter import Tk
@@ -28,6 +29,14 @@ class FunctionTest(unittest.TestCase):
                 self.assertEqual(pyshell.restart_line(width, ''), expect)
         self.assertEqual(pyshell.restart_line(taglen+2, ''), expect+' =')
 
+    def test_fix_user_path(self):
+        # gh-134300: the idlelib directory is removed, other entries kept.
+        eq = self.assertEqual
+        idlelib_dir = os.path.dirname(os.path.abspath(pyshell.__file__))
+        eq(pyshell.fix_user_path(['', '/a', idlelib_dir, '/b']), ['', '/a', '/b'])
+        eq(pyshell.fix_user_path(['/a', '/b']), ['/a', '/b'])
+        eq(pyshell.fix_user_path([idlelib_dir]), [])
+
 
 class PyShellFileListTest(unittest.TestCase):
 
index f117f0bfb52f2a3163ad46be79403fbe6bf3c6b1..ef3d014d936ce851d934fc7b9f2dcda11749c53b 100755 (executable)
@@ -408,6 +408,17 @@ def restart_line(width, filename):  # See bpo-38141.
         return tag[:-2]  # Remove ' ='.
 
 
+def fix_user_path(path):
+    """Return path without the idlelib directory (gh-134300).
+
+    That directory is on sys.path when idle.py is run as a script.
+    Otherwise user code could import idlelib submodules as top-level
+    modules, such as "import help".
+    """
+    idlelib_dir = os.path.dirname(os.path.abspath(__file__))
+    return [p for p in path if p != idlelib_dir]
+
+
 class ModifiedInterpreter(InteractiveInterpreter):
 
     def __init__(self, tkconsole):
@@ -568,6 +579,7 @@ class ModifiedInterpreter(InteractiveInterpreter):
             path.extend(sys.path)
         else:
             path = sys.path
+        path = fix_user_path(path)  # gh-134300
 
         self.runcommand("""if 1:
         import sys as _sys
diff --git a/Misc/NEWS.d/next/IDLE/2026-07-01-15-00-00.gh-issue-134300.iDlPaT.rst b/Misc/NEWS.d/next/IDLE/2026-07-01-15-00-00.gh-issue-134300.iDlPaT.rst
new file mode 100644 (file)
index 0000000..791acbb
--- /dev/null
@@ -0,0 +1,3 @@
+Do not add the ``idlelib`` directory to the path of the IDLE user process.
+User code run in IDLE can no longer import ``idlelib`` submodules as
+top-level modules, such as ``import help``.