Skip to content

feat: use NuGet for freethreading python #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: freethreaded
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 51 additions & 14 deletions builders/win-python-builder.psm1
Original file line number Diff line number Diff line change
@@ -25,21 +25,33 @@ class WinPythonBuilder : PythonBuilder {
[string] $InstallationTemplateName
[string] $InstallationScriptName
[string] $OutputArtifactName
[bool] $UseNuGet

WinPythonBuilder(
[semver] $version,
[string] $architecture,
[string] $platform
) : Base($version, $architecture, $platform) {
$this.InstallationTemplateName = "win-setup-template.ps1"
if ($this.IsFreeThreaded()) {
$this.UseNuGet = $true
}
else {
$this.UseNuGet = $false
}
if ($this.UseNuGet) {
$this.InstallationTemplateName = "win-nuget-template.ps1"
}
else {
$this.InstallationTemplateName = "win-setup-template.ps1"
}
$this.InstallationScriptName = "setup.ps1"
$this.OutputArtifactName = "python-$Version-$Platform-$Architecture.zip"
}

[string] GetPythonExtension() {
<#
.SYNOPSIS
Return extension for required version of Python executable.
Return extension for required version of Python executable.
#>

$extension = if ($this.Version -lt "3.5" -and $this.Version -ge "2.5") { ".msi" } else { ".exe" }
@@ -50,7 +62,7 @@ class WinPythonBuilder : PythonBuilder {
[string] GetArchitectureExtension() {
<#
.SYNOPSIS
Return architecture suffix for Python executable.
Return architecture suffix for Python executable.
#>

$ArchitectureExtension = ""
@@ -84,19 +96,39 @@ class WinPythonBuilder : PythonBuilder {
return $uri
}

[string] Download() {
[string] GetNuGetPackageName() {
$packageName = "python"
$arch = $this.GetHardwareArchitecture()
if ($arch -ne "x64") {
$packageName = "${packageName}${arch}"
}
if ($this.IsFreeThreaded()) {
$packageName = "${packageName}-freethreaded"
}
return $packageName
}

[void] Download() {
<#
.SYNOPSIS
Download Python installation executable into artifact location.
#>

$sourceUri = $this.GetSourceUri()

Write-Host "Sources URI: $sourceUri"
$sourcesLocation = Download-File -Uri $sourceUri -OutputFolder $this.WorkFolderLocation
Write-Debug "Done; Sources location: $sourcesLocation"

return $sourcesLocation
if ($this.UseNuGet) {
$packageName = $this.GetNuGetPackageName()
$version = $this.Version
$tempDir = Join-Path -Path $this.WorkFolderLocation -ChildPath "Temp"
$versionDir = Join-Path -Path $tempDir -ChildPath "${packageName}.${version}"
$toolsDir = Join-Path -Path $versionDir -ChildPath "tools"
Install-Package -ProviderName "NuGet" -Name $packageName -RequiredVersion $this.Version -Destination $tempDir -Confirm:$false -Force
Move-Item -Path "${toolsDir}\*" -Destination $this.WorkFolderLocation
Remove-Item -Path $tempDir -Force -Recurse
}
else {
$sourceUri = $this.GetSourceUri()
Write-Host "Sources URI: $sourceUri"
$sourcesLocation = Download-File -Uri $sourceUri -OutputFolder $this.WorkFolderLocation
Write-Debug "Done; Sources location: $sourcesLocation"
}
}

[void] CreateInstallationScript() {
@@ -105,8 +137,13 @@ class WinPythonBuilder : PythonBuilder {
Create Python artifact installation script based on specified template.
#>

$sourceUri = $this.GetSourceUri()
$pythonExecName = [IO.path]::GetFileName($sourceUri.AbsoluteUri)
if ($this.UseNuGet) {
$pythonExecName = ""
}
else {
$sourceUri = $this.GetSourceUri()
$pythonExecName = [IO.path]::GetFileName($sourceUri.AbsoluteUri)
}
$installationTemplateLocation = Join-Path -Path $this.InstallationTemplatesLocation -ChildPath $this.InstallationTemplateName
$installationTemplateContent = Get-Content -Path $installationTemplateLocation -Raw
$installationScriptLocation = New-Item -Path $this.WorkFolderLocation -Name $this.InstallationScriptName -ItemType File
52 changes: 52 additions & 0 deletions installers/win-nuget-template.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[String] $Architecture = "{{__ARCHITECTURE__}}"
[String] $Version = "{{__VERSION__}}"

$ToolcacheRoot = $env:AGENT_TOOLSDIRECTORY
if ([string]::IsNullOrEmpty($ToolcacheRoot)) {
# GitHub images don't have `AGENT_TOOLSDIRECTORY` variable
$ToolcacheRoot = $env:RUNNER_TOOL_CACHE
}
$PythonToolcachePath = Join-Path -Path $ToolcacheRoot -ChildPath "Python"
$PythonVersionPath = Join-Path -Path $PythonToolcachePath -ChildPath $Version
$PythonArchPath = Join-Path -Path $PythonVersionPath -ChildPath $Architecture

$IsFreeThreaded = $Architecture -match "-freethreaded"

$MajorVersion = $Version.Split('.')[0]
$MinorVersion = $Version.Split('.')[1]

Write-Host "Check if Python hostedtoolcache folder exist..."
if (-Not (Test-Path $PythonToolcachePath)) {
Write-Host "Create Python toolcache folder"
New-Item -ItemType Directory -Path $PythonToolcachePath | Out-Null
}

Write-Host "Check if current Python version is installed..."
if (Test-Path $PythonArchPath) {
Write-Host "Deleting $PythonArchPath..."
Remove-Item -Path $PythonArchPath -Recurse -Force
if (Test-Path -Path "$($PythonArchPath.Parent.FullName)/${Architecture}.complete") {
Remove-Item -Path "$($PythonArchPath.Parent.FullName)/${Architecture}.complete" -Force -Verbose
}
}

Write-Host "Create Python $Version folder in $PythonToolcachePath"
New-Item -ItemType Directory -Path $PythonArchPath -Force | Out-Null

Write-Host "Copy Python binaries to $PythonArchPath"
Copy-Item -Path ".\*" -Destination $PythonArchPath -Recurse
Remove-Item -Path "${PythonArchPath}\setup.ps1" -Force

Write-Host "Create `python3` symlink"
New-Item -Path "$PythonArchPath\python3.exe" -ItemType SymbolicLink -Value "$PythonArchPath\python.exe"

Write-Host "Install and upgrade Pip"
$Env:PIP_ROOT_USER_ACTION = "ignore"
$PythonExePath = Join-Path -Path $PythonArchPath -ChildPath "python.exe"
cmd.exe /c "$PythonExePath -m ensurepip && $PythonExePath -m pip install --upgrade --force-reinstall pip --no-warn-script-location"
if ($LASTEXITCODE -ne 0) {
Throw "Error happened during pip installation / upgrade"
}

Write-Host "Create complete file"
New-Item -ItemType File -Path $PythonVersionPath -Name "$Architecture.complete" | Out-Null