Home | History | Annotate | Download | only in appveyor
      1 # Sample script to install Python and pip under Windows
      2 # Authors: Olivier Grisel, Jonathan Helmus, Kyle Kastner, and Alex Willmer
      3 # License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
      4 # Source: https://github.com/ogrisel/python-appveyor-demo/blob/master/appveyor/install.ps1
      5 
      6 $BASE_URL = "https://www.python.org/ftp/python/"
      7 $GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py"
      8 $GET_PIP_PATH = "C:\get-pip.py"
      9 
     10 $PYTHON_PRERELEASE_REGEX = @"
     11 (?x)
     12 (?<major>\d+)
     13 \.
     14 (?<minor>\d+)
     15 \.
     16 (?<micro>\d+)
     17 (?<prerelease>[a-z]{1,2}\d+)
     18 "@
     19 
     20 
     21 function Download ($filename, $url) {
     22     $webclient = New-Object System.Net.WebClient
     23 
     24     $basedir = $pwd.Path + "\"
     25     $filepath = $basedir + $filename
     26     if (Test-Path $filename) {
     27         Write-Host "Reusing" $filepath
     28         return $filepath
     29     }
     30 
     31     # Download and retry up to 3 times in case of network transient errors.
     32     Write-Host "Downloading" $filename "from" $url
     33     $retry_attempts = 2
     34     for ($i = 0; $i -lt $retry_attempts; $i++) {
     35         try {
     36             $webclient.DownloadFile($url, $filepath)
     37             break
     38         }
     39         Catch [Exception]{
     40             Start-Sleep 1
     41         }
     42     }
     43     if (Test-Path $filepath) {
     44         Write-Host "File saved at" $filepath
     45     } else {
     46         # Retry once to get the error message if any at the last try
     47         $webclient.DownloadFile($url, $filepath)
     48     }
     49     return $filepath
     50 }
     51 
     52 
     53 function ParsePythonVersion ($python_version) {
     54     if ($python_version -match $PYTHON_PRERELEASE_REGEX) {
     55         return ([int]$matches.major, [int]$matches.minor, [int]$matches.micro,
     56                 $matches.prerelease)
     57     }
     58     $version_obj = [version]$python_version
     59     return ($version_obj.major, $version_obj.minor, $version_obj.build, "")
     60 }
     61 
     62 
     63 function DownloadPython ($python_version, $platform_suffix) {
     64     $major, $minor, $micro, $prerelease = ParsePythonVersion $python_version
     65 
     66     if (($major -le 2 -and $micro -eq 0) `
     67         -or ($major -eq 3 -and $minor -le 2 -and $micro -eq 0) `
     68         ) {
     69         $dir = "$major.$minor"
     70         $python_version = "$major.$minor$prerelease"
     71     } else {
     72         $dir = "$major.$minor.$micro"
     73     }
     74 
     75     if ($prerelease) {
     76         if (($major -le 2) `
     77             -or ($major -eq 3 -and $minor -eq 1) `
     78             -or ($major -eq 3 -and $minor -eq 2) `
     79             -or ($major -eq 3 -and $minor -eq 3) `
     80             ) {
     81             $dir = "$dir/prev"
     82         }
     83     }
     84 
     85     if (($major -le 2) -or ($major -le 3 -and $minor -le 4)) {
     86         $ext = "msi"
     87         if ($platform_suffix) {
     88             $platform_suffix = ".$platform_suffix"
     89         }
     90     } else {
     91         $ext = "exe"
     92         if ($platform_suffix) {
     93             $platform_suffix = "-$platform_suffix"
     94         }
     95     }
     96 
     97     $filename = "python-$python_version$platform_suffix.$ext"
     98     $url = "$BASE_URL$dir/$filename"
     99     $filepath = Download $filename $url
    100     return $filepath
    101 }
    102 
    103 
    104 function InstallPython ($python_version, $architecture, $python_home) {
    105     Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home
    106     if (Test-Path $python_home) {
    107         Write-Host $python_home "already exists, skipping."
    108         return $false
    109     }
    110     if ($architecture -eq "32") {
    111         $platform_suffix = ""
    112     } else {
    113         $platform_suffix = "amd64"
    114     }
    115     $installer_path = DownloadPython $python_version $platform_suffix
    116     $installer_ext = [System.IO.Path]::GetExtension($installer_path)
    117     Write-Host "Installing $installer_path to $python_home"
    118     $install_log = $python_home + ".log"
    119     if ($installer_ext -eq '.msi') {
    120         InstallPythonMSI $installer_path $python_home $install_log
    121     } else {
    122         InstallPythonEXE $installer_path $python_home $install_log
    123     }
    124     if (Test-Path $python_home) {
    125         Write-Host "Python $python_version ($architecture) installation complete"
    126     } else {
    127         Write-Host "Failed to install Python in $python_home"
    128         Get-Content -Path $install_log
    129         Exit 1
    130     }
    131 }
    132 
    133 
    134 function InstallPythonEXE ($exepath, $python_home, $install_log) {
    135     $install_args = "/quiet InstallAllUsers=1 TargetDir=$python_home"
    136     RunCommand $exepath $install_args
    137 }
    138 
    139 
    140 function InstallPythonMSI ($msipath, $python_home, $install_log) {
    141     $install_args = "/qn /log $install_log /i $msipath TARGETDIR=$python_home"
    142     $uninstall_args = "/qn /x $msipath"
    143     RunCommand "msiexec.exe" $install_args
    144     if (-not(Test-Path $python_home)) {
    145         Write-Host "Python seems to be installed else-where, reinstalling."
    146         RunCommand "msiexec.exe" $uninstall_args
    147         RunCommand "msiexec.exe" $install_args
    148     }
    149 }
    150 
    151 function RunCommand ($command, $command_args) {
    152     Write-Host $command $command_args
    153     Start-Process -FilePath $command -ArgumentList $command_args -Wait -Passthru
    154 }
    155 
    156 
    157 function InstallPip ($python_home) {
    158     $pip_path = $python_home + "\Scripts\pip.exe"
    159     $python_path = $python_home + "\python.exe"
    160     if (-not(Test-Path $pip_path)) {
    161         Write-Host "Installing pip..."
    162         $webclient = New-Object System.Net.WebClient
    163         $webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH)
    164         Write-Host "Executing:" $python_path $GET_PIP_PATH
    165         & $python_path $GET_PIP_PATH
    166     } else {
    167         Write-Host "pip already installed."
    168     }
    169 }
    170 
    171 
    172 function main () {
    173     InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON
    174     InstallPip $env:PYTHON
    175 }
    176 
    177 main