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