Skip to content

Instantly share code, notes, and snippets.

@JamesDawson
Last active April 23, 2024 07:34
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JamesDawson/4d90e7fcc535c582c617ed553feaf35d to your computer and use it in GitHub Desktop.
Save JamesDawson/4d90e7fcc535c582c617ed553feaf35d to your computer and use it in GitHub Desktop.
Setup python, pyenv-win and poetry on Windows
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string] $PythonVersion
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
Set-StrictMode -Version Latest
function _runCommand {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, Position=0)]
[string] $Command,
[switch] $PassThru
)
if ($PassThru) {
$res = Invoke-Expression $Command
}
else {
Invoke-Expression $Command
}
if ($LASTEXITCODE -ne 0) {
$msg = "'$Command' reported a non-zero status code [$LASTEXITCODE] - check previous output{0}"
if ($PassThru) {
Write-Error ($msg -f "`n$res")
}
else {
Write-Error ($msg -f ".")
}
}
if ($PassThru) {
return $res
}
}
function _addToUserPath {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, Position=0)]
[string] $AppName,
[Parameter(Mandatory=$true, Position=1)]
[string[]] $PathsToAdd
)
$pathEntries = [System.Environment]::GetEnvironmentVariable("PATH", [System.EnvironmentVariableTarget]::User) -split ";"
$pathUpdated = $false
foreach ($pathToAdd in $PathsToAdd) {
if ($pathToAdd -notin $pathEntries) {
$pathEntries += $pathToAdd
$pathUpdated = $true
}
}
if ($pathUpdated) {
Write-Host "$($AppName): Updating %PATH%..." -f Green
# Remove any duplicate or blank entries
$cleanPaths = $pathEntries | Select-Object -Unique | Where-Object { ![string]::IsNullOrEmpty($_) }
# Update the user-scoped PATH environment variable
[System.Environment]::SetEnvironmentVariable("PATH", ($cleanPaths -join ";").TrimEnd(";"), [System.EnvironmentVariableTarget]::User)
# Reload PATH in the current session, so we don't need to restart the console
$env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", [System.EnvironmentVariableTarget]::User)
}
else {
Write-Host "$($AppName): PATH already setup." -f Cyan
}
}
Write-Host "#################################################" -f White
Write-Host "## Python, pyenv & poetry Windows setup script ##" -f White
Write-Host "#################################################" -f White
# Install pyenv
if (!(Test-Path $HOME/.pyenv)) {
# Explicitly check whether running Windows PowerShell, as '$IsWindows' is only available for PowerShell Core
if ($PSVersionTable.PSEdition -eq 'Desktop' -or $IsWindows) {
Write-Host "pyenv: Installing for Windows..." -f Green
& git clone https://github.com/pyenv-win/pyenv-win.git $HOME/.pyenv
if ($LASTEXITCODE -ne 0) {
Write-Error "git reported a non-zero status code [$LASTEXITCODE] - check previous output."
}
}
else {
Write-Error "This script currently only supports Windows."
}
}
else {
Write-Host "pyenv: Already installed." -f Cyan
}
# Add pyenv to PATH
_addToUserPath "pyenv" @(
"$HOME\.pyenv\pyenv-win\bin"
"$HOME\.pyenv\pyenv-win\shims"
)
# Install default pyenv python version
$pyenvVersions = _runCommand "pyenv versions" -PassThru | Select-String $PythonVersion
if (!($pyenvVersions)) {
Write-Host "pyenv: Installing python version $PythonVersion..." -f Green
_runCommand "pyenv install $PythonVersion"
}
else {
Write-Host "pyenv: Python version $PythonVersion already installed." -f Cyan
}
# Set pyenv global version
$globalPythonVersion = _runCommand "pyenv global" -PassThru
if ($globalPythonVersion -ne $PythonVersion) {
Write-Host "pyenv: Setting global python version: $PythonVersion" -f Green
_runCommand "pyenv global $PythonVersion"
}
else {
Write-Host "pyenv: Global python version already set: $globalPythonVersion" -f Cyan
}
if (!(Get-Command poetry -ErrorAction Ignore)) {
$downloadPath = "$HOME/Downloads/install-poetry.py"
Write-Host "python-poetry: Installing..." -f Green
Invoke-WebRequest -Uri "https://install.python-poetry.org" `
-UseBasicParsing `
-OutFile $downloadPath
try {
_runCommand "pyenv exec python `"$downloadPath`""
}
finally {
Remove-Item $downloadPath
}
}
else {
Write-Host "python-poetry: Already installed." -f Cyan
}
# Add poetry to PATH
_addToUserPath "python-poetry" @("$HOME\AppData\Roaming\Python\Scripts")
# Test poetry is available
_runCommand "poetry --version"
Write-Host "####################" -f Green
Write-Host "## Setup Complete ##" -f Green
Write-Host "####################" -f Green
@Fastjur
Copy link

Fastjur commented Apr 19, 2024

The $IsWindows variable is not defined for me on windows 10.

@JamesDawson
Copy link
Author

JamesDawson commented Apr 22, 2024

Hi @Fastjur, thanks for the comment.

If you run $PSVersionTable, does this show you are running on PSVersion v5.1? This is the original 'Windows PowerShell' rather than the cross-platform 'PowerShell Core' version - unfortunately $IsWindows is only available in the latter as v5.1 isn't getting updated now. However, the intention was for this script to work on both editions so thanks for letting me know.

I've updated the gist to handle this properly, so hopefully it should work for you now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment