scripts/modules/prerequisites/python/install-python.ps1
# strangeloop Setup - Python Installation Module # Version: 1.0.0 param( [switch]$WSLMode, [switch]${test-only}, [switch]${what-if} ) # Import shared modules $SharedPath = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent | Join-Path -ChildPath "shared" . "$SharedPath\write-functions.ps1" . "$SharedPath\test-functions.ps1" function Test-PythonWindows { param( ) try { { Write-Info "Testing Python installation (Windows)..." } # Check if Python is installed if (-not (Test-Command "python")) { { Write-Warning "Python command not found" } return $false } # Check Python version $pythonVersion = python --version 2>$null if (-not $pythonVersion -or -not ($pythonVersion -match "Python 3\.")) { { Write-Warning "Python 3 not found or invalid version: $pythonVersion" } return $false } # Check pip if (-not (Test-Command "pip")) { { Write-Warning "pip not found" } return $false } { Write-Success "Python is properly installed: $pythonVersion" } return $true } catch { { Write-Warning "Error testing Python: $($_.Exception.Message)" } return $false } } function Test-PythonWSL { param( ) try { { Write-Info "Testing Python installation (WSL)..." } # Check if WSL is available if (-not (Test-Command "wsl")) { { Write-Warning "WSL not available" } return $false } # Check Python in WSL $wslPythonTest = wsl python3 --version 2>$null if (-not $wslPythonTest -or -not ($wslPythonTest -match "Python 3\.")) { { Write-Warning "Python 3 not found in WSL" } return $false } # Check pip in WSL $wslPipTest = wsl python3 -m pip --version 2>$null if (-not $wslPipTest) { { Write-Warning "pip not found in WSL" } return $false } { Write-Success "Python is properly installed in WSL: $wslPythonTest" } return $true } catch { { Write-Warning "Error testing Python in WSL: $($_.Exception.Message)" } return $false } } function Install-Python { param( [switch]$WSLMode, [switch]${test-only}, [switch]${what-if} ) # If test-only mode, just test current installation if (${test-only}) { if ($WSLMode) { return Test-PythonWSL } else { return Test-PythonWindows } } # If what-if mode, show what would be done if (${what-if}) { if ($WSLMode) { Write-Host "what if: Would install Python in WSL environment" -ForegroundColor Yellow Write-Host "what if: Would update package lists with 'apt update'" -ForegroundColor Yellow Write-Host "what if: Would install Python 3 and pip via 'apt install python3 python3-pip'" -ForegroundColor Yellow } else { Write-Host "what if: Would install Python on Windows" -ForegroundColor Yellow Write-Host "what if: Would download Python installer from python.org" -ForegroundColor Yellow Write-Host "what if: Would install Python with silent installation and add to PATH" -ForegroundColor Yellow Write-Host "what if: Would verify Python and pip installation" -ForegroundColor Yellow } return $true } if ($WSLMode) { Install-PythonWSL } else { Install-PythonWindows } } function Install-PythonWindows { param( ) Write-Step "Installing Python (Windows)..." try { # Check if Python is already installed if (Test-Command "python") { $pythonVersion = python --version 2>$null if ($pythonVersion -and $pythonVersion -match "Python 3\.") { Write-Success "Python is already installed: $pythonVersion" return Install-PipWindows } } $installChoice = Read-UserPrompt -Prompt "Python not found. Install Python 3?" -ValidValues @("y","n") if (-not (Test-YesResponse $installChoice)) { Write-Warning "Skipping Python installation" return $false } Write-Progress "Installing Python 3..." # Try different installation methods $installSuccess = $false # Method 1: Try winget (recommended) if (Test-Command "winget") { try { Write-Info "Installing Python via winget..." winget install Python.Python.3.12 --accept-package-agreements --accept-source-agreements --silent if ($LASTEXITCODE -eq 0) { $installSuccess = $true Write-Success "Python installed via winget" } } catch { Write-Warning "winget installation failed: $($_.Exception.Message)" } } # Method 2: Try chocolatey if winget failed if (-not $installSuccess -and (Test-Command "choco")) { try { Write-Info "Installing Python via chocolatey..." choco install python3 -y if ($LASTEXITCODE -eq 0) { $installSuccess = $true Write-Success "Python installed via chocolatey" } } catch { Write-Warning "Chocolatey installation failed: $($_.Exception.Message)" } } # Method 3: Microsoft Store version (fallback) if (-not $installSuccess) { Write-Info "Please install Python from the Microsoft Store or python.org" Write-Info "Microsoft Store: ms-windows-store://pdp/?productid=9NCVDN91XZQP" Write-Info "Python.org: https://www.python.org/downloads/" return $false } if ($installSuccess) { # Refresh PATH $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") # Install pip if needed return Install-PipWindows } return $false } catch { Write-Error "Python installation failed: $($_.Exception.Message)" return $false } } function Install-PythonWSL { param( ) Write-Step "Installing Python (WSL)..." try { # Check for WSL if (-not (Test-Command "wsl")) { Write-Error "WSL is not available. Please install WSL first." return $false } # Get default WSL distribution $defaultDistro = wsl -l -q | Select-Object -First 1 if (-not $defaultDistro) { Write-Error "No WSL distribution found" return $false } Write-Info "Installing Python in WSL distribution: $defaultDistro" # Update package lists Write-Progress "Updating package lists..." wsl -d $defaultDistro -- sudo apt update -qq # Install Python and pip Write-Progress "Installing Python 3 and pip..." wsl -d $defaultDistro -- sudo apt install -y python3 python3-pip python3-venv python3-dev # Verify installation $pythonVersion = wsl -d $defaultDistro -- python3 --version 2>$null if ($pythonVersion) { Write-Success "Python installed in WSL: $pythonVersion" # Install pipx Write-Progress "Installing pipx..." wsl -d $defaultDistro -- python3 -m pip install --user pipx wsl -d $defaultDistro -- pipx ensurepath Write-Success "Python and pipx installation completed in WSL" return $true } else { Write-Error "Python installation verification failed in WSL" return $false } } catch { Write-Error "Python WSL installation failed: $($_.Exception.Message)" return $false } } function Install-PipWindows { param( ) Write-Step "Installing pip and pipx (Windows)..." try { # Check if pip is available if (Test-Command "pip") { Write-Success "pip is already available" } else { Write-Info "Installing pip..." python -m ensurepip --upgrade } # Check if pipx is available if (Test-Command "pipx") { Write-Success "pipx is already available" } else { Write-Info "Installing pipx..." python -m pip install --user pipx python -m pipx ensurepath } # Refresh PATH $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") Write-Success "pip and pipx installation completed" return $true } catch { Write-Error "pip/pipx installation failed: $($_.Exception.Message)" return $false } } # Main execution if ($MyInvocation.InvocationName -ne '.') { $result = Install-Python -WSLMode:$WSLMode -test-only:${test-only} -what-if:${what-if} if ($result) { if (${test-only}) { Write-Success "Python test completed successfully" } else { Write-Success "Python installation completed successfully" } exit 0 } else { if (${test-only}) { Write-Error "Python test failed" } else { Write-Error "Python installation failed" } exit 1 } } # Export functions for module usage if ($MyInvocation.MyCommand.ModuleName) { Export-ModuleMember -Function @( 'Install-Python', 'Install-PythonWindows', 'Install-PythonWSL', 'Install-PipWindows' ) } |