✨ feat(windows): use SHGetKnownFolderPath API#380
Merged
gaborbernat merged 1 commit intotox-dev:mainfrom Feb 12, 2026
Merged
Conversation
Member
gaborbernat
requested changes
Sep 8, 2025
Member
gaborbernat
left a comment
There was a problem hiding this comment.
You'll need to fix the type checker at least 👍
gaborbernat
reviewed
Sep 8, 2025
6ebb0a3 to
206a824
Compare
Fix tox-dev#348 Co-authored-by: moi15moi <moi15moismokerlolilol@gmail.com>
206a824 to
59a74be
Compare
gaborbernat
approved these changes
Feb 12, 2026
gaborbernat
added a commit
to gaborbernat/platformdirs
that referenced
this pull request
Feb 13, 2026
SHGetKnownFolderPath with default flags (0) verifies that the target folder physically exists, raising FileNotFoundError in sandboxed Windows environments where USERPROFILE points to a directory without AppData\Local. This was a regression introduced in 4.7.0 when PR tox-dev#380 replaced SHGetFolderPathW with SHGetKnownFolderPath. Passing KF_FLAG_DONT_VERIFY (0x00004000) restores the pre-4.7.0 behavior of returning the expected path without existence checks, matching how the old SHGetFolderPathW API worked. Closes tox-dev#421
gaborbernat
added a commit
to gaborbernat/platformdirs
that referenced
this pull request
Feb 13, 2026
SHGetKnownFolderPath with default flags (0) verifies that the target folder physically exists, raising FileNotFoundError in sandboxed Windows environments where USERPROFILE points to a directory without AppData\Local. This was a regression introduced in 4.7.0 when PR tox-dev#380 replaced SHGetFolderPathW with SHGetKnownFolderPath. Passing KF_FLAG_DONT_VERIFY (0x00004000) restores the pre-4.7.0 behavior of returning the expected path without existence checks, matching how the old SHGetFolderPathW API worked. Closes tox-dev#421 Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
gaborbernat
added a commit
to gaborbernat/platformdirs
that referenced
this pull request
Feb 13, 2026
SHGetKnownFolderPath with default flags (0) verifies that the target folder physically exists, raising FileNotFoundError in sandboxed Windows environments where USERPROFILE points to a directory without AppData\Local. This was a regression introduced in 4.7.0 when PR tox-dev#380 replaced SHGetFolderPathW with SHGetKnownFolderPath. Passing KF_FLAG_DONT_VERIFY (0x00004000) restores the pre-4.7.0 behavior of returning the expected path without existence checks, matching how the old SHGetFolderPathW API worked. Closes tox-dev#421 Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
gaborbernat
added a commit
that referenced
this pull request
Feb 13, 2026
* 🐛 fix(windows): pass KF_FLAG_DONT_VERIFY to SHGetKnownFolderPath SHGetKnownFolderPath with default flags (0) verifies that the target folder physically exists, raising FileNotFoundError in sandboxed Windows environments where USERPROFILE points to a directory without AppData\Local. This was a regression introduced in 4.7.0 when PR #380 replaced SHGetFolderPathW with SHGetKnownFolderPath. Passing KF_FLAG_DONT_VERIFY (0x00004000) restores the pre-4.7.0 behavior of returning the expected path without existence checks, matching how the old SHGetFolderPathW API worked. Closes #421 Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net> * test(windows): use real ctypes on Windows CI On Windows, call get_win_folder_via_ctypes with the real Windows API for each CSIDL name to verify integration. Reserve mock-based tests for non-Windows where ctypes Windows bindings don't exist. * fix(tests): resolve unused type-ignore warnings on Windows Move ctypes.WinDLL mock assignment into _setup_ctypes_mocks so the type: ignore comment only exists in one place that ty can reason about. --------- Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The ctypes backend on Windows used
SHGetFolderPathW, a legacy API that Microsoft has marked deprecated since Windows Vista. It relies on integer CSIDL constants and has a hard-codedMAX_PATH(260 char) buffer, which silently truncates long paths. TheCSIDL_DOWNLOADSfolder had no dedicated constant at all, requiring a brittle workaround that appended"Downloads"to the user profile path -- breaking for any user who relocated their Downloads folder.🔄 This replaces it with
SHGetKnownFolderPath, the modern successor that uses KnownFolder GUIDs and allocates its own buffer (noMAX_PATHlimit). Every folder -- including Downloads and Desktop -- now has a proper GUID, so theCSIDL_DOWNLOADSworkaround is gone. The DLL function signatures are declared with properargtypes/restypeinstead of relying on the untypedctypes.windllsingleton, and the allocated memory is freed viaCoTaskMemFreeas required by the API contract.The fallback chain (ctypes -> registry -> env vars) is preserved. The
_pick_get_win_folderselector is simplified sincectypes.WinDLLis always available whenctypesis importable on CPython.Fix #348
Co-authored-by: moi15moi moi15moismokerlolilol@gmail.com