Skip to content

gh-70331: Protect IDLE's imports from user files in the current directory - #157643

Merged
terryjreedy merged 3 commits into
python:mainfrom
serhiy-storchaka:gh-70331-shadow-stdlib
Sep 23, 2026
Merged

terryjreedy merged 3 commits into
python:mainfrom
serhiy-storchaka:gh-70331-shadow-stdlib

Conversation

@serhiy-storchaka

Copy link
Copy Markdown
Member

A user file such as random.py, threading.py or tkinter.py in the directory from which IDLE was started (on Windows, "Edit with IDLE" starts it in the file's directory; on macOS, IDLE.app starts in ~/Documents) shadowed the stdlib modules imported by IDLE, in the IDLE process (python -m idlelib) or in the user process (started with python -c), and IDLE failed to start.

Now the user process is started with -P, so the current directory is not on sys.path while idlelib.run and its dependencies are imported. sys.path of the user process is set by transfer_path() later anyway, so user code sees the same sys.path as before. python -m idlelib removes the current directory from sys.path before importing idlelib.pyshell, which imports almost all of IDLE.

pyshell.main() still adds the current directory or the directories of the files to be edited to sys.path of the IDLE process, so the few modules imported later (pydoc) can still be shadowed. Changing this would change sys.path seen by user code, so it is left for a separate change.

🤖 Generated with Claude Code

… directory

Start the user process with -P, so that the current directory is not on
sys.path while idlelib.run and its dependencies are imported.  sys.path
is set later by transfer_path().

"python -m idlelib" now removes the current directory from sys.path.
@serhiy-storchaka serhiy-storchaka added needs backport to 3.13 only security fixes needs backport to 3.14 bugs and security fixes needs backport to 3.15 pre-release feature fixes, bugs and security fixes labels Sep 16, 2026

@terryjreedy terryjreedy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I once did some research on on what sys.path looks like after various methods of starting python without IDLE. Probably on some other issue. I should repeat and save somewhere in idlelib.

Comment thread Misc/NEWS.d/next/IDLE/2026-09-16-22-00-00.gh-issue-70331.shadow.rst Outdated
Comment thread Lib/idlelib/__main__.py
@bedevere-app

bedevere-app Bot commented Sep 23, 2026

Copy link
Copy Markdown

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

@serhiy-storchaka

Copy link
Copy Markdown
Member Author

Done for idlelib.idle: the same three lines at the top, before it imports os.path, guarded by __spec__ is not None so that running idle.py as a script keeps its own directory in sys.path. The test now shadows os.py too and checks both -m entry points.

idle.pyw and pyshell need nothing. .pyw can only be run as a script, so sys.path[0] is its own directory, like for idle3 and idle.bat. Every entry point fixes sys.path before importing pyshell, and module-level code there would also run in tests, where deleting sys.path[0] is wrong — that is also why I duplicated the lines instead of importing a shared module, which could itself be shadowed.

Measured sys.path[0]: the current directory for python -m idlelib and python -m idlelib.idle, the script's directory for idle.py, idle3, idle.bat and idle.pyw, and '' for the user process. The user process is affected whichever way IDLE is started, only the moment differs: at startup with Shell, at F5 from an editor. NEWS reworded accordingly.

I have made the requested changes; please review again

@bedevere-app

bedevere-app Bot commented Sep 23, 2026

Copy link
Copy Markdown

Thanks for making the requested changes!

@terryjreedy: please review the changes made to this pull request.

@bedevere-app
bedevere-app Bot requested a review from terryjreedy September 23, 2026 09:32
@terryjreedy

Copy link
Copy Markdown
Member

I included pyshell with idle(w) because it is also an entry point. I vaguely remember seeing is documented as such (though not sure if 'officially'). The lines if __name__ == "__main__":\n main() ended the initial version. I'd like to deprecate this, but have no idea how many scripts that would break. idle.py originally consisted of

#! /usr/bin/env python

import PyShell
PyShell.main()

Both were part of the initial commit.

Should it not get the same treatment?

@terryjreedy
terryjreedy enabled auto-merge (squash) September 23, 2026 21:08
@terryjreedy
terryjreedy merged commit 6893326 into python:main Sep 23, 2026
55 of 56 checks passed
@miss-islington-app

Copy link
Copy Markdown

Thanks @serhiy-storchaka for the PR, and @terryjreedy for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13, 3.14, 3.15.
🐍🍒⛏🤖

@bedevere-app

bedevere-app Bot commented Sep 23, 2026

Copy link
Copy Markdown

GH-158034 is a backport of this pull request to the 3.15 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.15 pre-release feature fixes, bugs and security fixes label Sep 23, 2026
@bedevere-app

bedevere-app Bot commented Sep 23, 2026

Copy link
Copy Markdown

GH-158035 is a backport of this pull request to the 3.14 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.14 bugs and security fixes label Sep 23, 2026
@bedevere-app

bedevere-app Bot commented Sep 23, 2026

Copy link
Copy Markdown

GH-158036 is a backport of this pull request to the 3.13 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.13 only security fixes label Sep 23, 2026
terryjreedy pushed a commit that referenced this pull request Sep 23, 2026
…t directory (GH-157643) (#158036)

gh-70331: Protect IDLE's imports from user files in the current directory (GH-157643)

Start the user process with -P, so that the current directory is not on
sys.path while idlelib.run and its dependencies are imported.  sys.path
is set later by transfer_path().  Protect __main__, idle, and pyshell entry points.
(cherry picked from commit 6893326)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
terryjreedy pushed a commit that referenced this pull request Sep 23, 2026
…t directory (GH-157643) (#158035)

gh-70331: Protect IDLE's imports from user files in the current directory (GH-157643)

Start the user process with -P, so that the current directory is not on
sys.path while idlelib.run and its dependencies are imported.  sys.path
is set later by transfer_path().  Protect __main__, idle, and pyshell entry points.
(cherry picked from commit 6893326)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
@python python deleted a comment from linakhan470-cell Sep 23, 2026
terryjreedy pushed a commit that referenced this pull request Oct 9, 2026
…t directory (GH-157643) (#158034)

gh-70331: Protect IDLE's imports from user files in the current directory (GH-157643)

Start the user process with -P, so that the current directory is not on
sys.path while idlelib.run and its dependencies are imported.  sys.path
is set later by transfer_path().  Protect __main__, idle, and pyshell entry points.
(cherry picked from commit 6893326)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants