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