fix: try every Python candidate in install.ps1

This commit is contained in:
Abdessamad Derraz committed 2026-11-05 12:10:08 +01:00
1 parent 9aa26143ad
commit 9a1d7390e6
2 files changed
+42 -14

No files matched your search

+19 -14
View File
@@ -68,18 +68,6 @@
$installer = $temporary
}
# The py launcher first, then python3 and python. The Microsoft Store
# places a python.exe that only points at the Store: it fails the
# version check like a missing one.
$findPython = {
$found = Get-Command py -ErrorAction SilentlyContinue
if ($found) { return ,@($found, @("-3")) }
foreach ($name in @("python3", "python")) {
$found = Get-Command $name -ErrorAction SilentlyContinue
if ($found) { return ,@($found, @()) }
}
return $null
}
$usable = {
param($candidate)
if (-not $candidate) { return $false }
@@ -87,11 +75,28 @@
& $candidate[0].Source @arguments -c "import sys, ssl, unicodedata, zlib; raise SystemExit(sys.version_info < (3, 8))" 2>$null | Out-Null
return ($LASTEXITCODE -eq 0)
}
# The py launcher first, then python3 and python, the first that
# passes the check: a py launcher left with no usable runtime hid a
# Python 3.12 on PATH. The Microsoft Store places a python.exe that
# only points at the Store: it fails the check like a missing one.
$findPython = {
$candidates = @()
$found = Get-Command py -ErrorAction SilentlyContinue
if ($found) { $candidates += ,@($found, @("-3")) }
foreach ($name in @("python3", "python")) {
$found = Get-Command $name -ErrorAction SilentlyContinue
if ($found) { $candidates += ,@($found, @()) }
}
foreach ($candidate in $candidates) {
if (& $usable $candidate) { return ,$candidate }
}
return $null
}
$needPython = "Python 3.8 or newer is required. Install it with " +
"'winget install Python.Python.3.12' or from https://www.python.org/downloads/ " +
"(tick 'Add python.exe to PATH'), then open a new PowerShell window and run this command again."
$candidate = & $findPython
if (-not (& $usable $candidate)) {
if (-not $candidate) {
# winget ships with Windows 10 and 11: at a console the bootstrap
# offers to run the install the message names, then carries on.
$winget = Get-Command winget -ErrorAction SilentlyContinue
@@ -109,7 +114,7 @@
$candidate = & $findPython
}
}
if (-not (& $usable $candidate)) { throw $needPython }
if (-not $candidate) { throw $needPython }
}
$python = $candidate[0]
$launcher = $candidate[1]
+23
View File
@@ -2694,6 +2694,29 @@ class WindowsWithoutPythonIsOfferedWinget(unittest.TestCase):
self.assertFalse((fake_bin / "python3").exists())
@unittest.skipUnless(shutil.which("pwsh"), "needs PowerShell")
class APyLauncherWithoutARuntimeIsPassed(unittest.TestCase):
"""findPython returned the py launcher as soon as it existed: one left
with no usable runtime hid a Python 3.12 on PATH, and the bootstrap
offered a second install or gave up."""
def test_python_on_path_runs_the_installer(self):
folder = Path(_tempdir(self))
shutil.copy(REPO_ROOT / "install.ps1", folder / "install.ps1")
(folder / "install.py").write_text("print('installer ran')\n")
fake_bin = folder / "bin"
fake_bin.mkdir()
(fake_bin / "py").write_text("#!/bin/sh\necho 'No installed Python found!' >&2\nexit 1\n")
(fake_bin / "py").chmod(0o755)
(fake_bin / "python3").symlink_to(sys.executable)
proc = subprocess.run(
[shutil.which("pwsh"), "-NoProfile", "-File", str(folder / "install.ps1")],
env={**os.environ, "PATH": f"{fake_bin}{os.pathsep}/usr/bin/nonexistent"},
capture_output=True, text=True, timeout=120, stdin=subprocess.DEVNULL)
self.assertEqual(proc.returncode, 0, proc.stdout + proc.stderr)
self.assertIn("installer ran", proc.stdout)
class ThePowerShellWrapperPassesTheStatusOn(unittest.TestCase):
"""Every non-zero exit became a red "installer failed" exception and
code 1: a --check that found work read as a crash, 2 and 130 were lost."""