Compare commits

..

4 Commits

Author SHA1 Message Date
aparnajyothi-y
d80ea3a25f Delete builders/nix-python-builder.psm1 2024-06-24 15:07:52 +05:30
aparnajyothi-y
7a302f1496 Update build-python-packages.yml 2024-06-24 15:03:36 +05:30
aparnajyothi-y
e18dd16151 Update win-python-builder.psm1 2024-06-20 14:46:12 +05:30
aparnajyothi-y
606312b02e Update build-python-packages.yml 2024-06-20 14:45:24 +05:30
21 changed files with 640 additions and 4876 deletions

View File

@@ -12,15 +12,10 @@ on:
required: true
type: boolean
default: false
THREADING_BUILD_MODES:
description: 'CPython threading build modes'
required: true
type: string
default: 'default,freethreaded'
PLATFORMS:
description: 'Platforms for execution in "os" or "os_arch" format (arch is "x64" by default)'
required: true
default: 'ubuntu-22.04,ubuntu-22.04_arm64,ubuntu-24.04,ubuntu-24.04_arm64,macos-13_x64,macos-14_arm64,windows-2019_x64,windows-2019_x86,windows-11_arm64'
default: 'ubuntu-20.04,ubuntu-22.04,ubuntu-22.04_arm64,ubuntu-24.04,macos-11_x64,macos-14_arm64,windows-2019_x64,windows-2019_x86,windows-2019_arm64'
pull_request:
paths-ignore:
- 'versions-manifest.json'
@@ -44,33 +39,31 @@ jobs:
- name: Generate execution matrix
id: generate-matrix
run: |
[String[]]$configurations = "${{ inputs.platforms || 'ubuntu-22.04,ubuntu-22.04_arm64,ubuntu-24.04,ubuntu-24.04_arm64,macos-13,macos-14_arm64,windows-2019_x64,windows-2019_x86,windows-11_arm64' }}".Split(",").Trim()
[String[]]$buildModes = "${{ inputs.threading_build_modes || 'default' }}".Split(",").Trim()
[String[]]$configurations = "${{ inputs.platforms || 'ubuntu-20.04,ubuntu-22.04,ubuntu-22.04_arm64,ubuntu-24.04,macos-11,macos-14_arm64,windows-2019_x64,windows-2019_x86,windows-2019_arm64' }}".Split(",").Trim()
$matrix = @()
foreach ($configuration in $configurations) {
foreach ($buildMode in $buildModes) {
$parts = $configuration.Split("_")
$os = $parts[0]
$arch = if ($parts[1]) {$parts[1]} else {"x64"}
switch -wildcard ($os) {
"*ubuntu*" { $platform = $os.Replace("ubuntu","linux"); if ($arch -eq "arm64" ) { $os = "${os}-arm" } }
"*macos*" { $platform = 'darwin' }
"*windows*" { $platform = 'win32'; if ($arch -eq "arm64" ) { $os = "${os}-arm" } }
}
$parts = $configuration.Split("_")
$os = $parts[0]
$arch = if ($parts[1]) {$parts[1]} else {"x64"}
if ($buildMode -eq "freethreaded") {
if ([semver]"${{ inputs.VERSION }}" -lt [semver]"3.13.0") {
continue;
}
$arch += "-freethreaded"
}
switch -wildcard ($os) {
"*ubuntu*" { $platform = $os.Replace("ubuntu","linux")}
"*macos*" { $platform = 'darwin' }
"*windows*" { $platform = 'win32' }
}
if ($configuration -eq "ubuntu-22.04_arm64") {
$os = "setup-actions-ubuntu-arm64-2-core"
}elseif ($configuration -eq "windows-2019_arm64") {
$os = "setup-actions-windows-arm64-4-core"
}
$matrix += @{
'platform' = $platform
'os' = $os
'arch' = $arch
$matrix += @{
'platform' = $platform
'os' = $os
'arch' = $arch
}
}
}
echo "matrix=$($matrix | ConvertTo-Json -Compress -AsArray)" >> $env:GITHUB_OUTPUT
@@ -85,20 +78,39 @@ jobs:
env:
ARTIFACT_NAME: python-${{ inputs.VERSION || '3.12.3' }}-${{ matrix.platform }}-${{ matrix.arch }}
steps:
- name: Setup Environment on Windows ARM64 Runner
if: matrix.os == 'setup-actions-windows-arm64-4-core'
shell: powershell
run: |
# Install Chocolatey
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
echo "C:\ProgramData\Chocolatey\bin" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
# Install PowerShell
choco install powershell-core -y
echo "C:\Program Files\PowerShell\7" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
# Install Git
choco install git -y
echo "C:\Program Files\Git\cmd" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
# Install 7-Zip
choco install 7zip -y
echo "C:\ProgramData\chocolatey\bin" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
- name: Check out repository code
uses: actions/checkout@v4
with:
submodules: true
- name: Adding Symlink
if: matrix.os == 'macos-13'
run: ln -sf /usr/local/opt/tcl-tk@8 /usr/local/opt/tcl-tk
- name: Build Python ${{ env.VERSION }}
run: |
./builders/build-python.ps1 -Version $env:VERSION `
-Platform ${{ matrix.platform }} -Architecture ${{ matrix.arch }}
- name: Publish artifact
uses: actions/upload-artifact@v4
with:
@@ -116,6 +128,30 @@ jobs:
env:
ARTIFACT_NAME: python-${{ inputs.VERSION || '3.12.3' }}-${{ matrix.platform }}-${{ matrix.arch }}
steps:
- name: Setup Environment on Windows ARM64 Runner
if: matrix.os == 'setup-actions-windows-arm64-4-core'
shell: powershell
run: |
# Install Chocolatey
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
echo "C:\ProgramData\Chocolatey\bin" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
# Install PowerShell
choco install powershell-core -y
echo "C:\Program Files\PowerShell\7" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
# Install Git
choco install git -y
echo "C:\Program Files\Git\cmd" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
# Install 7-Zip
choco install 7zip -y
echo "C:\ProgramData\chocolatey\bin" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
- name: Check out repository code
uses: actions/checkout@v4
with:
@@ -135,6 +171,7 @@ jobs:
name: ${{ env.ARTIFACT_NAME }}
path: ${{ runner.temp }}/${{ env.ARTIFACT_NAME }}
- name: Extract files
run: |
if ('${{ matrix.platform }}' -eq 'win32') {
@@ -163,9 +200,6 @@ jobs:
python-version: ${{ env.VERSION }}
architecture: ${{ matrix.arch }}
- name: Python version
run: python -VVV
- name: Verbose sysconfig dump
if: runner.os == 'Linux' || runner.os == 'macOS'
run: python ./sources/python-config-output.py
@@ -176,7 +210,6 @@ jobs:
run: |
$pythonLocation = which python
if ('${{ matrix.platform }}' -eq 'darwin') { otool -L $pythonLocation } else { ldd $pythonLocation }
- name: Run tests
run: |
Install-Module Pester -Force -Scope CurrentUser -SkipPublisherCheck
@@ -211,7 +244,6 @@ jobs:
release_name: ${{ env.VERSION }}
body: |
Python ${{ env.VERSION }}
- name: Generate hash for packages
run: |
$childItems = Get-Childitem -Path '.'

View File

@@ -13,5 +13,4 @@ jobs:
name: CodeQL analysis
uses: actions/reusable-workflows/.github/workflows/codeql-analysis.yml@main
with:
languages: '["python"]'
languages: "['python']"

View File

@@ -14,8 +14,8 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-22.04, ubuntu-latest, macos-13]
python: [3.9.13, 3.10.11, 3.11.8, 3.12.7, 3.13.0]
os: [macos-latest, windows-latest, ubuntu-20.04, ubuntu-22.04]
python: [3.9.13, 3.10.11, 3.11.8]
steps:
- name: setup-python ${{ matrix.python }}
uses: actions/setup-python@v5

View File

@@ -17,7 +17,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-22.04, ubuntu-latest, macos-13]
os: [macos-latest, windows-latest, ubuntu-20.04, ubuntu-22.04]
steps:
- name: Setup Python ${{ github.event.inputs.version }}
uses: actions/setup-python@main

View File

@@ -31,6 +31,14 @@ class macOSPythonBuilder : NixPythonBuilder {
.SYNOPSIS
Prepare system environment by installing dependencies and required packages.
#>
if ($this.Version -eq "3.7.17") {
# We have preinstalled ncurses and readLine on the hoster runners. But we need to install bzip2 for
# setting up an environemnt
# If we get any issues realted to ncurses or readline we can try to run this command
# brew install ncurses readline
Execute-Command -Command "brew install bzip2"
}
}
[void] Configure() {
@@ -50,20 +58,46 @@ class macOSPythonBuilder : NixPythonBuilder {
### will never be used itself by a Github Actions runner but using a universal2 Python is the only way to build
### universal2 C extensions and wheels. This is supported by Python >= 3.10 and was backported to Python >=
### 3.9.1 and >= 3.8.10.
### Disabled, discussion: https://github.com/actions/python-versions/pull/114
# if ($this.Version -ge "3.8.10" -and $this.Version -ne "3.8.13" -and $this.Version -ne "3.9.0" ) {
# $configureString += " --enable-universalsdk --with-universal-archs=universal2"
# }
### OS X 10.11, Apple no longer provides header files for the deprecated system version of OpenSSL.
### Solution is to install these libraries from a third-party package manager,
### and then add the appropriate paths for the header and library files to configure command.
### Link to documentation (https://cpython-devguide.readthedocs.io/setup/#build-dependencies)
$configureString += " --with-openssl=/usr/local/opt/openssl@3"
$configureString += " --with-tcltk-includes='-I /usr/local/opt/tcl-tk/include/tcl-tk' --with-tcltk-libs='-L/usr/local/opt/tcl-tk/lib -ltcl8.6 -ltk8.6'"
if ($this.Version -lt "3.7.0") {
$env:LDFLAGS = "-L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/zlib/lib"
$env:CFLAGS = "-I/usr/local/opt/openssl@1.1/include -I/usr/local/opt/zlib/include"
} else {
$configureString += " --with-openssl=/usr/local/opt/openssl@1.1"
### Compile with support of loadable sqlite extensions.
# For Python 3.7.2 and 3.7.3 we need to provide PATH for zlib to pack it properly. Otherwise the build will fail
# with the error: zipimport.ZipImportError: can't decompress data; zlib not available
if ($this.Version -eq "3.7.2" -or $this.Version -eq "3.7.3" -or $this.Version -eq "3.7.17") {
$env:LDFLAGS = "-L/usr/local/opt/zlib/lib"
$env:CFLAGS = "-I/usr/local/opt/zlib/include"
}
if ($this.Version -gt "3.7.12") {
$configureString += " --with-tcltk-includes='-I /usr/local/opt/tcl-tk/include' --with-tcltk-libs='-L/usr/local/opt/tcl-tk/lib -ltcl8.6 -ltk8.6'"
}
if ($this.Version -eq "3.7.17") {
$env:LDFLAGS += " -L$(brew --prefix bzip2)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix ncurses)/lib"
$env:CFLAGS += " -I$(brew --prefix bzip2)/include -I$(brew --prefix readline)/include -I$(brew --prefix ncurses)/include"
}
}
### Compile with support of loadable sqlite extensions. Unavailable for Python 2.*
### Link to documentation (https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.enable_load_extension)
$configureString += " --enable-loadable-sqlite-extensions"
$env:LDFLAGS += " -L$(brew --prefix sqlite3)/lib"
$env:CFLAGS += " -I$(brew --prefix sqlite3)/include"
$env:CPPFLAGS += "-I$(brew --prefix sqlite3)/include"
if ($this.Version -ge "3.2.0") {
$configureString += " --enable-loadable-sqlite-extensions"
$env:LDFLAGS += " -L$(brew --prefix sqlite3)/lib"
$env:CFLAGS += " -I$(brew --prefix sqlite3)/include"
$env:CPPFLAGS += "-I$(brew --prefix sqlite3)/include"
}
Write-Host "The passed configure options are: "
Write-Host $configureString
@@ -117,37 +151,6 @@ class macOSPythonBuilder : NixPythonBuilder {
return $pkgLocation
}
[string] GetFrameworkName() {
<#
.SYNOPSIS
Get the Python installation Package name.
#>
if ($this.IsFreeThreaded()) {
return "PythonT.framework"
} else {
return "Python.framework"
}
}
[string] GetPkgChoices() {
<#
.SYNOPSIS
Reads the configuration XML file for the Python installer
#>
$config = if ($this.IsFreeThreaded()) { "freethreaded" } else { "default" }
$choicesFile = Join-Path $PSScriptRoot "../config/macos-pkg-choices-$($config).xml"
$choicesTemplate = Get-Content -Path $choicesFile -Raw
$variablesToReplace = @{
"{{__VERSION_MAJOR_MINOR__}}" = "$($this.Version.Major).$($this.Version.Minor)";
}
$variablesToReplace.keys | ForEach-Object { $choicesTemplate = $choicesTemplate.Replace($_, $variablesToReplace[$_]) }
return $choicesTemplate
}
[void] CreateInstallationScriptPkg() {
<#
.SYNOPSIS
@@ -162,8 +165,6 @@ class macOSPythonBuilder : NixPythonBuilder {
"{{__VERSION_FULL__}}" = $this.Version;
"{{__PKG_NAME__}}" = $this.GetPkgName();
"{{__ARCH__}}" = $this.Architecture;
"{{__FRAMEWORK_NAME__}}" = $this.GetFrameworkName();
"{{__PKG_CHOICES__}}" = $this.GetPkgChoices();
}
$variablesToReplace.keys | ForEach-Object { $installationTemplateContent = $installationTemplateContent.Replace($_, $variablesToReplace[$_]) }

View File

@@ -1,168 +0,0 @@
using module "./python-builder.psm1"
class NixPythonBuilder : PythonBuilder {
<#
.SYNOPSIS
Base Python builder class for *Nix systems.
.DESCRIPTION
Contains methods that required to build Python artifact for *nix systems. Inherited from base PythonBuilder class.
.PARAMETER version
The version of Python that should be built.
.PARAMETER Platform
The type of platform for which Python should be built.
.PARAMETER PlatformVersion
The version of platform for which Python should be built.
.PARAMETER InstallationTemplateName
The name of template that will be used to create installation script for generated Python artifact.
.PARAMETER InstallationScriptName
The name of installation script that will be generated for Python artifact.
.PARAMETER OutputArtifactName
The name of archive with Python binaries that will be generated as part of Python artifact.
#>
[string] $InstallationTemplateName
[string] $InstallationScriptName
[string] $OutputArtifactName
NixPythonBuilder(
[semver] $version,
[string] $architecture,
[string] $platform
) : Base($version, $architecture, $platform) {
$this.InstallationTemplateName = "nix-setup-template.sh"
$this.InstallationScriptName = "setup.sh"
$this.OutputArtifactName = "python-$Version-$Platform-$Architecture.tar.gz"
}
[uri] GetSourceUri() {
<#
.SYNOPSIS
Get base Python URI and return complete URI for Python sources.
#>
$base = $this.GetBaseUri()
$versionName = $this.GetBaseVersion()
$nativeVersion = Convert-Version -version $this.Version
return "${base}/${versionName}/Python-${nativeVersion}.tgz"
}
[string] GetPythonBinary() {
<#
.SYNOPSIS
Return name of Python binary.
#>
return "python3"
}
[string] Download() {
<#
.SYNOPSIS
Download Python sources and extract them at temporary work folder. Returns expanded archive location path.
#>
$sourceUri = $this.GetSourceUri()
Write-Host "Sources URI: $sourceUri"
$archiveFilepath = Download-File -Uri $sourceUri -OutputFolder $this.WorkFolderLocation
$expandedSourceLocation = Join-Path -Path $this.TempFolderLocation -ChildPath "SourceCode"
New-Item -Path $expandedSourceLocation -ItemType Directory
Extract-TarArchive -ArchivePath $archiveFilepath -OutputDirectory $expandedSourceLocation
Write-Debug "Done; Sources location: $expandedSourceLocation"
return $expandedSourceLocation
}
[void] CreateInstallationScript() {
<#
.SYNOPSIS
Create Python artifact installation script based on template specified in InstallationTemplateName property.
#>
$installationScriptLocation = New-Item -Path $this.WorkFolderLocation -Name $this.InstallationScriptName -ItemType File
$installationTemplateLocation = Join-Path -Path $this.InstallationTemplatesLocation -ChildPath $this.InstallationTemplateName
$installationTemplateContent = Get-Content -Path $installationTemplateLocation -Raw
$variablesToReplace = @{
"{{__VERSION_FULL__}}" = $this.Version;
"{{__ARCH__}}" = $this.Architecture;
}
$variablesToReplace.keys | ForEach-Object { $installationTemplateContent = $installationTemplateContent.Replace($_, $variablesToReplace[$_]) }
$installationTemplateContent | Out-File -FilePath $installationScriptLocation
Write-Debug "Done; Installation script location: $installationScriptLocation)"
}
[void] Make() {
<#
.SYNOPSIS
Executes "make" and "make install" commands for configured build sources. Make output will be writen in build_output.txt located in artifact location folder.
#>
Write-Debug "make Python $($this.Version)-$($this.Architecture) $($this.Platform)"
$buildOutputLocation = New-Item -Path $this.WorkFolderLocation -Name "build_output.txt" -ItemType File
Execute-Command -Command "make 2>&1 | tee $buildOutputLocation" -ErrorAction Continue
Execute-Command -Command "make install" -ErrorAction Continue
Write-Debug "Done; Make log location: $buildOutputLocation"
}
[void] CopyBuildResults() {
$buildFolder = $this.GetFullPythonToolcacheLocation()
Move-Item -Path "$buildFolder/*" -Destination $this.WorkFolderLocation
}
[void] ArchiveArtifact() {
$OutputPath = Join-Path $this.ArtifactFolderLocation $this.OutputArtifactName
Create-TarArchive -SourceFolder $this.WorkFolderLocation -ArchivePath $OutputPath
}
[void] Build() {
<#
.SYNOPSIS
Build Python artifact from sources.
#>
Write-Host "Prepare Python Hostedtoolcache location..."
$this.PreparePythonToolcacheLocation()
Write-Host "Prepare system environment..."
$this.PrepareEnvironment()
Write-Host "Download Python $($this.Version)[$($this.Architecture)] sources..."
$sourcesLocation = $this.Download()
Push-Location -Path $sourcesLocation
Write-Host "Configure for $($this.Platform)..."
$this.Configure()
Write-Host "Make for $($this.Platform)..."
$this.Make()
Pop-Location
Write-Host "Generate structure dump"
New-ToolStructureDump -ToolPath $this.GetFullPythonToolcacheLocation() -OutputFolder $this.WorkFolderLocation
Write-Host "Copying build results to destination location"
$this.CopyBuildResults()
Write-Host "Create installation script..."
$this.CreateInstallationScript()
Write-Host "Archive artifact..."
$this.ArchiveArtifact()
}
}

View File

@@ -94,24 +94,6 @@ class PythonBuilder {
return "$($this.Version.Major).$($this.Version.Minor).$($this.Version.Patch)"
}
[string] GetHardwareArchitecture() {
<#
.SYNOPSIS
The hardware architecture (x64, arm64) without any Python free threading suffix.
#>
return $this.Architecture.Replace("-freethreaded", "")
}
[bool] IsFreeThreaded() {
<#
.SYNOPSIS
Check if Python version is free threaded.
#>
return $this.Architecture.EndsWith("-freethreaded")
}
[void] PreparePythonToolcacheLocation() {
<#
.SYNOPSIS

View File

@@ -37,14 +37,6 @@ class UbuntuPythonBuilder : NixPythonBuilder {
$configureString += " --enable-shared"
$configureString += " --enable-optimizations"
if ($this.IsFreeThreaded()) {
if ($this.Version -lt "3.13.0") {
Write-Host "Python versions lower than 3.13.0 do not support free threading"
exit 1
}
$configureString += " --disable-gil"
}
### Compile with support of loadable sqlite extensions.
### Link to documentation (https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.enable_load_extension)
$configureString += " --enable-loadable-sqlite-extensions"
@@ -61,8 +53,8 @@ class UbuntuPythonBuilder : NixPythonBuilder {
Prepare system environment by installing dependencies and required packages.
#>
if ($this.Version -lt "3.9.0") {
Write-Host "Python versions lower than 3.9.0 are not supported"
if ($this.Version -lt "3.5.3") {
Write-Host "Python versions lower than 3.5.3 are not supported"
exit 1
}

View File

@@ -1,3 +1,4 @@
using module "./python-builder.psm1"
class WinPythonBuilder : PythonBuilder {
@@ -42,7 +43,9 @@ class WinPythonBuilder : PythonBuilder {
Return extension for required version of Python executable.
#>
return ".exe"
$extension = if ($this.Version -lt "3.5" -and $this.Version -ge "2.5") { ".msi" } else { ".exe" }
return $extension
}
[string] GetArchitectureExtension() {
@@ -52,12 +55,17 @@ class WinPythonBuilder : PythonBuilder {
#>
$ArchitectureExtension = ""
if ($this.GetHardwareArchitecture() -eq "x64") {
$ArchitectureExtension = "-amd64"
} elseif ($this.GetHardwareArchitecture() -eq "arm64") {
if ($this.Architecture -eq "x64") {
if ($this.Version -ge "3.5") {
$ArchitectureExtension = "-amd64"
} else {
$ArchitectureExtension = ".amd64"
}
}elseif ($this.Architecture -eq "arm64") {
$ArchitectureExtension = "-arm64"
}
return $ArchitectureExtension
}
@@ -107,7 +115,6 @@ class WinPythonBuilder : PythonBuilder {
$variablesToReplace = @{
"{{__ARCHITECTURE__}}" = $this.Architecture;
"{{__HARDWARE_ARCHITECTURE__}}" = $this.GetHardwareArchitecture();
"{{__VERSION__}}" = $this.Version;
"{{__PYTHON_EXEC_NAME__}}" = $pythonExecName
}

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
</dict>
</array>
</plist>

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>attributeSetting</key>
<integer>1</integer>
<key>choiceAttribute</key>
<string>selected</string>
<key>choiceIdentifier</key>
<string>org.python.Python.PythonTFramework-{{__VERSION_MAJOR_MINOR__}}</string>
</dict>
</array>
</plist>

View File

@@ -1,5 +1,5 @@
{
"regex": "python-\\d+\\.\\d+\\.\\d+-(\\w+\\.\\d+)?-?(\\w+)-(\\d+\\.\\d+)?-?((x|arm)\\d+(-freethreaded)?)",
"regex": "python-\\d+\\.\\d+\\.\\d+-(\\w+\\.\\d+)?-?(\\w+)-(\\d+\\.\\d+)?-?((x|arm)\\d+)",
"groups": {
"arch": 4,
"platform": 2,

View File

@@ -2,11 +2,6 @@ set -e
PYTHON_FULL_VERSION="{{__VERSION_FULL__}}"
PYTHON_PKG_NAME="{{__PKG_NAME__}}"
PYTHON_FRAMEWORK_NAME="{{__FRAMEWORK_NAME__}}"
PYTHON_PKG_CHOICES=$(cat << 'EOF'
{{__PKG_CHOICES__}}
EOF
)
ARCH="{{__ARCH__}}"
MAJOR_VERSION=$(echo $PYTHON_FULL_VERSION | cut -d '.' -f 1)
MINOR_VERSION=$(echo $PYTHON_FULL_VERSION | cut -d '.' -f 2)
@@ -25,7 +20,7 @@ fi
PYTHON_TOOLCACHE_PATH=$TOOLCACHE_ROOT/Python
PYTHON_TOOLCACHE_VERSION_PATH=$PYTHON_TOOLCACHE_PATH/$PYTHON_FULL_VERSION
PYTHON_TOOLCACHE_VERSION_ARCH_PATH=$PYTHON_TOOLCACHE_VERSION_PATH/$ARCH
PYTHON_FRAMEWORK_PATH="/Library/Frameworks/${PYTHON_FRAMEWORK_NAME}/Versions/${MAJOR_VERSION}.${MINOR_VERSION}"
PYTHON_FRAMEWORK_PATH="/Library/Frameworks/Python.framework/Versions/${MAJOR_VERSION}.${MINOR_VERSION}"
PYTHON_APPLICATION_PATH="/Applications/Python ${MAJOR_VERSION}.${MINOR_VERSION}"
echo "Check if Python hostedtoolcache folder exist..."
@@ -43,11 +38,8 @@ else
done
fi
PYTHON_PKG_CHOICES_FILES=$(mktemp)
echo "$PYTHON_PKG_CHOICES" > $PYTHON_PKG_CHOICES_FILES
echo "Install Python binaries from prebuilt package"
sudo installer -pkg $PYTHON_PKG_NAME -applyChoiceChangesXML $PYTHON_PKG_CHOICES_FILES -target /
sudo installer -pkg $PYTHON_PKG_NAME -target /
echo "Create hostedtoolcach symlinks (Required for the backward compatibility)"
echo "Create Python $PYTHON_FULL_VERSION folder"
@@ -61,9 +53,7 @@ ln -s "${PYTHON_FRAMEWORK_PATH}/lib" lib
echo "Create additional symlinks (Required for the UsePythonVersion Azure Pipelines task and the setup-python GitHub Action)"
ln -s ./bin/$PYTHON_MAJOR_DOT_MINOR python
chmod +x python
# Note that bin is a symlink so referencing .. from bin will not work as expected
cd bin/
# This symlink already exists if Python version with the same major.minor version is installed,
@@ -72,15 +62,11 @@ if [ ! -f $PYTHON_MAJOR_MINOR ]; then
ln -s $PYTHON_MAJOR_DOT_MINOR $PYTHON_MAJOR_MINOR
fi
if [ ! -f $PYTHON_MAJOR ]; then
ln -s $PYTHON_MAJOR_DOT_MINOR $PYTHON_MAJOR
fi
if [ ! -f python ]; then
ln -s $PYTHON_MAJOR_DOT_MINOR python
fi
chmod +x $PYTHON_MAJOR $PYTHON_MAJOR_DOT_MINOR $PYTHON_MAJOR_MINOR python
chmod +x ../python $PYTHON_MAJOR $PYTHON_MAJOR_DOT_MINOR $PYTHON_MAJOR_MINOR python
echo "Upgrading pip..."
export PIP_ROOT_USER_ACTION=ignore

View File

@@ -24,9 +24,9 @@ echo "Check if Python hostedtoolcache folder exist..."
if [ ! -d $PYTHON_TOOLCACHE_PATH ]; then
echo "Creating Python hostedtoolcache folder..."
mkdir -p $PYTHON_TOOLCACHE_PATH
elif [ -d $PYTHON_TOOLCACHE_VERSION_ARCH_PATH ]; then
echo "Deleting Python $PYTHON_FULL_VERSION ($ARCH)"
rm -rf $PYTHON_TOOLCACHE_VERSION_ARCH_PATH
elif [ -d $PYTHON_TOOLCACHE_VERSION_PATH ]; then
echo "Deleting Python $PYTHON_FULL_VERSION"
rm -rf $PYTHON_TOOLCACHE_VERSION_PATH
fi
echo "Create Python $PYTHON_FULL_VERSION folder"
@@ -55,4 +55,4 @@ export PIP_ROOT_USER_ACTION=ignore
./python -m pip install --upgrade --force-reinstall pip --disable-pip-version-check --no-warn-script-location
echo "Create complete file"
touch $PYTHON_TOOLCACHE_VERSION_PATH/$ARCH.complete
touch $PYTHON_TOOLCACHE_VERSION_PATH/$ARCH.complete

View File

@@ -1,5 +1,4 @@
[String] $Architecture = "{{__ARCHITECTURE__}}"
[String] $HardwareArchitecture = "{{__HARDWARE_ARCHITECTURE__}}"
[String] $Version = "{{__VERSION__}}"
[String] $PythonExecName = "{{__PYTHON_EXEC_NAME__}}"
@@ -11,7 +10,12 @@ function Get-RegistryVersionFilter {
)
$archFilter = if ($Architecture -eq 'x86') { "32-bit" } else { "64-bit" }
"Python $MajorVersion.$MinorVersion.*($archFilter)"
### Python 2.7 x86 have no architecture postfix
if (($Architecture -eq "x86") -and ($MajorVersion -eq 2)) {
"Python $MajorVersion.$MinorVersion.\d+$"
} else {
"Python $MajorVersion.$MinorVersion.*($archFilter)"
}
}
function Remove-RegistryEntries {
@@ -21,7 +25,7 @@ function Remove-RegistryEntries {
[Parameter(Mandatory)][Int32] $MinorVersion
)
$versionFilter = Get-RegistryVersionFilter -Architecture $HardwareArchitecture -MajorVersion $MajorVersion -MinorVersion $MinorVersion
$versionFilter = Get-RegistryVersionFilter -Architecture $Architecture -MajorVersion $MajorVersion -MinorVersion $MinorVersion
$regPath = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products"
if (Test-Path -Path Registry::$regPath) {
@@ -57,15 +61,13 @@ function Remove-RegistryEntries {
function Get-ExecParams {
param(
[Parameter(Mandatory)][Boolean] $IsMSI,
[Parameter(Mandatory)][Boolean] $IsFreeThreaded,
[Parameter(Mandatory)][String] $PythonArchPath
)
if ($IsMSI) {
"TARGETDIR=$PythonArchPath ALLUSERS=1"
} else {
$Include_freethreaded = if ($IsFreeThreaded) { "Include_freethreaded=1" } else { "" }
"DefaultAllUsersTargetDir=$PythonArchPath InstallAllUsers=1 $Include_freethreaded"
"DefaultAllUsersTargetDir=$PythonArchPath InstallAllUsers=1"
}
}
@@ -79,7 +81,6 @@ $PythonVersionPath = Join-Path -Path $PythonToolcachePath -ChildPath $Version
$PythonArchPath = Join-Path -Path $PythonVersionPath -ChildPath $Architecture
$IsMSI = $PythonExecName -match "msi"
$IsFreeThreaded = $Architecture -match "-freethreaded"
$MajorVersion = $Version.Split('.')[0]
$MinorVersion = $Version.Split('.')[1]
@@ -119,21 +120,17 @@ Write-Host "Copy Python binaries to $PythonArchPath"
Copy-Item -Path ./$PythonExecName -Destination $PythonArchPath | Out-Null
Write-Host "Install Python $Version in $PythonToolcachePath..."
$ExecParams = Get-ExecParams -IsMSI $IsMSI -IsFreeThreaded $IsFreeThreaded -PythonArchPath $PythonArchPath
$ExecParams = Get-ExecParams -IsMSI $IsMSI -PythonArchPath $PythonArchPath
cmd.exe /c "cd $PythonArchPath && call $PythonExecName $ExecParams /quiet"
if ($LASTEXITCODE -ne 0) {
Throw "Error happened during Python installation"
}
if ($IsFreeThreaded) {
# Delete python.exe and create a symlink to free-threaded exe
Remove-Item -Path "$PythonArchPath\python.exe" -Force
New-Item -Path "$PythonArchPath\python.exe" -ItemType SymbolicLink -Value "$PythonArchPath\python${MajorVersion}.${MinorVersion}t.exe"
}
Write-Host "Create `python3` symlink"
New-Item -Path "$PythonArchPath\python3.exe" -ItemType SymbolicLink -Value "$PythonArchPath\python.exe"
if ($MajorVersion -ne "2") {
New-Item -Path "$PythonArchPath\python3.exe" -ItemType SymbolicLink -Value "$PythonArchPath\python.exe"
}
Write-Host "Install and upgrade Pip"
$Env:PIP_ROOT_USER_ACTION = "ignore"

View File

@@ -4,33 +4,19 @@ $ConfigurationFile = Join-Path $PSScriptRoot "../config/python-manifest-config.j
$Configuration = Read-ConfigurationFile -Filepath $ConfigurationFile
$stableTestCases = @(
@{ ReleaseName = "python-3.13.0-darwin-x64.tar.gz"; ExpectedResult = @{ platform = "darwin"; platform_version = $null; arch = "x64"} },
@{ ReleaseName = "python-3.13.0-linux-20.04-x64.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "20.04"; arch = "x64"} },
@{ ReleaseName = "python-3.13.0-linux-22.04-x64.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "22.04"; arch = "x64"} },
@{ ReleaseName = "python-3.13.0-win32-x64.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x64"} },
@{ ReleaseName = "python-3.13.0-win32-x86.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x86"} },
@{ ReleaseName = "python-3.13.0-darwin-x64-freethreaded.tar.gz"; ExpectedResult = @{ platform = "darwin"; platform_version = $null; arch = "x64-freethreaded"} },
@{ ReleaseName = "python-3.13.0-linux-20.04-x64-freethreaded.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "20.04"; arch = "x64-freethreaded"} },
@{ ReleaseName = "python-3.13.0-linux-22.04-x64-freethreaded.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "22.04"; arch = "x64-freethreaded"} },
@{ ReleaseName = "python-3.13.0-win32-x64-freethreaded.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x64-freethreaded"} },
@{ ReleaseName = "python-3.13.0-win32-x86-freethreaded.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x86-freethreaded"} }
@{ ReleaseName = "python-3.8.3-darwin-x64.tar.gz"; ExpectedResult = @{ platform = "darwin"; platform_version = $null; arch = "x64"} },
@{ ReleaseName = "python-3.8.3-linux-20.04-x64.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "20.04"; arch = "x64"} },
@{ ReleaseName = "python-3.8.3-linux-22.04-x64.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "22.04"; arch = "x64"} },
@{ ReleaseName = "python-3.8.3-win32-x64.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x64"} },
@{ ReleaseName = "python-3.8.3-win32-x86.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x86"} }
) | ForEach-Object { $_.Configuration = $Configuration; $_ }
$unstableTestCases = @(
@{ ReleaseName = "python-3.14.0-alpha.5-darwin-x64.tar.gz"; ExpectedResult = @{ platform = "darwin"; platform_version = $null; arch = "x64"} },
@{ ReleaseName = "python-3.14.0-alpha.5-linux-20.04-x64.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "20.04"; arch = "x64"} },
@{ ReleaseName = "python-3.14.0-alpha.5-linux-22.04-x64.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "22.04"; arch = "x64"} },
@{ ReleaseName = "python-3.14.0-alpha.5-win32-x64.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x64"} },
@{ ReleaseName = "python-3.14.0-alpha.5-win32-x86.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x86"} },
@{ ReleaseName = "python-3.14.0-alpha.5-darwin-x64-freethreaded.tar.gz"; ExpectedResult = @{ platform = "darwin"; platform_version = $null; arch = "x64-freethreaded"} },
@{ ReleaseName = "python-3.14.0-alpha.5-linux-20.04-x64-freethreaded.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "20.04"; arch = "x64-freethreaded"} },
@{ ReleaseName = "python-3.14.0-alpha.5-linux-22.04-x64-freethreaded.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "22.04"; arch = "x64-freethreaded"} },
@{ ReleaseName = "python-3.14.0-alpha.5-win32-x64-freethreaded.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x64-freethreaded"} },
@{ ReleaseName = "python-3.14.0-alpha.5-win32-x86-freethreaded.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x86-freethreaded"} }
@{ ReleaseName = "python-3.9.0-alpha.2-darwin-x64.tar.gz"; ExpectedResult = @{ platform = "darwin"; platform_version = $null; arch = "x64"} },
@{ ReleaseName = "python-3.9.0-beta.2-linux-20.04-x64.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "20.04"; arch = "x64"} },
@{ ReleaseName = "python-3.9.0-rc.4-linux-22.04-x64.tar.gz"; ExpectedResult = @{ platform = "linux"; platform_version = "22.04"; arch = "x64"} },
@{ ReleaseName = "python-3.9.0-beta.2-win32-x64.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x64"} },
@{ ReleaseName = "python-3.9.0-beta.2-win32-x86.zip"; ExpectedResult = @{ platform = "win32"; platform_version = $null; arch = "x86"} }
) | ForEach-Object { $_.Configuration = $Configuration; $_ }
Describe "Python manifest config" {

View File

@@ -7,8 +7,6 @@ param (
$Architecture
)
$HardwareArchitecture = $Architecture -replace "-freethreaded", ""
Import-Module (Join-Path $PSScriptRoot "../helpers/pester-extensions.psm1")
Import-Module (Join-Path $PSScriptRoot "../helpers/common-helpers.psm1")
Import-Module (Join-Path $PSScriptRoot "../builders/python-version.psm1")
@@ -60,7 +58,7 @@ Describe "Tests" {
# }
# }
if (($Version -lt "3.11.0") -and (($Platform -ne "darwin") -or ($HardwareArchitecture -ne "arm64"))) {
if (($Version -ge "3.2.0") -and ($Version -lt "3.11.0") -and (($Platform -ne "darwin") -or ($Architecture -ne "arm64"))) {
It "Check if sqlite3 module is installed" {
"python ./sources/python-sqlite3.py" | Should -ReturnZeroExitCode
}
@@ -92,6 +90,16 @@ Describe "Tests" {
}
}
# Pyinstaller 3.5 does not support Python 3.8.0. Check issue https://github.com/pyinstaller/pyinstaller/issues/4311
if ($Version -lt "3.8.0" -and $Version.Major -ne "2") {
It "Validate Pyinstaller" {
"pip install pyinstaller" | Should -ReturnZeroExitCode
"pyinstaller --onefile ./sources/simple-test.py" | Should -ReturnZeroExitCode
$distPath = [IO.Path]::Combine($pwd, "dist", "simple-test")
"$distPath" | Should -ReturnZeroExitCode
}
}
It "Check urlopen with HTTPS works" {
"python ./sources/python-urlopen-https.py" | Should -ReturnZeroExitCode
}

View File

@@ -8,31 +8,25 @@ os_type = platform.system()
version = sys.argv[1]
nativeVersion = sys.argv[2]
architecture = sys.argv[3]
hw_architecture = architecture.replace('-freethreaded', '')
versions=version.split(".")
version_major=int(versions[0])
version_minor=int(versions[1])
pkg_installer = os_type == 'Darwin' and ((version_major == 3 and version_minor >= 11) or (hw_architecture == "arm64"))
pkg_installer = os_type == 'Darwin' and ((version_major == 3 and version_minor >= 11) or (architecture == "arm64"))
lib_dir_path = sysconfig.get_config_var('LIBDIR')
ld_library_name = sysconfig.get_config_var('LDLIBRARY')
is_shared = sysconfig.get_config_var('Py_ENABLE_SHARED')
have_libreadline = sysconfig.get_config_var("HAVE_LIBREADLINE")
is_free_threaded = sysconfig.get_config_var('Py_GIL_DISABLED')
### Define expected variables
if os_type == 'Linux': expected_ld_library_extension = 'so'
if os_type == 'Darwin': expected_ld_library_extension = 'dylib'
if is_free_threaded:
framework_name = 'PythonT.framework'
else:
framework_name = 'Python.framework'
if pkg_installer:
expected_lib_dir_path = f'/Library/Frameworks/{framework_name}/Versions/{version_major}.{version_minor}/lib'
expected_lib_dir_path = f'/Library/Frameworks/Python.framework/Versions/{version_major}.{version_minor}/lib'
else:
expected_lib_dir_path = f'{os.getenv("AGENT_TOOLSDIRECTORY")}/Python/{version}/{architecture}/lib'
@@ -60,15 +54,15 @@ else:
if os_type == 'Darwin':
### Validate openssl links
if version_major == 3 and version_minor < 7:
expected_ldflags = '-L/usr/local/opt/openssl@3/lib'
expected_ldflags = '-L/usr/local/opt/openssl@1.1/lib'
ldflags = sysconfig.get_config_var('LDFLAGS')
if not expected_ldflags in ldflags:
print('Invalid ldflags: %s; Expected: %s' % (ldflags, expected_ldflags))
exit(1)
else:
expected_openssl_includes = '-I/usr/local/opt/openssl@3/include'
expected_openssl_ldflags ='-L/usr/local/opt/openssl@3/lib'
expected_openssl_includes = '-I/usr/local/opt/openssl@1.1/include'
expected_openssl_ldflags ='-L/usr/local/opt/openssl@1.1/lib'
openssl_includes = sysconfig.get_config_var('OPENSSL_INCLUDES')
openssl_ldflags = sysconfig.get_config_var('OPENSSL_LDFLAGS')

View File

@@ -3,10 +3,12 @@ Make sure all the optional modules are installed.
This is needed for Linux since we build from source.
"""
from __future__ import print_function
import importlib
import sys
# The Python standard library as of Python 3.9
# The Python standard library as of Python 3.0
standard_library = [
'abc',
'aifc',
@@ -15,7 +17,6 @@ standard_library = [
'ast',
'asynchat',
'asyncore',
'asyncio',
'base64',
'bdb',
'binhex',
@@ -33,17 +34,14 @@ standard_library = [
'collections',
'colorsys',
'compileall',
'concurrent',
'configparser',
'contextlib',
'contextvars',
'copy',
'copyreg',
'crypt',
'csv',
'ctypes',
'curses',
'dataclasses',
'datetime',
'dbm',
'decimal',
@@ -51,11 +49,9 @@ standard_library = [
'dis',
'distutils',
'doctest',
'dummy_threading',
'email',
'encodings',
'ensurepip',
'enum',
'faulthandler',
'filecmp',
'fileinput',
'fnmatch',
@@ -81,14 +77,13 @@ standard_library = [
'importlib',
'inspect',
'io',
'ipaddress',
'json',
'keyword',
'lib2to3',
'linecache',
'locale',
'logging',
'lzma',
'macpath',
'mailbox',
'mailcap',
'mimetypes',
@@ -103,7 +98,6 @@ standard_library = [
'operator',
'optparse',
'os',
'pathlib',
'pdb',
'pickle',
'pickletools',
@@ -130,8 +124,6 @@ standard_library = [
'rlcompleter',
'runpy',
'sched',
'secrets',
'selectors',
'shelve',
'shlex',
'shutil',
@@ -149,7 +141,6 @@ standard_library = [
'ssl',
'_ssl',
'stat',
'statistics',
'string',
'stringprep',
'struct',
@@ -172,17 +163,14 @@ standard_library = [
'tokenize',
'trace',
'traceback',
'tracemalloc',
'tty',
'turtle',
'turtledemo',
'types',
'typing',
'unittest',
'urllib',
'uu',
'uuid',
'venv',
'warnings',
'wave',
'weakref',
@@ -191,12 +179,83 @@ standard_library = [
'xdrlib',
'xml',
'xmlrpc',
'zipapp',
'zipfile'
]
# Modules that had different names in Python 2
if sys.version_info.major == 2:
def replace(lst, old, new):
lst[lst.index(old)] = new
# Keys are the Python 2 names
# Values are the Python 3 names
renames = {
'ConfigParser': 'configparser',
'copy_reg': 'copyreg',
'HTMLParser': 'html',
'httplib': 'http',
'Queue': 'queue',
'repr': 'reprlib',
'SocketServer': 'socketserver',
'xmlrpclib': 'xmlrpc',
'Tkinter': 'tkinter'
}
# All of the Python 3 names should be in the list
for python2name, python3name in renames.items():
replace(standard_library, python3name, python2name)
# Add new modules
# See https://docs.python.org/3/whatsnew/index.html
if sys.version_info >= (3, 2):
standard_library.extend([
'concurrent',
])
if sys.version_info >= (3, 3):
standard_library.extend([
'ipaddress',
'faulthandler',
'lzma',
'venv',
])
if sys.version_info >= (3, 4):
standard_library.extend([
'asyncio',
'ensurepip',
'enum',
'pathlib',
'selectors',
'statistics',
'tracemalloc',
])
if sys.version_info >= (3, 5):
standard_library.extend([
'typing',
'zipapp',
])
if sys.version_info >= (3, 6):
standard_library.extend([
'secrets',
])
if sys.version_info >= (3, 7):
standard_library.extend([
'contextvars',
'dataclasses',
])
# 'macpath' module has been removed from Python 3.8
if sys.version_info > (3, 7):
standard_library.remove('macpath')
# 'dummy_threading' module has been removed from Python 3.9
if sys.version_info > (3, 8):
standard_library.remove('dummy_threading')
# 'symbol' and 'formatter' modules have been removed from Python 3.10
if sys.version_info >= (3, 10):
standard_library.remove('symbol')
@@ -236,11 +295,6 @@ if sys.version_info >= (3, 13):
standard_library.remove('uu')
standard_library.remove('xdrlib')
if sys.version_info >= (3, 14):
standard_library.extend([
'annotationlib',
])
# Remove tkinter and Easter eggs
excluded_modules = [
'antigravity',

View File

@@ -1,5 +1,9 @@
import sys
from urllib.request import urlopen
if sys.version_info[0] == 2:
from urllib2 import urlopen
else:
from urllib.request import urlopen
response = urlopen("https://raw.githubusercontent.com/actions/python-versions/c641695f6a07526c18f10e374e503e649fef9427/.gitignore")
data = response.read()

File diff suppressed because it is too large Load Diff