Skip to content

🐛 fix(discovery): find .exe names on Windows PATH - #253

Open
darrenhuai wants to merge 3 commits into
tox-dev:mainfrom
darrenhuai:fix/exe-suffixed-name-spec
Open

darrenhuai wants to merge 3 commits into
tox-dev:mainfrom
darrenhuai:fix/exe-suffixed-name-spec

Conversation

@darrenhuai

Copy link
Copy Markdown
Contributor

On Windows, discovery can't find an interpreter on PATH by a name that already ends in .exe. get_interpreter("pythonw.exe") returns None with pythonw.exe on PATH, while get_interpreter("pythonw") finds that same file, and virtualenv -p pythonw.exe (virtualenv 21.15.5 with python-discovery 1.9.4) stops with failed to find interpreter. You only hit this if you spell out the .exe. A version, or a bare name like pythonw, works. This is current main, with PATH set to only the Scripts folder of a fresh python -m virtualenv --no-seed environment (virtualenv puts python.exe, python3.exe, pythonw.exe and pythonw3.exe in it):

'python3.exe'    -> None
'PYTHON3.EXE'    -> None
'pythonw.exe'    -> None
'pythonw3.exe'   -> None
'pythonw'        -> Scripts\pythonw.exe
'python.exe'     -> Scripts\python.exe

A name ending in .exe does not parse as a version spec, so it is looked up on PATH as a literal name. path_exe_finder then appends .exe on Windows regardless, and the direct candidate it checks in each directory becomes python3.exe.exe. The regex fallback only matches python[version].exe, which leaves pythonw.exe and pythonw3.exe out. It does match python3.exe, but python.exe for the same base interpreter comes first in a virtualenv's Scripts, fails the name check, and _find_interpreter then skips python3.exe because it already tried that base interpreter.

path_exe_finder now appends .exe only when the name does not already end in it, ignoring case, so python3.exe, PYTHON3.EXE and pythonw.exe are checked as typed. Since #220 the name check looks at the executable found on PATH, and that candidate now passes it. Names without the suffix still get .exe appended. With this branch, all four .exe names above resolve to their own file in Scripts, and virtualenv -p pythonw.exe creates the environment. The new tests fail on main, apart from the case that pins the bare-name behavior.

On Windows, get_interpreter("python3.exe") or get_interpreter("pythonw.exe") returned None even with that file on
PATH, while "pythonw" found the same pythonw.exe. A name ending in .exe does not parse as a version spec, so it is
looked up on PATH by name, and path_exe_finder appended .exe to it again. The direct candidate became
python3.exe.exe, which never exists.

The regex fallback only matches python[version].exe, so pythonw.exe was never proposed. In a venv it does find
python3.exe, but only after python.exe fails the name check, and then python3.exe is skipped because both share
one base interpreter.

The suffix is now added only when the name does not already end in .exe, ignoring case.
Move the Windows test to the end of test_windows.py so it does not sit in the same spot as other new tests there.
@darrenhuai
darrenhuai force-pushed the fix/exe-suffixed-name-spec branch from c580402 to 11930ae Compare November 10, 2026 01:34

This branch has not been deployed

No deployments
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.

1 participant