mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
Merge branch 'main' into gh-56809-load-tests-example
This commit is contained in:
commit
e274f3a1a0
4001 changed files with 646815 additions and 363492 deletions
|
@ -1,97 +1,16 @@
|
|||
variables:
|
||||
coverage: false
|
||||
|
||||
trigger: ['main', '3.10', '3.9', '3.8', '3.7']
|
||||
trigger: ['main', '3.12', '3.11', '3.10', '3.9', '3.8', '3.7']
|
||||
|
||||
jobs:
|
||||
- job: Prebuild
|
||||
displayName: Pre-build checks
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-20.04
|
||||
vmImage: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- template: ./prebuild-checks.yml
|
||||
|
||||
|
||||
- job: Docs_PR
|
||||
displayName: Docs PR
|
||||
dependsOn: Prebuild
|
||||
condition: and(succeeded(), eq(dependencies.Prebuild.outputs['docs.run'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- template: ./docs-steps.yml
|
||||
parameters:
|
||||
upload: true
|
||||
|
||||
|
||||
- job: macOS_CI_Tests
|
||||
displayName: macOS CI Tests
|
||||
dependsOn: Prebuild
|
||||
#condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true'))
|
||||
# bpo-39837: macOS tests on Azure Pipelines are disabled
|
||||
condition: false
|
||||
|
||||
variables:
|
||||
testRunTitle: '$(build.sourceBranchName)-macos'
|
||||
testRunPlatform: macos
|
||||
|
||||
pool:
|
||||
vmImage: macos-10.15
|
||||
|
||||
steps:
|
||||
- template: ./macos-steps.yml
|
||||
|
||||
|
||||
- job: Ubuntu_CI_Tests
|
||||
displayName: Ubuntu CI Tests
|
||||
dependsOn: Prebuild
|
||||
condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-20.04
|
||||
|
||||
variables:
|
||||
testRunTitle: '$(build.sourceBranchName)-linux'
|
||||
testRunPlatform: linux
|
||||
openssl_version: 1.1.1n
|
||||
|
||||
steps:
|
||||
- template: ./posix-steps.yml
|
||||
parameters:
|
||||
dependencies: apt
|
||||
|
||||
|
||||
- job: Ubuntu_Coverage_CI_Tests
|
||||
displayName: Ubuntu CI Tests (coverage)
|
||||
dependsOn: Prebuild
|
||||
condition: |
|
||||
and(
|
||||
and(
|
||||
succeeded(),
|
||||
eq(variables['coverage'], 'true')
|
||||
),
|
||||
eq(dependencies.Prebuild.outputs['tests.run'], 'true')
|
||||
)
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-20.04
|
||||
|
||||
variables:
|
||||
testRunTitle: '$(Build.SourceBranchName)-linux-coverage'
|
||||
testRunPlatform: linux-coverage
|
||||
openssl_version: 1.1.1n
|
||||
|
||||
steps:
|
||||
- template: ./posix-steps.yml
|
||||
parameters:
|
||||
dependencies: apt
|
||||
coverage: true
|
||||
|
||||
|
||||
- job: Windows_CI_Tests
|
||||
displayName: Windows CI Tests
|
||||
dependsOn: Prebuild
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
parameters:
|
||||
latex: false
|
||||
upload: false
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 5
|
||||
|
||||
- task: UsePythonVersion@0
|
||||
displayName: 'Use Python 3.6 or later'
|
||||
inputs:
|
||||
versionSpec: '>=3.6'
|
||||
|
||||
- script: python -m pip install -r requirements.txt
|
||||
workingDirectory: '$(build.sourcesDirectory)/Doc'
|
||||
displayName: 'Install build dependencies'
|
||||
|
||||
- ${{ if ne(parameters.latex, 'true') }}:
|
||||
- script: make check html PYTHON=python
|
||||
workingDirectory: '$(build.sourcesDirectory)/Doc'
|
||||
displayName: 'Build documentation'
|
||||
|
||||
- ${{ if eq(parameters.latex, 'true') }}:
|
||||
- script: sudo apt-get update && sudo apt-get install -qy --force-yes texlive-full
|
||||
displayName: 'Install LaTeX'
|
||||
|
||||
- script: make dist PYTHON=python SPHINXBUILD='python -m sphinx' BLURB='python -m blurb'
|
||||
workingDirectory: '$(build.sourcesDirectory)/Doc'
|
||||
displayName: 'Build documentation'
|
||||
|
||||
- ${{ if eq(parameters.upload, 'true') }}:
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish docs'
|
||||
|
||||
inputs:
|
||||
PathToPublish: '$(build.sourcesDirectory)/Doc/build'
|
||||
ArtifactName: docs
|
||||
publishLocation: Container
|
||||
|
||||
- ${{ if eq(parameters.latex, 'true') }}:
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish dist'
|
||||
inputs:
|
||||
PathToPublish: '$(build.sourcesDirectory)/Doc/dist'
|
||||
ArtifactName: docs_dist
|
||||
publishLocation: Container
|
|
@ -1,26 +0,0 @@
|
|||
# Locate a set of the tools used for builds
|
||||
|
||||
steps:
|
||||
- template: windows-release/find-sdk.yml
|
||||
parameters:
|
||||
toolname: 'signtool.exe'
|
||||
|
||||
- powershell: |
|
||||
$vcvarsall = (& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" `
|
||||
-prerelease `
|
||||
-latest `
|
||||
-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
|
||||
-find VC\Auxiliary\Build\vcvarsall.bat)
|
||||
Write-Host "Found vcvarsall at $vcvarsall"
|
||||
Write-Host "##vso[task.setVariable variable=vcvarsall]$vcvarsall"
|
||||
displayName: 'Find vcvarsall.bat'
|
||||
|
||||
- powershell: |
|
||||
$msbuild = (& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" `
|
||||
-prerelease `
|
||||
-latest `
|
||||
-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
|
||||
-find MSBuild\Current\Bin\msbuild.exe)
|
||||
Write-Host "Found MSBuild at $msbuild"
|
||||
Write-Host "##vso[task.setVariable variable=msbuild]$msbuild"
|
||||
displayName: 'Find MSBuild'
|
|
@ -1,86 +0,0 @@
|
|||
name: $(SourceTag)_$(Date:yyyyMMdd)$(Rev:.rr)
|
||||
|
||||
variables:
|
||||
IntDir: '$(Build.BinariesDirectory)'
|
||||
OutDir: '$(Build.ArtifactStagingDirectory)'
|
||||
|
||||
# MUST BE SET AT QUEUE TIME
|
||||
# SigningCertificate: 'Python Software Foundation'
|
||||
# SourcesRepo: 'https://github.com/python/cpython-source-deps'
|
||||
# SourceTag: 'libffi-3.4.2'
|
||||
|
||||
jobs:
|
||||
- job: Build_LibFFI
|
||||
displayName: LibFFI
|
||||
pool:
|
||||
vmImage: windows-latest
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- template: ./find-tools.yml
|
||||
|
||||
- powershell: |
|
||||
mkdir -Force "$(IntDir)\script"
|
||||
iwr "https://github.com/python/cpython/raw/main/PCbuild/prepare_libffi.bat" `
|
||||
-outfile "$(IntDir)\script\prepare_libffi.bat"
|
||||
displayName: 'Download build script'
|
||||
|
||||
- powershell: |
|
||||
git clone $(SourcesRepo) -b $(SourceTag) --depth 1 -c core.autocrlf=false -c core.eol=lf .
|
||||
displayName: 'Check out LibFFI sources'
|
||||
|
||||
- script: 'prepare_libffi.bat --install-cygwin'
|
||||
workingDirectory: '$(IntDir)\script'
|
||||
displayName: 'Install Cygwin and build'
|
||||
env:
|
||||
VCVARSALL: '$(vcvarsall)'
|
||||
LIBFFI_SOURCE: '$(Build.SourcesDirectory)'
|
||||
LIBFFI_OUT: '$(OutDir)'
|
||||
|
||||
- powershell: |
|
||||
if ((gci *\*.dll).Count -lt 4) {
|
||||
Write-Error "Did not generate enough DLL files"
|
||||
}
|
||||
if ((gci *\Include\ffi.h).Count -lt 4) {
|
||||
Write-Error "Did not generate enough include files"
|
||||
}
|
||||
failOnStderr: true
|
||||
workingDirectory: '$(OutDir)'
|
||||
displayName: 'Verify files were created'
|
||||
|
||||
- publish: '$(OutDir)'
|
||||
artifact: 'unsigned'
|
||||
displayName: 'Publish unsigned build'
|
||||
|
||||
- job: Sign_LibFFI
|
||||
displayName: Sign LibFFI
|
||||
dependsOn: Build_LibFFI
|
||||
pool:
|
||||
name: 'Windows Release'
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
- download: current
|
||||
artifact: unsigned
|
||||
|
||||
- template: ./find-tools.yml
|
||||
|
||||
- powershell: |
|
||||
signtool sign /q /a `
|
||||
/n "Python Software Foundation" `
|
||||
/fd sha256 `
|
||||
/tr http://timestamp.digicert.com/ /td sha256 `
|
||||
/d "LibFFI for Python" `
|
||||
(gci "$(Pipeline.Workspace)\unsigned\*.dll" -r)
|
||||
displayName: 'Sign files'
|
||||
|
||||
- publish: '$(Pipeline.Workspace)\unsigned'
|
||||
artifact: 'libffi'
|
||||
displayName: 'Publish libffi'
|
|
@ -1,27 +0,0 @@
|
|||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 5
|
||||
|
||||
- script: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl --prefix=/opt/python-azdev
|
||||
displayName: 'Configure CPython (debug)'
|
||||
|
||||
- script: make -j4
|
||||
displayName: 'Build CPython'
|
||||
|
||||
- script: make pythoninfo
|
||||
displayName: 'Display build info'
|
||||
|
||||
- script: make buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=$(build.binariesDirectory)/test-results.xml"
|
||||
displayName: 'Tests'
|
||||
continueOnError: true
|
||||
timeoutInMinutes: 30
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results'
|
||||
inputs:
|
||||
testResultsFiles: '$(build.binariesDirectory)/test-results.xml'
|
||||
mergeTestResults: true
|
||||
testRunTitle: $(testRunTitle)
|
||||
platform: $(testRunPlatform)
|
||||
condition: succeededOrFailed()
|
|
@ -1,110 +0,0 @@
|
|||
name: $(SourceTag)_$(Date:yyyyMMdd)$(Rev:.rr)
|
||||
|
||||
variables:
|
||||
IntDir: '$(Build.BinariesDirectory)'
|
||||
OutDir: '$(Build.ArtifactStagingDirectory)'
|
||||
|
||||
# MUST BE SET AT QUEUE TIME
|
||||
# SigningCertificate: 'Python Software Foundation'
|
||||
# SourcesRepo: 'https://github.com/python/cpython-source-deps'
|
||||
# SourceTag: 'openssl-1.1.1k'
|
||||
|
||||
jobs:
|
||||
- job: Build_SSL
|
||||
displayName: OpenSSL
|
||||
pool:
|
||||
name: 'Windows Release'
|
||||
#vmImage: windows-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
win32:
|
||||
Platform: 'win32'
|
||||
VCPlatform: 'amd64_x86'
|
||||
OpenSSLPlatform: 'VC-WIN32 no-asm'
|
||||
amd64:
|
||||
Platform: 'amd64'
|
||||
VCPlatform: 'amd64'
|
||||
OpenSSLPlatform: 'VC-WIN64A-masm'
|
||||
arm32:
|
||||
Platform: 'arm32'
|
||||
VCPlatform: 'amd64_arm'
|
||||
OpenSSLPlatform: 'VC-WIN32-ARM'
|
||||
arm64:
|
||||
Platform: 'arm64'
|
||||
VCPlatform: 'amd64_arm64'
|
||||
OpenSSLPlatform: 'VC-WIN64-ARM'
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- template: ./find-tools.yml
|
||||
|
||||
- powershell: |
|
||||
git clone $(SourcesRepo) -b $(SourceTag) --depth 1 .
|
||||
displayName: 'Check out OpenSSL sources'
|
||||
|
||||
- powershell: |
|
||||
$f = gi ms\uplink.c
|
||||
$c1 = gc $f
|
||||
$c2 = $c1 -replace '\(\(h = GetModuleHandle\(NULL\)\) == NULL\)', '((h = GetModuleHandleA("_ssl.pyd")) == NULL) if ((h = GetModuleHandleA("_ssl_d.pyd")) == NULL) if ((h = GetModuleHandle(NULL)) == NULL /*patched*/)'
|
||||
if ($c2 -ne $c1) {
|
||||
$c2 | Out-File $f -Encoding ASCII
|
||||
} else {
|
||||
Write-Host '##warning Failed to patch uplink.c'
|
||||
}
|
||||
displayName: 'Apply uplink.c patch'
|
||||
|
||||
- script: |
|
||||
call "$(vcvarsall)" $(VCPlatform)
|
||||
perl "$(Build.SourcesDirectory)\Configure" $(OpenSSLPlatform)
|
||||
nmake
|
||||
workingDirectory: '$(IntDir)'
|
||||
displayName: 'Build OpenSSL'
|
||||
|
||||
- script: |
|
||||
call "$(vcvarsall)" $(VCPlatform)
|
||||
signtool sign /q /a /n "$(SigningCertificate)" /fd sha256 /tr http://timestamp.digicert.com/ /td sha256 /d "OpenSSL for Python" *.dll
|
||||
workingDirectory: '$(IntDir)'
|
||||
displayName: 'Sign OpenSSL Build'
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy built libraries for upload'
|
||||
inputs:
|
||||
SourceFolder: '$(IntDir)'
|
||||
Contents: |
|
||||
lib*.dll
|
||||
lib*.pdb
|
||||
lib*.lib
|
||||
include\openssl\*.h
|
||||
TargetFolder: '$(OutDir)'
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy header files for upload'
|
||||
inputs:
|
||||
SourceFolder: '$(Build.SourcesDirectory)'
|
||||
Contents: |
|
||||
include\openssl\*
|
||||
TargetFolder: '$(OutDir)'
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy applink files for upload'
|
||||
inputs:
|
||||
SourceFolder: '$(Build.SourcesDirectory)\ms'
|
||||
Contents: applink.c
|
||||
TargetFolder: '$(OutDir)\include'
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy LICENSE for upload'
|
||||
inputs:
|
||||
SourceFolder: '$(Build.SourcesDirectory)'
|
||||
Contents: LICENSE
|
||||
TargetFolder: '$(OutDir)'
|
||||
|
||||
- publish: '$(OutDir)'
|
||||
artifact: '$(Platform)'
|
||||
displayName: 'Publishing $(Platform)'
|
|
@ -1,10 +1,3 @@
|
|||
parameters:
|
||||
coverage: false
|
||||
sudo_dependencies: sudo
|
||||
dependencies: apt
|
||||
patchcheck: true
|
||||
xvfb: true
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
|
@ -14,7 +7,7 @@ steps:
|
|||
- script: sudo setfacl -Rb /home/vsts
|
||||
displayName: 'Workaround ACL issue'
|
||||
|
||||
- script: ${{ parameters.sudo_dependencies }} ./.azure-pipelines/posix-deps-${{ parameters.dependencies }}.sh $(openssl_version)
|
||||
- script: sudo ./.azure-pipelines/posix-deps-apt.sh $(openssl_version)
|
||||
displayName: 'Install dependencies'
|
||||
|
||||
- script: ./configure --with-pydebug
|
||||
|
@ -23,61 +16,11 @@ steps:
|
|||
- script: make -j4
|
||||
displayName: 'Build CPython'
|
||||
|
||||
- ${{ if eq(parameters.coverage, 'true') }}:
|
||||
- script: ./python -m venv venv && ./venv/bin/python -m pip install -U coverage
|
||||
displayName: 'Set up virtual environment'
|
||||
- script: make pythoninfo
|
||||
displayName: 'Display build info'
|
||||
|
||||
- script: ./venv/bin/python -m test.pythoninfo
|
||||
displayName: 'Display build info'
|
||||
|
||||
- script: |
|
||||
$COMMAND -m coverage run --pylib -m test \
|
||||
--fail-env-changed \
|
||||
-uall,-cpu \
|
||||
--junit-xml=$(build.binariesDirectory)/test-results.xml \
|
||||
-x test_multiprocessing_fork \
|
||||
-x test_multiprocessing_forkserver \
|
||||
-x test_multiprocessing_spawn \
|
||||
-x test_concurrent_futures
|
||||
displayName: 'Tests with coverage'
|
||||
env:
|
||||
${{ if eq(parameters.xvfb, 'true') }}:
|
||||
COMMAND: xvfb-run ./venv/bin/python
|
||||
${{ if ne(parameters.xvfb, 'true') }}:
|
||||
COMMAND: ./venv/bin/python
|
||||
|
||||
- script: ./venv/bin/python -m coverage xml
|
||||
displayName: 'Generate coverage.xml'
|
||||
|
||||
- script: source ./venv/bin/activate && bash <(curl -s https://codecov.io/bash) -y .github/codecov.yml
|
||||
displayName: 'Publish code coverage results'
|
||||
|
||||
|
||||
- ${{ if ne(parameters.coverage, 'true') }}:
|
||||
- script: make pythoninfo
|
||||
displayName: 'Display build info'
|
||||
|
||||
- script: $COMMAND buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=$(build.binariesDirectory)/test-results.xml"
|
||||
displayName: 'Tests'
|
||||
env:
|
||||
${{ if eq(parameters.xvfb, 'true') }}:
|
||||
COMMAND: xvfb-run make
|
||||
${{ if ne(parameters.xvfb, 'true') }}:
|
||||
COMMAND: make
|
||||
|
||||
- ${{ if eq(parameters.patchcheck, 'true') }}:
|
||||
- script: |
|
||||
git fetch origin
|
||||
./python Tools/scripts/patchcheck.py --ci true
|
||||
displayName: 'Run patchcheck.py'
|
||||
condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
|
||||
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results'
|
||||
inputs:
|
||||
testResultsFiles: '$(build.binariesDirectory)/test-results.xml'
|
||||
mergeTestResults: true
|
||||
testRunTitle: $(testRunTitle)
|
||||
platform: $(testRunPlatform)
|
||||
condition: succeededOrFailed()
|
||||
- script: |
|
||||
git fetch origin
|
||||
./python Tools/patchcheck/patchcheck.py --ci true
|
||||
displayName: 'Run patchcheck.py'
|
||||
condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
|
||||
|
|
|
@ -1,123 +1,28 @@
|
|||
variables:
|
||||
coverage: false
|
||||
|
||||
pr: ['main', '3.10', '3.9', '3.8', '3.7']
|
||||
pr: ['main', '3.12', '3.11', '3.10', '3.9', '3.8', '3.7']
|
||||
|
||||
jobs:
|
||||
- job: Prebuild
|
||||
displayName: Pre-build checks
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-20.04
|
||||
vmImage: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- template: ./prebuild-checks.yml
|
||||
|
||||
|
||||
- job: Docs_PR
|
||||
displayName: Docs PR
|
||||
dependsOn: Prebuild
|
||||
condition: and(succeeded(), eq(dependencies.Prebuild.outputs['docs.run'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- template: ./docs-steps.yml
|
||||
|
||||
|
||||
- job: macOS_PR_Tests
|
||||
displayName: macOS PR Tests
|
||||
dependsOn: Prebuild
|
||||
#condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true'))
|
||||
# bpo-39837: macOS tests on Azure Pipelines are disabled
|
||||
condition: false
|
||||
|
||||
variables:
|
||||
testRunTitle: '$(system.pullRequest.TargetBranch)-macos'
|
||||
testRunPlatform: macos
|
||||
|
||||
pool:
|
||||
vmImage: macos-10.15
|
||||
|
||||
steps:
|
||||
- template: ./macos-steps.yml
|
||||
parameters:
|
||||
targetBranch: $(System.PullRequest.TargetBranch)
|
||||
|
||||
|
||||
- job: Ubuntu_PR_Tests
|
||||
displayName: Ubuntu PR Tests
|
||||
- job: Ubuntu_Patchcheck
|
||||
displayName: Ubuntu patchcheck
|
||||
dependsOn: Prebuild
|
||||
condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-20.04
|
||||
vmImage: ubuntu-22.04
|
||||
|
||||
variables:
|
||||
testRunTitle: '$(system.pullRequest.TargetBranch)-linux'
|
||||
testRunPlatform: linux
|
||||
openssl_version: 1.1.1n
|
||||
openssl_version: 1.1.1u
|
||||
|
||||
steps:
|
||||
- template: ./posix-steps.yml
|
||||
parameters:
|
||||
dependencies: apt
|
||||
|
||||
|
||||
- job: Ubuntu_Coverage_PR_Tests
|
||||
displayName: Ubuntu PR Tests (coverage)
|
||||
dependsOn: Prebuild
|
||||
condition: |
|
||||
and(
|
||||
and(
|
||||
succeeded(),
|
||||
eq(variables['coverage'], 'true')
|
||||
),
|
||||
eq(dependencies.Prebuild.outputs['tests.run'], 'true')
|
||||
)
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-20.04
|
||||
|
||||
variables:
|
||||
testRunTitle: '$(Build.SourceBranchName)-linux-coverage'
|
||||
testRunPlatform: linux-coverage
|
||||
openssl_version: 1.1.1n
|
||||
|
||||
steps:
|
||||
- template: ./posix-steps.yml
|
||||
parameters:
|
||||
dependencies: apt
|
||||
coverage: true
|
||||
|
||||
|
||||
- job: Windows_PR_Tests
|
||||
displayName: Windows PR Tests
|
||||
dependsOn: Prebuild
|
||||
condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
win32:
|
||||
arch: win32
|
||||
buildOpt: '-p Win32'
|
||||
testRunTitle: '$(System.PullRequest.TargetBranch)-win32'
|
||||
testRunPlatform: win32
|
||||
win64:
|
||||
arch: amd64
|
||||
buildOpt: '-p x64'
|
||||
testRunTitle: '$(System.PullRequest.TargetBranch)-win64'
|
||||
testRunPlatform: win64
|
||||
winarm64:
|
||||
arch: arm64
|
||||
buildOpt: '-p arm64'
|
||||
maxParallel: 4
|
||||
|
||||
steps:
|
||||
- template: ./windows-steps.yml
|
||||
parameters:
|
||||
targetBranch: $(System.PullRequest.TargetBranch)
|
||||
|
|
|
@ -11,18 +11,6 @@ steps:
|
|||
displayName: Fetch comparison tree
|
||||
condition: and(succeeded(), variables['System.PullRequest.TargetBranch'])
|
||||
|
||||
- script: |
|
||||
if ! git diff --name-only $(diffTarget) | grep -qE '(\.rst$|^Doc|^Misc)'
|
||||
then
|
||||
echo "No docs were updated: docs.run=false"
|
||||
echo "##vso[task.setvariable variable=run;isOutput=true]false"
|
||||
else
|
||||
echo "Docs were updated: docs.run=true"
|
||||
echo "##vso[task.setvariable variable=run;isOutput=true]true"
|
||||
fi
|
||||
displayName: Detect documentation changes
|
||||
name: docs
|
||||
|
||||
- script: |
|
||||
if ! git diff --name-only $(diffTarget) | grep -qvE '(\.rst$|^Doc|^Misc)'
|
||||
then
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
name: tcl$(TkSourceTag)_$(Date:yyyyMMdd)$(Rev:.rr)
|
||||
|
||||
variables:
|
||||
IntDir: '$(Build.BinariesDirectory)\obj'
|
||||
ExternalsDir: '$(Build.BinariesDirectory)\externals'
|
||||
OutDir: '$(Build.ArtifactStagingDirectory)'
|
||||
Configuration: 'Release'
|
||||
|
||||
# MUST BE SET AT QUEUE TIME
|
||||
# SigningCertificate: 'Python Software Foundation'
|
||||
# SourcesRepo: 'https://github.com/python/cpython-source-deps'
|
||||
# TclSourceTag: 'tcl-core-8.6.12.0'
|
||||
# TkSourceTag: 'tk-8.6.12.0'
|
||||
# TixSourceTag: 'tix-8.4.3.6'
|
||||
|
||||
jobs:
|
||||
- job: Build_TclTk
|
||||
displayName: 'Tcl/Tk'
|
||||
pool:
|
||||
name: 'Windows Release'
|
||||
#vmImage: windows-latest
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- template: ./find-tools.yml
|
||||
|
||||
- powershell: |
|
||||
git clone $(SourcesRepo) -b $(TclSourceTag) --depth 1 "$(ExternalsDir)\$(TclSourceTag)"
|
||||
displayName: 'Check out Tcl sources'
|
||||
|
||||
- powershell: |
|
||||
git clone $(SourcesRepo) -b $(TkSourceTag) --depth 1 "$(ExternalsDir)\$(TkSourceTag)"
|
||||
displayName: 'Check out Tk sources'
|
||||
|
||||
- powershell: |
|
||||
git clone $(SourcesRepo) -b $(TixSourceTag) --depth 1 "$(ExternalsDir)\$(TixSourceTag)"
|
||||
displayName: 'Check out Tix sources'
|
||||
|
||||
# This msbuild.rsp file will be used by the build to forcibly override these variables
|
||||
- powershell: |
|
||||
del -Force -EA 0 msbuild.rsp
|
||||
"/p:IntDir=$(IntDir)\" >> msbuild.rsp
|
||||
"/p:ExternalsDir=$(ExternalsDir)\" >> msbuild.rsp
|
||||
"/p:tclDir=$(ExternalsDir)\$(TclSourceTag)\" >> msbuild.rsp
|
||||
"/p:tkDir=$(ExternalsDir)\$(TkSourceTag)\" >> msbuild.rsp
|
||||
"/p:tixDir=$(ExternalsDir)\$(TixSourceTag)\" >> msbuild.rsp
|
||||
displayName: 'Generate msbuild.rsp'
|
||||
|
||||
- powershell: |
|
||||
& "$(msbuild)" PCbuild\tcl.vcxproj "@msbuild.rsp" /p:Platform=Win32 /p:tcltkDir="$(OutDir)\win32"
|
||||
& "$(msbuild)" PCbuild\tk.vcxproj "@msbuild.rsp" /p:Platform=Win32 /p:tcltkDir="$(OutDir)\win32"
|
||||
& "$(msbuild)" PCbuild\tix.vcxproj "@msbuild.rsp" /p:Platform=Win32 /p:tcltkDir="$(OutDir)\win32"
|
||||
displayName: 'Build for win32'
|
||||
|
||||
- powershell: |
|
||||
& "$(msbuild)" PCbuild\tcl.vcxproj "@msbuild.rsp" /p:Platform=x64 /p:tcltkDir="$(OutDir)\amd64"
|
||||
& "$(msbuild)" PCbuild\tk.vcxproj "@msbuild.rsp" /p:Platform=x64 /p:tcltkDir="$(OutDir)\amd64"
|
||||
& "$(msbuild)" PCbuild\tix.vcxproj "@msbuild.rsp" /p:Platform=x64 /p:tcltkDir="$(OutDir)\amd64"
|
||||
displayName: 'Build for amd64'
|
||||
|
||||
- powershell: |
|
||||
& "$(msbuild)" PCbuild\tcl.vcxproj "@msbuild.rsp" /p:Platform=ARM64 /p:tcltkDir="$(OutDir)\arm64"
|
||||
& "$(msbuild)" PCbuild\tk.vcxproj "@msbuild.rsp" /p:Platform=ARM64 /p:tcltkDir="$(OutDir)\arm64"
|
||||
& "$(msbuild)" PCbuild\tix.vcxproj "@msbuild.rsp" /p:Platform=ARM64 /p:tcltkDir="$(OutDir)\arm64"
|
||||
displayName: 'Build for arm64'
|
||||
|
||||
- publish: '$(OutDir)'
|
||||
artifact: 'tcltk'
|
||||
displayName: 'Publishing tcltk'
|
|
@ -12,7 +12,7 @@ steps:
|
|||
displayName: Show layout info (${{ parameters.kind }})
|
||||
|
||||
- ${{ if eq(parameters.fulltest, 'true') }}:
|
||||
- script: .\python.exe -m test -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 --junit-xml="$(Build.BinariesDirectory)\test-results-${{ parameters.kind }}.xml" --tempdir "$(Build.BinariesDirectory)\tmp-${{ parameters.kind }}-$(arch)"
|
||||
- script: .\python.exe -m test -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 --junit-xml="$(Build.BinariesDirectory)\test-results-${{ parameters.kind }}.xml" --tempdir "$(Build.BinariesDirectory)\tmp-${{ parameters.kind }}-$(arch)" -i test_launcher
|
||||
workingDirectory: $(Build.BinariesDirectory)\layout-${{ parameters.kind }}-$(arch)
|
||||
displayName: ${{ parameters.kind }} Tests
|
||||
env:
|
||||
|
|
|
@ -1,220 +0,0 @@
|
|||
name: Release_$(Build.SourceBranchName)_$(SourceTag)_$(Date:yyyyMMdd)$(Rev:.rr)
|
||||
|
||||
parameters:
|
||||
- name: GitRemote
|
||||
displayName: "Git remote"
|
||||
type: string
|
||||
default: python
|
||||
values:
|
||||
- 'python'
|
||||
- 'pablogsal'
|
||||
- 'ambv'
|
||||
- '(Other)'
|
||||
- name: GitRemote_Other
|
||||
displayName: "If Other, specify Git remote"
|
||||
type: string
|
||||
default: 'python'
|
||||
- name: SourceTag
|
||||
displayName: "Git tag"
|
||||
type: string
|
||||
default: main
|
||||
- name: DoPublish
|
||||
displayName: "Publish release"
|
||||
type: boolean
|
||||
default: false
|
||||
- name: SigningCertificate
|
||||
displayName: "Code signing certificate"
|
||||
type: string
|
||||
default: 'Python Software Foundation'
|
||||
values:
|
||||
- 'Python Software Foundation'
|
||||
- 'TestSign'
|
||||
- 'Unsigned'
|
||||
- name: SigningDescription
|
||||
displayName: "Signature description"
|
||||
type: string
|
||||
default: 'Built: $(Build.BuildNumber)'
|
||||
- name: DoARM64
|
||||
displayName: "Publish ARM64 build"
|
||||
type: boolean
|
||||
default: true
|
||||
# Because there is no ARM64 Tcl/Tk pre-3.11, we need a separate option
|
||||
# to keep those builds working when the files are going to be absent.
|
||||
# Eventually when we stop releasing anything that old, we can drop this
|
||||
# argument (and make it implicitly always 'true')
|
||||
- name: ARM64TclTk
|
||||
displayName: "Use Tcl/Tk for ARM64 (3.11 and later)"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: DoPGO
|
||||
displayName: "Run PGO"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: DoCHM
|
||||
displayName: "Produce compiled help document (pre-3.11)"
|
||||
type: boolean
|
||||
default: false
|
||||
- name: DoLayout
|
||||
displayName: "Produce full layout artifact"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: DoMSIX
|
||||
displayName: "Produce Store packages"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: DoNuget
|
||||
displayName: "Produce Nuget packages"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: DoEmbed
|
||||
displayName: "Produce embeddable package"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: DoMSI
|
||||
displayName: "Produce EXE/MSI installer"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: BuildToPublish
|
||||
displayName: "Build number to publish (0 to skip)"
|
||||
type: number
|
||||
default: '0'
|
||||
|
||||
variables:
|
||||
__RealSigningCertificate: 'Python Software Foundation'
|
||||
${{ if ne(parameters.GitRemote, '(Other)') }}:
|
||||
GitRemote: ${{ parameters.GitRemote }}
|
||||
${{ else }}:
|
||||
GitRemote: ${{ parameters.GitRemote_Other }}
|
||||
SourceTag: ${{ parameters.SourceTag }}
|
||||
DoPGO: ${{ parameters.DoPGO }}
|
||||
${{ if ne(parameters.SigningCertificate, 'Unsigned') }}:
|
||||
SigningCertificate: ${{ parameters.SigningCertificate }}
|
||||
SigningDescription: ${{ parameters.SigningDescription }}
|
||||
DoCHM: ${{ parameters.DoCHM }}
|
||||
DoLayout: ${{ parameters.DoLayout }}
|
||||
DoMSIX: ${{ parameters.DoMSIX }}
|
||||
DoNuget: ${{ parameters.DoNuget }}
|
||||
DoEmbed: ${{ parameters.DoEmbed }}
|
||||
DoMSI: ${{ parameters.DoMSI }}
|
||||
DoPublish: ${{ parameters.DoPublish }}
|
||||
PublishARM64: ${{ parameters.DoARM64 }}
|
||||
# QUEUE TIME VARIABLES
|
||||
# PyDotOrgUsername: ''
|
||||
# PyDotOrgServer: ''
|
||||
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
stages:
|
||||
- ${{ if eq(parameters.BuildToPublish, '0') }}:
|
||||
- stage: Build
|
||||
displayName: Build binaries
|
||||
jobs:
|
||||
- template: windows-release/stage-build.yml
|
||||
parameters:
|
||||
ARM64TclTk: ${{ parameters.ARM64TclTk }}
|
||||
|
||||
- stage: Sign
|
||||
displayName: Sign binaries
|
||||
dependsOn: Build
|
||||
jobs:
|
||||
- template: windows-release/stage-sign.yml
|
||||
|
||||
- stage: Layout
|
||||
displayName: Generate layouts
|
||||
dependsOn: Sign
|
||||
jobs:
|
||||
- template: windows-release/stage-layout-full.yml
|
||||
parameters:
|
||||
ARM64TclTk: ${{ parameters.ARM64TclTk }}
|
||||
- template: windows-release/stage-layout-embed.yml
|
||||
- template: windows-release/stage-layout-nuget.yml
|
||||
|
||||
- stage: Pack
|
||||
dependsOn: Layout
|
||||
jobs:
|
||||
- template: windows-release/stage-pack-nuget.yml
|
||||
|
||||
- stage: Test
|
||||
dependsOn: Pack
|
||||
jobs:
|
||||
- template: windows-release/stage-test-embed.yml
|
||||
- template: windows-release/stage-test-nuget.yml
|
||||
|
||||
- ${{ if eq(parameters.DoMSIX, 'true') }}:
|
||||
- stage: Layout_MSIX
|
||||
displayName: Generate MSIX layouts
|
||||
dependsOn: Sign
|
||||
jobs:
|
||||
- template: windows-release/stage-layout-msix.yml
|
||||
parameters:
|
||||
ARM64TclTk: ${{ parameters.ARM64TclTk }}
|
||||
|
||||
- stage: Pack_MSIX
|
||||
displayName: Package MSIX
|
||||
dependsOn: Layout_MSIX
|
||||
jobs:
|
||||
- template: windows-release/stage-pack-msix.yml
|
||||
|
||||
- ${{ if eq(parameters.DoMSI, 'true') }}:
|
||||
- stage: Build_MSI
|
||||
displayName: Build MSI installer
|
||||
dependsOn: Sign
|
||||
jobs:
|
||||
- template: windows-release/stage-msi.yml
|
||||
parameters:
|
||||
ARM64TclTk: ${{ parameters.ARM64TclTk }}
|
||||
|
||||
- stage: Test_MSI
|
||||
displayName: Test MSI installer
|
||||
dependsOn: Build_MSI
|
||||
jobs:
|
||||
- template: windows-release/stage-test-msi.yml
|
||||
|
||||
- ${{ if eq(parameters.DoPublish, 'true') }}:
|
||||
- ${{ if eq(parameters.DoMSI, 'true') }}:
|
||||
- stage: PublishPyDotOrg
|
||||
displayName: Publish to python.org
|
||||
dependsOn: ['Test_MSI', 'Test']
|
||||
jobs:
|
||||
- template: windows-release/stage-publish-pythonorg.yml
|
||||
|
||||
- ${{ if eq(parameters.DoNuget, 'true') }}:
|
||||
- stage: PublishNuget
|
||||
displayName: Publish to nuget.org
|
||||
${{ if eq(parameters.DoMSI, 'true') }}:
|
||||
dependsOn: ['Test_MSI', 'Test']
|
||||
${{ else }}:
|
||||
dependsOn: 'Test'
|
||||
jobs:
|
||||
- template: windows-release/stage-publish-nugetorg.yml
|
||||
|
||||
- ${{ if eq(parameters.DoMSIX, 'true') }}:
|
||||
- stage: PublishStore
|
||||
displayName: Publish to Store
|
||||
${{ if eq(parameters.DoMSI, 'true') }}:
|
||||
dependsOn: ['Test_MSI', 'Pack_MSIX']
|
||||
${{ else }}:
|
||||
dependsOn: 'Pack_MSIX'
|
||||
jobs:
|
||||
- template: windows-release/stage-publish-store.yml
|
||||
|
||||
- ${{ else }}:
|
||||
- stage: PublishExisting
|
||||
displayName: Publish existing build
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- ${{ if eq(parameters.DoMSI, 'true') }}:
|
||||
- template: windows-release/stage-publish-pythonorg.yml
|
||||
parameters:
|
||||
BuildToPublish: ${{ parameters.BuildToPublish }}
|
||||
|
||||
- ${{ if eq(parameters.DoNuget, 'true') }}:
|
||||
- template: windows-release/stage-publish-nugetorg.yml
|
||||
parameters:
|
||||
BuildToPublish: ${{ parameters.BuildToPublish }}
|
||||
|
||||
- ${{ if eq(parameters.DoMSIX, 'true') }}:
|
||||
- template: windows-release/stage-publish-store.yml
|
||||
parameters:
|
||||
BuildToPublish: ${{ parameters.BuildToPublish }}
|
|
@ -1,84 +0,0 @@
|
|||
parameters:
|
||||
ShouldPGO: false
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
|
||||
- powershell: |
|
||||
$d = (.\PCbuild\build.bat -V) | %{ if($_ -match '\s+(\w+):\s*(.+)\s*$') { @{$Matches[1] = $Matches[2];} }};
|
||||
Write-Host "##vso[task.setvariable variable=VersionText]$($d.PythonVersion)"
|
||||
Write-Host "##vso[task.setvariable variable=VersionNumber]$($d.PythonVersionNumber)"
|
||||
Write-Host "##vso[task.setvariable variable=VersionHex]$($d.PythonVersionHex)"
|
||||
Write-Host "##vso[task.setvariable variable=VersionUnique]$($d.PythonVersionUnique)"
|
||||
Write-Host "##vso[build.addbuildtag]$($d.PythonVersion)"
|
||||
Write-Host "##vso[build.addbuildtag]$($d.PythonVersion)-$(Name)"
|
||||
displayName: 'Extract version numbers'
|
||||
|
||||
- ${{ if eq(parameters.ShouldPGO, 'false') }}:
|
||||
- powershell: |
|
||||
$env:SigningCertificate = $null
|
||||
.\PCbuild\build.bat -v -p $(Platform) -c $(Configuration)
|
||||
displayName: 'Run build'
|
||||
env:
|
||||
IncludeUwp: true
|
||||
Py_OutDir: '$(Build.BinariesDirectory)\bin'
|
||||
|
||||
- ${{ if eq(parameters.ShouldPGO, 'true') }}:
|
||||
- powershell: |
|
||||
$env:SigningCertificate = $null
|
||||
.\PCbuild\build.bat -v -p $(Platform) --pgo
|
||||
displayName: 'Run build with PGO'
|
||||
env:
|
||||
IncludeUwp: true
|
||||
Py_OutDir: '$(Build.BinariesDirectory)\bin'
|
||||
|
||||
- powershell: |
|
||||
$kitroot = (gp 'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots\').KitsRoot10
|
||||
$tool = (gci -r "$kitroot\Bin\*\x64\signtool.exe" | sort FullName -Desc | select -First 1)
|
||||
if (-not $tool) {
|
||||
throw "SDK is not available"
|
||||
}
|
||||
Write-Host "##vso[task.prependpath]$($tool.Directory)"
|
||||
displayName: 'Add WinSDK tools to path'
|
||||
|
||||
- powershell: |
|
||||
$env:SigningCertificate = $null
|
||||
$(_HostPython) PC\layout -vv -b "$(Build.BinariesDirectory)\bin" -t "$(Build.BinariesDirectory)\catalog" --catalog "${env:CAT}.cdf" --preset-default --arch $(Arch)
|
||||
makecat "${env:CAT}.cdf"
|
||||
del "${env:CAT}.cdf"
|
||||
if (-not (Test-Path "${env:CAT}.cat")) {
|
||||
throw "Failed to build catalog file"
|
||||
}
|
||||
displayName: 'Generate catalog'
|
||||
env:
|
||||
CAT: $(Build.BinariesDirectory)\bin\$(Arch)\python
|
||||
PYTHON_HEXVERSION: $(VersionHex)
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish binaries'
|
||||
condition: and(succeeded(), not(and(eq(variables['Configuration'], 'Release'), variables['SigningCertificate'])))
|
||||
inputs:
|
||||
targetPath: '$(Build.BinariesDirectory)\bin\$(Arch)'
|
||||
artifactName: bin_$(Name)
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish binaries for signing'
|
||||
condition: and(succeeded(), and(eq(variables['Configuration'], 'Release'), variables['SigningCertificate']))
|
||||
inputs:
|
||||
targetPath: '$(Build.BinariesDirectory)\bin\$(Arch)'
|
||||
artifactName: unsigned_bin_$(Name)
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Layout Artifact: symbols'
|
||||
inputs:
|
||||
sourceFolder: $(Build.BinariesDirectory)\bin\$(Arch)
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)\symbols\$(Name)
|
||||
flatten: true
|
||||
contents: |
|
||||
**\*.pdb
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: symbols'
|
||||
inputs:
|
||||
PathToPublish: '$(Build.ArtifactStagingDirectory)\symbols'
|
||||
ArtifactName: symbols
|
|
@ -1,21 +0,0 @@
|
|||
parameters:
|
||||
depth: 3
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- script: git clone --progress -v --depth ${{ parameters.depth }} --branch $(SourceTag) --single-branch https://github.com/$(GitRemote)/cpython.git .
|
||||
displayName: 'git clone ($(GitRemote)/$(SourceTag))'
|
||||
condition: and(succeeded(), and(variables['GitRemote'], variables['SourceTag']))
|
||||
|
||||
- script: git clone --progress -v --depth ${{ parameters.depth }} --branch $(SourceTag) --single-branch $(Build.Repository.Uri) .
|
||||
displayName: 'git clone (<default>/$(SourceTag))'
|
||||
condition: and(succeeded(), and(not(variables['GitRemote']), variables['SourceTag']))
|
||||
|
||||
- script: git clone --progress -v --depth ${{ parameters.depth }} --branch $(Build.SourceBranchName) --single-branch https://github.com/$(GitRemote)/cpython.git .
|
||||
displayName: 'git clone ($(GitRemote)/<default>)'
|
||||
condition: and(succeeded(), and(variables['GitRemote'], not(variables['SourceTag'])))
|
||||
|
||||
- script: git clone --progress -v --depth ${{ parameters.depth }} --branch $(Build.SourceBranchName) --single-branch $(Build.Repository.Uri) .
|
||||
displayName: 'git clone'
|
||||
condition: and(succeeded(), and(not(variables['GitRemote']), not(variables['SourceTag'])))
|
|
@ -1,17 +0,0 @@
|
|||
# Locate the Windows SDK and add its binaries directory to PATH
|
||||
#
|
||||
# `toolname` can be overridden to use a different marker file.
|
||||
|
||||
parameters:
|
||||
toolname: signtool.exe
|
||||
|
||||
steps:
|
||||
- powershell: |
|
||||
$kitroot = (gp 'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots\').KitsRoot10
|
||||
$tool = (gci -r "$kitroot\Bin\*\${{ parameters.toolname }}" | sort FullName -Desc | select -First 1)
|
||||
if (-not $tool) {
|
||||
throw "SDK is not available"
|
||||
}
|
||||
Write-Host "##vso[task.prependpath]$($tool.Directory)"
|
||||
Write-Host "Adding $($tool.Directory) to PATH"
|
||||
displayName: 'Add WinSDK tools to path'
|
|
@ -1,23 +0,0 @@
|
|||
steps:
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_$(HostArch)'
|
||||
condition: and(succeeded(), variables['HostArch'])
|
||||
inputs:
|
||||
artifactName: bin_$(HostArch)
|
||||
targetPath: $(Build.BinariesDirectory)\bin_$(HostArch)
|
||||
|
||||
- powershell: >
|
||||
Write-Host (
|
||||
'##vso[task.setvariable variable=LayoutCmd]&
|
||||
"$(Python)"
|
||||
"{1}\PC\layout"
|
||||
-vv
|
||||
--source "{1}"
|
||||
--build "{0}\bin"
|
||||
--arch "$(Name)"
|
||||
--temp "{0}\layout-temp"
|
||||
--include-cat "{0}\bin\python.cat"
|
||||
--doc-build "{0}\doc"'
|
||||
-f ("$(Build.BinariesDirectory)", "$(Build.SourcesDirectory)")
|
||||
)
|
||||
displayName: 'Set LayoutCmd'
|
|
@ -1,13 +0,0 @@
|
|||
parameters:
|
||||
DllToolOpt: -m i386:x86-64
|
||||
#DllToolOpt: -m i386 --as-flags=--32
|
||||
|
||||
steps:
|
||||
- powershell: |
|
||||
git clone https://github.com/python/cpython-bin-deps --branch binutils --single-branch --depth 1 --progress -v "binutils"
|
||||
gci "bin\$(Arch)\python*.dll" | %{
|
||||
& "binutils\gendef.exe" $_ | Out-File -Encoding ascii tmp.def
|
||||
& "binutils\dlltool.exe" --dllname $($_.BaseName).dll --def tmp.def --output-lib "$($_.Directory)\lib$($_.BaseName).a" ${{ parameters.DllToolOpt }}
|
||||
}
|
||||
displayName: 'Generate MinGW import library'
|
||||
workingDirectory: $(Build.BinariesDirectory)
|
|
@ -1,181 +0,0 @@
|
|||
parameters:
|
||||
ARM64TclTk: true
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
|
||||
- powershell: |
|
||||
$d = (.\PCbuild\build.bat -V) | %{ if($_ -match '\s+(\w+):\s*(.+)\s*$') { @{$Matches[1] = $Matches[2];} }};
|
||||
Write-Host "##vso[task.setvariable variable=SigningDescription]Python $($d.PythonVersion)"
|
||||
displayName: 'Update signing description'
|
||||
condition: and(succeeded(), not(variables['SigningDescription']))
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: doc'
|
||||
inputs:
|
||||
artifactName: doc
|
||||
targetPath: $(Build.BinariesDirectory)\doc
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Merge documentation files'
|
||||
inputs:
|
||||
sourceFolder: $(Build.BinariesDirectory)\doc
|
||||
targetFolder: $(Build.SourcesDirectory)\Doc\build
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_win32'
|
||||
inputs:
|
||||
artifactName: bin_win32
|
||||
targetPath: $(Build.BinariesDirectory)\win32
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_win32_d'
|
||||
inputs:
|
||||
artifactName: bin_win32_d
|
||||
targetPath: $(Build.BinariesDirectory)\win32
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_amd64'
|
||||
inputs:
|
||||
artifactName: bin_amd64
|
||||
targetPath: $(Build.BinariesDirectory)\amd64
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_amd64_d'
|
||||
inputs:
|
||||
artifactName: bin_amd64_d
|
||||
targetPath: $(Build.BinariesDirectory)\amd64
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_arm64'
|
||||
condition: and(succeeded(), eq(variables['PublishARM64'], 'true'))
|
||||
inputs:
|
||||
artifactName: bin_arm64
|
||||
targetPath: $(Build.BinariesDirectory)\arm64
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_arm64_d'
|
||||
condition: and(succeeded(), eq(variables['PublishARM64'], 'true'))
|
||||
inputs:
|
||||
artifactName: bin_arm64_d
|
||||
targetPath: $(Build.BinariesDirectory)\arm64
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: tcltk_lib_win32'
|
||||
inputs:
|
||||
artifactName: tcltk_lib_win32
|
||||
targetPath: $(Build.BinariesDirectory)\tcltk_lib_win32
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: tcltk_lib_amd64'
|
||||
inputs:
|
||||
artifactName: tcltk_lib_amd64
|
||||
targetPath: $(Build.BinariesDirectory)\tcltk_lib_amd64
|
||||
|
||||
- ${{ if eq(parameters.ARM64TclTk, true) }}:
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: tcltk_lib_arm64'
|
||||
condition: and(succeeded(), eq(variables['PublishARM64'], 'true'))
|
||||
inputs:
|
||||
artifactName: tcltk_lib_arm64
|
||||
targetPath: $(Build.BinariesDirectory)\tcltk_lib_arm64
|
||||
|
||||
- powershell: |
|
||||
copy $(Build.BinariesDirectory)\amd64\Activate.ps1 Lib\venv\scripts\common\Activate.ps1 -Force
|
||||
displayName: 'Copy signed files into sources'
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
|
||||
- script: |
|
||||
call Tools\msi\get_externals.bat
|
||||
call PCbuild\find_python.bat
|
||||
echo ##vso[task.setvariable variable=PYTHON]%PYTHON%
|
||||
call PCbuild/find_msbuild.bat
|
||||
echo ##vso[task.setvariable variable=MSBUILD]%MSBUILD%
|
||||
displayName: 'Get external dependencies'
|
||||
|
||||
- script: |
|
||||
%PYTHON% -m pip install blurb
|
||||
%PYTHON% -m blurb merge -f Misc\NEWS
|
||||
displayName: 'Merge NEWS file'
|
||||
|
||||
- script: |
|
||||
%MSBUILD% Tools\msi\launcher\launcher.wixproj
|
||||
displayName: 'Build launcher installer'
|
||||
env:
|
||||
Platform: x86
|
||||
Py_OutDir: $(Build.BinariesDirectory)
|
||||
|
||||
- script: |
|
||||
%MSBUILD% Tools\msi\bundle\releaselocal.wixproj /t:Rebuild /p:RebuildAll=true
|
||||
displayName: 'Build win32 installer'
|
||||
env:
|
||||
Platform: x86
|
||||
Py_OutDir: $(Build.BinariesDirectory)
|
||||
PYTHON: $(Build.BinariesDirectory)\win32\python.exe
|
||||
PythonForBuild: $(Build.BinariesDirectory)\win32\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
TclTkLibraryDir: $(Build.BinariesDirectory)\tcltk_lib_win32
|
||||
BuildForRelease: true
|
||||
|
||||
- script: |
|
||||
%MSBUILD% Tools\msi\bundle\releaselocal.wixproj /t:Rebuild /p:RebuildAll=true
|
||||
displayName: 'Build amd64 installer'
|
||||
env:
|
||||
Platform: x64
|
||||
Py_OutDir: $(Build.BinariesDirectory)
|
||||
PYTHON: $(Build.BinariesDirectory)\amd64\python.exe
|
||||
PythonForBuild: $(Build.BinariesDirectory)\amd64\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
TclTkLibraryDir: $(Build.BinariesDirectory)\tcltk_lib_amd64
|
||||
BuildForRelease: true
|
||||
|
||||
- script: |
|
||||
%MSBUILD% Tools\msi\bundle\releaselocal.wixproj /t:Rebuild /p:RebuildAll=true
|
||||
displayName: 'Build arm64 installer'
|
||||
condition: and(succeeded(), eq(variables['PublishARM64'], 'true'))
|
||||
env:
|
||||
Platform: ARM64
|
||||
Py_OutDir: $(Build.BinariesDirectory)
|
||||
PYTHON: $(Build.BinariesDirectory)\win32\python.exe
|
||||
PythonForBuild: $(Build.BinariesDirectory)\win32\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
BuildForRelease: true
|
||||
${{ if eq(parameters.ARM64TclTk, true) }}:
|
||||
TclTkLibraryDir: $(Build.BinariesDirectory)\tcltk_lib_arm64
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Assemble artifact: msi (win32)'
|
||||
inputs:
|
||||
sourceFolder: $(Build.BinariesDirectory)\win32\en-us
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)\msi\win32
|
||||
contents: |
|
||||
*.msi
|
||||
*.cab
|
||||
*.exe
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Assemble artifact: msi (amd64)'
|
||||
inputs:
|
||||
sourceFolder: $(Build.BinariesDirectory)\amd64\en-us
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)\msi\amd64
|
||||
contents: |
|
||||
*.msi
|
||||
*.cab
|
||||
*.exe
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Assemble artifact: msi (arm64)'
|
||||
condition: and(succeeded(), eq(variables['PublishARM64'], 'true'))
|
||||
inputs:
|
||||
sourceFolder: $(Build.BinariesDirectory)\arm64\en-us
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)\msi\arm64
|
||||
contents: |
|
||||
*.msi
|
||||
*.cab
|
||||
*.exe
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish MSI'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)\msi'
|
||||
artifactName: msi
|
|
@ -1,193 +0,0 @@
|
|||
parameters:
|
||||
ARM64TclTk: true
|
||||
|
||||
jobs:
|
||||
- job: Build_Docs
|
||||
displayName: Docs build
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
|
||||
- script: Doc\make.bat html
|
||||
displayName: 'Build HTML docs'
|
||||
env:
|
||||
BUILDDIR: $(Build.BinariesDirectory)\Doc
|
||||
|
||||
- script: Doc\make.bat htmlhelp
|
||||
displayName: 'Build CHM docs'
|
||||
condition: and(succeeded(), eq(variables['DoCHM'], 'true'))
|
||||
env:
|
||||
BUILDDIR: $(Build.BinariesDirectory)\Doc
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Assemble artifact: Doc'
|
||||
inputs:
|
||||
sourceFolder: $(Build.BinariesDirectory)\Doc
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)\Doc
|
||||
contents: |
|
||||
html\**\*
|
||||
htmlhelp\*.chm
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish artifact: doc'
|
||||
inputs:
|
||||
targetPath: $(Build.ArtifactStagingDirectory)\Doc
|
||||
artifactName: doc
|
||||
|
||||
|
||||
- job: Build_Python
|
||||
displayName: Python build
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
win32:
|
||||
Name: win32
|
||||
Arch: win32
|
||||
Platform: x86
|
||||
Configuration: Release
|
||||
_HostPython: .\python
|
||||
win32_d:
|
||||
Name: win32_d
|
||||
Arch: win32
|
||||
Platform: x86
|
||||
Configuration: Debug
|
||||
_HostPython: .\python
|
||||
amd64_d:
|
||||
Name: amd64_d
|
||||
Arch: amd64
|
||||
Platform: x64
|
||||
Configuration: Debug
|
||||
_HostPython: .\python
|
||||
arm64:
|
||||
Name: arm64
|
||||
Arch: arm64
|
||||
Platform: ARM64
|
||||
Configuration: Release
|
||||
_HostPython: python
|
||||
arm64_d:
|
||||
Name: arm64_d
|
||||
Arch: arm64
|
||||
Platform: ARM64
|
||||
Configuration: Debug
|
||||
_HostPython: python
|
||||
|
||||
steps:
|
||||
- template: ./build-steps.yml
|
||||
|
||||
- job: Build_Python_NonPGO
|
||||
displayName: Python non-PGO build
|
||||
condition: and(succeeded(), ne(variables['DoPGO'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
amd64:
|
||||
Name: amd64
|
||||
Arch: amd64
|
||||
Platform: x64
|
||||
Configuration: Release
|
||||
_HostPython: .\python
|
||||
|
||||
steps:
|
||||
- template: ./build-steps.yml
|
||||
|
||||
|
||||
- job: Build_Python_PGO
|
||||
displayName: Python PGO build
|
||||
condition: and(succeeded(), eq(variables['DoPGO'], 'true'))
|
||||
|
||||
# Allow up to five hours for PGO
|
||||
timeoutInMinutes: 300
|
||||
|
||||
pool:
|
||||
name: 'Windows Release'
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
amd64:
|
||||
Name: amd64
|
||||
Arch: amd64
|
||||
Platform: x64
|
||||
Configuration: Release
|
||||
_HostPython: .\python
|
||||
|
||||
steps:
|
||||
- template: ./build-steps.yml
|
||||
parameters:
|
||||
ShouldPGO: true
|
||||
|
||||
|
||||
- job: TclTk_Lib
|
||||
displayName: Publish Tcl/Tk Library
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
|
||||
- script: PCbuild\get_externals.bat --no-openssl --no-libffi
|
||||
displayName: 'Get external dependencies'
|
||||
|
||||
- task: MSBuild@1
|
||||
displayName: 'Copy Tcl/Tk lib for publish'
|
||||
inputs:
|
||||
solution: PCbuild\tcltk.props
|
||||
platform: x86
|
||||
msbuildArguments: /t:CopyTclTkLib /p:OutDir="$(Build.ArtifactStagingDirectory)\tcl_win32"
|
||||
|
||||
- task: MSBuild@1
|
||||
displayName: 'Copy Tcl/Tk lib for publish'
|
||||
inputs:
|
||||
solution: PCbuild\tcltk.props
|
||||
platform: x64
|
||||
msbuildArguments: /t:CopyTclTkLib /p:OutDir="$(Build.ArtifactStagingDirectory)\tcl_amd64"
|
||||
|
||||
- ${{ if eq(parameters.ARM64TclTk, true) }}:
|
||||
- task: MSBuild@1
|
||||
displayName: 'Copy Tcl/Tk lib for publish'
|
||||
inputs:
|
||||
solution: PCbuild\tcltk.props
|
||||
platform: ARM64
|
||||
msbuildArguments: /t:CopyTclTkLib /p:OutDir="$(Build.ArtifactStagingDirectory)\tcl_arm64"
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish artifact: tcltk_lib_win32'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)\tcl_win32'
|
||||
artifactName: tcltk_lib_win32
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish artifact: tcltk_lib_amd64'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)\tcl_amd64'
|
||||
artifactName: tcltk_lib_amd64
|
||||
|
||||
- ${{ if eq(parameters.ARM64TclTk, true) }}:
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish artifact: tcltk_lib_arm64'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)\tcl_arm64'
|
||||
artifactName: tcltk_lib_arm64
|
|
@ -1,61 +0,0 @@
|
|||
jobs:
|
||||
- job: Make_Embed_Layout
|
||||
displayName: Make embeddable layout
|
||||
condition: and(succeeded(), eq(variables['DoEmbed'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
win32:
|
||||
Name: win32
|
||||
Python: $(Build.BinariesDirectory)\bin\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
amd64:
|
||||
Name: amd64
|
||||
Python: $(Build.BinariesDirectory)\bin\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
arm64:
|
||||
Name: arm64
|
||||
HostArch: amd64
|
||||
Python: $(Build.BinariesDirectory)\bin_amd64\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_$(Name)'
|
||||
inputs:
|
||||
artifactName: bin_$(Name)
|
||||
targetPath: $(Build.BinariesDirectory)\bin
|
||||
|
||||
- template: ./layout-command.yml
|
||||
|
||||
- powershell: |
|
||||
$d = (.\PCbuild\build.bat -V) | %{ if($_ -match '\s+(\w+):\s*(.+)\s*$') { @{$Matches[1] = $Matches[2];} }};
|
||||
Write-Host "##vso[task.setvariable variable=VersionText]$($d.PythonVersion)"
|
||||
displayName: 'Extract version numbers'
|
||||
|
||||
- powershell: >
|
||||
$(LayoutCmd)
|
||||
--copy "$(Build.ArtifactStagingDirectory)\layout"
|
||||
--zip "$(Build.ArtifactStagingDirectory)\embed\python-$(VersionText)-embed-$(Name).zip"
|
||||
--preset-embed
|
||||
displayName: 'Generate embeddable layout'
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish Artifact: layout_embed_$(Name)'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)\layout'
|
||||
artifactName: layout_embed_$(Name)
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: embed'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)\embed'
|
||||
ArtifactName: embed
|
|
@ -1,80 +0,0 @@
|
|||
parameters:
|
||||
ARM64TclTk: true
|
||||
|
||||
jobs:
|
||||
- job: Make_Layouts
|
||||
displayName: Make layouts
|
||||
condition: and(succeeded(), eq(variables['DoLayout'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
win32:
|
||||
Name: win32
|
||||
Python: $(Build.BinariesDirectory)\bin\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
TclLibrary: $(Build.BinariesDirectory)\tcltk_lib\tcl8
|
||||
amd64:
|
||||
Name: amd64
|
||||
Python: $(Build.BinariesDirectory)\bin\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
TclLibrary: $(Build.BinariesDirectory)\tcltk_lib\tcl8
|
||||
arm64:
|
||||
Name: arm64
|
||||
HostArch: amd64
|
||||
Python: $(Build.BinariesDirectory)\bin_amd64\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
${{ if eq(parameters.ARM64TclTk, true) }}:
|
||||
TclLibrary: $(Build.BinariesDirectory)\tcltk_lib\tcl8
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_$(Name)'
|
||||
inputs:
|
||||
artifactName: bin_$(Name)
|
||||
targetPath: $(Build.BinariesDirectory)\bin
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_$(Name)_d'
|
||||
inputs:
|
||||
artifactName: bin_$(Name)_d
|
||||
targetPath: $(Build.BinariesDirectory)\bin
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: doc'
|
||||
inputs:
|
||||
artifactName: doc
|
||||
targetPath: $(Build.BinariesDirectory)\doc
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: tcltk_lib_$(Name)'
|
||||
condition: and(succeeded(), variables['TclLibrary'])
|
||||
inputs:
|
||||
artifactName: tcltk_lib_$(Name)
|
||||
targetPath: $(Build.BinariesDirectory)\tcltk_lib
|
||||
|
||||
- powershell: |
|
||||
copy "$(Build.BinariesDirectory)\bin\Activate.ps1" Lib\venv\scripts\common\Activate.ps1 -Force
|
||||
displayName: 'Copy signed files into sources'
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
|
||||
- template: ./layout-command.yml
|
||||
|
||||
- powershell: |
|
||||
$(LayoutCmd) --copy "$(Build.ArtifactStagingDirectory)\layout" --preset-default
|
||||
displayName: 'Generate full layout'
|
||||
env:
|
||||
TCL_LIBRARY: $(TclLibrary)
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish Artifact: layout_full_$(Name)'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)\layout'
|
||||
artifactName: layout_full_$(Name)
|
|
@ -1,102 +0,0 @@
|
|||
parameters:
|
||||
ARM64TclTk: true
|
||||
|
||||
jobs:
|
||||
- job: Make_MSIX_Layout
|
||||
displayName: Make MSIX layout
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
#win32:
|
||||
# Name: win32
|
||||
# Python: $(Build.BinariesDirectory)\bin\python.exe
|
||||
# PYTHONHOME: $(Build.SourcesDirectory)
|
||||
# TclLibrary: $(Build.BinariesDirectory)\tcltk_lib\tcl8
|
||||
amd64:
|
||||
Name: amd64
|
||||
Python: $(Build.BinariesDirectory)\bin\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
TclLibrary: $(Build.BinariesDirectory)\tcltk_lib\tcl8
|
||||
arm64:
|
||||
Name: arm64
|
||||
HostArch: amd64
|
||||
Python: $(Build.BinariesDirectory)\bin_amd64\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
${{ if eq(parameters.ARM64TclTk, true) }}:
|
||||
TclLibrary: $(Build.BinariesDirectory)\tcltk_lib\tcl8
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_$(Name)'
|
||||
inputs:
|
||||
artifactName: bin_$(Name)
|
||||
targetPath: $(Build.BinariesDirectory)\bin
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_$(Name)_d'
|
||||
inputs:
|
||||
artifactName: bin_$(Name)_d
|
||||
targetPath: $(Build.BinariesDirectory)\bin
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: tcltk_lib_$(Name)'
|
||||
condition: and(succeeded(), variables['TclLibrary'])
|
||||
inputs:
|
||||
artifactName: tcltk_lib_$(Name)
|
||||
targetPath: $(Build.BinariesDirectory)\tcltk_lib
|
||||
|
||||
- powershell: |
|
||||
copy "$(Build.BinariesDirectory)\bin\Activate.ps1" Lib\venv\scripts\common\Activate.ps1 -Force
|
||||
displayName: 'Copy signed files into sources'
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
|
||||
- template: ./layout-command.yml
|
||||
|
||||
- powershell: |
|
||||
Remove-Item "$(Build.ArtifactStagingDirectory)\appx-store" -Recurse -Force -EA 0
|
||||
$(LayoutCmd) --copy "$(Build.ArtifactStagingDirectory)\appx-store" --preset-appx --precompile
|
||||
displayName: 'Generate store APPX layout'
|
||||
env:
|
||||
TCL_LIBRARY: $(TclLibrary)
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish Artifact: layout_appxstore_$(Name)'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)\appx-store'
|
||||
artifactName: layout_appxstore_$(Name)
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: cert'
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
inputs:
|
||||
artifactName: cert
|
||||
targetPath: $(Build.BinariesDirectory)\cert
|
||||
|
||||
- powershell: |
|
||||
$info = (gc "$(Build.BinariesDirectory)\cert\certinfo.json" | ConvertFrom-JSON)
|
||||
Write-Host "Side-loadable APPX must be signed with '$($info.Subject)'"
|
||||
Write-Host "##vso[task.setvariable variable=APPX_DATA_PUBLISHER]$($info.Subject)"
|
||||
Write-Host "##vso[task.setvariable variable=APPX_DATA_SHA256]$($info.SHA256)"
|
||||
displayName: 'Override signing parameters'
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
|
||||
- powershell: |
|
||||
Remove-Item "$(Build.ArtifactStagingDirectory)\appx" -Recurse -Force -EA 0
|
||||
$(LayoutCmd) --copy "$(Build.ArtifactStagingDirectory)\appx" --preset-appx --precompile --include-symbols --include-tests
|
||||
displayName: 'Generate sideloading APPX layout'
|
||||
env:
|
||||
TCL_LIBRARY: $(TclLibrary)
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish Artifact: layout_appx_$(Name)'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)\appx'
|
||||
artifactName: layout_appx_$(Name)
|
|
@ -1,52 +0,0 @@
|
|||
jobs:
|
||||
- job: Make_Nuget_Layout
|
||||
displayName: Make Nuget layout
|
||||
condition: and(succeeded(), eq(variables['DoNuget'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
win32:
|
||||
Name: win32
|
||||
Python: $(Build.BinariesDirectory)\bin\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
amd64:
|
||||
Name: amd64
|
||||
Python: $(Build.BinariesDirectory)\bin\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
arm64:
|
||||
Name: arm64
|
||||
HostArch: amd64
|
||||
Python: $(Build.BinariesDirectory)\bin_amd64\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: bin_$(Name)'
|
||||
inputs:
|
||||
artifactName: bin_$(Name)
|
||||
targetPath: $(Build.BinariesDirectory)\bin
|
||||
|
||||
- powershell: |
|
||||
copy $(Build.BinariesDirectory)\bin\Activate.ps1 Lib\venv\scripts\common\Activate.ps1 -Force
|
||||
displayName: 'Copy signed files into sources'
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
|
||||
- template: ./layout-command.yml
|
||||
|
||||
- powershell: |
|
||||
$(LayoutCmd) --copy "$(Build.ArtifactStagingDirectory)\nuget" --preset-nuget
|
||||
displayName: 'Generate nuget layout'
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish Artifact: layout_nuget_$(Name)'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)\nuget'
|
||||
artifactName: layout_nuget_$(Name)
|
|
@ -1,43 +0,0 @@
|
|||
parameters:
|
||||
ARM64TclTk: true
|
||||
|
||||
jobs:
|
||||
- job: Make_MSI
|
||||
displayName: Make MSI
|
||||
condition: and(succeeded(), not(variables['SigningCertificate']))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
variables:
|
||||
ReleaseUri: http://www.python.org/{arch}
|
||||
DownloadUrl: https://www.python.org/ftp/python/{version}/{arch}{releasename}/{msi}
|
||||
Py_OutDir: $(Build.BinariesDirectory)
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- template: msi-steps.yml
|
||||
parameters:
|
||||
ARM64TclTk: ${{ parameters.ARM64TclTk }}
|
||||
|
||||
- job: Make_Signed_MSI
|
||||
displayName: Make signed MSI
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
|
||||
pool:
|
||||
name: 'Windows Release'
|
||||
|
||||
variables:
|
||||
ReleaseUri: http://www.python.org/{arch}
|
||||
DownloadUrl: https://www.python.org/ftp/python/{version}/{arch}{releasename}/{msi}
|
||||
Py_OutDir: $(Build.BinariesDirectory)
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- template: msi-steps.yml
|
||||
parameters:
|
||||
ARM64TclTk: ${{ parameters.ARM64TclTk }}
|
|
@ -1,148 +0,0 @@
|
|||
jobs:
|
||||
- job: Pack_MSIX
|
||||
displayName: Pack MSIX bundles
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
amd64:
|
||||
Name: amd64
|
||||
Artifact: appx
|
||||
Suffix:
|
||||
ShouldSign: true
|
||||
amd64_store:
|
||||
Name: amd64
|
||||
Artifact: appxstore
|
||||
Suffix: -store
|
||||
Upload: true
|
||||
arm64:
|
||||
Name: arm64
|
||||
Artifact: appx
|
||||
Suffix:
|
||||
ShouldSign: true
|
||||
arm64_store:
|
||||
Name: arm64
|
||||
Artifact: appxstore
|
||||
Suffix: -store
|
||||
Upload: true
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: layout_$(Artifact)_$(Name)'
|
||||
inputs:
|
||||
artifactName: layout_$(Artifact)_$(Name)
|
||||
targetPath: $(Build.BinariesDirectory)\layout
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: symbols'
|
||||
inputs:
|
||||
artifactName: symbols
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
|
||||
- powershell: |
|
||||
$d = (.\PCbuild\build.bat -V) | %{ if($_ -match '\s+(\w+):\s*(.+)\s*$') { @{$Matches[1] = $Matches[2];} }};
|
||||
Write-Host "##vso[task.setvariable variable=VersionText]$($d.PythonVersion)"
|
||||
Write-Host "##vso[task.setvariable variable=VersionNumber]$($d.PythonVersionNumber)"
|
||||
Write-Host "##vso[task.setvariable variable=VersionHex]$($d.PythonVersionHex)"
|
||||
Write-Host "##vso[task.setvariable variable=VersionUnique]$($d.PythonVersionUnique)"
|
||||
Write-Host "##vso[task.setvariable variable=Filename]python-$($d.PythonVersion)-$(Name)$(Suffix)"
|
||||
displayName: 'Extract version numbers'
|
||||
|
||||
- powershell: |
|
||||
./Tools/msi/make_appx.ps1 -layout "$(Build.BinariesDirectory)\layout" -msix "$(Build.ArtifactStagingDirectory)\msix\$(Filename).msix"
|
||||
displayName: 'Build msix'
|
||||
|
||||
- powershell: |
|
||||
7z a -tzip "$(Build.ArtifactStagingDirectory)\msix\$(Filename).appxsym" *.pdb
|
||||
displayName: 'Build appxsym'
|
||||
workingDirectory: $(Build.BinariesDirectory)\symbols\$(Name)
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: MSIX'
|
||||
condition: and(succeeded(), or(ne(variables['ShouldSign'], 'true'), not(variables['SigningCertificate'])))
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)\msix'
|
||||
ArtifactName: msix
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: MSIX'
|
||||
condition: and(succeeded(), and(eq(variables['ShouldSign'], 'true'), variables['SigningCertificate']))
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)\msix'
|
||||
ArtifactName: unsigned_msix
|
||||
|
||||
- powershell: |
|
||||
7z a -tzip "$(Build.ArtifactStagingDirectory)\msixupload\$(Filename).msixupload" *
|
||||
displayName: 'Build msixupload'
|
||||
condition: and(succeeded(), eq(variables['Upload'], 'true'))
|
||||
workingDirectory: $(Build.ArtifactStagingDirectory)\msix
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: MSIXUpload'
|
||||
condition: and(succeeded(), eq(variables['Upload'], 'true'))
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)\msixupload'
|
||||
ArtifactName: msixupload
|
||||
|
||||
|
||||
- job: Sign_MSIX
|
||||
displayName: Sign side-loadable MSIX bundles
|
||||
dependsOn:
|
||||
- Pack_MSIX
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
|
||||
pool:
|
||||
name: 'Windows Release'
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
- template: ./find-sdk.yml
|
||||
|
||||
- powershell: |
|
||||
$d = (.\PCbuild\build.bat -V) | %{ if($_ -match '\s+(\w+):\s*(.+)\s*$') { @{$Matches[1] = $Matches[2];} }};
|
||||
Write-Host "##vso[task.setvariable variable=SigningDescription]Python $($d.PythonVersion)"
|
||||
displayName: 'Update signing description'
|
||||
condition: and(succeeded(), not(variables['SigningDescription']))
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download Artifact: unsigned_msix'
|
||||
inputs:
|
||||
artifactName: unsigned_msix
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
|
||||
# MSIX must be signed and timestamped simultaneously
|
||||
#
|
||||
# Getting "Error: SignerSign() failed." (-2147024885/0x8007000b)"?
|
||||
# It may be that the certificate info collected in stage-sign.yml is wrong. Check that
|
||||
# you do not have multiple matches for the certificate name you have specified.
|
||||
- powershell: |
|
||||
$failed = $true
|
||||
foreach ($retry in 1..3) {
|
||||
signtool sign /a /n "$(SigningCertificate)" /fd sha256 /tr http://timestamp.digicert.com/ /td sha256 /d "$(SigningDescription)" (gi *.msix)
|
||||
if ($?) {
|
||||
$failed = $false
|
||||
break
|
||||
}
|
||||
sleep 1
|
||||
}
|
||||
if ($failed) {
|
||||
throw "Failed to sign MSIX"
|
||||
}
|
||||
displayName: 'Sign MSIX'
|
||||
workingDirectory: $(Build.BinariesDirectory)\unsigned_msix
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: MSIX'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.BinariesDirectory)\unsigned_msix'
|
||||
ArtifactName: msix
|
|
@ -1,66 +0,0 @@
|
|||
jobs:
|
||||
- job: Pack_Nuget
|
||||
displayName: Pack Nuget bundles
|
||||
condition: and(succeeded(), eq(variables['DoNuget'], 'true'))
|
||||
|
||||
pool:
|
||||
name: 'Windows Release'
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
amd64:
|
||||
Name: amd64
|
||||
win32:
|
||||
Name: win32
|
||||
arm64:
|
||||
Name: arm64
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: layout_nuget_$(Name)'
|
||||
inputs:
|
||||
artifactName: layout_nuget_$(Name)
|
||||
targetPath: $(Build.BinariesDirectory)\layout
|
||||
|
||||
- task: NugetToolInstaller@0
|
||||
displayName: 'Install Nuget'
|
||||
inputs:
|
||||
versionSpec: '>=5.0'
|
||||
|
||||
- powershell: >
|
||||
nuget pack
|
||||
"$(Build.BinariesDirectory)\layout\python.nuspec"
|
||||
-OutputDirectory $(Build.ArtifactStagingDirectory)
|
||||
-NoPackageAnalysis
|
||||
-NonInteractive
|
||||
condition: and(succeeded(), not(variables['OverrideNugetVersion']))
|
||||
displayName: 'Create nuget package'
|
||||
|
||||
- powershell: >
|
||||
nuget pack
|
||||
"$(Build.BinariesDirectory)\layout\python.nuspec"
|
||||
-OutputDirectory $(Build.ArtifactStagingDirectory)
|
||||
-NoPackageAnalysis
|
||||
-NonInteractive
|
||||
-Version "$(OverrideNugetVersion)"
|
||||
condition: and(succeeded(), variables['OverrideNugetVersion'])
|
||||
displayName: 'Create nuget package'
|
||||
|
||||
- powershell: |
|
||||
gci *.nupkg | %{
|
||||
nuget sign "$_" -CertificateSubjectName "$(SigningCertificate)" -Timestamper http://timestamp.digicert.com/ -Overwrite
|
||||
}
|
||||
displayName: 'Sign nuget package'
|
||||
workingDirectory: $(Build.ArtifactStagingDirectory)
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: nuget'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
ArtifactName: nuget
|
|
@ -1,50 +0,0 @@
|
|||
parameters:
|
||||
BuildToPublish: ''
|
||||
|
||||
jobs:
|
||||
- job: Publish_Nuget
|
||||
displayName: Publish Nuget packages
|
||||
condition: and(succeeded(), eq(variables['DoNuget'], 'true'), ne(variables['SkipNugetPublish'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- ${{ if parameters.BuildToPublish }}:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact from ${{ parameters.BuildToPublish }}'
|
||||
inputs:
|
||||
artifactName: nuget
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
buildType: specific
|
||||
project: $(System.TeamProject)
|
||||
pipeline: $(Build.DefinitionName)
|
||||
buildVersionToDownload: specific
|
||||
buildId: ${{ parameters.BuildToPublish }}
|
||||
|
||||
- ${{ else }}:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: nuget'
|
||||
inputs:
|
||||
artifactName: nuget
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
|
||||
|
||||
- powershell: 'gci pythonarm*.nupkg | %{ Write-Host "Not publishing: $($_.Name)"; gi $_ } | del'
|
||||
displayName: 'Prevent publishing ARM64 packages'
|
||||
workingDirectory: '$(Build.BinariesDirectory)\nuget'
|
||||
condition: and(succeeded(), ne(variables['PublishARM64'], 'true'))
|
||||
|
||||
- task: NuGetCommand@2
|
||||
displayName: Push packages
|
||||
condition: and(succeeded(), eq(variables['SigningCertificate'], variables['__RealSigningCertificate']))
|
||||
inputs:
|
||||
command: push
|
||||
packagesToPush: '$(Build.BinariesDirectory)\nuget\*.nupkg'
|
||||
nuGetFeedType: external
|
||||
publishFeedCredentials: 'Python on Nuget'
|
|
@ -1,192 +0,0 @@
|
|||
parameters:
|
||||
BuildToPublish: ''
|
||||
|
||||
jobs:
|
||||
- job: Publish_Python
|
||||
displayName: Publish python.org packages
|
||||
condition: and(succeeded(), eq(variables['DoMSI'], 'true'), eq(variables['DoEmbed'], 'true'), ne(variables['SkipPythonOrgPublish'], 'true'))
|
||||
|
||||
pool:
|
||||
#vmImage: windows-2022
|
||||
name: 'Windows Release'
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
|
||||
- task: UsePythonVersion@0
|
||||
displayName: 'Use Python 3.6 or later'
|
||||
inputs:
|
||||
versionSpec: '>=3.6'
|
||||
|
||||
- ${{ if parameters.BuildToPublish }}:
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact from ${{ parameters.BuildToPublish }}: Doc'
|
||||
inputs:
|
||||
artifactName: Doc
|
||||
targetPath: $(Build.BinariesDirectory)\Doc
|
||||
buildType: specific
|
||||
project: $(System.TeamProject)
|
||||
pipeline: $(Build.DefinitionName)
|
||||
buildVersionToDownload: specific
|
||||
buildId: ${{ parameters.BuildToPublish }}
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact from ${{ parameters.BuildToPublish }}: msi'
|
||||
inputs:
|
||||
artifactName: msi
|
||||
targetPath: $(Build.BinariesDirectory)\msi
|
||||
buildType: specific
|
||||
project: $(System.TeamProject)
|
||||
pipeline: $(Build.DefinitionName)
|
||||
buildVersionToDownload: specific
|
||||
buildId: ${{ parameters.BuildToPublish }}
|
||||
|
||||
# Note that embed is a 'build' artifact, not a 'pipeline' artifact
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact from ${{ parameters.BuildToPublish }}: embed'
|
||||
inputs:
|
||||
artifactName: embed
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
buildType: specific
|
||||
project: $(System.TeamProject)
|
||||
pipeline: $(Build.DefinitionName)
|
||||
buildVersionToDownload: specific
|
||||
buildId: ${{ parameters.BuildToPublish }}
|
||||
|
||||
- ${{ else }}:
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: Doc'
|
||||
inputs:
|
||||
artifactName: Doc
|
||||
targetPath: $(Build.BinariesDirectory)\Doc
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: msi'
|
||||
inputs:
|
||||
artifactName: msi
|
||||
targetPath: $(Build.BinariesDirectory)\msi
|
||||
|
||||
# Note that embed is a 'build' artifact, not a 'pipeline' artifact
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: embed'
|
||||
inputs:
|
||||
artifactName: embed
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
|
||||
|
||||
# Note that ARM64 MSIs are skipped at build when this option is specified
|
||||
- powershell: 'gci *embed-arm*.zip | %{ Write-Host "Not publishing: $($_.Name)"; gi $_ } | del'
|
||||
displayName: 'Prevent publishing ARM64 packages'
|
||||
workingDirectory: '$(Build.BinariesDirectory)\embed'
|
||||
condition: and(succeeded(), ne(variables['PublishARM64'], 'true'))
|
||||
|
||||
|
||||
- task: DownloadSecureFile@1
|
||||
name: gpgkey
|
||||
inputs:
|
||||
secureFile: 'python-signing.key'
|
||||
displayName: 'Download GPG key'
|
||||
|
||||
- powershell: |
|
||||
git clone https://github.com/python/cpython-bin-deps --branch gpg --single-branch --depth 1 --progress -v "gpg"
|
||||
gpg/gpg2.exe --import "$(gpgkey.secureFilePath)"
|
||||
$files = gci -File "msi\*\*", "embed\*.zip"
|
||||
if ("$(DoCHM)" -ieq "true") {
|
||||
$files = $files + (gci -File "doc\htmlhelp\*.chm")
|
||||
}
|
||||
$files.FullName | %{
|
||||
gpg/gpg2.exe -ba --batch --passphrase $(GPGPassphrase) $_
|
||||
"Made signature for $_"
|
||||
}
|
||||
displayName: 'Generate GPG signatures'
|
||||
workingDirectory: $(Build.BinariesDirectory)
|
||||
|
||||
- powershell: |
|
||||
$p = gps "gpg-agent" -EA 0
|
||||
if ($p) { $p.Kill() }
|
||||
displayName: 'Kill GPG agent'
|
||||
condition: true
|
||||
|
||||
|
||||
- powershell: >
|
||||
$(Build.SourcesDirectory)\Tools\msi\uploadrelease.ps1
|
||||
-build msi
|
||||
-user $(PyDotOrgUsername)
|
||||
-server $(PyDotOrgServer)
|
||||
-doc_htmlhelp doc\htmlhelp
|
||||
-embed embed
|
||||
-skippurge
|
||||
-skiptest
|
||||
-skiphash
|
||||
condition: and(succeeded(), eq(variables['SigningCertificate'], variables['__RealSigningCertificate']))
|
||||
workingDirectory: $(Build.BinariesDirectory)
|
||||
displayName: 'Upload files to python.org'
|
||||
|
||||
- powershell: >
|
||||
python
|
||||
"$(Build.SourcesDirectory)\Tools\msi\purge.py"
|
||||
(gci msi\*\python-*.exe | %{ $_.Name -replace 'python-(.+?)(-|\.exe).+', '$1' } | select -First 1)
|
||||
workingDirectory: $(Build.BinariesDirectory)
|
||||
condition: and(succeeded(), eq(variables['SigningCertificate'], variables['__RealSigningCertificate']))
|
||||
displayName: 'Purge CDN'
|
||||
|
||||
- powershell: |
|
||||
$failures = 0
|
||||
gci "msi\*\*.exe" -File | %{
|
||||
$d = mkdir "tests\$($_.BaseName)" -Force
|
||||
gci $d -r -File | del
|
||||
$ic = copy $_ $d -PassThru
|
||||
"Checking layout for $($ic.Name)"
|
||||
Start-Process -wait $ic "/passive", "/layout", "$d\layout", "/log", "$d\log\install.log"
|
||||
if (-not $?) {
|
||||
Write-Error "Failed to validate layout of $($inst.Name)"
|
||||
$failures += 1
|
||||
}
|
||||
}
|
||||
if ($failures) {
|
||||
Write-Error "Failed to validate $failures installers"
|
||||
exit 1
|
||||
}
|
||||
condition: and(succeeded(), eq(variables['SigningCertificate'], variables['__RealSigningCertificate']))
|
||||
workingDirectory: $(Build.BinariesDirectory)
|
||||
displayName: 'Test layouts'
|
||||
|
||||
- powershell: |
|
||||
$files = gci -File "msi\*\*.exe", "embed\*.zip"
|
||||
if ("$(DoCHM)" -ieq "true") {
|
||||
$files = $files + (gci -File "doc\htmlhelp\python*.chm")
|
||||
}
|
||||
$hashes = $files | `
|
||||
Sort-Object Name | `
|
||||
Format-Table Name, @{
|
||||
Label="MD5";
|
||||
Expression={(Get-FileHash $_ -Algorithm MD5).Hash}
|
||||
}, Length -AutoSize | `
|
||||
Out-String -Width 4096
|
||||
$d = mkdir "$(Build.ArtifactStagingDirectory)\hashes" -Force
|
||||
$hashes | Out-File "$d\hashes.txt" -Encoding ascii
|
||||
$hashes
|
||||
workingDirectory: $(Build.BinariesDirectory)
|
||||
displayName: 'Generate hashes'
|
||||
|
||||
- powershell: |
|
||||
"Copying:"
|
||||
$files = gci -File "msi\*\python*.asc", "embed\*.asc"
|
||||
if ("$(DoCHM)" -ieq "true") {
|
||||
$files = $files + (gci -File "doc\htmlhelp\*.asc")
|
||||
}
|
||||
$files.FullName
|
||||
$d = mkdir "$(Build.ArtifactStagingDirectory)\hashes" -Force
|
||||
move $files $d -Force
|
||||
gci msi -Directory | %{ move "msi\$_\*.asc" (mkdir "$d\$_" -Force) }
|
||||
workingDirectory: $(Build.BinariesDirectory)
|
||||
displayName: 'Copy GPG signatures for build'
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish Artifact: hashes'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)\hashes'
|
||||
artifactName: hashes
|
|
@ -1,38 +0,0 @@
|
|||
parameters:
|
||||
BuildToPublish: ''
|
||||
|
||||
jobs:
|
||||
- job: Publish_Store
|
||||
displayName: Publish Store packages
|
||||
condition: and(succeeded(), eq(variables['DoMSIX'], 'true'), ne(variables['SkipMSIXPublish'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- ${{ if parameters.BuildToPublish }}:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: msixupload'
|
||||
inputs:
|
||||
artifactName: msixupload
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
buildType: specific
|
||||
project: cpython
|
||||
pipeline: Windows-Release
|
||||
buildVersionToDownload: specific
|
||||
buildId: ${{ parameters.BuildToPublish }}
|
||||
|
||||
- ${{ else }}:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: msixupload'
|
||||
inputs:
|
||||
artifactName: msixupload
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
|
||||
# TODO: eq(variables['SigningCertificate'], variables['__RealSigningCertificate'])
|
||||
# If we are not real-signed, DO NOT PUBLISH
|
|
@ -1,130 +0,0 @@
|
|||
parameters:
|
||||
Include: '*.exe, *.dll, *.pyd, *.cat, *.ps1'
|
||||
Exclude: 'vcruntime*, libffi*, libcrypto*, libssl*'
|
||||
|
||||
jobs:
|
||||
- job: Sign_Python
|
||||
displayName: Sign Python binaries
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
|
||||
pool:
|
||||
name: 'Windows Release'
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
win32:
|
||||
Name: win32
|
||||
amd64:
|
||||
Name: amd64
|
||||
arm64:
|
||||
Name: arm64
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
- template: ./find-sdk.yml
|
||||
|
||||
- powershell: |
|
||||
$d = (.\PCbuild\build.bat -V) | %{ if($_ -match '\s+(\w+):\s*(.+)\s*$') { @{$Matches[1] = $Matches[2];} }};
|
||||
Write-Host "##vso[task.setvariable variable=SigningDescription]Python $($d.PythonVersion)"
|
||||
displayName: 'Update signing description'
|
||||
condition: and(succeeded(), not(variables['SigningDescription']))
|
||||
|
||||
- powershell: |
|
||||
Write-Host "##vso[build.addbuildtag]signed"
|
||||
displayName: 'Add build tags'
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: unsigned_bin_$(Name)'
|
||||
inputs:
|
||||
artifactName: unsigned_bin_$(Name)
|
||||
targetPath: $(Build.BinariesDirectory)\bin
|
||||
|
||||
- powershell: |
|
||||
copy "$(Build.SourcesDirectory)\Lib\venv\scripts\common\Activate.ps1" .
|
||||
displayName: 'Copy files from source'
|
||||
workingDirectory: $(Build.BinariesDirectory)\bin
|
||||
|
||||
- powershell: |
|
||||
$files = (gi ${{ parameters.Include }} -Exclude ${{ parameters.Exclude }})
|
||||
signtool sign /a /n "$(SigningCertificate)" /fd sha256 /d "$(SigningDescription)" $files
|
||||
displayName: 'Sign binaries'
|
||||
workingDirectory: $(Build.BinariesDirectory)\bin
|
||||
|
||||
- powershell: |
|
||||
$files = (gi ${{ parameters.Include }} -Exclude ${{ parameters.Exclude }})
|
||||
$failed = $true
|
||||
foreach ($retry in 1..10) {
|
||||
signtool timestamp /tr http://timestamp.digicert.com/ /td sha256 $files
|
||||
if ($?) {
|
||||
$failed = $false
|
||||
break
|
||||
}
|
||||
sleep 5
|
||||
}
|
||||
if ($failed) {
|
||||
Write-Host "##vso[task.logissue type=error]Failed to timestamp files"
|
||||
}
|
||||
displayName: 'Timestamp binaries'
|
||||
workingDirectory: $(Build.BinariesDirectory)\bin
|
||||
continueOnError: true
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish artifact: bin_$(Name)'
|
||||
inputs:
|
||||
targetPath: '$(Build.BinariesDirectory)\bin'
|
||||
artifactName: bin_$(Name)
|
||||
|
||||
|
||||
- job: Dump_CertInfo
|
||||
displayName: Capture certificate info
|
||||
condition: and(succeeded(), variables['SigningCertificate'])
|
||||
|
||||
pool:
|
||||
name: 'Windows Release'
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- powershell: |
|
||||
$m = 'CN=$(SigningCertificate)'
|
||||
$c = ((gci Cert:\CurrentUser\My), (gci Cert:\LocalMachine\My)) | %{ $_ } | `
|
||||
?{ $_.Subject -match $m -and $_.NotBefore -lt (Get-Date) -and $_.NotAfter -gt (Get-Date) } | `
|
||||
select -First 1
|
||||
if (-not $c) {
|
||||
Write-Host "Failed to find certificate for $(SigningCertificate)"
|
||||
exit
|
||||
}
|
||||
$d = mkdir "$(Build.BinariesDirectory)\tmp" -Force
|
||||
$cf = "$d\cert.cer"
|
||||
[IO.File]::WriteAllBytes($cf, $c.Export("Cer"))
|
||||
$csha = (certutil -dump $cf | sls "Cert Hash\(sha256\): (.+)").Matches.Groups[1].Value
|
||||
|
||||
$info = @{ Subject=$c.Subject; SHA256=$csha; }
|
||||
|
||||
$d = mkdir "$(Build.BinariesDirectory)\cert" -Force
|
||||
$info | ConvertTo-JSON -Compress | Out-File -Encoding utf8 "$d\certinfo.json"
|
||||
displayName: "Extract certificate info"
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish artifact: cert'
|
||||
inputs:
|
||||
targetPath: '$(Build.BinariesDirectory)\cert'
|
||||
artifactName: cert
|
||||
|
||||
|
||||
- job: Mark_Unsigned
|
||||
displayName: Tag unsigned build
|
||||
condition: and(succeeded(), not(variables['SigningCertificate']))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- powershell: |
|
||||
Write-Host "##vso[build.addbuildtag]unsigned"
|
||||
displayName: 'Add build tag'
|
|
@ -1,41 +0,0 @@
|
|||
jobs:
|
||||
- job: Test_Embed
|
||||
displayName: Test Embed
|
||||
condition: and(succeeded(), eq(variables['DoEmbed'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
win32:
|
||||
Name: win32
|
||||
amd64:
|
||||
Name: amd64
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: embed'
|
||||
inputs:
|
||||
artifactName: embed
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
|
||||
- powershell: |
|
||||
$p = gi "$(Build.BinariesDirectory)\embed\python*embed-$(Name).zip"
|
||||
Expand-Archive -Path $p -DestinationPath "$(Build.BinariesDirectory)\Python"
|
||||
$p = gi "$(Build.BinariesDirectory)\Python\python.exe"
|
||||
Write-Host "##vso[task.prependpath]$(Split-Path -Parent $p)"
|
||||
displayName: 'Install Python and add to PATH'
|
||||
|
||||
- script: |
|
||||
python -c "import sys; print(sys.version)"
|
||||
displayName: 'Collect version number'
|
||||
|
||||
- script: |
|
||||
python -m site
|
||||
displayName: 'Collect site'
|
|
@ -1,108 +0,0 @@
|
|||
jobs:
|
||||
- job: Test_MSI
|
||||
displayName: Test MSI
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
win32_User:
|
||||
ExeMatch: 'python-[\dabrc.]+\.exe'
|
||||
Logs: $(Build.ArtifactStagingDirectory)\logs\win32_User
|
||||
InstallAllUsers: 0
|
||||
win32_Machine:
|
||||
ExeMatch: 'python-[\dabrc.]+\.exe'
|
||||
Logs: $(Build.ArtifactStagingDirectory)\logs\win32_Machine
|
||||
InstallAllUsers: 1
|
||||
amd64_User:
|
||||
ExeMatch: 'python-[\dabrc.]+-amd64\.exe'
|
||||
Logs: $(Build.ArtifactStagingDirectory)\logs\amd64_User
|
||||
InstallAllUsers: 0
|
||||
amd64_Machine:
|
||||
ExeMatch: 'python-[\dabrc.]+-amd64\.exe'
|
||||
Logs: $(Build.ArtifactStagingDirectory)\logs\amd64_Machine
|
||||
InstallAllUsers: 1
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: msi'
|
||||
inputs:
|
||||
artifactName: msi
|
||||
targetPath: $(Build.BinariesDirectory)\msi
|
||||
|
||||
- powershell: |
|
||||
$p = (gci -r *.exe | ?{ $_.Name -match '$(ExeMatch)' } | select -First 1)
|
||||
Write-Host "##vso[task.setvariable variable=SetupExe]$($p.FullName)"
|
||||
Write-Host "##vso[task.setvariable variable=SetupExeName]$($p.Name)"
|
||||
displayName: 'Find installer executable'
|
||||
workingDirectory: $(Build.BinariesDirectory)\msi
|
||||
|
||||
- script: >
|
||||
"$(SetupExe)"
|
||||
/passive
|
||||
/log "$(Logs)\install\log.txt"
|
||||
TargetDir="$(Build.BinariesDirectory)\Python"
|
||||
Include_debug=1
|
||||
Include_symbols=1
|
||||
InstallAllUsers=$(InstallAllUsers)
|
||||
displayName: 'Install Python'
|
||||
|
||||
- powershell: |
|
||||
$p = gi "$(Build.BinariesDirectory)\Python\python.exe"
|
||||
Write-Host "##vso[task.prependpath]$(Split-Path -Parent $p)"
|
||||
displayName: 'Add test Python to PATH'
|
||||
|
||||
- script: |
|
||||
python -c "import sys; print(sys.version)"
|
||||
displayName: 'Collect version number'
|
||||
|
||||
- script: |
|
||||
python -m site
|
||||
displayName: 'Collect site'
|
||||
|
||||
- powershell: |
|
||||
gci -r "${env:PROGRAMDATA}\Microsoft\Windows\Start Menu\Programs\Python*"
|
||||
displayName: 'Capture per-machine Start Menu items'
|
||||
- powershell: |
|
||||
gci -r "${env:APPDATA}\Microsoft\Windows\Start Menu\Programs\Python*"
|
||||
displayName: 'Capture per-user Start Menu items'
|
||||
|
||||
- powershell: |
|
||||
gci -r "HKLM:\Software\WOW6432Node\Python"
|
||||
displayName: 'Capture per-machine 32-bit registry'
|
||||
- powershell: |
|
||||
gci -r "HKLM:\Software\Python"
|
||||
displayName: 'Capture per-machine native registry'
|
||||
- powershell: |
|
||||
gci -r "HKCU:\Software\Python"
|
||||
displayName: 'Capture current-user registry'
|
||||
|
||||
- script: |
|
||||
python -m pip install "azure<0.10"
|
||||
python -m pip uninstall -y azure python-dateutil six
|
||||
displayName: 'Test (un)install package'
|
||||
|
||||
- script: |
|
||||
python -m test -uall -v test_ttk_guionly test_tk test_idle
|
||||
displayName: 'Test Tkinter and Idle'
|
||||
|
||||
- script: >
|
||||
"$(SetupExe)"
|
||||
/passive
|
||||
/uninstall
|
||||
/log "$(Logs)\uninstall\log.txt"
|
||||
displayName: 'Uninstall Python'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: logs'
|
||||
condition: true
|
||||
continueOnError: true
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)\logs'
|
||||
ArtifactName: msi_testlogs
|
|
@ -1,58 +0,0 @@
|
|||
jobs:
|
||||
- job: Test_Nuget
|
||||
displayName: Test Nuget
|
||||
condition: and(succeeded(), eq(variables['DoNuget'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
win32:
|
||||
Package: pythonx86
|
||||
amd64:
|
||||
Package: python
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: nuget'
|
||||
inputs:
|
||||
artifactName: nuget
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
|
||||
- task: NugetToolInstaller@0
|
||||
inputs:
|
||||
versionSpec: '>= 5'
|
||||
|
||||
- powershell: >
|
||||
nuget install
|
||||
$(Package)
|
||||
-Source "$(Build.BinariesDirectory)\nuget"
|
||||
-OutputDirectory "$(Build.BinariesDirectory)\install"
|
||||
-Prerelease
|
||||
-ExcludeVersion
|
||||
-NonInteractive
|
||||
displayName: 'Install Python'
|
||||
|
||||
- powershell: |
|
||||
$p = gi "$(Build.BinariesDirectory)\install\$(Package)\tools\python.exe"
|
||||
Write-Host "##vso[task.prependpath]$(Split-Path -Parent $p)"
|
||||
displayName: 'Add test Python to PATH'
|
||||
|
||||
- script: |
|
||||
python -c "import sys; print(sys.version)"
|
||||
displayName: 'Collect version number'
|
||||
|
||||
- script: |
|
||||
python -m site
|
||||
displayName: 'Collect site'
|
||||
|
||||
- script: |
|
||||
python -m pip install "azure<0.10"
|
||||
python -m pip uninstall -y azure python-dateutil six
|
||||
displayName: 'Test (un)install package'
|
24
.coveragerc
Normal file
24
.coveragerc
Normal file
|
@ -0,0 +1,24 @@
|
|||
[run]
|
||||
branch = True
|
||||
|
||||
[report]
|
||||
# Regexes for lines to exclude from consideration
|
||||
exclude_lines =
|
||||
# Don't complain if non-runnable code isn't run:
|
||||
if 0:
|
||||
if __name__ == .__main__.:
|
||||
raise AssertionError\(
|
||||
|
||||
# Empty bodies in protocols or abstract methods
|
||||
^\s*def [a-zA-Z0-9_]+\(.*\)(\s*->.*)?:\s*\.\.\.(\s*#.*)?$
|
||||
^\s*\.\.\.(\s*#.*)?$
|
||||
|
||||
.*# pragma: no cover
|
||||
.*# pragma: no branch
|
||||
|
||||
# Additions for IDLE:
|
||||
.*# htest #
|
||||
if not (_htest or _utest):
|
||||
if not .*_utest:
|
||||
if .*_htest:
|
||||
|
24
.devcontainer/Dockerfile
Normal file
24
.devcontainer/Dockerfile
Normal file
|
@ -0,0 +1,24 @@
|
|||
FROM docker.io/library/fedora:40
|
||||
|
||||
ENV CC=clang
|
||||
|
||||
ENV WASI_SDK_VERSION=21
|
||||
ENV WASI_SDK_PATH=/opt/wasi-sdk
|
||||
|
||||
ENV WASMTIME_HOME=/opt/wasmtime
|
||||
ENV WASMTIME_VERSION=18.0.3
|
||||
ENV WASMTIME_CPU_ARCH=x86_64
|
||||
|
||||
RUN dnf -y --nodocs --setopt=install_weak_deps=False install /usr/bin/{blurb,clang,curl,git,ln,tar,xz} 'dnf-command(builddep)' && \
|
||||
dnf -y --nodocs --setopt=install_weak_deps=False builddep python3 && \
|
||||
dnf -y clean all
|
||||
|
||||
RUN mkdir ${WASI_SDK_PATH} && \
|
||||
curl --location https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-linux.tar.gz | \
|
||||
tar --strip-components 1 --directory ${WASI_SDK_PATH} --extract --gunzip
|
||||
|
||||
RUN mkdir --parents ${WASMTIME_HOME} && \
|
||||
curl --location "https://github.com/bytecodealliance/wasmtime/releases/download/v${WASMTIME_VERSION}/wasmtime-v${WASMTIME_VERSION}-${WASMTIME_CPU_ARCH}-linux.tar.xz" | \
|
||||
xz --decompress | \
|
||||
tar --strip-components 1 --directory ${WASMTIME_HOME} -x && \
|
||||
ln -s ${WASMTIME_HOME}/wasmtime /usr/local/bin
|
88
.devcontainer/devcontainer.json
Normal file
88
.devcontainer/devcontainer.json
Normal file
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile"
|
||||
},
|
||||
"onCreateCommand": [
|
||||
// Install common tooling.
|
||||
"dnf",
|
||||
"install",
|
||||
"-y",
|
||||
"which",
|
||||
"zsh",
|
||||
"fish",
|
||||
// For umask fix below.
|
||||
"/usr/bin/setfacl"
|
||||
],
|
||||
"updateContentCommand": {
|
||||
// Using the shell for `nproc` usage.
|
||||
"python": "./configure --config-cache --with-pydebug && make -s -j `nproc`",
|
||||
"docs": [
|
||||
"make",
|
||||
"--directory",
|
||||
"Doc",
|
||||
"venv",
|
||||
"html"
|
||||
]
|
||||
},
|
||||
"postCreateCommand": {
|
||||
// https://github.com/orgs/community/discussions/26026
|
||||
"umask fix: workspace": ["sudo", "setfacl", "-bnR", "."],
|
||||
"umask fix: /tmp": ["sudo", "setfacl", "-bnR", "/tmp"]
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
// Highlighting for Parser/Python.asdl.
|
||||
"brettcannon.zephyr-asdl",
|
||||
// Highlighting for configure.ac.
|
||||
"maelvalais.autoconf",
|
||||
// C auto-complete.
|
||||
"ms-vscode.cpptools",
|
||||
// To view HTML build of docs.
|
||||
"ms-vscode.live-server",
|
||||
// Python auto-complete.
|
||||
"ms-python.python"
|
||||
],
|
||||
"settings": {
|
||||
"C_Cpp.default.compilerPath": "/usr/bin/clang",
|
||||
"C_Cpp.default.cStandard": "c11",
|
||||
"C_Cpp.default.defines": [
|
||||
"CONFIG_64",
|
||||
"Py_BUILD_CORE"
|
||||
],
|
||||
"C_Cpp.default.includePath": [
|
||||
"${workspaceFolder}/*",
|
||||
"${workspaceFolder}/Include/**"
|
||||
],
|
||||
// https://github.com/microsoft/vscode-cpptools/issues/10732
|
||||
"C_Cpp.errorSquiggles": "disabled",
|
||||
"editor.insertSpaces": true,
|
||||
"editor.rulers": [
|
||||
80
|
||||
],
|
||||
"editor.tabSize": 4,
|
||||
"editor.trimAutoWhitespace": true,
|
||||
"files.associations": {
|
||||
"*.h": "c"
|
||||
},
|
||||
"files.encoding": "utf8",
|
||||
"files.eol": "\n",
|
||||
"files.insertFinalNewline": true,
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"python.analysis.diagnosticSeverityOverrides": {
|
||||
// Complains about shadowing the stdlib w/ the stdlib.
|
||||
"reportShadowedImports": "none",
|
||||
// Doesn't like _frozen_importlib.
|
||||
"reportMissingImports": "none"
|
||||
},
|
||||
"python.analysis.extraPaths": [
|
||||
"Lib"
|
||||
],
|
||||
"python.defaultInterpreterPath": "./python",
|
||||
"[restructuredtext]": {
|
||||
"editor.tabSize": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
root = true
|
||||
|
||||
[*.{py,c,cpp,h,rst,md,yml}]
|
||||
[*.{py,c,cpp,h,js,rst,md,yml}]
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
|
@ -8,5 +8,8 @@ indent_style = space
|
|||
[*.{py,c,cpp,h}]
|
||||
indent_size = 4
|
||||
|
||||
[*.yml]
|
||||
[*.rst]
|
||||
indent_size = 3
|
||||
|
||||
[*.{js,yml}]
|
||||
indent_size = 2
|
||||
|
|
71
.gitattributes
vendored
71
.gitattributes
vendored
|
@ -18,20 +18,23 @@
|
|||
*.zip binary
|
||||
|
||||
# Specific binary files
|
||||
Lib/test/sndhdrdata/sndhdr.* binary
|
||||
PC/classicAppCompat.* binary
|
||||
|
||||
# Text files that should not be subject to eol conversion
|
||||
[attr]noeol -text
|
||||
|
||||
Lib/test/cjkencodings/* noeol
|
||||
Lib/test/coding20731.py noeol
|
||||
Lib/test/tokenizedata/coding20731.py noeol
|
||||
Lib/test/decimaltestdata/*.decTest noeol
|
||||
Lib/test/test_email/data/*.txt noeol
|
||||
Lib/test/test_importlib/data01/* noeol
|
||||
Lib/test/test_importlib/namespacedata01/* noeol
|
||||
Lib/test/test_importlib/resources/data01/* noeol
|
||||
Lib/test/test_importlib/resources/namespacedata01/* noeol
|
||||
Lib/test/xmltestdata/* noeol
|
||||
|
||||
# Shell scripts should have LF even on Windows because of Cygwin
|
||||
Lib/venv/scripts/common/activate text eol=lf
|
||||
Lib/venv/scripts/posix/* text eol=lf
|
||||
|
||||
# CRLF files
|
||||
[attr]dos text eol=crlf
|
||||
|
||||
|
@ -62,25 +65,41 @@ PCbuild/readme.txt dos
|
|||
#
|
||||
[attr]generated linguist-generated=true diff=generated
|
||||
|
||||
**/clinic/*.c.h generated
|
||||
*_db.h generated
|
||||
Doc/data/stable_abi.dat generated
|
||||
Doc/library/token-list.inc generated
|
||||
Include/internal/pycore_ast.h generated
|
||||
Include/internal/pycore_ast_state.h generated
|
||||
Include/opcode.h generated
|
||||
Include/token.h generated
|
||||
Lib/keyword.py generated
|
||||
Lib/test/test_stable_abi_ctypes.py generated
|
||||
Lib/token.py generated
|
||||
Objects/typeslots.inc generated
|
||||
PC/python3dll.c generated
|
||||
Parser/parser.c generated
|
||||
Parser/token.c generated
|
||||
Programs/test_frozenmain.h generated
|
||||
Python/Python-ast.c generated
|
||||
Python/opcode_targets.h generated
|
||||
Python/stdlib_module_names.h generated
|
||||
Tools/peg_generator/pegen/grammar_parser.py generated
|
||||
aclocal.m4 generated
|
||||
configure generated
|
||||
**/clinic/*.c.h generated
|
||||
**/clinic/*.cpp.h generated
|
||||
**/clinic/*.h.h generated
|
||||
*_db.h generated
|
||||
Doc/data/stable_abi.dat generated
|
||||
Doc/library/token-list.inc generated
|
||||
Include/internal/pycore_ast.h generated
|
||||
Include/internal/pycore_ast_state.h generated
|
||||
Include/internal/pycore_opcode.h generated
|
||||
Include/internal/pycore_opcode_metadata.h generated
|
||||
Include/internal/pycore_*_generated.h generated
|
||||
Include/internal/pycore_uop_ids.h generated
|
||||
Include/internal/pycore_uop_metadata.h generated
|
||||
Include/opcode.h generated
|
||||
Include/opcode_ids.h generated
|
||||
Include/token.h generated
|
||||
Lib/_opcode_metadata.py generated
|
||||
Lib/keyword.py generated
|
||||
Lib/test/certdata/*.pem generated
|
||||
Lib/test/certdata/*.0 generated
|
||||
Lib/test/levenshtein_examples.json generated
|
||||
Lib/test/test_stable_abi_ctypes.py generated
|
||||
Lib/token.py generated
|
||||
Misc/sbom.spdx.json generated
|
||||
Objects/typeslots.inc generated
|
||||
PC/python3dll.c generated
|
||||
Parser/parser.c generated
|
||||
Parser/token.c generated
|
||||
Programs/test_frozenmain.h generated
|
||||
Python/Python-ast.c generated
|
||||
Python/executor_cases.c.h generated
|
||||
Python/generated_cases.c.h generated
|
||||
Python/optimizer_cases.c.h generated
|
||||
Python/opcode_targets.h generated
|
||||
Python/stdlib_module_names.h generated
|
||||
Tools/peg_generator/pegen/grammar_parser.py generated
|
||||
aclocal.m4 generated
|
||||
configure generated
|
||||
|
|
169
.github/CODEOWNERS
vendored
169
.github/CODEOWNERS
vendored
|
@ -4,24 +4,72 @@
|
|||
# It uses the same pattern rule for gitignore file
|
||||
# https://git-scm.com/docs/gitignore#_pattern_format
|
||||
|
||||
# GitHub
|
||||
.github/** @ezio-melotti @hugovk
|
||||
|
||||
# pre-commit
|
||||
.pre-commit-config.yaml @hugovk @AlexWaygood
|
||||
.ruff.toml @hugovk @AlexWaygood
|
||||
|
||||
# Build system
|
||||
configure* @erlend-aasland @corona10
|
||||
|
||||
# asyncio
|
||||
**/*asyncio* @1st1 @asvetlov
|
||||
**/*asyncio* @1st1 @asvetlov @gvanrossum @kumaraditya303 @willingc
|
||||
|
||||
# Core
|
||||
**/*context* @1st1
|
||||
**/*genobject* @1st1 @markshannon
|
||||
**/*genobject* @markshannon
|
||||
**/*hamt* @1st1
|
||||
**/*jit* @brandtbucher
|
||||
Objects/set* @rhettinger
|
||||
Objects/dict* @methane @markshannon
|
||||
Objects/typevarobject.c @JelleZijlstra
|
||||
Objects/type* @markshannon
|
||||
Objects/codeobject.c @markshannon
|
||||
Objects/frameobject.c @markshannon
|
||||
Objects/call.c @markshannon
|
||||
Python/ceval.c @markshannon
|
||||
Python/compile.c @markshannon
|
||||
Python/ceval*.c @markshannon @gvanrossum
|
||||
Python/ceval*.h @markshannon @gvanrossum
|
||||
Python/compile.c @markshannon @iritkatriel
|
||||
Python/assemble.c @markshannon @iritkatriel
|
||||
Python/flowgraph.c @markshannon @iritkatriel
|
||||
Python/ast_opt.c @isidentical
|
||||
Python/bytecodes.c @markshannon @gvanrossum
|
||||
Python/optimizer*.c @markshannon @gvanrossum
|
||||
Python/optimizer_analysis.c @Fidget-Spinner
|
||||
Python/optimizer_bytecodes.c @Fidget-Spinner
|
||||
Lib/test/test_patma.py @brandtbucher
|
||||
Lib/test/test_peepholer.py @brandtbucher
|
||||
Lib/test/test_type_*.py @JelleZijlstra
|
||||
Lib/test/test_capi/test_misc.py @markshannon @gvanrossum
|
||||
Tools/c-analyzer/ @ericsnowcurrently
|
||||
|
||||
# dbm
|
||||
**/*dbm* @corona10 @erlend-aasland @serhiy-storchaka
|
||||
|
||||
# runtime state/lifecycle
|
||||
**/*pylifecycle* @ericsnowcurrently
|
||||
**/*pystate* @ericsnowcurrently
|
||||
**/*preconfig* @ericsnowcurrently
|
||||
**/*initconfig* @ericsnowcurrently
|
||||
**/*pathconfig* @ericsnowcurrently
|
||||
**/*sysmodule* @ericsnowcurrently
|
||||
**/*bltinmodule* @ericsnowcurrently
|
||||
**/*gil* @ericsnowcurrently
|
||||
Include/internal/pycore_runtime.h @ericsnowcurrently
|
||||
Include/internal/pycore_interp.h @ericsnowcurrently
|
||||
Include/internal/pycore_tstate.h @ericsnowcurrently
|
||||
Include/internal/pycore_*_state.h @ericsnowcurrently
|
||||
Include/internal/pycore_*_init.h @ericsnowcurrently
|
||||
Include/internal/pycore_atexit.h @ericsnowcurrently
|
||||
Include/internal/pycore_freelist.h @ericsnowcurrently
|
||||
Include/internal/pycore_global_objects.h @ericsnowcurrently
|
||||
Include/internal/pycore_obmalloc.h @ericsnowcurrently
|
||||
Include/internal/pycore_pymem.h @ericsnowcurrently
|
||||
Modules/main.c @ericsnowcurrently
|
||||
Programs/_bootstrap_python.c @ericsnowcurrently
|
||||
Programs/python.c @ericsnowcurrently
|
||||
Tools/build/generate_global_objects.py @ericsnowcurrently
|
||||
|
||||
# Exceptions
|
||||
Lib/traceback.py @iritkatriel
|
||||
|
@ -29,16 +77,15 @@ Lib/test/test_except*.py @iritkatriel
|
|||
Lib/test/test_traceback.py @iritkatriel
|
||||
Objects/exceptions.c @iritkatriel
|
||||
Python/traceback.c @iritkatriel
|
||||
Python/pythonrun.c @iritkatriel
|
||||
|
||||
# Hashing
|
||||
**/*hashlib* @tiran
|
||||
**/*pyhash* @tiran
|
||||
**/*sha* @tiran
|
||||
**/*md5* @tiran
|
||||
**/*blake* @tiran
|
||||
/Modules/_blake2/** @tiran
|
||||
/Modules/_sha3/** @tiran
|
||||
**/*hashlib* @gpshead @tiran
|
||||
**/*pyhash* @gpshead @tiran
|
||||
**/sha* @gpshead @tiran
|
||||
Modules/md5* @gpshead @tiran
|
||||
**/*blake* @gpshead @tiran
|
||||
Modules/_blake2/** @gpshead @tiran
|
||||
Modules/_hacl/** @gpshead
|
||||
|
||||
# logging
|
||||
**/*logging* @vsajip
|
||||
|
@ -53,13 +100,26 @@ Python/pythonrun.c @iritkatriel
|
|||
/Lib/html/ @ezio-melotti
|
||||
/Lib/_markupbase.py @ezio-melotti
|
||||
/Lib/test/test_html*.py @ezio-melotti
|
||||
/Tools/build/parse_html5_entities.py @ezio-melotti
|
||||
|
||||
# Import (including importlib).
|
||||
# Ignoring importlib.h so as to not get flagged on
|
||||
# all pull requests that change the emitted
|
||||
# bytecode.
|
||||
**/*import*.c @brettcannon @encukou @ericsnowcurrently @ncoghlan @warsaw
|
||||
**/*import*.py @brettcannon @encukou @ericsnowcurrently @ncoghlan @warsaw
|
||||
**/*import* @brettcannon @ericsnowcurrently @ncoghlan @warsaw
|
||||
/Python/import.c @kumaraditya303
|
||||
Python/dynload_*.c @ericsnowcurrently
|
||||
**/*freeze* @ericsnowcurrently
|
||||
**/*frozen* @ericsnowcurrently
|
||||
**/*modsupport* @ericsnowcurrently
|
||||
**/*modulefinder* @ericsnowcurrently
|
||||
**/*moduleobject* @ericsnowcurrently
|
||||
**/*multiphase* @ericsnowcurrently
|
||||
**/*pkgutil* @ericsnowcurrently
|
||||
**/*pythonrun* @ericsnowcurrently
|
||||
**/*runpy* @ericsnowcurrently
|
||||
**/*singlephase* @ericsnowcurrently
|
||||
Lib/test/test_module/ @ericsnowcurrently
|
||||
Doc/c-api/module.rst @ericsnowcurrently
|
||||
**/*importlib/resources/* @jaraco @warsaw @FFY00
|
||||
**/*importlib/metadata/* @jaraco @warsaw
|
||||
|
||||
# Dates and times
|
||||
**/*datetime* @pganssle @abalkin
|
||||
|
@ -68,7 +128,7 @@ Doc/library/time.rst @pganssle @abalkin
|
|||
Lib/test/test_time.py @pganssle @abalkin
|
||||
Modules/timemodule.c @pganssle @abalkin
|
||||
Python/pytime.c @pganssle @abalkin
|
||||
Include/pytime.h @pganssle @abalkin
|
||||
Include/internal/pycore_time.h @pganssle @abalkin
|
||||
|
||||
# Email and related
|
||||
**/*mail* @python/email-team
|
||||
|
@ -86,6 +146,11 @@ Include/pytime.h @pganssle @abalkin
|
|||
/Tools/peg_generator/ @pablogsal @lysnikolaou
|
||||
/Lib/test/test_peg_generator/ @pablogsal @lysnikolaou
|
||||
/Grammar/python.gram @pablogsal @lysnikolaou
|
||||
/Lib/tokenize.py @pablogsal @lysnikolaou
|
||||
/Lib/test/test_tokenize.py @pablogsal @lysnikolaou
|
||||
|
||||
# Code generator
|
||||
/Tools/cases_generator/ @gvanrossum
|
||||
|
||||
# AST
|
||||
Python/ast.c @isidentical
|
||||
|
@ -95,16 +160,25 @@ Lib/ast.py @isidentical
|
|||
|
||||
# Mock
|
||||
/Lib/unittest/mock.py @cjw296
|
||||
/Lib/unittest/test/testmock/* @cjw296
|
||||
/Lib/test/test_unittest/testmock/* @cjw296
|
||||
|
||||
# multiprocessing
|
||||
**/*multiprocessing* @gpshead
|
||||
|
||||
# SQLite 3
|
||||
**/*sqlite* @berkerpeksag
|
||||
**/*sqlite* @berkerpeksag @erlend-aasland
|
||||
|
||||
# subprocess
|
||||
/Lib/subprocess.py @gpshead
|
||||
/Lib/test/test_subprocess.py @gpshead
|
||||
/Modules/*subprocess* @gpshead
|
||||
|
||||
# Limited C API & stable ABI
|
||||
Tools/build/stable_abi.py @encukou
|
||||
Misc/stable_abi.toml @encukou
|
||||
Doc/data/*.abi @encukou
|
||||
Doc/c-api/stable.rst @encukou
|
||||
|
||||
# Windows
|
||||
/PC/ @python/windows-team
|
||||
/PCbuild/ @python/windows-team
|
||||
|
@ -128,12 +202,12 @@ Lib/ast.py @isidentical
|
|||
|
||||
**/*dataclasses* @ericvsmith
|
||||
|
||||
**/*ensurepip* @pfmoore @pradyunsg
|
||||
|
||||
**/*idlelib* @terryjreedy
|
||||
|
||||
**/*typing* @gvanrossum @Fidget-Spinner @JelleZijlstra
|
||||
**/*typing* @JelleZijlstra @AlexWaygood
|
||||
|
||||
**/*asyncore @giampaolo
|
||||
**/*asynchat @giampaolo
|
||||
**/*ftplib @giampaolo
|
||||
**/*shutil @giampaolo
|
||||
|
||||
|
@ -141,11 +215,54 @@ Lib/ast.py @isidentical
|
|||
**/*cgi* @ethanfurman
|
||||
**/*tarfile* @ethanfurman
|
||||
|
||||
**/*tomllib* @encukou
|
||||
**/*tomllib* @encukou @hauntsaninja
|
||||
|
||||
**/*sysconfig* @FFY00
|
||||
|
||||
**/*cjkcodecs* @corona10
|
||||
|
||||
# macOS
|
||||
/Mac/ @python/macos-team
|
||||
**/*osx_support* @python/macos-team
|
||||
|
||||
# pathlib
|
||||
**/*pathlib* @brettcannon
|
||||
**/*pathlib* @barneygale
|
||||
|
||||
# zipfile.Path
|
||||
**/*zipfile/_path/* @jaraco
|
||||
|
||||
# Argument Clinic
|
||||
/Tools/clinic/** @erlend-aasland
|
||||
/Lib/test/test_clinic.py @erlend-aasland
|
||||
Doc/howto/clinic.rst @erlend-aasland
|
||||
|
||||
# Subinterpreters
|
||||
**/*interpreteridobject.* @ericsnowcurrently
|
||||
**/*crossinterp* @ericsnowcurrently
|
||||
Lib/test/support/interpreters/ @ericsnowcurrently
|
||||
Modules/_xx*interp*module.c @ericsnowcurrently
|
||||
Lib/test/test_interpreters/ @ericsnowcurrently
|
||||
|
||||
# Android
|
||||
**/*Android* @mhsmith
|
||||
**/*android* @mhsmith
|
||||
|
||||
# iOS (but not termios)
|
||||
**/iOS* @freakboy3742
|
||||
**/ios* @freakboy3742
|
||||
**/*_iOS* @freakboy3742
|
||||
**/*_ios* @freakboy3742
|
||||
**/*-iOS* @freakboy3742
|
||||
**/*-ios* @freakboy3742
|
||||
|
||||
# WebAssembly
|
||||
/Tools/wasm/ @brettcannon
|
||||
|
||||
# SBOM
|
||||
/Misc/externals.spdx.json @sethmlarson
|
||||
/Misc/sbom.spdx.json @sethmlarson
|
||||
/Tools/build/generate_sbom.py @sethmlarson
|
||||
|
||||
# Config Parser
|
||||
Lib/configparser.py @jaraco
|
||||
Lib/test/test_configparser.py @jaraco
|
||||
|
|
18
.github/CONTRIBUTING.rst
vendored
18
.github/CONTRIBUTING.rst
vendored
|
@ -4,21 +4,9 @@ Contributing to Python
|
|||
Build Status
|
||||
------------
|
||||
|
||||
- main
|
||||
- `Buildbot status overview <https://buildbot.python.org/all/#/release_status>`_
|
||||
|
||||
+ `Stable buildbots <http://buildbot.python.org/3.x.stable/>`_
|
||||
|
||||
- 3.9
|
||||
|
||||
+ `Stable buildbots <http://buildbot.python.org/3.9.stable/>`_
|
||||
|
||||
- 3.8
|
||||
|
||||
+ `Stable buildbots <http://buildbot.python.org/3.8.stable/>`_
|
||||
|
||||
- 3.7
|
||||
|
||||
+ `Stable buildbots <http://buildbot.python.org/3.7.stable/>`_
|
||||
- `GitHub Actions status <https://github.com/python/cpython/actions/workflows/build.yml>`_
|
||||
|
||||
|
||||
Thank You
|
||||
|
@ -38,7 +26,7 @@ also suggestions on how you can most effectively help the project.
|
|||
|
||||
Please be aware that our workflow does deviate slightly from the typical GitHub
|
||||
project. Details on how to properly submit a pull request are covered in
|
||||
`Lifecycle of a Pull Request <https://devguide.python.org/pullrequest/>`_.
|
||||
`Lifecycle of a Pull Request <https://devguide.python.org/getting-started/pull-request-lifecycle.html>`_.
|
||||
We utilize various bots and status checks to help with this, so do follow the
|
||||
comments they leave and their "Details" links, respectively. The key points of
|
||||
our workflow that are not covered by a bot or status check are:
|
||||
|
|
32
.github/ISSUE_TEMPLATE/bug.md
vendored
32
.github/ISSUE_TEMPLATE/bug.md
vendored
|
@ -1,32 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Submit a bug report
|
||||
labels: "type-bug"
|
||||
---
|
||||
|
||||
<!--
|
||||
If you're new to Python and you're not sure whether what you're experiencing is a bug, the CPython issue tracker is not
|
||||
the right place to seek help. Consider the following options instead:
|
||||
|
||||
- reading the Python tutorial: https://docs.python.org/3/tutorial/
|
||||
- posting in the "Users" category on discuss.python.org: https://discuss.python.org/c/users/7
|
||||
- emailing the Python-list mailing list: https://mail.python.org/mailman/listinfo/python-list
|
||||
- searching our issue tracker (https://github.com/python/cpython/issues) to see if
|
||||
your problem has already been reported
|
||||
-->
|
||||
|
||||
**Bug report**
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
Include a minimal, reproducible example (https://stackoverflow.com/help/minimal-reproducible-example), if possible.
|
||||
|
||||
**Your environment**
|
||||
|
||||
<!-- Include as many relevant details as possible about the environment you experienced the bug in -->
|
||||
|
||||
- CPython versions tested on:
|
||||
- Operating system and architecture:
|
||||
|
||||
<!--
|
||||
You can freely edit this text. Remove any lines you believe are unnecessary.
|
||||
-->
|
56
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
56
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
name: Bug report
|
||||
description: Submit a bug report
|
||||
labels: ["type-bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**New to Python?**
|
||||
|
||||
For help or advice on using Python, try one of the following options instead of opening a GitHub issue:
|
||||
|
||||
- Asking on [Discourse](https://discuss.python.org/c/users/7) or [Stack Overflow](https://stackoverflow.com)
|
||||
- Reading the [Python tutorial](https://docs.python.org/3/tutorial/)
|
||||
- Emailing [python-list](https://mail.python.org/mailman/listinfo/python-list)
|
||||
|
||||
Make sure to also search the [CPython issue tracker](https://github.com/python/cpython/issues?q=is%3Aissue+sort%3Acreated-desc) to check that the bug has not already been reported.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Bug description:"
|
||||
description: >
|
||||
Give a clear and concise description of what happened.
|
||||
Include a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) if possible.
|
||||
[Copy and paste code where possible rather than using screenshots](https://meta.stackoverflow.com/a/285557/13990016),
|
||||
and put any code blocks inside triple backticks.
|
||||
|
||||
value: |
|
||||
```python
|
||||
# Add a code block here, if required
|
||||
```
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: "CPython versions tested on:"
|
||||
multiple: true
|
||||
options:
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
- "3.13"
|
||||
- "CPython main branch"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: "Operating systems tested on:"
|
||||
multiple: true
|
||||
options:
|
||||
- Linux
|
||||
- macOS
|
||||
- Windows
|
||||
- Other
|
||||
validations:
|
||||
required: false
|
33
.github/ISSUE_TEMPLATE/crash.md
vendored
33
.github/ISSUE_TEMPLATE/crash.md
vendored
|
@ -1,33 +0,0 @@
|
|||
---
|
||||
name: Crash report
|
||||
about: A hard crash of the interpreter, possibly with a core dump
|
||||
labels: "type-crash"
|
||||
---
|
||||
|
||||
<!--
|
||||
Use this template for hard crashes of the interpreter, segmentation faults, failed C-level assertions, and similar.
|
||||
Do not submit this form if you encounter an exception being unexpectedly raised from a Python function.
|
||||
Most of the time, these should be filed as bugs, rather than crashes.
|
||||
|
||||
The CPython interpreter is itself written in a different programming language, C.
|
||||
For CPython, a "crash" is when Python itself fails, leading to a traceback in the C stack.
|
||||
-->
|
||||
|
||||
**Crash report**
|
||||
|
||||
Tell us what happened, ideally including a minimal, reproducible example (https://stackoverflow.com/help/minimal-reproducible-example).
|
||||
|
||||
**Error messages**
|
||||
|
||||
Enter any relevant error message caused by the crash, including a core dump if there is one.
|
||||
|
||||
**Your environment**
|
||||
|
||||
<!-- Include as many relevant details as possible about the environment you experienced the bug in -->
|
||||
|
||||
- CPython versions tested on:
|
||||
- Operating system and architecture:
|
||||
|
||||
<!--
|
||||
You can freely edit this text. Remove any lines you believe are unnecessary.
|
||||
-->
|
54
.github/ISSUE_TEMPLATE/crash.yml
vendored
Normal file
54
.github/ISSUE_TEMPLATE/crash.yml
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
name: Crash report
|
||||
description: A hard crash of the interpreter, possibly with a core dump
|
||||
labels: ["type-crash"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
This form is for hard crashes of the Python interpreter, segmentation faults, failed C-level assertions, and similar. Unexpected exceptions raised from Python functions in the standard library count as bugs rather than crashes.
|
||||
|
||||
The CPython interpreter is written in a different programming language, C. A "CPython crash" is when Python itself fails, leading to a traceback in the C stack.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: >
|
||||
Include a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) if possible.
|
||||
[Copy and paste code where possible rather than using screenshots](https://meta.stackoverflow.com/a/285557/13990016),
|
||||
and put any code blocks inside triple backticks.
|
||||
|
||||
value: |
|
||||
```python
|
||||
# Add a code block here, if required
|
||||
```
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: "CPython versions tested on:"
|
||||
multiple: true
|
||||
options:
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
- "CPython main branch"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: "Operating systems tested on:"
|
||||
multiple: true
|
||||
options:
|
||||
- Linux
|
||||
- macOS
|
||||
- Windows
|
||||
- Other
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Output from running 'python -VV' on the command line:"
|
||||
description: If you tested with multiple operating systems or architectures, feel free to provide details in the main bug description.
|
||||
validations:
|
||||
required: false
|
2
.github/ISSUE_TEMPLATE/documentation.md
vendored
2
.github/ISSUE_TEMPLATE/documentation.md
vendored
|
@ -4,6 +4,6 @@ about: Report a problem with the documentation
|
|||
labels: "docs"
|
||||
---
|
||||
|
||||
**Documentation**
|
||||
# Documentation
|
||||
|
||||
(A clear and concise description of the issue.)
|
||||
|
|
28
.github/ISSUE_TEMPLATE/feature.md
vendored
28
.github/ISSUE_TEMPLATE/feature.md
vendored
|
@ -1,28 +0,0 @@
|
|||
---
|
||||
name: Feature or enhancement
|
||||
about: Submit a proposal for a new CPython feature or enhancement
|
||||
labels: "type-feature"
|
||||
---
|
||||
|
||||
**Feature or enhancement**
|
||||
|
||||
(A clear and concise description of your proposal.)
|
||||
|
||||
**Pitch**
|
||||
|
||||
(Explain why this feature or enhacement should be implemented and how it would be used.
|
||||
Add examples, if applicable.)
|
||||
|
||||
**Previous discussion**
|
||||
|
||||
<!--
|
||||
New features to Python should first be discussed elsewhere before creating issues on GitHub,
|
||||
for example in the "ideas" category (https://discuss.python.org/c/ideas/6) of discuss.python.org,
|
||||
or the python-ideas mailing list (https://mail.python.org/mailman3/lists/python-ideas.python.org/).
|
||||
Use this space to post links to the places where you have already discussed this feature proposal:
|
||||
-->
|
||||
|
||||
|
||||
<!--
|
||||
You can freely edit this text. Remove any lines you believe are unnecessary.
|
||||
-->
|
40
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
40
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
name: Feature or enhancement
|
||||
description: Submit a proposal for a new CPython feature or enhancement
|
||||
labels: ["type-feature"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# Proposing a feature to CPython?
|
||||
|
||||
You'll need to demonstrate widespread support for your idea among the community.
|
||||
|
||||
Major feature proposals should generally be discussed on [Discourse](https://discuss.python.org/c/ideas/6) before opening a GitHub issue. Wait until it's clear that most people support your idea before filling in this form.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Proposal:"
|
||||
description: >
|
||||
Explain your proposal, why it should be implemented, and how it would be used.
|
||||
Add examples, if applicable.
|
||||
Put any code blocks inside triple backticks.
|
||||
value: |
|
||||
```python
|
||||
# Add a code block here, if required
|
||||
```
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Has this already been discussed elsewhere?
|
||||
options:
|
||||
- No response given
|
||||
- I have already discussed this feature proposal on Discourse
|
||||
- This is a minor feature, which does not need previous discussion elsewhere
|
||||
multiple: false
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Links to previous discussion of this feature:"
|
||||
validations:
|
||||
required: false
|
2
.github/SECURITY.md
vendored
2
.github/SECURITY.md
vendored
|
@ -4,7 +4,7 @@
|
|||
|
||||
The Python team applies security fixes according to the table
|
||||
in [the devguide](
|
||||
https://devguide.python.org/#status-of-python-branches
|
||||
https://devguide.python.org/versions/#supported-versions
|
||||
).
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
|
12
.github/dependabot.yml
vendored
12
.github/dependabot.yml
vendored
|
@ -7,3 +7,15 @@ updates:
|
|||
labels:
|
||||
- "skip issue"
|
||||
- "skip news"
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types:
|
||||
- "version-update:semver-minor"
|
||||
- "version-update:semver-patch"
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/Tools/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
labels:
|
||||
- "skip issue"
|
||||
- "skip news"
|
||||
|
|
40
.github/problem-matchers/sphinx.json
vendored
40
.github/problem-matchers/sphinx.json
vendored
|
@ -1,40 +0,0 @@
|
|||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "sphinx-problem-matcher",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.*):(\\d+):\\s+(\\w*):\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"severity": 3,
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "sphinx-problem-matcher-loose",
|
||||
"pattern": [
|
||||
{
|
||||
"_comment": "A bit of a looser pattern, doesn't look for line numbers, just looks for file names relying on them to start with / and end with .rst",
|
||||
"regexp": "(\/.*\\.rst):\\s+(\\w*):\\s+(.*)$",
|
||||
"file": 1,
|
||||
"severity": 2,
|
||||
"message": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "sphinx-problem-matcher-loose-no-severity",
|
||||
"pattern": [
|
||||
{
|
||||
"_comment": "Looks for file names ending with .rst and line numbers but without severity",
|
||||
"regexp": "^(.*\\.rst):(\\d+):(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
53
.github/workflows/add-issue-header.yml
vendored
Normal file
53
.github/workflows/add-issue-header.yml
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
name: Add issue header
|
||||
# Automatically edits an issue's descriptions with a header,
|
||||
# one of:
|
||||
#
|
||||
# - Bug report
|
||||
# - Crash report
|
||||
# - Feature or enhancement
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
# Only ever run once
|
||||
- opened
|
||||
|
||||
|
||||
jobs:
|
||||
add-header:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
# language=JavaScript
|
||||
script: |
|
||||
// https://devguide.python.org/triage/labels/#type-labels
|
||||
const HEADERS = new Map([
|
||||
['type-bug', 'Bug report'],
|
||||
['type-crash', 'Crash report'],
|
||||
['type-feature', 'Feature or enhancement'],
|
||||
]);
|
||||
let issue_data = await github.rest.issues.get({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
}).then(issue => issue.data);
|
||||
let header = '';
|
||||
for (const label_data of issue_data.labels) {
|
||||
const label_name = (typeof label_data === 'string') ? label_data : label_data.name;
|
||||
if (HEADERS.has(label_name)) {
|
||||
header = HEADERS.get(label_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (header !== '') {
|
||||
console.log(`Setting new header: ${header}`);
|
||||
await github.rest.issues.update({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: `# ${header}\n\n${issue_data.body.replaceAll('\r', '')}`
|
||||
});
|
||||
}
|
572
.github/workflows/build.yml
vendored
572
.github/workflows/build.yml
vendored
|
@ -8,33 +8,37 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- '3.10'
|
||||
- '3.9'
|
||||
- '3.8'
|
||||
- '3.7'
|
||||
- '3.*'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
- '3.10'
|
||||
- '3.9'
|
||||
- '3.8'
|
||||
- '3.7'
|
||||
- '3.*'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}-reusable
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
check_source:
|
||||
name: 'Check for source changes'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
run-docs: ${{ steps.docs-changes.outputs.run-docs || false }}
|
||||
run_tests: ${{ steps.check.outputs.run_tests }}
|
||||
run_ssl_tests: ${{ steps.check.outputs.run_ssl_tests }}
|
||||
run_hypothesis: ${{ steps.check.outputs.run_hypothesis }}
|
||||
run_cifuzz: ${{ steps.check.outputs.run_cifuzz }}
|
||||
config_hash: ${{ steps.config_hash.outputs.hash }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check for source changes
|
||||
id: check
|
||||
run: |
|
||||
if [ -z "$GITHUB_BASE_REF" ]; then
|
||||
echo '::set-output name=run_tests::true'
|
||||
echo '::set-output name=run_ssl_tests::true'
|
||||
echo "run_tests=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
git fetch origin $GITHUB_BASE_REF --depth=1
|
||||
# git diff "origin/$GITHUB_BASE_REF..." (3 dots) may be more
|
||||
|
@ -50,43 +54,108 @@ jobs:
|
|||
# into the PR branch anyway.
|
||||
#
|
||||
# https://github.com/python/core-workflow/issues/373
|
||||
git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qvE '(\.rst$|^Doc|^Misc)' && echo '::set-output name=run_tests::true' || true
|
||||
git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qE '(ssl|hashlib|hmac|^.github)' && echo '::set-output name=run_ssl_tests::true' || true
|
||||
git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qvE '(\.rst$|^Doc|^Misc|^\.pre-commit-config\.yaml$|\.ruff\.toml$)' && echo "run_tests=true" >> $GITHUB_OUTPUT || true
|
||||
fi
|
||||
|
||||
# Check if we should run hypothesis tests
|
||||
GIT_BRANCH=${GITHUB_BASE_REF:-${GITHUB_REF#refs/heads/}}
|
||||
echo $GIT_BRANCH
|
||||
if $(echo "$GIT_BRANCH" | grep -q -w '3\.\(8\|9\|10\|11\)'); then
|
||||
echo "Branch too old for hypothesis tests"
|
||||
echo "run_hypothesis=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Run hypothesis tests"
|
||||
echo "run_hypothesis=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# oss-fuzz maintains a configuration for fuzzing the main branch of
|
||||
# CPython, so CIFuzz should be run only for code that is likely to be
|
||||
# merged into the main branch; compatibility with older branches may
|
||||
# be broken.
|
||||
FUZZ_RELEVANT_FILES='(\.c$|\.h$|\.cpp$|^configure$|^\.github/workflows/build\.yml$|^Modules/_xxtestfuzz)'
|
||||
if [ "$GITHUB_BASE_REF" = "main" ] && [ "$(git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qE $FUZZ_RELEVANT_FILES; echo $?)" -eq 0 ]; then
|
||||
# The tests are pretty slow so they are executed only for PRs
|
||||
# changing relevant files.
|
||||
echo "Run CIFuzz tests"
|
||||
echo "run_cifuzz=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Branch too old for CIFuzz tests; or no C files were changed"
|
||||
echo "run_cifuzz=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Compute hash for config cache key
|
||||
id: config_hash
|
||||
run: |
|
||||
echo "hash=${{ hashFiles('configure', 'configure.ac', '.github/workflows/build.yml') }}" >> $GITHUB_OUTPUT
|
||||
- name: Get a list of the changed documentation-related files
|
||||
if: github.event_name == 'pull_request'
|
||||
id: changed-docs-files
|
||||
uses: Ana06/get-changed-files@v2.3.0
|
||||
with:
|
||||
filter: |
|
||||
Doc/**
|
||||
Misc/**
|
||||
.github/workflows/reusable-docs.yml
|
||||
format: csv # works for paths with spaces
|
||||
- name: Check for docs changes
|
||||
if: >-
|
||||
github.event_name == 'pull_request'
|
||||
&& steps.changed-docs-files.outputs.added_modified_renamed != ''
|
||||
id: docs-changes
|
||||
run: |
|
||||
echo "run-docs=true" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
check-docs:
|
||||
name: Docs
|
||||
needs: check_source
|
||||
if: fromJSON(needs.check_source.outputs.run-docs)
|
||||
uses: ./.github/workflows/reusable-docs.yml
|
||||
|
||||
check_generated_files:
|
||||
name: 'Check if generated files are up to date'
|
||||
runs-on: ubuntu-latest
|
||||
# Don't use ubuntu-latest but a specific version to make the job
|
||||
# reproducible: to get the same tools versions (autoconf, aclocal, ...)
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Runner image version
|
||||
run: echo "IMAGE_VERSION=${ImageVersion}" >> $GITHUB_ENV
|
||||
- name: Restore config.cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: config.cache
|
||||
# Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ needs.check_source.outputs.config_hash }}-${{ env.pythonLocation }}
|
||||
- name: Install Dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: Add ccache to PATH
|
||||
run: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
- name: Check Autoconf version 2.69 and aclocal 1.16.3
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: false
|
||||
- name: Check Autoconf and aclocal versions
|
||||
run: |
|
||||
grep "Generated by GNU Autoconf 2.69" configure
|
||||
grep "aclocal 1.16.3" aclocal.m4
|
||||
grep "Generated by GNU Autoconf 2.71" configure
|
||||
grep "aclocal 1.16.5" aclocal.m4
|
||||
grep -q "runstatedir" configure
|
||||
grep -q "PKG_PROG_PKG_CONFIG" aclocal.m4
|
||||
- name: Configure CPython
|
||||
run: |
|
||||
# Build Python with the libpython dynamic library
|
||||
./configure --with-pydebug --enable-shared
|
||||
- name: Regenerate autoconf files with container image
|
||||
run: make regen-configure
|
||||
./configure --config-cache --with-pydebug --enable-shared
|
||||
- name: Regenerate autoconf files
|
||||
# Same command used by Tools/build/regen-configure.sh ($AUTORECONF)
|
||||
run: autoreconf -ivf -Werror
|
||||
- name: Build CPython
|
||||
run: |
|
||||
# Deepfreeze will usually cause global objects to be added or removed,
|
||||
# so we run it before regen-global-objects gets rum (in regen-all).
|
||||
make regen-deepfreeze
|
||||
make -j4 regen-all
|
||||
make regen-stdlib-module-names
|
||||
make regen-stdlib-module-names regen-sbom
|
||||
- name: Check for changes
|
||||
run: |
|
||||
git add -u
|
||||
|
@ -105,75 +174,96 @@ jobs:
|
|||
run: make smelly
|
||||
- name: Check limited ABI symbols
|
||||
run: make check-limited-abi
|
||||
- name: Check for unsupported C global variables
|
||||
if: github.event_name == 'pull_request' # $GITHUB_EVENT_NAME
|
||||
run: make check-c-globals
|
||||
|
||||
build_win32:
|
||||
name: 'Windows (x86)'
|
||||
runs-on: windows-latest
|
||||
build_windows:
|
||||
name: 'Windows'
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
env:
|
||||
IncludeUwp: 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build CPython
|
||||
run: .\PCbuild\build.bat -e -d -p Win32
|
||||
timeout-minutes: 30
|
||||
- name: Display build info
|
||||
run: .\python.bat -m test.pythoninfo
|
||||
- name: Tests
|
||||
run: .\PCbuild\rt.bat -p Win32 -d -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0
|
||||
uses: ./.github/workflows/reusable-windows.yml
|
||||
|
||||
build_win_amd64:
|
||||
name: 'Windows (x64)'
|
||||
runs-on: windows-latest
|
||||
build_windows_free_threading:
|
||||
name: 'Windows (free-threading)'
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
env:
|
||||
IncludeUwp: 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Register MSVC problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/msvc.json"
|
||||
- name: Build CPython
|
||||
run: .\PCbuild\build.bat -e -d -p x64
|
||||
timeout-minutes: 30
|
||||
- name: Display build info
|
||||
run: .\python.bat -m test.pythoninfo
|
||||
- name: Tests
|
||||
run: .\PCbuild\rt.bat -p x64 -d -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0
|
||||
uses: ./.github/workflows/reusable-windows.yml
|
||||
with:
|
||||
free-threading: true
|
||||
|
||||
build_macos:
|
||||
name: 'macOS'
|
||||
runs-on: macos-latest
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
env:
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Prepare homebrew environment variables
|
||||
run: |
|
||||
echo "LDFLAGS=-L$(brew --prefix tcl-tk)/lib" >> $GITHUB_ENV
|
||||
echo "PKG_CONFIG_PATH=$(brew --prefix openssl@1.1)/lib/pkgconfig:$(brew --prefix tcl-tk)/lib/pkgconfig" >> $GITHUB_ENV
|
||||
- name: Configure CPython
|
||||
run: ./configure --with-pydebug --prefix=/opt/python-dev
|
||||
- name: Build CPython
|
||||
run: make -j4
|
||||
- name: Display build info
|
||||
run: make pythoninfo
|
||||
- name: Tests
|
||||
run: make buildbottest TESTOPTS="-j4 -uall,-cpu"
|
||||
uses: ./.github/workflows/reusable-macos.yml
|
||||
with:
|
||||
config_hash: ${{ needs.check_source.outputs.config_hash }}
|
||||
# macos-14 is M1, macos-13 is Intel
|
||||
os-matrix: '["macos-14", "macos-13"]'
|
||||
|
||||
build_macos_free_threading:
|
||||
name: 'macOS (free-threading)'
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
uses: ./.github/workflows/reusable-macos.yml
|
||||
with:
|
||||
config_hash: ${{ needs.check_source.outputs.config_hash }}
|
||||
free-threading: true
|
||||
# macos-14-large is Intel with 12 cores (most parallelism)
|
||||
os-matrix: '["macos-14"]'
|
||||
|
||||
build_ubuntu:
|
||||
name: 'Ubuntu'
|
||||
runs-on: ubuntu-20.04
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
uses: ./.github/workflows/reusable-ubuntu.yml
|
||||
with:
|
||||
config_hash: ${{ needs.check_source.outputs.config_hash }}
|
||||
options: |
|
||||
../cpython-ro-srcdir/configure \
|
||||
--config-cache \
|
||||
--with-pydebug \
|
||||
--with-openssl=$OPENSSL_DIR
|
||||
|
||||
build_ubuntu_free_threading:
|
||||
name: 'Ubuntu (free-threading)'
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
uses: ./.github/workflows/reusable-ubuntu.yml
|
||||
with:
|
||||
config_hash: ${{ needs.check_source.outputs.config_hash }}
|
||||
options: |
|
||||
../cpython-ro-srcdir/configure \
|
||||
--config-cache \
|
||||
--with-pydebug \
|
||||
--with-openssl=$OPENSSL_DIR \
|
||||
--disable-gil
|
||||
|
||||
build_ubuntu_ssltests:
|
||||
name: 'Ubuntu SSL tests with OpenSSL'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
openssl_ver: [1.1.1w, 3.0.13, 3.1.5, 3.2.1]
|
||||
env:
|
||||
OPENSSL_VER: 1.1.1n
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
OPENSSL_VER: ${{ matrix.openssl_ver }}
|
||||
MULTISSL_DIR: ${{ github.workspace }}/multissl
|
||||
OPENSSL_DIR: ${{ github.workspace }}/multissl/openssl/${{ matrix.openssl_ver }}
|
||||
LD_LIBRARY_PATH: ${{ github.workspace }}/multissl/openssl/${{ matrix.openssl_ver }}/lib
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Runner image version
|
||||
run: echo "IMAGE_VERSION=${ImageVersion}" >> $GITHUB_ENV
|
||||
- name: Restore config.cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: config.cache
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ needs.check_source.outputs.config_hash }}
|
||||
- name: Register gcc problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
|
||||
- name: Install Dependencies
|
||||
|
@ -185,7 +275,7 @@ jobs:
|
|||
echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV
|
||||
- name: 'Restore OpenSSL build'
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v2.1.7
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
|
||||
|
@ -196,7 +286,62 @@ jobs:
|
|||
run: |
|
||||
echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: false
|
||||
- name: Configure CPython
|
||||
run: ./configure --config-cache --with-pydebug --with-openssl=$OPENSSL_DIR
|
||||
- name: Build CPython
|
||||
run: make -j4
|
||||
- name: Display build info
|
||||
run: make pythoninfo
|
||||
- name: SSL tests
|
||||
run: ./python Lib/test/ssltests.py
|
||||
|
||||
build_wasi:
|
||||
name: 'WASI'
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
uses: ./.github/workflows/reusable-wasi.yml
|
||||
with:
|
||||
config_hash: ${{ needs.check_source.outputs.config_hash }}
|
||||
|
||||
test_hypothesis:
|
||||
name: "Hypothesis tests on Ubuntu"
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true' && needs.check_source.outputs.run_hypothesis == 'true'
|
||||
env:
|
||||
OPENSSL_VER: 3.0.13
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Register gcc problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
|
||||
- name: Install Dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: Configure OpenSSL env vars
|
||||
run: |
|
||||
echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> $GITHUB_ENV
|
||||
echo "OPENSSL_DIR=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}" >> $GITHUB_ENV
|
||||
echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV
|
||||
- name: 'Restore OpenSSL build'
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
|
||||
- name: Install OpenSSL
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
run: python3 Tools/ssl/multissltests.py --steps=library --base-directory $MULTISSL_DIR --openssl $OPENSSL_VER --system Linux
|
||||
- name: Add ccache to PATH
|
||||
run: |
|
||||
echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: false
|
||||
- name: Setup directory envs for out-of-tree builds
|
||||
run: |
|
||||
echo "CPYTHON_RO_SRCDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-ro-srcdir)" >> $GITHUB_ENV
|
||||
|
@ -205,9 +350,20 @@ jobs:
|
|||
run: mkdir -p $CPYTHON_RO_SRCDIR $CPYTHON_BUILDDIR
|
||||
- name: Bind mount sources read-only
|
||||
run: sudo mount --bind -o ro $GITHUB_WORKSPACE $CPYTHON_RO_SRCDIR
|
||||
- name: Runner image version
|
||||
run: echo "IMAGE_VERSION=${ImageVersion}" >> $GITHUB_ENV
|
||||
- name: Restore config.cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.CPYTHON_BUILDDIR }}/config.cache
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ needs.check_source.outputs.config_hash }}
|
||||
- name: Configure CPython out-of-tree
|
||||
working-directory: ${{ env.CPYTHON_BUILDDIR }}
|
||||
run: ../cpython-ro-srcdir/configure --with-pydebug --with-openssl=$OPENSSL_DIR
|
||||
run: |
|
||||
../cpython-ro-srcdir/configure \
|
||||
--config-cache \
|
||||
--with-pydebug \
|
||||
--with-openssl=$OPENSSL_DIR
|
||||
- name: Build CPython out-of-tree
|
||||
working-directory: ${{ env.CPYTHON_BUILDDIR }}
|
||||
run: make -j4
|
||||
|
@ -217,74 +373,79 @@ jobs:
|
|||
- name: Remount sources writable for tests
|
||||
# some tests write to srcdir, lack of pyc files slows down testing
|
||||
run: sudo mount $CPYTHON_RO_SRCDIR -oremount,rw
|
||||
- name: Tests
|
||||
- name: Setup directory envs for out-of-tree builds
|
||||
run: |
|
||||
echo "CPYTHON_BUILDDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-builddir)" >> $GITHUB_ENV
|
||||
- name: "Create hypothesis venv"
|
||||
working-directory: ${{ env.CPYTHON_BUILDDIR }}
|
||||
run: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu"
|
||||
|
||||
build_ubuntu_ssltests:
|
||||
name: 'Ubuntu SSL tests with OpenSSL'
|
||||
runs-on: ubuntu-20.04
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true' && needs.check_source.outputs.run_ssl_tests == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
openssl_ver: [1.1.1n, 3.0.2]
|
||||
env:
|
||||
OPENSSL_VER: ${{ matrix.openssl_ver }}
|
||||
MULTISSL_DIR: ${{ github.workspace }}/multissl
|
||||
OPENSSL_DIR: ${{ github.workspace }}/multissl/openssl/${{ matrix.openssl_ver }}
|
||||
LD_LIBRARY_PATH: ${{ github.workspace }}/multissl/openssl/${{ matrix.openssl_ver }}/lib
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Register gcc problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
|
||||
- name: Install Dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: Configure OpenSSL env vars
|
||||
run: |
|
||||
echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> $GITHUB_ENV
|
||||
echo "OPENSSL_DIR=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}" >> $GITHUB_ENV
|
||||
echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV
|
||||
- name: 'Restore OpenSSL build'
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v2.1.7
|
||||
VENV_LOC=$(realpath -m .)/hypovenv
|
||||
VENV_PYTHON=$VENV_LOC/bin/python
|
||||
echo "HYPOVENV=${VENV_LOC}" >> $GITHUB_ENV
|
||||
echo "VENV_PYTHON=${VENV_PYTHON}" >> $GITHUB_ENV
|
||||
./python -m venv $VENV_LOC && $VENV_PYTHON -m pip install -r ${GITHUB_WORKSPACE}/Tools/requirements-hypothesis.txt
|
||||
- name: 'Restore Hypothesis database'
|
||||
id: cache-hypothesis-database
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
|
||||
- name: Install OpenSSL
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
run: python3 Tools/ssl/multissltests.py --steps=library --base-directory $MULTISSL_DIR --openssl $OPENSSL_VER --system Linux
|
||||
- name: Add ccache to PATH
|
||||
path: ./hypothesis
|
||||
key: hypothesis-database-${{ github.head_ref || github.run_id }}
|
||||
restore-keys: |
|
||||
- hypothesis-database-
|
||||
- name: "Run tests"
|
||||
working-directory: ${{ env.CPYTHON_BUILDDIR }}
|
||||
run: |
|
||||
echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
- name: Configure CPython
|
||||
run: ./configure --with-pydebug --with-openssl=$OPENSSL_DIR
|
||||
- name: Build CPython
|
||||
run: make -j4
|
||||
- name: Display build info
|
||||
run: make pythoninfo
|
||||
- name: SSL tests
|
||||
run: ./python Lib/test/ssltests.py
|
||||
# Most of the excluded tests are slow test suites with no property tests
|
||||
#
|
||||
# (GH-104097) test_sysconfig is skipped because it has tests that are
|
||||
# failing when executed from inside a virtual environment.
|
||||
${{ env.VENV_PYTHON }} -m test \
|
||||
-W \
|
||||
-o \
|
||||
-j4 \
|
||||
-x test_asyncio \
|
||||
-x test_multiprocessing_fork \
|
||||
-x test_multiprocessing_forkserver \
|
||||
-x test_multiprocessing_spawn \
|
||||
-x test_concurrent_futures \
|
||||
-x test_socket \
|
||||
-x test_subprocess \
|
||||
-x test_signal \
|
||||
-x test_sysconfig
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: hypothesis-example-db
|
||||
path: .hypothesis/examples/
|
||||
|
||||
|
||||
build_asan:
|
||||
name: 'Address sanitizer'
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
env:
|
||||
OPENSSL_VER: 1.1.1n
|
||||
OPENSSL_VER: 3.0.13
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Runner image version
|
||||
run: echo "IMAGE_VERSION=${ImageVersion}" >> $GITHUB_ENV
|
||||
- name: Restore config.cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: config.cache
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ needs.check_source.outputs.config_hash }}
|
||||
- name: Register gcc problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
|
||||
- name: Install Dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: Set up GCC-10 for ASAN
|
||||
uses: egor-tensin/setup-gcc@v1
|
||||
with:
|
||||
version: 10
|
||||
- name: Configure OpenSSL env vars
|
||||
run: |
|
||||
echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> $GITHUB_ENV
|
||||
|
@ -292,7 +453,7 @@ jobs:
|
|||
echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV
|
||||
- name: 'Restore OpenSSL build'
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v2.1.7
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
|
||||
|
@ -303,12 +464,151 @@ jobs:
|
|||
run: |
|
||||
echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: ${{ github.event_name == 'push' }}
|
||||
max-size: "200M"
|
||||
- name: Configure CPython
|
||||
run: ./configure --with-address-sanitizer --without-pymalloc
|
||||
run: ./configure --config-cache --with-address-sanitizer --without-pymalloc
|
||||
- name: Build CPython
|
||||
run: make -j4
|
||||
- name: Display build info
|
||||
run: make pythoninfo
|
||||
- name: Tests
|
||||
run: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu"
|
||||
run: xvfb-run make test
|
||||
|
||||
build_tsan:
|
||||
name: 'Thread sanitizer'
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
uses: ./.github/workflows/reusable-tsan.yml
|
||||
with:
|
||||
config_hash: ${{ needs.check_source.outputs.config_hash }}
|
||||
options: ./configure --config-cache --with-thread-sanitizer --with-pydebug
|
||||
suppressions_path: Tools/tsan/supressions.txt
|
||||
tsan_logs_artifact_name: tsan-logs-default
|
||||
|
||||
build_tsan_free_threading:
|
||||
name: 'Thread sanitizer (free-threading)'
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
uses: ./.github/workflows/reusable-tsan.yml
|
||||
with:
|
||||
config_hash: ${{ needs.check_source.outputs.config_hash }}
|
||||
options: ./configure --config-cache --disable-gil --with-thread-sanitizer --with-pydebug
|
||||
suppressions_path: Tools/tsan/suppressions_free_threading.txt
|
||||
tsan_logs_artifact_name: tsan-logs-free-threading
|
||||
|
||||
# CIFuzz job based on https://google.github.io/oss-fuzz/getting-started/continuous-integration/
|
||||
cifuzz:
|
||||
name: CIFuzz
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_cifuzz == 'true'
|
||||
permissions:
|
||||
security-events: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
sanitizer: [address, undefined, memory]
|
||||
steps:
|
||||
- name: Build fuzzers (${{ matrix.sanitizer }})
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: cpython3
|
||||
sanitizer: ${{ matrix.sanitizer }}
|
||||
- name: Run fuzzers (${{ matrix.sanitizer }})
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
fuzz-seconds: 600
|
||||
oss-fuzz-project-name: cpython3
|
||||
output-sarif: true
|
||||
sanitizer: ${{ matrix.sanitizer }}
|
||||
- name: Upload crash
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: ${{ matrix.sanitizer }}-artifacts
|
||||
path: ./out/artifacts
|
||||
- name: Upload SARIF
|
||||
if: always() && steps.build.outcome == 'success'
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: cifuzz-sarif/results.sarif
|
||||
checkout_path: cifuzz-sarif
|
||||
|
||||
all-required-green: # This job does nothing and is only used for the branch protection
|
||||
name: All required checks pass
|
||||
if: always()
|
||||
|
||||
needs:
|
||||
- check_source # Transitive dependency, needed to access `run_tests` value
|
||||
- check-docs
|
||||
- check_generated_files
|
||||
- build_macos
|
||||
- build_macos_free_threading
|
||||
- build_ubuntu
|
||||
- build_ubuntu_free_threading
|
||||
- build_ubuntu_ssltests
|
||||
- build_wasi
|
||||
- build_windows
|
||||
- build_windows_free_threading
|
||||
- test_hypothesis
|
||||
- build_asan
|
||||
- build_tsan
|
||||
- build_tsan_free_threading
|
||||
- cifuzz
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check whether the needed jobs succeeded or failed
|
||||
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe
|
||||
with:
|
||||
allowed-failures: >-
|
||||
build_ubuntu_ssltests,
|
||||
cifuzz,
|
||||
test_hypothesis,
|
||||
allowed-skips: >-
|
||||
${{
|
||||
!fromJSON(needs.check_source.outputs.run-docs)
|
||||
&& '
|
||||
check-docs,
|
||||
'
|
||||
|| ''
|
||||
}}
|
||||
${{
|
||||
needs.check_source.outputs.run_tests != 'true'
|
||||
&& '
|
||||
check_generated_files,
|
||||
build_macos,
|
||||
build_macos_free_threading,
|
||||
build_ubuntu,
|
||||
build_ubuntu_free_threading,
|
||||
build_ubuntu_ssltests,
|
||||
build_wasi,
|
||||
build_windows,
|
||||
build_windows_free_threading,
|
||||
build_asan,
|
||||
build_tsan,
|
||||
build_tsan_free_threading,
|
||||
'
|
||||
|| ''
|
||||
}}
|
||||
${{
|
||||
!fromJSON(needs.check_source.outputs.run_cifuzz)
|
||||
&& '
|
||||
cifuzz,
|
||||
'
|
||||
|| ''
|
||||
}}
|
||||
${{
|
||||
!fromJSON(needs.check_source.outputs.run_hypothesis)
|
||||
&& '
|
||||
test_hypothesis,
|
||||
'
|
||||
|| ''
|
||||
}}
|
||||
jobs: ${{ toJSON(needs) }}
|
||||
|
|
49
.github/workflows/build_msi.yml
vendored
49
.github/workflows/build_msi.yml
vendored
|
@ -5,43 +5,36 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- '3.10'
|
||||
- '3.9'
|
||||
- '3.8'
|
||||
- '3.7'
|
||||
- '3.*'
|
||||
paths:
|
||||
- 'Tools/msi/**'
|
||||
- '.github/workflows/build_msi.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
- '3.10'
|
||||
- '3.9'
|
||||
- '3.8'
|
||||
- '3.7'
|
||||
- '3.*'
|
||||
paths:
|
||||
- 'Tools/msi/**'
|
||||
- '.github/workflows/build_msi.yml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build_win32:
|
||||
name: 'Windows (x86) Installer'
|
||||
build:
|
||||
name: Windows Installer
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
type: [x86, x64, arm64]
|
||||
env:
|
||||
IncludeFreethreaded: true
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build CPython installer
|
||||
run: .\Tools\msi\build.bat -x86
|
||||
|
||||
build_win_amd64:
|
||||
name: 'Windows (x64) Installer'
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build CPython installer
|
||||
run: .\Tools\msi\build.bat -x64
|
||||
|
||||
build_win_arm64:
|
||||
name: 'Windows (ARM64) Installer'
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build CPython installer
|
||||
run: .\Tools\msi\build.bat -arm64
|
||||
run: .\Tools\msi\build.bat --doc -${{ matrix.type }}
|
||||
|
|
54
.github/workflows/doc.yml
vendored
54
.github/workflows/doc.yml
vendored
|
@ -1,54 +0,0 @@
|
|||
name: Docs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
#push:
|
||||
# branches:
|
||||
# - 'main'
|
||||
# - '3.10'
|
||||
# - '3.9'
|
||||
# - '3.8'
|
||||
# - '3.7'
|
||||
# paths:
|
||||
# - 'Doc/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
- '3.10'
|
||||
- '3.9'
|
||||
- '3.8'
|
||||
- '3.7'
|
||||
paths:
|
||||
- 'Doc/**'
|
||||
- 'Misc/**'
|
||||
|
||||
jobs:
|
||||
build_doc:
|
||||
name: 'Docs'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Register Sphinx problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/sphinx.json"
|
||||
- name: 'Install Dependencies'
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh && sudo apt-get install wamerican
|
||||
- name: 'Configure CPython'
|
||||
run: ./configure --with-pydebug
|
||||
- name: 'Build CPython'
|
||||
run: make -j4
|
||||
- name: 'Install build dependencies'
|
||||
run: make -C Doc/ PYTHON=../python venv
|
||||
# Run "check doctest html" as 3 steps to get a more readable output
|
||||
# in the web UI
|
||||
- name: 'Check documentation'
|
||||
run: make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W --keep-going -j4" check
|
||||
# Use "xvfb-run" since some doctest tests open GUI windows
|
||||
- name: 'Run documentation doctest'
|
||||
run: xvfb-run make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W --keep-going -j4" doctest
|
||||
- name: 'Build HTML documentation'
|
||||
run: make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W --keep-going -j4" html
|
||||
- name: 'Upload'
|
||||
uses: actions/upload-artifact@v2.3.1
|
||||
with:
|
||||
name: doc-html
|
||||
path: Doc/build/html
|
27
.github/workflows/documentation-links.yml
vendored
Normal file
27
.github/workflows/documentation-links.yml
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
name: Read the Docs PR preview
|
||||
# Automatically edits a pull request's descriptions with a link
|
||||
# to the documentation's preview on Read the Docs.
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
paths:
|
||||
- 'Doc/**'
|
||||
- '.github/workflows/doc.yml'
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
documentation-links:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: readthedocs/actions/preview@v1
|
||||
with:
|
||||
project-slug: "cpython-previews"
|
||||
single-version: "true"
|
152
.github/workflows/jit.yml
vendored
Normal file
152
.github/workflows/jit.yml
vendored
Normal file
|
@ -0,0 +1,152 @@
|
|||
name: JIT
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**jit**'
|
||||
- 'Python/bytecodes.c'
|
||||
- 'Python/optimizer*.c'
|
||||
- '!Python/perf_jit_trampoline.c'
|
||||
- '!**/*.md'
|
||||
- '!**/*.ini'
|
||||
push:
|
||||
paths:
|
||||
- '**jit**'
|
||||
- 'Python/bytecodes.c'
|
||||
- 'Python/optimizer*.c'
|
||||
- '!Python/perf_jit_trampoline.c'
|
||||
- '!**/*.md'
|
||||
- '!**/*.ini'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
jit:
|
||||
name: ${{ matrix.target }} (${{ matrix.debug && 'Debug' || 'Release' }})
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
- i686-pc-windows-msvc/msvc
|
||||
- x86_64-pc-windows-msvc/msvc
|
||||
- aarch64-pc-windows-msvc/msvc
|
||||
- x86_64-apple-darwin/clang
|
||||
- aarch64-apple-darwin/clang
|
||||
- x86_64-unknown-linux-gnu/gcc
|
||||
- x86_64-unknown-linux-gnu/clang
|
||||
- aarch64-unknown-linux-gnu/gcc
|
||||
- aarch64-unknown-linux-gnu/clang
|
||||
debug:
|
||||
- true
|
||||
- false
|
||||
llvm:
|
||||
- 18
|
||||
include:
|
||||
- target: i686-pc-windows-msvc/msvc
|
||||
architecture: Win32
|
||||
runner: windows-latest
|
||||
compiler: msvc
|
||||
- target: x86_64-pc-windows-msvc/msvc
|
||||
architecture: x64
|
||||
runner: windows-latest
|
||||
compiler: msvc
|
||||
- target: aarch64-pc-windows-msvc/msvc
|
||||
architecture: ARM64
|
||||
runner: windows-latest
|
||||
compiler: msvc
|
||||
- target: x86_64-apple-darwin/clang
|
||||
architecture: x86_64
|
||||
runner: macos-13
|
||||
compiler: clang
|
||||
- target: aarch64-apple-darwin/clang
|
||||
architecture: aarch64
|
||||
runner: macos-14
|
||||
compiler: clang
|
||||
- target: x86_64-unknown-linux-gnu/gcc
|
||||
architecture: x86_64
|
||||
runner: ubuntu-latest
|
||||
compiler: gcc
|
||||
- target: x86_64-unknown-linux-gnu/clang
|
||||
architecture: x86_64
|
||||
runner: ubuntu-latest
|
||||
compiler: clang
|
||||
- target: aarch64-unknown-linux-gnu/gcc
|
||||
architecture: aarch64
|
||||
runner: ubuntu-latest
|
||||
compiler: gcc
|
||||
- target: aarch64-unknown-linux-gnu/clang
|
||||
architecture: aarch64
|
||||
runner: ubuntu-latest
|
||||
compiler: clang
|
||||
env:
|
||||
CC: ${{ matrix.compiler }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Native Windows
|
||||
if: runner.os == 'Windows' && matrix.architecture != 'ARM64'
|
||||
run: |
|
||||
choco upgrade llvm -y
|
||||
choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}
|
||||
./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '--pgo' }} -p ${{ matrix.architecture }}
|
||||
./PCbuild/rt.bat ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
||||
# No PGO or tests (yet):
|
||||
- name: Emulated Windows
|
||||
if: runner.os == 'Windows' && matrix.architecture == 'ARM64'
|
||||
run: |
|
||||
choco upgrade llvm -y
|
||||
choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}
|
||||
./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }}
|
||||
|
||||
- name: Native macOS
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew update
|
||||
brew install llvm@${{ matrix.llvm }}
|
||||
SDKROOT="$(xcrun --show-sdk-path)" \
|
||||
./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations --with-lto' }}
|
||||
make all --jobs 4
|
||||
./python.exe -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
||||
# --with-lto has been removed temporarily as a result of an open issue in LLVM 18 (see https://github.com/llvm/llvm-project/issues/87553)
|
||||
- name: Native Linux
|
||||
if: runner.os == 'Linux' && matrix.architecture == 'x86_64'
|
||||
run: |
|
||||
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
|
||||
export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
|
||||
./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations' }}
|
||||
make all --jobs 4
|
||||
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
||||
# --with-lto has been removed temporarily as a result of an open issue in LLVM 18 (see https://github.com/llvm/llvm-project/issues/87553)
|
||||
- name: Emulated Linux
|
||||
if: runner.os == 'Linux' && matrix.architecture != 'x86_64'
|
||||
# The --ignorefile on ./python -m test is used to exclude tests known to fail when running on an emulated Linux.
|
||||
run: |
|
||||
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
|
||||
export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
|
||||
./configure --prefix="$(pwd)/../build"
|
||||
make install --jobs 4
|
||||
make clean --jobs 4
|
||||
export HOST=${{ matrix.architecture }}-linux-gnu
|
||||
sudo apt install --yes "gcc-$HOST" qemu-user
|
||||
${{ !matrix.debug && matrix.compiler == 'clang' && './configure --enable-optimizations' || '' }}
|
||||
${{ !matrix.debug && matrix.compiler == 'clang' && 'make profile-run-stamp --jobs 4' || '' }}
|
||||
export QEMU_LD_PREFIX="/usr/$HOST"
|
||||
CC="${{ matrix.compiler == 'clang' && 'clang --target=$HOST' || '$HOST-gcc' }}" \
|
||||
CPP="$CC --preprocess" \
|
||||
HOSTRUNNER=qemu-${{ matrix.architecture }} \
|
||||
./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations ' }} --build=x86_64-linux-gnu --host="$HOST" --with-build-python=../build/bin/python3 --with-pkg-config=no ac_cv_buggy_getaddrinfo=no ac_cv_file__dev_ptc=no ac_cv_file__dev_ptmx=yes
|
||||
make all --jobs 4
|
||||
./python -m test --ignorefile=Tools/jit/ignore-tests-emulated-linux.txt --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
26
.github/workflows/lint.yml
vendored
Normal file
26
.github/workflows/lint.yml
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
name: Lint
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
RUFF_OUTPUT_FORMAT: github
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- uses: pre-commit/action@v3.0.1
|
60
.github/workflows/mypy.yml
vendored
Normal file
60
.github/workflows/mypy.yml
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
# Workflow to run mypy on select parts of the CPython repo
|
||||
name: mypy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/mypy.yml"
|
||||
- "Lib/_pyrepl/**"
|
||||
- "Lib/test/libregrtest/**"
|
||||
- "Tools/build/generate_sbom.py"
|
||||
- "Tools/cases_generator/**"
|
||||
- "Tools/clinic/**"
|
||||
- "Tools/jit/**"
|
||||
- "Tools/peg_generator/**"
|
||||
- "Tools/requirements-dev.txt"
|
||||
- "Tools/wasm/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
PIP_DISABLE_PIP_VERSION_CHECK: 1
|
||||
FORCE_COLOR: 1
|
||||
TERM: xterm-256color # needed for FORCE_COLOR to work on mypy on Ubuntu, see https://github.com/python/mypy/issues/13817
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
mypy:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: [
|
||||
"Lib/_pyrepl",
|
||||
"Lib/test/libregrtest",
|
||||
"Tools/build",
|
||||
"Tools/cases_generator",
|
||||
"Tools/clinic",
|
||||
"Tools/jit",
|
||||
"Tools/peg_generator",
|
||||
"Tools/wasm",
|
||||
]
|
||||
name: Run mypy on ${{ matrix.target }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
cache: pip
|
||||
cache-dependency-path: Tools/requirements-dev.txt
|
||||
- run: pip install -r Tools/requirements-dev.txt
|
||||
- run: mypy --config-file ${{ matrix.target }}/mypy.ini
|
23
.github/workflows/new-bugs-announce-notifier.yml
vendored
23
.github/workflows/new-bugs-announce-notifier.yml
vendored
|
@ -5,24 +5,28 @@ on:
|
|||
types:
|
||||
- opened
|
||||
|
||||
permissions:
|
||||
issues: read
|
||||
|
||||
jobs:
|
||||
notify-new-bugs-announce:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 14
|
||||
node-version: 20
|
||||
- run: npm install mailgun.js form-data
|
||||
- name: Send notification
|
||||
uses: actions/github-script@v5
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
MAILGUN_API_KEY: ${{ secrets.PSF_MAILGUN_KEY }}
|
||||
MAILGUN_API_KEY: ${{ secrets.MAILGUN_PYTHON_ORG_MAILGUN_KEY }}
|
||||
with:
|
||||
script: |
|
||||
const Mailgun = require("mailgun.js");
|
||||
const formData = require('form-data');
|
||||
const mailgun = new Mailgun(formData);
|
||||
const DOMAIN = "mg.python.org";
|
||||
const DOMAIN = "mailgun.python.org";
|
||||
const mg = mailgun.client({username: 'api', key: process.env.MAILGUN_API_KEY});
|
||||
github.rest.issues.get({
|
||||
issue_number: context.issue.number,
|
||||
|
@ -37,11 +41,14 @@ jobs:
|
|||
url : issue.data.html_url,
|
||||
labels : issue.data.labels.map(label => { return label.name }).join(", "),
|
||||
assignee : issue.data.assignees.map(assignee => { return assignee.login }),
|
||||
body : issue.data.body
|
||||
// We need to truncate the body size, because the max size for
|
||||
// the whole payload is 16kb. We want to be safe and assume that
|
||||
// body can take up to ~8kb of space.
|
||||
body : issue.data.body.substring(0, 8000)
|
||||
};
|
||||
|
||||
|
||||
const data = {
|
||||
from: "CPython Issues <github@mg.python.org>",
|
||||
from: "CPython Issues <github@mailgun.python.org>",
|
||||
to: "new-bugs-announce@python.org",
|
||||
subject: `[Issue ${issue.data.number}] ${issue.data.title}`,
|
||||
template: "new-github-issue",
|
||||
|
|
4
.github/workflows/posix-deps-apt.sh
vendored
4
.github/workflows/posix-deps-apt.sh
vendored
|
@ -1,9 +1,11 @@
|
|||
#!/bin/sh
|
||||
apt-get update
|
||||
|
||||
# autoconf-archive is needed by autoreconf (check_generated_files job)
|
||||
apt-get -yq install \
|
||||
build-essential \
|
||||
pkg-config \
|
||||
autoconf-archive \
|
||||
ccache \
|
||||
gdb \
|
||||
lcov \
|
||||
|
@ -13,12 +15,14 @@ apt-get -yq install \
|
|||
libgdbm-dev \
|
||||
libgdbm-compat-dev \
|
||||
liblzma-dev \
|
||||
libmpdec-dev \
|
||||
libncurses5-dev \
|
||||
libreadline6-dev \
|
||||
libsqlite3-dev \
|
||||
libssl-dev \
|
||||
lzma \
|
||||
lzma-dev \
|
||||
strace \
|
||||
tk-dev \
|
||||
uuid-dev \
|
||||
xvfb \
|
||||
|
|
30
.github/workflows/project-updater.yml
vendored
Normal file
30
.github/workflows/project-updater.yml
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
name: Update GH projects
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
- labeled
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
add-to-project:
|
||||
name: Add issues to projects
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
# if an issue has any of these labels, it will be added
|
||||
# to the corresponding project
|
||||
- { project: 2, label: "release-blocker, deferred-blocker" }
|
||||
- { project: 32, label: sprint }
|
||||
|
||||
steps:
|
||||
- uses: actions/add-to-project@v1.0.0
|
||||
with:
|
||||
project-url: https://github.com/orgs/python/projects/${{ matrix.project }}
|
||||
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
|
||||
labeled: ${{ matrix.label }}
|
8
.github/workflows/regen-abidump.sh
vendored
Normal file
8
.github/workflows/regen-abidump.sh
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
set -ex
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
./.github/workflows/posix-deps-apt.sh
|
||||
apt-get install -yq abigail-tools python3
|
||||
export CFLAGS="-g3 -O0"
|
||||
./configure --enable-shared && make
|
||||
make regen-abidump
|
23
.github/workflows/require-pr-label.yml
vendored
Normal file
23
.github/workflows/require-pr-label.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
name: Check labels
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, labeled, unlabeled, synchronize]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
label:
|
||||
name: DO-NOT-MERGE / unresolved review
|
||||
if: github.repository_owner == 'python'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- uses: mheap/github-action-required-labels@v5
|
||||
with:
|
||||
mode: exactly
|
||||
count: 0
|
||||
labels: "DO-NOT-MERGE, awaiting changes, awaiting change review"
|
109
.github/workflows/reusable-docs.yml
vendored
Normal file
109
.github/workflows/reusable-docs.yml
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
name: Docs
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build_doc:
|
||||
name: 'Docs'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
branch_base: 'origin/${{ github.event.pull_request.base.ref }}'
|
||||
branch_pr: 'origin/${{ github.event.pull_request.head.ref }}'
|
||||
refspec_base: '+${{ github.event.pull_request.base.sha }}:remotes/origin/${{ github.event.pull_request.base.ref }}'
|
||||
refspec_pr: '+${{ github.event.pull_request.head.sha }}:remotes/origin/${{ github.event.pull_request.head.ref }}'
|
||||
steps:
|
||||
- name: 'Check out latest PR branch commit'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
# Adapted from https://github.com/actions/checkout/issues/520#issuecomment-1167205721
|
||||
- name: 'Fetch commits to get branch diff'
|
||||
run: |
|
||||
# Fetch enough history to find a common ancestor commit (aka merge-base):
|
||||
git fetch origin ${{ env.refspec_pr }} --depth=$(( ${{ github.event.pull_request.commits }} + 1 )) \
|
||||
--no-tags --prune --no-recurse-submodules
|
||||
|
||||
# This should get the oldest commit in the local fetched history (which may not be the commit the PR branched from):
|
||||
COMMON_ANCESTOR=$( git rev-list --first-parent --max-parents=0 --max-count=1 ${{ env.branch_pr }} )
|
||||
DATE=$( git log --date=iso8601 --format=%cd "${COMMON_ANCESTOR}" )
|
||||
|
||||
# Get all commits since that commit date from the base branch (eg: master or main):
|
||||
git fetch origin ${{ env.refspec_base }} --shallow-since="${DATE}" \
|
||||
--no-tags --prune --no-recurse-submodules
|
||||
- name: 'Set up Python'
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'Doc/requirements.txt'
|
||||
- name: 'Install build dependencies'
|
||||
run: make -C Doc/ venv
|
||||
|
||||
# To annotate PRs with Sphinx nitpicks (missing references)
|
||||
- name: 'Build HTML documentation'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
# Build docs with the '-n' (nit-picky) option; write warnings to file
|
||||
make -C Doc/ PYTHON=../python SPHINXOPTS="-q -n -W --keep-going -w sphinx-warnings.txt" html
|
||||
- name: 'Check warnings'
|
||||
if: github.event_name == 'pull_request'
|
||||
run: |
|
||||
python Doc/tools/check-warnings.py \
|
||||
--annotate-diff '${{ env.branch_base }}' '${{ env.branch_pr }}' \
|
||||
--fail-if-regression \
|
||||
--fail-if-improved \
|
||||
--fail-if-new-news-nit
|
||||
|
||||
# This build doesn't use problem matchers or check annotations
|
||||
build_doc_oldest_supported_sphinx:
|
||||
name: 'Docs (Oldest Sphinx)'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: 'Set up Python'
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12' # known to work with Sphinx 6.2.1
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'Doc/requirements-oldest-sphinx.txt'
|
||||
- name: 'Install build dependencies'
|
||||
run: make -C Doc/ venv REQUIREMENTS="requirements-oldest-sphinx.txt"
|
||||
- name: 'Build HTML documentation'
|
||||
run: make -C Doc/ SPHINXOPTS="-q" SPHINXERRORHANDLING="-W --keep-going" html
|
||||
|
||||
# Run "doctest" on HEAD as new syntax doesn't exist in the latest stable release
|
||||
doctest:
|
||||
name: 'Doctest'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ubuntu-doc-${{ hashFiles('Doc/requirements.txt') }}
|
||||
restore-keys: |
|
||||
ubuntu-doc-
|
||||
- name: 'Install Dependencies'
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh && sudo apt-get install wamerican
|
||||
- name: 'Configure CPython'
|
||||
run: ./configure --with-pydebug
|
||||
- name: 'Build CPython'
|
||||
run: make -j4
|
||||
- name: 'Install build dependencies'
|
||||
run: make -C Doc/ PYTHON=../python venv
|
||||
# Use "xvfb-run" since some doctest tests open GUI windows
|
||||
- name: 'Run documentation doctest'
|
||||
run: xvfb-run make -C Doc/ PYTHON=../python SPHINXERRORHANDLING="-W --keep-going" doctest
|
57
.github/workflows/reusable-macos.yml
vendored
Normal file
57
.github/workflows/reusable-macos.yml
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
config_hash:
|
||||
required: true
|
||||
type: string
|
||||
free-threading:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
os-matrix:
|
||||
required: false
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build_macos:
|
||||
name: 'build and test'
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
HOMEBREW_NO_ANALYTICS: 1
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
HOMEBREW_NO_INSTALL_CLEANUP: 1
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
TERM: linux
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ${{fromJson(inputs.os-matrix)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Runner image version
|
||||
run: echo "IMAGE_VERSION=${ImageVersion}" >> $GITHUB_ENV
|
||||
- name: Restore config.cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: config.cache
|
||||
key: ${{ github.job }}-${{ matrix.os }}-${{ env.IMAGE_VERSION }}-${{ inputs.config_hash }}
|
||||
- name: Install Homebrew dependencies
|
||||
run: brew install pkg-config openssl@3.0 xz gdbm tcl-tk
|
||||
- name: Configure CPython
|
||||
run: |
|
||||
GDBM_CFLAGS="-I$(brew --prefix gdbm)/include" \
|
||||
GDBM_LIBS="-L$(brew --prefix gdbm)/lib -lgdbm" \
|
||||
./configure \
|
||||
--config-cache \
|
||||
--with-pydebug \
|
||||
${{ inputs.free-threading && '--disable-gil' || '' }} \
|
||||
--prefix=/opt/python-dev \
|
||||
--with-openssl="$(brew --prefix openssl@3.0)"
|
||||
- name: Build CPython
|
||||
run: make -j8
|
||||
- name: Display build info
|
||||
run: make pythoninfo
|
||||
- name: Tests
|
||||
run: make test
|
76
.github/workflows/reusable-tsan.yml
vendored
Normal file
76
.github/workflows/reusable-tsan.yml
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
config_hash:
|
||||
required: true
|
||||
type: string
|
||||
options:
|
||||
required: true
|
||||
type: string
|
||||
suppressions_path:
|
||||
description: 'A repo relative path to the suppressions file'
|
||||
required: true
|
||||
type: string
|
||||
tsan_logs_artifact_name:
|
||||
description: 'Name of the TSAN logs artifact. Must be unique for each job.'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build_tsan_reusable:
|
||||
name: 'Thread sanitizer'
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Runner image version
|
||||
run: echo "IMAGE_VERSION=${ImageVersion}" >> $GITHUB_ENV
|
||||
- name: Restore config.cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: config.cache
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ inputs.config_hash }}
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo ./.github/workflows/posix-deps-apt.sh
|
||||
# Install clang-18
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 18
|
||||
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-18 100
|
||||
sudo update-alternatives --set clang /usr/bin/clang-18
|
||||
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-18 100
|
||||
sudo update-alternatives --set clang++ /usr/bin/clang++-18
|
||||
# Reduce ASLR to avoid TSAN crashing
|
||||
sudo sysctl -w vm.mmap_rnd_bits=28
|
||||
- name: TSAN Option Setup
|
||||
run: |
|
||||
echo "TSAN_OPTIONS=log_path=${GITHUB_WORKSPACE}/tsan_log suppressions=${GITHUB_WORKSPACE}/${{ inputs.suppressions_path }} handle_segv=0" >> $GITHUB_ENV
|
||||
echo "CC=clang" >> $GITHUB_ENV
|
||||
echo "CXX=clang++" >> $GITHUB_ENV
|
||||
- name: Add ccache to PATH
|
||||
run: |
|
||||
echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: ${{ github.event_name == 'push' }}
|
||||
max-size: "200M"
|
||||
- name: Configure CPython
|
||||
run: ${{ inputs.options }}
|
||||
- name: Build CPython
|
||||
run: make -j4
|
||||
- name: Display build info
|
||||
run: make pythoninfo
|
||||
- name: Tests
|
||||
run: ./python -m test --tsan -j4
|
||||
- name: Display TSAN logs
|
||||
if: always()
|
||||
run: find ${GITHUB_WORKSPACE} -name 'tsan_log.*' | xargs head -n 1000
|
||||
- name: Archive TSAN logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ inputs.tsan_logs_artifact_name }}
|
||||
path: tsan_log.*
|
||||
if-no-files-found: ignore
|
78
.github/workflows/reusable-ubuntu.yml
vendored
Normal file
78
.github/workflows/reusable-ubuntu.yml
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
config_hash:
|
||||
required: true
|
||||
type: string
|
||||
options:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build_ubuntu_reusable:
|
||||
name: 'build and test'
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
OPENSSL_VER: 3.0.13
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
TERM: linux
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Register gcc problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
|
||||
- name: Install dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: Configure OpenSSL env vars
|
||||
run: |
|
||||
echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> $GITHUB_ENV
|
||||
echo "OPENSSL_DIR=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}" >> $GITHUB_ENV
|
||||
echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> $GITHUB_ENV
|
||||
- name: 'Restore OpenSSL build'
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
|
||||
- name: Install OpenSSL
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
run: python3 Tools/ssl/multissltests.py --steps=library --base-directory $MULTISSL_DIR --openssl $OPENSSL_VER --system Linux
|
||||
- name: Add ccache to PATH
|
||||
run: |
|
||||
echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: ${{ github.event_name == 'push' }}
|
||||
max-size: "200M"
|
||||
- name: Setup directory envs for out-of-tree builds
|
||||
run: |
|
||||
echo "CPYTHON_RO_SRCDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-ro-srcdir)" >> $GITHUB_ENV
|
||||
echo "CPYTHON_BUILDDIR=$(realpath -m ${GITHUB_WORKSPACE}/../cpython-builddir)" >> $GITHUB_ENV
|
||||
- name: Create directories for read-only out-of-tree builds
|
||||
run: mkdir -p $CPYTHON_RO_SRCDIR $CPYTHON_BUILDDIR
|
||||
- name: Bind mount sources read-only
|
||||
run: sudo mount --bind -o ro $GITHUB_WORKSPACE $CPYTHON_RO_SRCDIR
|
||||
- name: Runner image version
|
||||
run: echo "IMAGE_VERSION=${ImageVersion}" >> $GITHUB_ENV
|
||||
- name: Restore config.cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.CPYTHON_BUILDDIR }}/config.cache
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ inputs.config_hash }}
|
||||
- name: Configure CPython out-of-tree
|
||||
working-directory: ${{ env.CPYTHON_BUILDDIR }}
|
||||
run: ${{ inputs.options }}
|
||||
- name: Build CPython out-of-tree
|
||||
working-directory: ${{ env.CPYTHON_BUILDDIR }}
|
||||
run: make -j4
|
||||
- name: Display build info
|
||||
working-directory: ${{ env.CPYTHON_BUILDDIR }}
|
||||
run: make pythoninfo
|
||||
- name: Remount sources writable for tests
|
||||
# some tests write to srcdir, lack of pyc files slows down testing
|
||||
run: sudo mount $CPYTHON_RO_SRCDIR -oremount,rw
|
||||
- name: Tests
|
||||
working-directory: ${{ env.CPYTHON_BUILDDIR }}
|
||||
run: xvfb-run make test
|
73
.github/workflows/reusable-wasi.yml
vendored
Normal file
73
.github/workflows/reusable-wasi.yml
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
config_hash:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build_wasi_reusable:
|
||||
name: 'build and test'
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
WASMTIME_VERSION: 18.0.3
|
||||
WASI_SDK_VERSION: 21
|
||||
WASI_SDK_PATH: /opt/wasi-sdk
|
||||
CROSS_BUILD_PYTHON: cross-build/build
|
||||
CROSS_BUILD_WASI: cross-build/wasm32-wasi
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# No problem resolver registered as one doesn't currently exist for Clang.
|
||||
- name: "Install wasmtime"
|
||||
uses: jcbhmr/setup-wasmtime@v2
|
||||
with:
|
||||
wasmtime-version: ${{ env.WASMTIME_VERSION }}
|
||||
- name: "Restore WASI SDK"
|
||||
id: cache-wasi-sdk
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.WASI_SDK_PATH }}
|
||||
key: ${{ runner.os }}-wasi-sdk-${{ env.WASI_SDK_VERSION }}
|
||||
- name: "Install WASI SDK"
|
||||
if: steps.cache-wasi-sdk.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
mkdir ${{ env.WASI_SDK_PATH }} && \
|
||||
curl -s -S --location https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${{ env.WASI_SDK_VERSION }}/wasi-sdk-${{ env.WASI_SDK_VERSION }}.0-linux.tar.gz | \
|
||||
tar --strip-components 1 --directory ${{ env.WASI_SDK_PATH }} --extract --gunzip
|
||||
- name: "Configure ccache action"
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: ${{ github.event_name == 'push' }}
|
||||
max-size: "200M"
|
||||
- name: "Add ccache to PATH"
|
||||
run: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
|
||||
- name: "Install Python"
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: "Restore Python build config.cache"
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.CROSS_BUILD_PYTHON }}/config.cache
|
||||
# Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ inputs.config_hash }}-${{ env.pythonLocation }}
|
||||
- name: "Configure build Python"
|
||||
run: python3 Tools/wasm/wasi.py configure-build-python -- --config-cache --with-pydebug
|
||||
- name: "Make build Python"
|
||||
run: python3 Tools/wasm/wasi.py make-build-python
|
||||
- name: "Restore host config.cache"
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.CROSS_BUILD_WASI }}/config.cache
|
||||
# Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-wasi-sdk-${{ env.WASI_SDK_VERSION }}-${{ inputs.config_hash }}-${{ env.pythonLocation }}
|
||||
- name: "Configure host"
|
||||
# `--with-pydebug` inferred from configure-build-python
|
||||
run: python3 Tools/wasm/wasi.py configure-host -- --config-cache
|
||||
- name: "Make host"
|
||||
run: python3 Tools/wasm/wasi.py make-host
|
||||
- name: "Display build info"
|
||||
run: make --directory ${{ env.CROSS_BUILD_WASI }} pythoninfo
|
||||
- name: "Test"
|
||||
run: make --directory ${{ env.CROSS_BUILD_WASI }} test
|
53
.github/workflows/reusable-windows.yml
vendored
Normal file
53
.github/workflows/reusable-windows.yml
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
free-threading:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build_win32:
|
||||
name: 'build and test (x86)'
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
IncludeUwp: 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build CPython
|
||||
run: .\PCbuild\build.bat -e -d -v -p Win32 ${{ inputs.free-threading && '--disable-gil' || '' }}
|
||||
- name: Display build info
|
||||
run: .\python.bat -m test.pythoninfo
|
||||
- name: Tests
|
||||
run: .\PCbuild\rt.bat -p Win32 -d -q --fast-ci ${{ inputs.free-threading && '--disable-gil' || '' }}
|
||||
|
||||
build_win_amd64:
|
||||
name: 'build and test (x64)'
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
IncludeUwp: 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Register MSVC problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/msvc.json"
|
||||
- name: Build CPython
|
||||
run: .\PCbuild\build.bat -e -d -v -p x64 ${{ inputs.free-threading && '--disable-gil' || '' }}
|
||||
- name: Display build info
|
||||
run: .\python.bat -m test.pythoninfo
|
||||
- name: Tests
|
||||
run: .\PCbuild\rt.bat -p x64 -d -q --fast-ci ${{ inputs.free-threading && '--disable-gil' || '' }}
|
||||
|
||||
build_win_arm64:
|
||||
name: 'build (arm64)'
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
IncludeUwp: 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Register MSVC problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/msvc.json"
|
||||
- name: Build CPython
|
||||
run: .\PCbuild\build.bat -e -d -v -p arm64 ${{ inputs.free-threading && '--disable-gil' || '' }}
|
8
.github/workflows/stale.yml
vendored
8
.github/workflows/stale.yml
vendored
|
@ -2,7 +2,7 @@ name: Mark stale pull requests
|
|||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
- cron: "0 */6 * * *"
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
@ -12,15 +12,17 @@ jobs:
|
|||
if: github.repository_owner == 'python'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: "Check PRs"
|
||||
uses: actions/stale@v4
|
||||
uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-pr-message: 'This PR is stale because it has been open for 30 days with no activity.'
|
||||
stale-pr-label: 'stale'
|
||||
days-before-stale: 30
|
||||
days-before-issue-stale: -1
|
||||
days-before-pr-stale: 30
|
||||
days-before-close: -1
|
||||
ascending: true
|
||||
operations-per-run: 120
|
||||
|
|
33
.github/workflows/verify-ensurepip-wheels.yml
vendored
Normal file
33
.github/workflows/verify-ensurepip-wheels.yml
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
name: Verify bundled wheels
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'Lib/ensurepip/_bundled/**'
|
||||
- '.github/workflows/verify-ensurepip-wheels.yml'
|
||||
- 'Tools/build/verify_ensurepip_wheels.py'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'Lib/ensurepip/_bundled/**'
|
||||
- '.github/workflows/verify-ensurepip-wheels.yml'
|
||||
- 'Tools/build/verify_ensurepip_wheels.py'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3'
|
||||
- name: Compare checksum of bundled wheels to the ones published on PyPI
|
||||
run: ./Tools/build/verify_ensurepip_wheels.py
|
31
.gitignore
vendored
31
.gitignore
vendored
|
@ -5,10 +5,12 @@
|
|||
*.cover
|
||||
*.iml
|
||||
*.o
|
||||
*.lto
|
||||
*.a
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
*.dSYM
|
||||
*.dll
|
||||
*.wasm
|
||||
*.orig
|
||||
|
@ -21,6 +23,10 @@
|
|||
*.gc??
|
||||
*.profclang?
|
||||
*.profraw
|
||||
# Copies of binaries before BOLT optimizations.
|
||||
*.prebolt
|
||||
# BOLT profile data.
|
||||
*.fdata
|
||||
*.dyn
|
||||
.gdb_history
|
||||
.purify
|
||||
|
@ -36,10 +42,10 @@ gmon.out
|
|||
.coverage
|
||||
.mypy_cache/
|
||||
.pytest_cache/
|
||||
.ruff_cache/
|
||||
.DS_Store
|
||||
|
||||
*.exe
|
||||
!Lib/distutils/command/*.exe
|
||||
|
||||
# Ignore core dumps... but not Tools/msi/core/ or the like.
|
||||
core
|
||||
|
@ -56,8 +62,6 @@ Doc/.venv/
|
|||
Doc/env/
|
||||
Doc/.env/
|
||||
Include/pydtrace_probes.h
|
||||
Lib/distutils/command/*.pdb
|
||||
Lib/lib2to3/*.pickle
|
||||
Lib/site-packages/*
|
||||
!Lib/site-packages/README.txt
|
||||
Lib/test/data/*
|
||||
|
@ -65,6 +69,17 @@ Lib/test/data/*
|
|||
/_bootstrap_python
|
||||
/Makefile
|
||||
/Makefile.pre
|
||||
/iOSTestbed.*
|
||||
iOS/Frameworks/
|
||||
iOS/Resources/Info.plist
|
||||
iOS/testbed/build
|
||||
iOS/testbed/Python.xcframework/ios-*/bin
|
||||
iOS/testbed/Python.xcframework/ios-*/include
|
||||
iOS/testbed/Python.xcframework/ios-*/lib
|
||||
iOS/testbed/Python.xcframework/ios-*/Python.framework
|
||||
iOS/testbed/iOSTestbed.xcodeproj/project.xcworkspace
|
||||
iOS/testbed/iOSTestbed.xcodeproj/xcuserdata
|
||||
iOS/testbed/iOSTestbed.xcodeproj/xcshareddata
|
||||
Mac/Makefile
|
||||
Mac/PythonLauncher/Info.plist
|
||||
Mac/PythonLauncher/Makefile
|
||||
|
@ -114,16 +129,19 @@ PCbuild/win32/
|
|||
Tools/unicode/data/
|
||||
/autom4te.cache
|
||||
/build/
|
||||
/builddir/
|
||||
/config.cache
|
||||
/config.log
|
||||
/config.status
|
||||
/config.status.lineno
|
||||
# hendrikmuhs/ccache-action@v1
|
||||
/.ccache
|
||||
/cross-build/
|
||||
/jit_stencils.h
|
||||
/platform
|
||||
/profile-clean-stamp
|
||||
/profile-run-stamp
|
||||
/Python/deepfreeze/*.c
|
||||
/profile-bolt-stamp
|
||||
/pybuilddir.txt
|
||||
/pyconfig.h
|
||||
/python-config
|
||||
|
@ -141,7 +159,7 @@ Tools/ssl/win32
|
|||
Tools/freeze/test/outdir
|
||||
|
||||
# The frozen modules are always generated by the build so we don't
|
||||
# keep them in the repo. Also see Tools/scripts/freeze_modules.py.
|
||||
# keep them in the repo. Also see Tools/build/freeze_modules.py.
|
||||
Python/frozen_modules/*.h
|
||||
# The manifest can be generated at any time with "make regen-frozen".
|
||||
Python/frozen_modules/MANIFEST
|
||||
|
@ -150,3 +168,6 @@ Python/frozen_modules/MANIFEST
|
|||
# Ignore ./python binary on Unix but still look into ./Python/ directory.
|
||||
/python
|
||||
!/Python/
|
||||
|
||||
# main branch only: ABI files are not checked/maintained.
|
||||
Doc/data/python*.abi
|
||||
|
|
3
.mailmap
Normal file
3
.mailmap
Normal file
|
@ -0,0 +1,3 @@
|
|||
# This file sets the canonical name for contributors to the repository.
|
||||
# Documentation: https://git-scm.com/docs/gitmailmap
|
||||
Amethyst Reese <amethyst@n7.gg> <john@noswap.com>
|
46
.pre-commit-config.yaml
Normal file
46
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,46 @@
|
|||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.3.4
|
||||
hooks:
|
||||
- id: ruff
|
||||
name: Run Ruff on Lib/test/
|
||||
args: [--exit-non-zero-on-fix]
|
||||
files: ^Lib/test/
|
||||
- id: ruff
|
||||
name: Run Ruff on Argument Clinic
|
||||
args: [--exit-non-zero-on-fix, --config=Tools/clinic/.ruff.toml]
|
||||
files: ^Tools/clinic/|Lib/test/test_clinic.py
|
||||
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 24.4.2
|
||||
hooks:
|
||||
- id: black
|
||||
name: Run Black on Tools/jit/
|
||||
files: ^Tools/jit/
|
||||
language_version: python3.12
|
||||
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
- id: check-case-conflict
|
||||
- id: check-merge-conflict
|
||||
- id: check-toml
|
||||
exclude: ^Lib/test/test_tomllib/
|
||||
- id: check-yaml
|
||||
- id: end-of-file-fixer
|
||||
types: [python]
|
||||
exclude: Lib/test/tokenizedata/coding20731.py
|
||||
- id: trailing-whitespace
|
||||
types_or: [c, inc, python, rst]
|
||||
|
||||
- repo: https://github.com/sphinx-contrib/sphinx-lint
|
||||
rev: v0.9.1
|
||||
hooks:
|
||||
- id: sphinx-lint
|
||||
args: [--enable=default-role]
|
||||
files: ^Doc/|^Misc/NEWS.d/
|
||||
|
||||
- repo: meta
|
||||
hooks:
|
||||
- id: check-hooks-apply
|
||||
- id: check-useless-excludes
|
32
.readthedocs.yml
Normal file
32
.readthedocs.yml
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
# Project page: https://readthedocs.org/projects/cpython-previews/
|
||||
|
||||
version: 2
|
||||
|
||||
sphinx:
|
||||
configuration: Doc/conf.py
|
||||
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3"
|
||||
|
||||
commands:
|
||||
# https://docs.readthedocs.io/en/stable/build-customization.html#cancel-build-based-on-a-condition
|
||||
#
|
||||
# Cancel building pull requests when there aren't changes in the Doc directory.
|
||||
#
|
||||
# If there are no changes (git diff exits with 0) we force the command to return with 183.
|
||||
# This is a special exit code on Read the Docs that will cancel the build immediately.
|
||||
- |
|
||||
if [ "$READTHEDOCS_VERSION_TYPE" = "external" ] && [ "$(git diff --quiet origin/main -- Doc/ .readthedocs.yml; echo $?)" -eq 0 ];
|
||||
then
|
||||
echo "No changes to Doc/ - exiting the build.";
|
||||
exit 183;
|
||||
fi
|
||||
|
||||
- make -C Doc venv html
|
||||
- mkdir _readthedocs
|
||||
- mv Doc/build/html _readthedocs/html
|
||||
|
97
Android/README.md
Normal file
97
Android/README.md
Normal file
|
@ -0,0 +1,97 @@
|
|||
# Python for Android
|
||||
|
||||
These instructions are only needed if you're planning to compile Python for
|
||||
Android yourself. Most users should *not* need to do this. If you're looking to
|
||||
use Python on Android, one of the following tools will provide a much more
|
||||
approachable user experience:
|
||||
|
||||
* [Briefcase](https://briefcase.readthedocs.io), from the BeeWare project
|
||||
* [Buildozer](https://buildozer.readthedocs.io), from the Kivy project
|
||||
* [Chaquopy](https://chaquo.com/chaquopy/)
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Export the `ANDROID_HOME` environment variable to point at your Android SDK. If
|
||||
you don't already have the SDK, here's how to install it:
|
||||
|
||||
* Download the "Command line tools" from <https://developer.android.com/studio>.
|
||||
* Create a directory `android-sdk/cmdline-tools`, and unzip the command line
|
||||
tools package into it.
|
||||
* Rename `android-sdk/cmdline-tools/cmdline-tools` to
|
||||
`android-sdk/cmdline-tools/latest`.
|
||||
* `export ANDROID_HOME=/path/to/android-sdk`
|
||||
|
||||
The `android.py` script also requires the following commands to be on the `PATH`:
|
||||
|
||||
* `curl`
|
||||
* `java`
|
||||
* `tar`
|
||||
* `unzip`
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
Python can be built for Android on any POSIX platform supported by the Android
|
||||
development tools, which currently means Linux or macOS. This involves doing a
|
||||
cross-build where you use a "build" Python (for your development machine) to
|
||||
help produce a "host" Python for Android.
|
||||
|
||||
First, make sure you have all the usual tools and libraries needed to build
|
||||
Python for your development machine. The only Android tool you need to install
|
||||
is the command line tools package above: the build script will download the
|
||||
rest.
|
||||
|
||||
The easiest way to do a build is to use the `android.py` script. You can either
|
||||
have it perform the entire build process from start to finish in one step, or
|
||||
you can do it in discrete steps that mirror running `configure` and `make` for
|
||||
each of the two builds of Python you end up producing.
|
||||
|
||||
The discrete steps for building via `android.py` are:
|
||||
|
||||
```sh
|
||||
./android.py configure-build
|
||||
./android.py make-build
|
||||
./android.py configure-host HOST
|
||||
./android.py make-host HOST
|
||||
```
|
||||
|
||||
`HOST` identifies which architecture to build. To see the possible values, run
|
||||
`./android.py configure-host --help`.
|
||||
|
||||
To do all steps in a single command, run:
|
||||
|
||||
```sh
|
||||
./android.py build HOST
|
||||
```
|
||||
|
||||
In the end you should have a build Python in `cross-build/build`, and an Android
|
||||
build in `cross-build/HOST`.
|
||||
|
||||
You can use `--` as a separator for any of the `configure`-related commands –
|
||||
including `build` itself – to pass arguments to the underlying `configure`
|
||||
call. For example, if you want a pydebug build that also caches the results from
|
||||
`configure`, you can do:
|
||||
|
||||
```sh
|
||||
./android.py build HOST -- -C --with-pydebug
|
||||
```
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
To run the Python test suite on Android:
|
||||
|
||||
* Install Android Studio, if you don't already have it.
|
||||
* Follow the instructions in the previous section to build all supported
|
||||
architectures.
|
||||
* Run `./android.py setup-testbed` to download the Gradle wrapper.
|
||||
* Open the `testbed` directory in Android Studio.
|
||||
* In the *Device Manager* dock, connect a device or start an emulator.
|
||||
Then select it from the drop-down list in the toolbar.
|
||||
* Click the "Run" button in the toolbar.
|
||||
* The testbed app displays nothing on screen while running. To see its output,
|
||||
open the [Logcat window](https://developer.android.com/studio/debug/logcat).
|
||||
|
||||
To run specific tests, or pass any other arguments to the test suite, edit the
|
||||
command line in testbed/app/src/main/python/main.py.
|
93
Android/android-env.sh
Normal file
93
Android/android-env.sh
Normal file
|
@ -0,0 +1,93 @@
|
|||
# This script must be sourced with the following variables already set:
|
||||
: ${ANDROID_HOME:?} # Path to Android SDK
|
||||
: ${HOST:?} # GNU target triplet
|
||||
|
||||
# You may also override the following:
|
||||
: ${api_level:=21} # Minimum Android API level the build will run on
|
||||
: ${PREFIX:-} # Path in which to find required libraries
|
||||
|
||||
|
||||
# Print all messages on stderr so they're visible when running within build-wheel.
|
||||
log() {
|
||||
echo "$1" >&2
|
||||
}
|
||||
|
||||
fail() {
|
||||
log "$1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# When moving to a new version of the NDK, carefully review the following:
|
||||
#
|
||||
# * https://developer.android.com/ndk/downloads/revision_history
|
||||
#
|
||||
# * https://android.googlesource.com/platform/ndk/+/ndk-rXX-release/docs/BuildSystemMaintainers.md
|
||||
# where XX is the NDK version. Do a diff against the version you're upgrading from, e.g.:
|
||||
# https://android.googlesource.com/platform/ndk/+/ndk-r25-release..ndk-r26-release/docs/BuildSystemMaintainers.md
|
||||
ndk_version=26.2.11394342
|
||||
|
||||
ndk=$ANDROID_HOME/ndk/$ndk_version
|
||||
if ! [ -e $ndk ]; then
|
||||
log "Installing NDK: this may take several minutes"
|
||||
yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "ndk;$ndk_version"
|
||||
fi
|
||||
|
||||
if [ $HOST = "arm-linux-androideabi" ]; then
|
||||
clang_triplet=armv7a-linux-androideabi
|
||||
else
|
||||
clang_triplet=$HOST
|
||||
fi
|
||||
|
||||
# These variables are based on BuildSystemMaintainers.md above, and
|
||||
# $ndk/build/cmake/android.toolchain.cmake.
|
||||
toolchain=$(echo $ndk/toolchains/llvm/prebuilt/*)
|
||||
export AR="$toolchain/bin/llvm-ar"
|
||||
export AS="$toolchain/bin/llvm-as"
|
||||
export CC="$toolchain/bin/${clang_triplet}${api_level}-clang"
|
||||
export CXX="${CC}++"
|
||||
export LD="$toolchain/bin/ld"
|
||||
export NM="$toolchain/bin/llvm-nm"
|
||||
export RANLIB="$toolchain/bin/llvm-ranlib"
|
||||
export READELF="$toolchain/bin/llvm-readelf"
|
||||
export STRIP="$toolchain/bin/llvm-strip"
|
||||
|
||||
# The quotes make sure the wildcard in the `toolchain` assignment has been expanded.
|
||||
for path in "$AR" "$AS" "$CC" "$CXX" "$LD" "$NM" "$RANLIB" "$READELF" "$STRIP"; do
|
||||
if ! [ -e "$path" ]; then
|
||||
fail "$path does not exist"
|
||||
fi
|
||||
done
|
||||
|
||||
export CFLAGS=""
|
||||
export LDFLAGS="-Wl,--build-id=sha1 -Wl,--no-rosegment"
|
||||
|
||||
# Unlike Linux, Android does not implicitly use a dlopened library to resolve
|
||||
# relocations in subsequently-loaded libraries, even if RTLD_GLOBAL is used
|
||||
# (https://github.com/android/ndk/issues/1244). So any library that fails to
|
||||
# build with this flag, would also fail to load at runtime.
|
||||
LDFLAGS="$LDFLAGS -Wl,--no-undefined"
|
||||
|
||||
# Many packages get away with omitting -lm on Linux, but Android is stricter.
|
||||
LDFLAGS="$LDFLAGS -lm"
|
||||
|
||||
# -mstackrealign is included where necessary in the clang launcher scripts which are
|
||||
# pointed to by $CC, so we don't need to include it here.
|
||||
if [ $HOST = "arm-linux-androideabi" ]; then
|
||||
CFLAGS="$CFLAGS -march=armv7-a -mthumb"
|
||||
fi
|
||||
|
||||
if [ -n "${PREFIX:-}" ]; then
|
||||
abs_prefix=$(realpath $PREFIX)
|
||||
CFLAGS="$CFLAGS -I$abs_prefix/include"
|
||||
LDFLAGS="$LDFLAGS -L$abs_prefix/lib"
|
||||
|
||||
export PKG_CONFIG="pkg-config --define-prefix"
|
||||
export PKG_CONFIG_LIBDIR="$abs_prefix/lib/pkgconfig"
|
||||
fi
|
||||
|
||||
# Use the same variable name as conda-build
|
||||
if [ $(uname) = "Darwin" ]; then
|
||||
export CPU_COUNT=$(sysctl -n hw.ncpu)
|
||||
else
|
||||
export CPU_COUNT=$(nproc)
|
||||
fi
|
237
Android/android.py
Executable file
237
Android/android.py
Executable file
|
@ -0,0 +1,237 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import sysconfig
|
||||
from os.path import basename, relpath
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
SCRIPT_NAME = Path(__file__).name
|
||||
CHECKOUT = Path(__file__).resolve().parent.parent
|
||||
CROSS_BUILD_DIR = CHECKOUT / "cross-build"
|
||||
|
||||
|
||||
def delete_if_exists(path):
|
||||
if path.exists():
|
||||
print(f"Deleting {path} ...")
|
||||
shutil.rmtree(path)
|
||||
|
||||
|
||||
def subdir(name, *, clean=None):
|
||||
path = CROSS_BUILD_DIR / name
|
||||
if clean:
|
||||
delete_if_exists(path)
|
||||
if not path.exists():
|
||||
if clean is None:
|
||||
sys.exit(
|
||||
f"{path} does not exist. Create it by running the appropriate "
|
||||
f"`configure` subcommand of {SCRIPT_NAME}.")
|
||||
else:
|
||||
path.mkdir(parents=True)
|
||||
return path
|
||||
|
||||
|
||||
def run(command, *, host=None, **kwargs):
|
||||
env = os.environ.copy()
|
||||
if host:
|
||||
env_script = CHECKOUT / "Android/android-env.sh"
|
||||
env_output = subprocess.run(
|
||||
f"set -eu; "
|
||||
f"HOST={host}; "
|
||||
f"PREFIX={subdir(host)}/prefix; "
|
||||
f". {env_script}; "
|
||||
f"export",
|
||||
check=True, shell=True, text=True, stdout=subprocess.PIPE
|
||||
).stdout
|
||||
|
||||
for line in env_output.splitlines():
|
||||
# We don't require every line to match, as there may be some other
|
||||
# output from installing the NDK.
|
||||
if match := re.search(
|
||||
"^(declare -x |export )?(\\w+)=['\"]?(.*?)['\"]?$", line
|
||||
):
|
||||
key, value = match[2], match[3]
|
||||
if env.get(key) != value:
|
||||
print(line)
|
||||
env[key] = value
|
||||
|
||||
if env == os.environ:
|
||||
raise ValueError(f"Found no variables in {env_script.name} output:\n"
|
||||
+ env_output)
|
||||
|
||||
print(">", " ".join(map(str, command)))
|
||||
try:
|
||||
subprocess.run(command, check=True, env=env, **kwargs)
|
||||
except subprocess.CalledProcessError as e:
|
||||
sys.exit(e)
|
||||
|
||||
|
||||
def build_python_path():
|
||||
"""The path to the build Python binary."""
|
||||
build_dir = subdir("build")
|
||||
binary = build_dir / "python"
|
||||
if not binary.is_file():
|
||||
binary = binary.with_suffix(".exe")
|
||||
if not binary.is_file():
|
||||
raise FileNotFoundError("Unable to find `python(.exe)` in "
|
||||
f"{build_dir}")
|
||||
|
||||
return binary
|
||||
|
||||
|
||||
def configure_build_python(context):
|
||||
os.chdir(subdir("build", clean=context.clean))
|
||||
|
||||
command = [relpath(CHECKOUT / "configure")]
|
||||
if context.args:
|
||||
command.extend(context.args)
|
||||
run(command)
|
||||
|
||||
|
||||
def make_build_python(context):
|
||||
os.chdir(subdir("build"))
|
||||
run(["make", "-j", str(os.cpu_count())])
|
||||
|
||||
|
||||
def unpack_deps(host):
|
||||
deps_url = "https://github.com/beeware/cpython-android-source-deps/releases/download"
|
||||
for name_ver in ["bzip2-1.0.8-1", "libffi-3.4.4-2", "openssl-3.0.13-1",
|
||||
"sqlite-3.45.1-0", "xz-5.4.6-0"]:
|
||||
filename = f"{name_ver}-{host}.tar.gz"
|
||||
download(f"{deps_url}/{name_ver}/{filename}")
|
||||
run(["tar", "-xf", filename])
|
||||
os.remove(filename)
|
||||
|
||||
|
||||
def download(url, target_dir="."):
|
||||
out_path = f"{target_dir}/{basename(url)}"
|
||||
run(["curl", "-Lf", "-o", out_path, url])
|
||||
return out_path
|
||||
|
||||
|
||||
def configure_host_python(context):
|
||||
host_dir = subdir(context.host, clean=context.clean)
|
||||
|
||||
prefix_dir = host_dir / "prefix"
|
||||
if not prefix_dir.exists():
|
||||
prefix_dir.mkdir()
|
||||
os.chdir(prefix_dir)
|
||||
unpack_deps(context.host)
|
||||
|
||||
build_dir = host_dir / "build"
|
||||
build_dir.mkdir(exist_ok=True)
|
||||
os.chdir(build_dir)
|
||||
|
||||
command = [
|
||||
# Basic cross-compiling configuration
|
||||
relpath(CHECKOUT / "configure"),
|
||||
f"--host={context.host}",
|
||||
f"--build={sysconfig.get_config_var('BUILD_GNU_TYPE')}",
|
||||
f"--with-build-python={build_python_path()}",
|
||||
"--without-ensurepip",
|
||||
|
||||
# Android always uses a shared libpython.
|
||||
"--enable-shared",
|
||||
"--without-static-libpython",
|
||||
|
||||
# Dependent libraries. The others are found using pkg-config: see
|
||||
# android-env.sh.
|
||||
f"--with-openssl={prefix_dir}",
|
||||
]
|
||||
|
||||
if context.args:
|
||||
command.extend(context.args)
|
||||
run(command, host=context.host)
|
||||
|
||||
|
||||
def make_host_python(context):
|
||||
host_dir = subdir(context.host)
|
||||
os.chdir(host_dir / "build")
|
||||
run(["make", "-j", str(os.cpu_count())], host=context.host)
|
||||
run(["make", "install", f"prefix={host_dir}/prefix"], host=context.host)
|
||||
|
||||
|
||||
def build_all(context):
|
||||
steps = [configure_build_python, make_build_python, configure_host_python,
|
||||
make_host_python]
|
||||
for step in steps:
|
||||
step(context)
|
||||
|
||||
|
||||
def clean_all(context):
|
||||
delete_if_exists(CROSS_BUILD_DIR)
|
||||
|
||||
|
||||
# To avoid distributing compiled artifacts without corresponding source code,
|
||||
# the Gradle wrapper is not included in the CPython repository. Instead, we
|
||||
# extract it from the Gradle release.
|
||||
def setup_testbed(context):
|
||||
ver_long = "8.7.0"
|
||||
ver_short = ver_long.removesuffix(".0")
|
||||
testbed_dir = CHECKOUT / "Android/testbed"
|
||||
|
||||
for filename in ["gradlew", "gradlew.bat"]:
|
||||
out_path = download(
|
||||
f"https://raw.githubusercontent.com/gradle/gradle/v{ver_long}/{filename}",
|
||||
testbed_dir)
|
||||
os.chmod(out_path, 0o755)
|
||||
|
||||
with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir:
|
||||
os.chdir(temp_dir)
|
||||
bin_zip = download(
|
||||
f"https://services.gradle.org/distributions/gradle-{ver_short}-bin.zip")
|
||||
outer_jar = f"gradle-{ver_short}/lib/plugins/gradle-wrapper-{ver_short}.jar"
|
||||
run(["unzip", bin_zip, outer_jar])
|
||||
run(["unzip", "-o", "-d", f"{testbed_dir}/gradle/wrapper", outer_jar,
|
||||
"gradle-wrapper.jar"])
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
subcommands = parser.add_subparsers(dest="subcommand")
|
||||
build = subcommands.add_parser("build", help="Build everything")
|
||||
configure_build = subcommands.add_parser("configure-build",
|
||||
help="Run `configure` for the "
|
||||
"build Python")
|
||||
make_build = subcommands.add_parser("make-build",
|
||||
help="Run `make` for the build Python")
|
||||
configure_host = subcommands.add_parser("configure-host",
|
||||
help="Run `configure` for Android")
|
||||
make_host = subcommands.add_parser("make-host",
|
||||
help="Run `make` for Android")
|
||||
subcommands.add_parser(
|
||||
"clean", help="Delete the cross-build directory")
|
||||
subcommands.add_parser(
|
||||
"setup-testbed", help="Download the testbed Gradle wrapper")
|
||||
|
||||
for subcommand in build, configure_build, configure_host:
|
||||
subcommand.add_argument(
|
||||
"--clean", action="store_true", default=False, dest="clean",
|
||||
help="Delete any relevant directories before building")
|
||||
for subcommand in build, configure_host, make_host:
|
||||
subcommand.add_argument(
|
||||
"host", metavar="HOST",
|
||||
choices=["aarch64-linux-android", "x86_64-linux-android"],
|
||||
help="Host triplet: choices=[%(choices)s]")
|
||||
for subcommand in build, configure_build, configure_host:
|
||||
subcommand.add_argument("args", nargs="*",
|
||||
help="Extra arguments to pass to `configure`")
|
||||
|
||||
context = parser.parse_args()
|
||||
dispatch = {"configure-build": configure_build_python,
|
||||
"make-build": make_build_python,
|
||||
"configure-host": configure_host_python,
|
||||
"make-host": make_host_python,
|
||||
"build": build_all,
|
||||
"clean": clean_all,
|
||||
"setup-testbed": setup_testbed}
|
||||
dispatch[context.subcommand](context)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
21
Android/testbed/.gitignore
vendored
Normal file
21
Android/testbed/.gitignore
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# The Gradle wrapper should be downloaded by running `../android.py setup-testbed`.
|
||||
/gradlew
|
||||
/gradlew.bat
|
||||
/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/deploymentTargetDropdown.xml
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
1
Android/testbed/app/.gitignore
vendored
Normal file
1
Android/testbed/app/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
129
Android/testbed/app/build.gradle.kts
Normal file
129
Android/testbed/app/build.gradle.kts
Normal file
|
@ -0,0 +1,129 @@
|
|||
import com.android.build.api.variant.*
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
}
|
||||
|
||||
val PYTHON_DIR = File(projectDir, "../../..").canonicalPath
|
||||
val PYTHON_CROSS_DIR = "$PYTHON_DIR/cross-build"
|
||||
val ABIS = mapOf(
|
||||
"arm64-v8a" to "aarch64-linux-android",
|
||||
"x86_64" to "x86_64-linux-android",
|
||||
)
|
||||
|
||||
val PYTHON_VERSION = File("$PYTHON_DIR/Include/patchlevel.h").useLines {
|
||||
for (line in it) {
|
||||
val match = """#define PY_VERSION\s+"(\d+\.\d+)""".toRegex().find(line)
|
||||
if (match != null) {
|
||||
return@useLines match.groupValues[1]
|
||||
}
|
||||
}
|
||||
throw GradleException("Failed to find Python version")
|
||||
}
|
||||
|
||||
|
||||
android {
|
||||
namespace = "org.python.testbed"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "org.python.testbed"
|
||||
minSdk = 21
|
||||
targetSdk = 34
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
ndk.abiFilters.addAll(ABIS.keys)
|
||||
externalNativeBuild.cmake.arguments(
|
||||
"-DPYTHON_CROSS_DIR=$PYTHON_CROSS_DIR",
|
||||
"-DPYTHON_VERSION=$PYTHON_VERSION")
|
||||
}
|
||||
|
||||
externalNativeBuild.cmake {
|
||||
path("src/main/c/CMakeLists.txt")
|
||||
}
|
||||
|
||||
// Set this property to something non-empty, otherwise it'll use the default
|
||||
// list, which ignores asset directories beginning with an underscore.
|
||||
aaptOptions.ignoreAssetsPattern = ".git"
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||
implementation("com.google.android.material:material:1.11.0")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
}
|
||||
|
||||
|
||||
// Create some custom tasks to copy Python and its standard library from
|
||||
// elsewhere in the repository.
|
||||
androidComponents.onVariants { variant ->
|
||||
generateTask(variant, variant.sources.assets!!) {
|
||||
into("python") {
|
||||
for (triplet in ABIS.values) {
|
||||
for (subDir in listOf("include", "lib")) {
|
||||
into(subDir) {
|
||||
from("$PYTHON_CROSS_DIR/$triplet/prefix/$subDir")
|
||||
include("python$PYTHON_VERSION/**")
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
}
|
||||
}
|
||||
into("lib/python$PYTHON_VERSION") {
|
||||
// Uncomment this to pick up edits from the source directory
|
||||
// without having to rerun `make install`.
|
||||
// from("$PYTHON_DIR/Lib")
|
||||
// duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
|
||||
into("site-packages") {
|
||||
from("$projectDir/src/main/python")
|
||||
}
|
||||
}
|
||||
}
|
||||
exclude("**/__pycache__")
|
||||
}
|
||||
|
||||
generateTask(variant, variant.sources.jniLibs!!) {
|
||||
for ((abi, triplet) in ABIS.entries) {
|
||||
into(abi) {
|
||||
from("$PYTHON_CROSS_DIR/$triplet/prefix/lib")
|
||||
include("libpython*.*.so")
|
||||
include("lib*_python.so")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun generateTask(
|
||||
variant: ApplicationVariant, directories: SourceDirectories,
|
||||
configure: GenerateTask.() -> Unit
|
||||
) {
|
||||
val taskName = "generate" +
|
||||
listOf(variant.name, "Python", directories.name)
|
||||
.map { it.replaceFirstChar(Char::uppercase) }
|
||||
.joinToString("")
|
||||
|
||||
directories.addGeneratedSourceDirectory(
|
||||
tasks.register<GenerateTask>(taskName) {
|
||||
into(outputDir)
|
||||
configure()
|
||||
},
|
||||
GenerateTask::outputDir)
|
||||
}
|
||||
|
||||
|
||||
// addGeneratedSourceDirectory requires the task to have a DirectoryProperty.
|
||||
abstract class GenerateTask: Sync() {
|
||||
@get:OutputDirectory
|
||||
abstract val outputDir: DirectoryProperty
|
||||
}
|
20
Android/testbed/app/src/main/AndroidManifest.xml
Normal file
20
Android/testbed/app/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.Material3.Light.NoActionBar">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
9
Android/testbed/app/src/main/c/CMakeLists.txt
Normal file
9
Android/testbed/app/src/main/c/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(testbed)
|
||||
|
||||
set(PREFIX_DIR ${PYTHON_CROSS_DIR}/${CMAKE_LIBRARY_ARCHITECTURE}/prefix)
|
||||
include_directories(${PREFIX_DIR}/include/python${PYTHON_VERSION})
|
||||
link_directories(${PREFIX_DIR}/lib)
|
||||
link_libraries(log python${PYTHON_VERSION})
|
||||
|
||||
add_library(main_activity SHARED main_activity.c)
|
147
Android/testbed/app/src/main/c/main_activity.c
Normal file
147
Android/testbed/app/src/main/c/main_activity.c
Normal file
|
@ -0,0 +1,147 @@
|
|||
#include <android/log.h>
|
||||
#include <errno.h>
|
||||
#include <jni.h>
|
||||
#include <pthread.h>
|
||||
#include <Python.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static void throw_runtime_exception(JNIEnv *env, const char *message) {
|
||||
(*env)->ThrowNew(
|
||||
env,
|
||||
(*env)->FindClass(env, "java/lang/RuntimeException"),
|
||||
message);
|
||||
}
|
||||
|
||||
|
||||
// --- Stdio redirection ------------------------------------------------------
|
||||
|
||||
// Most apps won't need this, because the Python-level sys.stdout and sys.stderr
|
||||
// are redirected to the Android logcat by Python itself. However, in the
|
||||
// testbed it's useful to redirect the native streams as well, to debug problems
|
||||
// in the Python startup or redirection process.
|
||||
//
|
||||
// Based on
|
||||
// https://github.com/beeware/briefcase-android-gradle-template/blob/v0.3.11/%7B%7B%20cookiecutter.safe_formal_name%20%7D%7D/app/src/main/cpp/native-lib.cpp
|
||||
|
||||
typedef struct {
|
||||
FILE *file;
|
||||
int fd;
|
||||
android_LogPriority priority;
|
||||
char *tag;
|
||||
int pipe[2];
|
||||
} StreamInfo;
|
||||
|
||||
static StreamInfo STREAMS[] = {
|
||||
{stdout, STDOUT_FILENO, ANDROID_LOG_INFO, "native.stdout", {-1, -1}},
|
||||
{stderr, STDERR_FILENO, ANDROID_LOG_WARN, "native.stderr", {-1, -1}},
|
||||
{NULL, -1, ANDROID_LOG_UNKNOWN, NULL, {-1, -1}},
|
||||
};
|
||||
|
||||
// The maximum length of a log message in bytes, including the level marker and
|
||||
// tag, is defined as LOGGER_ENTRY_MAX_PAYLOAD in
|
||||
// platform/system/logging/liblog/include/log/log.h. As of API level 30, messages
|
||||
// longer than this will be be truncated by logcat. This limit has already been
|
||||
// reduced at least once in the history of Android (from 4076 to 4068 between API
|
||||
// level 23 and 26), so leave some headroom.
|
||||
static const int MAX_BYTES_PER_WRITE = 4000;
|
||||
|
||||
static void *redirection_thread(void *arg) {
|
||||
StreamInfo *si = (StreamInfo*)arg;
|
||||
ssize_t read_size;
|
||||
char buf[MAX_BYTES_PER_WRITE];
|
||||
while ((read_size = read(si->pipe[0], buf, sizeof buf - 1)) > 0) {
|
||||
buf[read_size] = '\0'; /* add null-terminator */
|
||||
__android_log_write(si->priority, si->tag, buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *redirect_stream(StreamInfo *si) {
|
||||
/* make the FILE unbuffered, to ensure messages are never lost */
|
||||
if (setvbuf(si->file, 0, _IONBF, 0)) {
|
||||
return "setvbuf";
|
||||
}
|
||||
|
||||
/* create the pipe and redirect the file descriptor */
|
||||
if (pipe(si->pipe)) {
|
||||
return "pipe";
|
||||
}
|
||||
if (dup2(si->pipe[1], si->fd) == -1) {
|
||||
return "dup2";
|
||||
}
|
||||
|
||||
/* start the logging thread */
|
||||
pthread_t thr;
|
||||
if ((errno = pthread_create(&thr, 0, redirection_thread, si))) {
|
||||
return "pthread_create";
|
||||
}
|
||||
if ((errno = pthread_detach(thr))) {
|
||||
return "pthread_detach";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_python_testbed_MainActivity_redirectStdioToLogcat(
|
||||
JNIEnv *env, jobject obj
|
||||
) {
|
||||
for (StreamInfo *si = STREAMS; si->file; si++) {
|
||||
char *error_prefix;
|
||||
if ((error_prefix = redirect_stream(si))) {
|
||||
char error_message[1024];
|
||||
snprintf(error_message, sizeof(error_message),
|
||||
"%s: %s", error_prefix, strerror(errno));
|
||||
throw_runtime_exception(env, error_message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- Python intialization ----------------------------------------------------
|
||||
|
||||
static PyStatus set_config_string(
|
||||
JNIEnv *env, PyConfig *config, wchar_t **config_str, jstring value
|
||||
) {
|
||||
const char *value_utf8 = (*env)->GetStringUTFChars(env, value, NULL);
|
||||
PyStatus status = PyConfig_SetBytesString(config, config_str, value_utf8);
|
||||
(*env)->ReleaseStringUTFChars(env, value, value_utf8);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void throw_status(JNIEnv *env, PyStatus status) {
|
||||
throw_runtime_exception(env, status.err_msg ? status.err_msg : "");
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_python_testbed_MainActivity_runPython(
|
||||
JNIEnv *env, jobject obj, jstring home, jstring runModule
|
||||
) {
|
||||
PyConfig config;
|
||||
PyStatus status;
|
||||
PyConfig_InitIsolatedConfig(&config);
|
||||
|
||||
status = set_config_string(env, &config, &config.home, home);
|
||||
if (PyStatus_Exception(status)) {
|
||||
throw_status(env, status);
|
||||
return;
|
||||
}
|
||||
|
||||
status = set_config_string(env, &config, &config.run_module, runModule);
|
||||
if (PyStatus_Exception(status)) {
|
||||
throw_status(env, status);
|
||||
return;
|
||||
}
|
||||
|
||||
// Some tests generate SIGPIPE and SIGXFSZ, which should be ignored.
|
||||
config.install_signal_handlers = 1;
|
||||
|
||||
status = Py_InitializeFromConfig(&config);
|
||||
if (PyStatus_Exception(status)) {
|
||||
throw_status(env, status);
|
||||
return;
|
||||
}
|
||||
|
||||
Py_RunMain();
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package org.python.testbed
|
||||
|
||||
import android.os.*
|
||||
import android.system.Os
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.*
|
||||
import java.io.*
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
// Python needs this variable to help it find the temporary directory,
|
||||
// but Android only sets it on API level 33 and later.
|
||||
Os.setenv("TMPDIR", cacheDir.toString(), false)
|
||||
|
||||
val pythonHome = extractAssets()
|
||||
System.loadLibrary("main_activity")
|
||||
redirectStdioToLogcat()
|
||||
runPython(pythonHome.toString(), "main")
|
||||
findViewById<TextView>(R.id.tvHello).text = "Python complete"
|
||||
}
|
||||
|
||||
private fun extractAssets() : File {
|
||||
val pythonHome = File(filesDir, "python")
|
||||
if (pythonHome.exists() && !pythonHome.deleteRecursively()) {
|
||||
throw RuntimeException("Failed to delete $pythonHome")
|
||||
}
|
||||
extractAssetDir("python", filesDir)
|
||||
return pythonHome
|
||||
}
|
||||
|
||||
private fun extractAssetDir(path: String, targetDir: File) {
|
||||
val names = assets.list(path)
|
||||
?: throw RuntimeException("Failed to list $path")
|
||||
val targetSubdir = File(targetDir, path)
|
||||
if (!targetSubdir.mkdirs()) {
|
||||
throw RuntimeException("Failed to create $targetSubdir")
|
||||
}
|
||||
|
||||
for (name in names) {
|
||||
val subPath = "$path/$name"
|
||||
val input: InputStream
|
||||
try {
|
||||
input = assets.open(subPath)
|
||||
} catch (e: FileNotFoundException) {
|
||||
extractAssetDir(subPath, targetDir)
|
||||
continue
|
||||
}
|
||||
input.use {
|
||||
File(targetSubdir, name).outputStream().use { output ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private external fun redirectStdioToLogcat()
|
||||
private external fun runPython(home: String, runModule: String)
|
||||
}
|
17
Android/testbed/app/src/main/python/main.py
Normal file
17
Android/testbed/app/src/main/python/main.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
import runpy
|
||||
import signal
|
||||
import sys
|
||||
|
||||
# Some tests use SIGUSR1, but that's blocked by default in an Android app in
|
||||
# order to make it available to `sigwait` in the "Signal Catcher" thread. That
|
||||
# thread's functionality is only relevant to the JVM ("forcing GC (no HPROF) and
|
||||
# profile save"), so disabling it should not weaken the tests.
|
||||
signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGUSR1])
|
||||
|
||||
# To run specific tests, or pass any other arguments to the test suite, edit
|
||||
# this command line.
|
||||
sys.argv[1:] = [
|
||||
"--use", "all,-cpu",
|
||||
"--verbose3",
|
||||
]
|
||||
runpy.run_module("test")
|
BIN
Android/testbed/app/src/main/res/drawable-xxhdpi/ic_launcher.png
Normal file
BIN
Android/testbed/app/src/main/res/drawable-xxhdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3 KiB |
19
Android/testbed/app/src/main/res/layout/activity_main.xml
Normal file
19
Android/testbed/app/src/main/res/layout/activity_main.xml
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvHello"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World!"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
3
Android/testbed/app/src/main/res/values/strings.xml
Normal file
3
Android/testbed/app/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">Python testbed</string>
|
||||
</resources>
|
5
Android/testbed/build.gradle.kts
Normal file
5
Android/testbed/build.gradle.kts
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id("com.android.application") version "8.2.2" apply false
|
||||
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
|
||||
}
|
23
Android/testbed/gradle.properties
Normal file
23
Android/testbed/gradle.properties
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
6
Android/testbed/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
Android/testbed/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
#Mon Feb 19 20:29:06 GMT 2024
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
18
Android/testbed/settings.gradle.kts
Normal file
18
Android/testbed/settings.gradle.kts
Normal file
|
@ -0,0 +1,18 @@
|
|||
pluginManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "Python testbed"
|
||||
include(":app")
|
||||
|
83
Doc/Makefile
83
Doc/Makefile
|
@ -7,31 +7,34 @@
|
|||
PYTHON = python3
|
||||
VENVDIR = ./venv
|
||||
SPHINXBUILD = PATH=$(VENVDIR)/bin:$$PATH sphinx-build
|
||||
SPHINXLINT = PATH=$(VENVDIR)/bin:$$PATH sphinx-lint
|
||||
BLURB = PATH=$(VENVDIR)/bin:$$PATH blurb
|
||||
JOBS = auto
|
||||
PAPER =
|
||||
SOURCES =
|
||||
DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py)
|
||||
REQUIREMENTS = requirements.txt
|
||||
SPHINXERRORHANDLING = -W
|
||||
SERVE_PORT =
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_elements.papersize=a4paper
|
||||
PAPEROPT_letter = -D latex_elements.papersize=letterpaper
|
||||
|
||||
ALLSPHINXOPTS = -b $(BUILDER) -d build/doctrees $(PAPEROPT_$(PAPER)) \
|
||||
$(SPHINXOPTS) $(SPHINXERRORHANDLING) . build/$(BUILDER) $(SOURCES)
|
||||
|
||||
.PHONY: help build html htmlhelp latex text texinfo changes linkcheck \
|
||||
suspicious coverage doctest pydoc-topics htmlview clean dist check serve \
|
||||
autobuild-dev autobuild-stable venv
|
||||
ALLSPHINXOPTS = -b $(BUILDER) \
|
||||
-d build/doctrees \
|
||||
-j $(JOBS) \
|
||||
$(PAPEROPT_$(PAPER)) \
|
||||
$(SPHINXOPTS) $(SPHINXERRORHANDLING) \
|
||||
. build/$(BUILDER) $(SOURCES)
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " clean to remove build files"
|
||||
@echo " venv to create a venv with necessary tools"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " gettext to generate POT files"
|
||||
@echo " htmlview to open the index page built by the html target in your browser"
|
||||
@echo " htmllive to rebuild and reload HTML files in your browser"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " text to make plain text files"
|
||||
|
@ -43,10 +46,9 @@ help:
|
|||
@echo " doctest to run doctests in the documentation"
|
||||
@echo " pydoc-topics to regenerate the pydoc topics file"
|
||||
@echo " dist to create a \"dist\" directory with archived docs for download"
|
||||
@echo " suspicious to check for suspicious markup in output text"
|
||||
@echo " check to run a check for frequent markup errors"
|
||||
@echo " serve to serve the documentation on the localhost (8000)"
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
-mkdir -p build
|
||||
# Look first for a Misc/NEWS file (building from a source release tarball
|
||||
|
@ -73,38 +75,46 @@ build:
|
|||
$(SPHINXBUILD) $(ALLSPHINXOPTS)
|
||||
@echo
|
||||
|
||||
.PHONY: html
|
||||
html: BUILDER = html
|
||||
html: build
|
||||
@echo "Build finished. The HTML pages are in build/html."
|
||||
|
||||
.PHONY: htmlhelp
|
||||
htmlhelp: BUILDER = htmlhelp
|
||||
htmlhelp: build
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
"build/htmlhelp/pydoc.hhp project file."
|
||||
|
||||
.PHONY: latex
|
||||
latex: BUILDER = latex
|
||||
latex: build
|
||||
@echo "Build finished; the LaTeX files are in build/latex."
|
||||
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
|
||||
"run these through (pdf)latex."
|
||||
|
||||
.PHONY: text
|
||||
text: BUILDER = text
|
||||
text: build
|
||||
@echo "Build finished; the text files are in build/text."
|
||||
|
||||
.PHONY: texinfo
|
||||
texinfo: BUILDER = texinfo
|
||||
texinfo: build
|
||||
@echo "Build finished; the python.texi file is in build/texinfo."
|
||||
@echo "Run \`make info' in that directory to run it through makeinfo."
|
||||
|
||||
.PHONY: epub
|
||||
epub: BUILDER = epub
|
||||
epub: build
|
||||
@echo "Build finished; the epub files are in build/epub."
|
||||
|
||||
.PHONY: changes
|
||||
changes: BUILDER = changes
|
||||
changes: build
|
||||
@echo "The overview file is in build/changes."
|
||||
|
||||
.PHONY: linkcheck
|
||||
linkcheck: BUILDER = linkcheck
|
||||
linkcheck:
|
||||
@$(MAKE) build BUILDER=$(BUILDER) || { \
|
||||
|
@ -112,22 +122,12 @@ linkcheck:
|
|||
"or in build/$(BUILDER)/output.txt"; \
|
||||
false; }
|
||||
|
||||
suspicious: BUILDER = suspicious
|
||||
suspicious:
|
||||
@$(MAKE) build BUILDER=$(BUILDER) || { \
|
||||
echo "Suspicious check complete; look for any errors in the above output" \
|
||||
"or in build/$(BUILDER)/suspicious.csv. If all issues are false" \
|
||||
"positives, append that file to tools/susp-ignored.csv."; \
|
||||
false; }
|
||||
@echo "⚠ make suspicious is deprecated and will be removed soon."
|
||||
@echo "⚠ Use:"
|
||||
@echo "⚠ make check"
|
||||
@echo "⚠ instead."
|
||||
|
||||
.PHONY: coverage
|
||||
coverage: BUILDER = coverage
|
||||
coverage: build
|
||||
@echo "Coverage finished; see c.txt and python.txt in build/coverage"
|
||||
|
||||
.PHONY: doctest
|
||||
doctest: BUILDER = doctest
|
||||
doctest:
|
||||
@$(MAKE) build BUILDER=$(BUILDER) || { \
|
||||
|
@ -135,31 +135,48 @@ doctest:
|
|||
"results in build/doctest/output.txt"; \
|
||||
false; }
|
||||
|
||||
.PHONY: pydoc-topics
|
||||
pydoc-topics: BUILDER = pydoc-topics
|
||||
pydoc-topics: build
|
||||
@echo "Building finished; now run this:" \
|
||||
"cp build/pydoc-topics/topics.py ../Lib/pydoc_data/topics.py"
|
||||
|
||||
htmlview: html
|
||||
$(PYTHON) -c "import webbrowser; webbrowser.open('build/html/index.html')"
|
||||
.PHONY: gettext
|
||||
gettext: BUILDER = gettext
|
||||
gettext: SPHINXOPTS += '-d build/doctrees-gettext'
|
||||
gettext: build
|
||||
|
||||
.PHONY: htmlview
|
||||
htmlview: html
|
||||
$(PYTHON) -c "import os, webbrowser; webbrowser.open('file://' + os.path.realpath('build/html/index.html'))"
|
||||
|
||||
.PHONY: htmllive
|
||||
htmllive: SPHINXBUILD = $(VENVDIR)/bin/sphinx-autobuild
|
||||
htmllive: SPHINXOPTS = --re-ignore="/venv/" --open-browser --delay 0
|
||||
htmllive: html
|
||||
|
||||
.PHONY: clean
|
||||
clean: clean-venv
|
||||
-rm -rf build/*
|
||||
|
||||
.PHONY: clean-venv
|
||||
clean-venv:
|
||||
rm -rf $(VENVDIR)
|
||||
|
||||
.PHONY: venv
|
||||
venv:
|
||||
@if [ -d $(VENVDIR) ] ; then \
|
||||
echo "venv already exists."; \
|
||||
echo "To recreate it, remove it first with \`make clean-venv'."; \
|
||||
else \
|
||||
echo "Creating venv in $(VENVDIR)"; \
|
||||
$(PYTHON) -m venv $(VENVDIR); \
|
||||
$(VENVDIR)/bin/python3 -m pip install -U pip setuptools; \
|
||||
$(VENVDIR)/bin/python3 -m pip install -r requirements.txt; \
|
||||
$(VENVDIR)/bin/python3 -m pip install --upgrade pip; \
|
||||
$(VENVDIR)/bin/python3 -m pip install -r $(REQUIREMENTS); \
|
||||
echo "The venv has been created in the $(VENVDIR) directory"; \
|
||||
fi
|
||||
|
||||
.PHONY: dist
|
||||
dist:
|
||||
rm -rf dist
|
||||
mkdir -p dist
|
||||
|
@ -214,12 +231,14 @@ dist:
|
|||
rm -r dist/python-$(DISTVERSION)-docs-texinfo
|
||||
rm dist/python-$(DISTVERSION)-docs-texinfo.tar
|
||||
|
||||
check:
|
||||
$(SPHINXLINT) -i tools -i $(VENVDIR) -i README.rst
|
||||
$(SPHINXLINT) ../Misc/NEWS.d/next/
|
||||
.PHONY: check
|
||||
check: venv
|
||||
$(VENVDIR)/bin/python3 -m pre_commit --version > /dev/null || $(VENVDIR)/bin/python3 -m pip install pre-commit
|
||||
$(VENVDIR)/bin/python3 -m pre_commit run --all-files
|
||||
|
||||
.PHONY: serve
|
||||
serve:
|
||||
$(PYTHON) ../Tools/scripts/serve.py build/html $(SERVE_PORT)
|
||||
@echo "The serve target was removed, use htmlview instead (see bpo-36329)"
|
||||
|
||||
# Targets for daily automated doc build
|
||||
# By default, Sphinx only rebuilds pages where the page content has changed.
|
||||
|
@ -229,15 +248,18 @@ serve:
|
|||
# output files)
|
||||
|
||||
# for development releases: always build
|
||||
.PHONY: autobuild-dev
|
||||
autobuild-dev:
|
||||
make dist SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1'
|
||||
|
||||
# for quick rebuilds (HTML only)
|
||||
.PHONY: autobuild-dev-html
|
||||
autobuild-dev-html:
|
||||
make html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1'
|
||||
|
||||
# for stable releases: only build if not in pre-release stage (alpha, beta)
|
||||
# release candidate downloads are okay, since the stable tree can be in that stage
|
||||
.PHONY: autobuild-stable
|
||||
autobuild-stable:
|
||||
@case $(DISTVERSION) in *[ab]*) \
|
||||
echo "Not building; $(DISTVERSION) is not a release version."; \
|
||||
|
@ -245,6 +267,7 @@ autobuild-stable:
|
|||
esac
|
||||
@make autobuild-dev
|
||||
|
||||
.PHONY: autobuild-stable-html
|
||||
autobuild-stable-html:
|
||||
@case $(DISTVERSION) in *[ab]*) \
|
||||
echo "Not building; $(DISTVERSION) is not a release version."; \
|
||||
|
|
|
@ -40,7 +40,7 @@ If you'd like to create the virtual environment in a different location,
|
|||
you can specify it using the ``VENVDIR`` variable.
|
||||
|
||||
You can also skip creating the virtual environment altogether, in which case
|
||||
the Makefile will look for instances of ``sphinxbuild`` and ``blurb``
|
||||
the Makefile will look for instances of ``sphinx-build`` and ``blurb``
|
||||
installed on your process ``PATH`` (configurable with the ``SPHINXBUILD`` and
|
||||
``BLURB`` variables).
|
||||
|
||||
|
@ -93,9 +93,6 @@ Available make targets are:
|
|||
plain text documentation for the labels defined in
|
||||
``tools/pyspecific.py`` -- pydoc needs these to show topic and keyword help.
|
||||
|
||||
* "suspicious", which checks the parsed markup for text that looks like
|
||||
malformed and thus unconverted reST.
|
||||
|
||||
* "check", which checks for frequent markup errors.
|
||||
|
||||
* "serve", which serves the build/html directory on port 8000.
|
||||
|
@ -130,7 +127,7 @@ Contributing
|
|||
============
|
||||
|
||||
Bugs in the content should be reported to the
|
||||
`Python bug tracker <https://bugs.python.org>`_.
|
||||
`Python bug tracker <https://github.com/python/cpython/issues>`_.
|
||||
|
||||
Bugs in the toolset should be reported to the tools themselves.
|
||||
|
||||
|
|
BIN
Doc/_static/og-image.png
Normal file
BIN
Doc/_static/og-image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -6,8 +6,8 @@ About these documents
|
|||
These documents are generated from `reStructuredText`_ sources by `Sphinx`_, a
|
||||
document processor specifically written for the Python documentation.
|
||||
|
||||
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
|
||||
.. _Sphinx: http://sphinx-doc.org/
|
||||
.. _reStructuredText: https://docutils.sourceforge.io/rst.html
|
||||
.. _Sphinx: https://www.sphinx-doc.org/
|
||||
|
||||
.. In the online version of these documents, you can submit comments and suggest
|
||||
changes directly on the documentation pages.
|
||||
|
@ -21,7 +21,7 @@ Many thanks go to:
|
|||
|
||||
* Fred L. Drake, Jr., the creator of the original Python documentation toolset
|
||||
and writer of much of the content;
|
||||
* the `Docutils <http://docutils.sourceforge.net/>`_ project for creating
|
||||
* the `Docutils <https://docutils.sourceforge.io/>`_ project for creating
|
||||
reStructuredText and the Docutils suite;
|
||||
* Fredrik Lundh for his Alternative Python Reference project from which Sphinx
|
||||
got many good ideas.
|
||||
|
|
11
Doc/bugs.rst
11
Doc/bugs.rst
|
@ -19,6 +19,13 @@ If you find a bug in this documentation or would like to propose an improvement,
|
|||
please submit a bug report on the :ref:`tracker <using-the-tracker>`. If you
|
||||
have a suggestion on how to fix it, include that as well.
|
||||
|
||||
You can also open a discussion item on our
|
||||
`Documentation Discourse forum <https://discuss.python.org/c/documentation/26>`_.
|
||||
|
||||
If you find a bug in the theme (HTML / CSS / JavaScript) of the
|
||||
documentation, please submit a bug report on the `python-doc-theme bug
|
||||
tracker <https://github.com/python/python-docs-theme>`_.
|
||||
|
||||
If you're short on time, you can also email documentation bug reports to
|
||||
docs@python.org (behavioral bugs can be sent to python-list@python.org).
|
||||
'docs@' is a mailing list run by volunteers; your request will be noticed,
|
||||
|
@ -35,7 +42,7 @@ though it may take a while to be processed.
|
|||
`Helping with Documentation <https://devguide.python.org/docquality/#helping-with-documentation>`_
|
||||
Comprehensive guide for individuals that are interested in contributing to Python documentation.
|
||||
|
||||
`Documentation Translations <https://devguide.python.org/documenting/#translating>`_
|
||||
`Documentation Translations <https://devguide.python.org/documentation/translating/>`_
|
||||
A list of GitHub pages for documentation translation and their primary contacts.
|
||||
|
||||
|
||||
|
@ -67,7 +74,7 @@ Click on the "New issue" button in the top bar to report a new issue.
|
|||
The submission form has two fields, "Title" and "Comment".
|
||||
|
||||
For the "Title" field, enter a *very* short description of the problem;
|
||||
less than ten words is good.
|
||||
fewer than ten words is good.
|
||||
|
||||
In the "Comment" field, describe the problem in detail, including what you
|
||||
expected to happen and what did happen. Be sure to include whether any
|
||||
|
|
|
@ -24,4 +24,3 @@ but whose items have not been set to some non-\ ``NULL`` value yet.
|
|||
mapping.rst
|
||||
iter.rst
|
||||
buffer.rst
|
||||
objbuffer.rst
|
||||
|
|
|
@ -14,7 +14,7 @@ Allocating Objects on the Heap
|
|||
|
||||
.. c:function:: PyObject* PyObject_Init(PyObject *op, PyTypeObject *type)
|
||||
|
||||
Initialize a newly-allocated object *op* with its type and initial
|
||||
Initialize a newly allocated object *op* with its type and initial
|
||||
reference. Returns the initialized object. If *type* indicates that the
|
||||
object participates in the cyclic garbage detector, it is added to the
|
||||
detector's set of observed objects. Other fields of the object are not
|
||||
|
@ -27,22 +27,26 @@ Allocating Objects on the Heap
|
|||
length information for a variable-size object.
|
||||
|
||||
|
||||
.. c:function:: TYPE* PyObject_New(TYPE, PyTypeObject *type)
|
||||
.. c:macro:: PyObject_New(TYPE, typeobj)
|
||||
|
||||
Allocate a new Python object using the C structure type *TYPE*
|
||||
and the Python type object *typeobj* (``PyTypeObject*``).
|
||||
Fields not defined by the Python object header are not initialized.
|
||||
The caller will own the only reference to the object
|
||||
(i.e. its reference count will be one).
|
||||
The size of the memory allocation is determined from the
|
||||
:c:member:`~PyTypeObject.tp_basicsize` field of the type object.
|
||||
|
||||
|
||||
.. c:macro:: PyObject_NewVar(TYPE, typeobj, size)
|
||||
|
||||
Allocate a new Python object using the C structure type *TYPE* and the
|
||||
Python type object *type*. Fields not defined by the Python object header
|
||||
are not initialized; the object's reference count will be one. The size of
|
||||
the memory allocation is determined from the :c:member:`~PyTypeObject.tp_basicsize` field of
|
||||
the type object.
|
||||
|
||||
|
||||
.. c:function:: TYPE* PyObject_NewVar(TYPE, PyTypeObject *type, Py_ssize_t size)
|
||||
|
||||
Allocate a new Python object using the C structure type *TYPE* and the
|
||||
Python type object *type*. Fields not defined by the Python object header
|
||||
Python type object *typeobj* (``PyTypeObject*``).
|
||||
Fields not defined by the Python object header
|
||||
are not initialized. The allocated memory allows for the *TYPE* structure
|
||||
plus *size* fields of the size given by the :c:member:`~PyTypeObject.tp_itemsize` field of
|
||||
*type*. This is useful for implementing objects like tuples, which are
|
||||
plus *size* (``Py_ssize_t``) fields of the size
|
||||
given by the :c:member:`~PyTypeObject.tp_itemsize` field of
|
||||
*typeobj*. This is useful for implementing objects like tuples, which are
|
||||
able to determine their size at construction time. Embedding the array of
|
||||
fields into the same allocation decreases the number of allocations,
|
||||
improving the memory management efficiency.
|
||||
|
@ -50,8 +54,8 @@ Allocating Objects on the Heap
|
|||
|
||||
.. c:function:: void PyObject_Del(void *op)
|
||||
|
||||
Releases memory allocated to an object using :c:func:`PyObject_New` or
|
||||
:c:func:`PyObject_NewVar`. This is normally called from the
|
||||
Releases memory allocated to an object using :c:macro:`PyObject_New` or
|
||||
:c:macro:`PyObject_NewVar`. This is normally called from the
|
||||
:c:member:`~PyTypeObject.tp_dealloc` handler specified in the object's type. The fields of
|
||||
the object should not be accessed after this call as the memory is no
|
||||
longer a valid Python object.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue