Skip to content

Commit 957c312

Browse files
authored
Add functions to check Windows ARM64 Python support
1 parent 000c79e commit 957c312

1 file changed

Lines changed: 77 additions & 9 deletions

File tree

deepstudio/xtester/install.ps1

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,42 @@ function Resolve-LocalPackagePath {
109109
return (Resolve-Path -LiteralPath $candidate).Path
110110
}
111111

112+
function Get-HostArchitecture {
113+
try {
114+
return [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString()
115+
}
116+
catch {
117+
return $env:PROCESSOR_ARCHITECTURE
118+
}
119+
}
120+
121+
function Test-IsWindowsArm64Host {
122+
$isWindowsHost = $false
123+
try { $isWindowsHost = $IsWindows } catch { }
124+
if (-not $isWindowsHost -and $env:OS -eq "Windows_NT") { $isWindowsHost = $true }
125+
if (-not $isWindowsHost) { return $false }
126+
127+
$arch = Get-HostArchitecture
128+
return $arch -match "^(Arm64|AArch64)$"
129+
}
130+
131+
function Get-PythonMachine([string]$FilePath, [string[]]$Arguments) {
132+
try {
133+
$output = & $FilePath @Arguments -c "import platform; print(platform.machine())" 2>&1
134+
if ($LASTEXITCODE -ne 0) { return $null }
135+
return ($output | Out-String).Trim()
136+
}
137+
catch {
138+
return $null
139+
}
140+
}
141+
142+
function Test-IsUnsupportedWindowsArm64Python([string]$FilePath, [string[]]$Arguments) {
143+
if (-not (Test-IsWindowsArm64Host)) { return $false }
144+
$machine = Get-PythonMachine $FilePath $Arguments
145+
return $machine -match "^(ARM64|AARCH64)$"
146+
}
147+
112148
function New-ManagedVenv($PythonInfo) {
113149
if ($Force -and (Test-Path -LiteralPath $VenvPath)) {
114150
Invoke-Step "Removing existing managed venv: $VenvPath" {
@@ -126,6 +162,19 @@ function New-ManagedVenv($PythonInfo) {
126162
}
127163

128164
$venvPython = Join-Path $VenvPath "Scripts\python.exe"
165+
if ((Test-Path -LiteralPath $venvPython) -and (Test-IsUnsupportedWindowsArm64Python $venvPython @())) {
166+
Invoke-Step "Removing native ARM64 managed venv: $VenvPath" {
167+
Remove-Item -LiteralPath $VenvPath -Recurse -Force
168+
}
169+
Invoke-Step "Creating managed X-Tester venv: $VenvPath" {
170+
$venvArgs = @()
171+
if ($PythonInfo.Arguments) { $venvArgs += $PythonInfo.Arguments }
172+
$venvArgs += @("-m", "venv", $VenvPath)
173+
Invoke-External $PythonInfo.FilePath $venvArgs
174+
}
175+
$venvPython = Join-Path $VenvPath "Scripts\python.exe"
176+
}
177+
129178
if (-not (Test-Path -LiteralPath $venvPython)) {
130179
# Microsoft Store / UWP Python redirects writes under %LOCALAPPDATA% into
131180
# %LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.*\LocalCache\Local\<rest>.
@@ -164,7 +213,7 @@ function Install-XTesterIntoVenv([string]$VenvPython) {
164213
Invoke-WithCleanPythonPath {
165214
Invoke-Step "Upgrading pip and installing private-feed auth helpers" {
166215
Invoke-External $VenvPython @("-m", "pip", "install", "-U", "pip")
167-
Invoke-External $VenvPython @("-m", "pip", "install", "-U", "keyring", "artifacts-keyring")
216+
Invoke-External $VenvPython @("-m", "pip", "install", "-U", "--prefer-binary", "keyring", "artifacts-keyring")
168217
}
169218

170219
if ($Source -eq "local") {
@@ -184,7 +233,7 @@ function Install-XTesterIntoVenv([string]$VenvPython) {
184233

185234
Invoke-Step "Installing $installLabel" {
186235
Invoke-External $VenvPython @(
187-
"-m", "pip", "install", "-U",
236+
"-m", "pip", "install", "-U", "--prefer-binary",
188237
"--index-url", $FeedUrl,
189238
"--extra-index-url", $ExtraIndexUrl,
190239
$packageSpec
@@ -334,6 +383,10 @@ function Test-PythonExecutable([string]$FilePath, [string[]]$Arguments) {
334383
$minor = [int]$Matches[2]
335384
if ($major -lt 3 -or ($major -eq 3 -and $minor -lt 11)) { return $null }
336385

386+
if (Test-IsUnsupportedWindowsArm64Python $FilePath $Arguments) {
387+
return $null
388+
}
389+
337390
# Reject Microsoft Store Python distributions. They virtualize writes under
338391
# %LOCALAPPDATA% into %LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.*\LocalCache\Local\,
339392
# which breaks `python -m venv` against our managed venv path.
@@ -373,7 +426,7 @@ function Find-PythonCandidate {
373426

374427
$py = Get-Command "py" -ErrorAction SilentlyContinue
375428
if ($py) {
376-
foreach ($flag in @("-3.13", "-3.12", "-3.11", "-3")) {
429+
foreach ($flag in @("-3.12", "-3.11", "-3.13", "-3")) {
377430
$candidates += ,@($py.Source, @($flag))
378431
}
379432
}
@@ -409,9 +462,15 @@ function Install-PythonViaWinget {
409462
# --disable-interactivity suppresses winget's animated progress bar so the
410463
# console is not flooded with redraw lines (which can also render as
411464
# mojibake on legacy code pages).
412-
& $winget.Source install -e --id Python.Python.3.12 --scope user `
413-
--accept-source-agreements --accept-package-agreements --silent `
414-
--disable-interactivity 2>&1 | ForEach-Object {
465+
$wingetArgs = @("install", "-e", "--id", "Python.Python.3.12", "--scope", "user")
466+
if (Test-IsWindowsArm64Host) {
467+
$wingetArgs += @("--architecture", "x64")
468+
}
469+
$wingetArgs += @(
470+
"--accept-source-agreements", "--accept-package-agreements", "--silent",
471+
"--disable-interactivity"
472+
)
473+
& $winget.Source @wingetArgs 2>&1 | ForEach-Object {
415474
$line = [string]$_
416475
# Drop empty/whitespace lines and progress redraw lines (block glyphs,
417476
# carriage-return progress percentages, and MB/KB transfer counters).
@@ -447,16 +506,25 @@ function Resolve-Python {
447506
}
448507

449508
Fail "No working Python 3.11+ interpreter was found."
450-
Info "Tried: python, python3, py -3.13, py -3.12, py -3.11, py -3 plus %LOCALAPPDATA%\Programs\Python\Python3*."
509+
Info "Tried: python, python3, py -3.12, py -3.11, py -3.13, py -3 plus %LOCALAPPDATA%\Programs\Python\Python3*."
451510
Info "The Microsoft Store stub at WindowsApps\python.exe is intentionally ignored."
511+
if (Test-IsWindowsArm64Host) {
512+
Info "Native ARM64 Python is intentionally ignored because required auth-helper wheels can fall back to cryptography/OpenSSL source builds."
513+
Info "Use x64 Python 3.12 on Windows ARM64 for this installer."
514+
}
452515
Info "Install Python manually with one of:"
453-
Info " winget install -e --id Python.Python.3.12"
516+
if (Test-IsWindowsArm64Host) {
517+
Info " winget install -e --id Python.Python.3.12 --architecture x64"
518+
} else {
519+
Info " winget install -e --id Python.Python.3.12"
520+
}
454521
Info " choco install python --version=3.12"
455522
Info " https://www.python.org/downloads/"
456523
Info "Then open a new terminal and re-run this installer."
457-
exit 1
524+
throw "No working Python 3.11+ interpreter was found."
458525
}
459526

527+
# Entry point
460528
Write-Host ""
461529
Write-Host " __ __ _____ _ " -ForegroundColor Magenta
462530
Write-Host " \ \/ / |_ _|__ ___| |_ ___ _ __ " -ForegroundColor Magenta

0 commit comments

Comments
 (0)