You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, uninstall --purge will remove recognised installs and the known directories, but we should do a better job of cleaning up unrecognised files.
This is more complicated than just rmtree(...), because we want to ensure we don't purge any runtimes that are in use. So we still need to keep the atomic-unlink for those, and only apply special handling to other directories.
It might also be worth having a purge option that keeps recognised installs, so that users can clean up broken ones without affecting the good ones.
I've opened #389 to address the unrecognised-files part of this issue.
The PR removes entries left under the install directory after the existing recognised-install and managed-directory cleanup, while preserving recognised runtime prefixes when their atomic removal reports files still in use. It also ensures that recursive deletion does not traverse directory symlink or Windows junction targets.
For the less-destructive variant, I suggest keeping the existing --purge semantics unchanged and adding a separate explicit mode, for example --purge-unknown (the exact name is open to discussion).
That mode could:
discover and preserve all recognised install prefixes;
preserve their registrations, shortcuts, and global commands, so valid runtimes remain fully usable;
remove only unrecognised entries under the install directory;
leave cache and shared-directory cleanup to the existing destructive --purge mode.
This would clearly separate “remove everything managed, including leftovers” from “clean up broken or unrecognised installs”, without changing the behavior of existing scripts.
If this matches the intended UX, I can handle it as a separate follow-up after #389.
I think it should be py uninstall --cleanup, and it should do what you propose for the additional mode except it does clean up cached files. Basically, everything that isn't necessary for running the recognised installs can go. The refresh_all_shortcuts function (or whatever it's called) should clean up all the other entries outside of the main install target dir.
Naming things isn't my strong suit. So let's go for py uninstall --cleanup!
I checked the helper name (update_all_shortcuts), and it should handle recreating the valid entries while cleaning up the stale aliases and registrations outside the install directory. I’ll keep #389 focused and handle --cleanup as a separate follow-up once it lands.
Yes to all of the above. They should probably both reject positional tags, I don't think there's any good reason to have them there, and it probably means that the caller didn't want to purge.
The confirmation flow for --cleanup should say "Clean up unnecessary or unused files? This will not affect any installed runtimes." (or tweak if you see a major issue with that wording that I missed - I've only thought about it for a minute right now, not very long)
I checked the wording against the current code paths and would suggest:
"Clean up cached files and unrecognized content? Recognized runtimes will be preserved."
There is no usage tracking, so “unused” could imply a distinction the command does not actually make. “Preserved” also states the intended invariant without suggesting that shortcuts and registrations remain untouched, since update_all_shortcuts may refresh them.
I’ll make preservation of every recognized runtime prefix an explicit test for the follow-up.
"will be preserved" is more passive language than I like to use in a prompt. Preserved by whom? I'd prefer that part to be framed as an intentional action of the current operation ("this").
Activity
Punisheroot commentedon Jul 31, 2026
I've opened #389 to address the unrecognised-files part of this issue.
The PR removes entries left under the install directory after the existing recognised-install and managed-directory cleanup, while preserving recognised runtime prefixes when their atomic removal reports files still in use. It also ensures that recursive deletion does not traverse directory symlink or Windows junction targets.
For the less-destructive variant, I suggest keeping the existing
--purgesemantics unchanged and adding a separate explicit mode, for example--purge-unknown(the exact name is open to discussion).That mode could:
--purgemode.This would clearly separate “remove everything managed, including leftovers” from “clean up broken or unrecognised installs”, without changing the behavior of existing scripts.
If this matches the intended UX, I can handle it as a separate follow-up after #389.
pythongh-300: Skip junction tests without _winapi
zooba commentedon Jul 31, 2026
I think it should be
py uninstall --cleanup, and it should do what you propose for the additional mode except it does clean up cached files. Basically, everything that isn't necessary for running the recognised installs can go. Therefresh_all_shortcutsfunction (or whatever it's called) should clean up all the other entries outside of the main install target dir.gh-300: Improve purge handling of unrecognized files (#389)
Punisheroot commentedon Jul 31, 2026
Naming things isn't my strong suit. So let's go for
py uninstall --cleanup!I checked the helper name (
update_all_shortcuts), and it should handle recreating the valid entries while cleaning up the stale aliases and registrations outside the install directory. I’ll keep #389 focused and handle--cleanupas a separate follow-up once it lands.Punisheroot commentedon Jul 31, 2026
Well... "once it lands" officially happened while I was posting that comment. Time to open the follow-up!
Punisheroot commentedon Jul 31, 2026
@zooba One small set of CLI details before I open the follow-up:
--purgeand ignore positional runtime tags;--cleanupwith--purge, rather than silently choosing one;--yesbypassing the prompt.Does that match the intended behaviour?
zooba commentedon Jul 31, 2026
Yes to all of the above. They should probably both reject positional tags, I don't think there's any good reason to have them there, and it probably means that the caller didn't want to purge.
The confirmation flow for
--cleanupshould say "Clean up unnecessary or unused files? This will not affect any installed runtimes." (or tweak if you see a major issue with that wording that I missed - I've only thought about it for a minute right now, not very long)Punisheroot commentedon Jul 31, 2026
I checked the wording against the current code paths and would suggest:
"Clean up cached files and unrecognized content? Recognized runtimes will be preserved."
There is no usage tracking, so “unused” could imply a distinction the command does not actually make. “Preserved” also states the intended invariant without suggesting that shortcuts and registrations remain untouched, since
update_all_shortcutsmay refresh them.I’ll make preservation of every recognized runtime prefix an explicit test for the follow-up.
zooba commentedon Jul 31, 2026
"will be preserved" is more passive language than I like to use in a prompt. Preserved by whom? I'd prefer that part to be framed as an intentional action of the current operation ("this").
gh-300: Add `uninstall --cleanup` option (#390)