mirror of
https://github.com/python/cpython.git
synced 2025-12-23 09:19:18 +00:00
Merge branch 'main' into __instancecheck__
This commit is contained in:
commit
6c7026fc48
3966 changed files with 602833 additions and 377737 deletions
|
|
@ -1,104 +1,23 @@
|
|||
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.1l
|
||||
|
||||
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.1l
|
||||
|
||||
steps:
|
||||
- template: ./posix-steps.yml
|
||||
parameters:
|
||||
dependencies: apt
|
||||
coverage: true
|
||||
|
||||
|
||||
- job: Windows_CI_Tests
|
||||
displayName: Windows CI Tests
|
||||
dependsOn: Prebuild
|
||||
condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
vmImage: windows-2022
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
|
|
|
|||
|
|
@ -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,59 +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: ./python Tools/scripts/patchcheck.py --travis 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.1l
|
||||
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.1l
|
||||
|
||||
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-2019
|
||||
|
||||
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,65 +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'
|
||||
|
||||
- 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,129 +0,0 @@
|
|||
name: Release_$(Build.SourceBranchName)_$(SourceTag)_$(Date:yyyyMMdd)$(Rev:.rr)
|
||||
|
||||
variables:
|
||||
__RealSigningCertificate: 'Python Software Foundation'
|
||||
# QUEUE TIME VARIABLES
|
||||
# GitRemote: python
|
||||
# SourceTag:
|
||||
# DoPGO: true
|
||||
# SigningCertificate: 'Python Software Foundation'
|
||||
# SigningDescription: 'Built: $(Build.BuildNumber)'
|
||||
# DoLayout: true
|
||||
# DoMSIX: true
|
||||
# DoNuget: true
|
||||
# DoEmbed: true
|
||||
# DoMSI: true
|
||||
# DoPublish: false
|
||||
# PyDotOrgUsername: ''
|
||||
# PyDotOrgServer: ''
|
||||
# BuildToPublish: ''
|
||||
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
stages:
|
||||
- stage: Build
|
||||
displayName: Build binaries
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
jobs:
|
||||
- template: windows-release/stage-build.yml
|
||||
|
||||
- stage: Sign
|
||||
displayName: Sign binaries
|
||||
dependsOn: Build
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
jobs:
|
||||
- template: windows-release/stage-sign.yml
|
||||
|
||||
- stage: Layout
|
||||
displayName: Generate layouts
|
||||
dependsOn: Sign
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
jobs:
|
||||
- template: windows-release/stage-layout-full.yml
|
||||
- template: windows-release/stage-layout-embed.yml
|
||||
- template: windows-release/stage-layout-nuget.yml
|
||||
|
||||
- stage: Pack
|
||||
dependsOn: Layout
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
jobs:
|
||||
- template: windows-release/stage-pack-nuget.yml
|
||||
|
||||
- stage: Test
|
||||
dependsOn: Pack
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
jobs:
|
||||
- template: windows-release/stage-test-embed.yml
|
||||
- template: windows-release/stage-test-nuget.yml
|
||||
|
||||
- stage: Layout_MSIX
|
||||
displayName: Generate MSIX layouts
|
||||
dependsOn: Sign
|
||||
condition: and(succeeded(), and(eq(variables['DoMSIX'], 'true'), not(variables['BuildToPublish'])))
|
||||
jobs:
|
||||
- template: windows-release/stage-layout-msix.yml
|
||||
|
||||
- stage: Pack_MSIX
|
||||
displayName: Package MSIX
|
||||
dependsOn: Layout_MSIX
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
jobs:
|
||||
- template: windows-release/stage-pack-msix.yml
|
||||
|
||||
- stage: Build_MSI
|
||||
displayName: Build MSI installer
|
||||
dependsOn: Sign
|
||||
condition: and(succeeded(), and(eq(variables['DoMSI'], 'true'), not(variables['BuildToPublish'])))
|
||||
jobs:
|
||||
- template: windows-release/stage-msi.yml
|
||||
|
||||
- stage: Test_MSI
|
||||
displayName: Test MSI installer
|
||||
dependsOn: Build_MSI
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
jobs:
|
||||
- template: windows-release/stage-test-msi.yml
|
||||
|
||||
- stage: PublishPyDotOrg
|
||||
displayName: Publish to python.org
|
||||
dependsOn: ['Test_MSI', 'Test']
|
||||
condition: and(succeeded(), and(eq(variables['DoPublish'], 'true'), not(variables['BuildToPublish'])))
|
||||
jobs:
|
||||
- template: windows-release/stage-publish-pythonorg.yml
|
||||
|
||||
- stage: PublishNuget
|
||||
displayName: Publish to nuget.org
|
||||
dependsOn: Test
|
||||
condition: and(succeeded(), and(eq(variables['DoPublish'], 'true'), not(variables['BuildToPublish'])))
|
||||
jobs:
|
||||
- template: windows-release/stage-publish-nugetorg.yml
|
||||
|
||||
- stage: PublishStore
|
||||
displayName: Publish to Store
|
||||
dependsOn: Pack_MSIX
|
||||
condition: and(succeeded(), and(eq(variables['DoPublish'], 'true'), not(variables['BuildToPublish'])))
|
||||
jobs:
|
||||
- template: windows-release/stage-publish-store.yml
|
||||
|
||||
|
||||
- stage: PublishExistingPyDotOrg
|
||||
displayName: Publish existing build to python.org
|
||||
dependsOn: []
|
||||
condition: and(succeeded(), and(eq(variables['DoPublish'], 'true'), variables['BuildToPublish']))
|
||||
jobs:
|
||||
- template: windows-release/stage-publish-pythonorg.yml
|
||||
|
||||
- stage: PublishExistingNuget
|
||||
displayName: Publish existing build to nuget.org
|
||||
dependsOn: []
|
||||
condition: and(succeeded(), and(eq(variables['DoPublish'], 'true'), variables['BuildToPublish']))
|
||||
jobs:
|
||||
- template: windows-release/stage-publish-nugetorg.yml
|
||||
|
||||
- stage: PublishExistingStore
|
||||
displayName: Publish existing build to Store
|
||||
dependsOn: []
|
||||
condition: and(succeeded(), and(eq(variables['DoPublish'], 'true'), variables['BuildToPublish']))
|
||||
jobs:
|
||||
- template: windows-release/stage-publish-store.yml
|
||||
|
|
@ -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,28 +0,0 @@
|
|||
parameters:
|
||||
GPGKeyFile: $(GPGKey)
|
||||
GPGPassphrase: $(GPGPassphrase)
|
||||
Files: '*'
|
||||
WorkingDirectory: $(Build.BinariesDirectory)
|
||||
|
||||
steps:
|
||||
- task: DownloadSecureFile@1
|
||||
name: gpgkey
|
||||
inputs:
|
||||
secureFile: ${{ parameters.GPGKeyFile }}
|
||||
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)"
|
||||
(gci -File ${{ parameters.Files }}).FullName | %{
|
||||
gpg/gpg2.exe -ba --batch --passphrase ${{ parameters.GPGPassphrase }} $_
|
||||
"Made signature for $_"
|
||||
}
|
||||
displayName: 'Generate GPG signatures'
|
||||
workingDirectory: ${{ parameters.WorkingDirectory }}
|
||||
|
||||
- powershell: |
|
||||
$p = gps "gpg-agent" -EA 0
|
||||
if ($p) { $p.Kill() }
|
||||
displayName: 'Kill GPG agent'
|
||||
condition: true
|
||||
|
|
@ -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,135 +0,0 @@
|
|||
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
|
||||
contents: |
|
||||
htmlhelp\*.chm
|
||||
|
||||
- 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: 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
|
||||
|
||||
- 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
|
||||
%MSBUILD% Tools\msi\bundle\releaseweb.wixproj /t:Rebuild /p:RebuildAll=false
|
||||
displayName: 'Build win32 installer'
|
||||
env:
|
||||
Platform: x86
|
||||
Py_OutDir: $(Build.BinariesDirectory)
|
||||
PYTHON: $(Build.BinariesDirectory)\win32\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
TclTkLibraryDir: $(Build.BinariesDirectory)\tcltk_lib_win32
|
||||
BuildForRelease: true
|
||||
SuppressMinGWLib: true
|
||||
|
||||
- script: |
|
||||
%MSBUILD% Tools\msi\bundle\releaselocal.wixproj /t:Rebuild /p:RebuildAll=true
|
||||
%MSBUILD% Tools\msi\bundle\releaseweb.wixproj /t:Rebuild /p:RebuildAll=false
|
||||
displayName: 'Build amd64 installer'
|
||||
env:
|
||||
Platform: x64
|
||||
Py_OutDir: $(Build.BinariesDirectory)
|
||||
PYTHON: $(Build.BinariesDirectory)\amd64\python.exe
|
||||
PYTHONHOME: $(Build.SourcesDirectory)
|
||||
TclTkLibraryDir: $(Build.BinariesDirectory)\tcltk_lib_amd64
|
||||
BuildForRelease: true
|
||||
SuppressMinGWLib: true
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Assemble artifact: msi (1/2)'
|
||||
inputs:
|
||||
sourceFolder: $(Build.BinariesDirectory)\win32\en-us
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)\msi\win32
|
||||
contents: |
|
||||
*.msi
|
||||
*.cab
|
||||
*.exe
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Assemble artifact: msi (2/2)'
|
||||
inputs:
|
||||
sourceFolder: $(Build.BinariesDirectory)\amd64\en-us
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)\msi\amd64
|
||||
contents: |
|
||||
*.msi
|
||||
*.cab
|
||||
*.exe
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: 'Publish MSI'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)\msi'
|
||||
artifactName: msi
|
||||
|
|
@ -1,179 +0,0 @@
|
|||
jobs:
|
||||
- job: Build_Docs
|
||||
displayName: Docs build
|
||||
pool:
|
||||
name: 'Windows Release'
|
||||
#vmImage: windows-2019
|
||||
|
||||
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'
|
||||
env:
|
||||
BUILDDIR: $(Build.BinariesDirectory)\Doc
|
||||
|
||||
#- powershell: |
|
||||
# mkdir -Force "$(Build.BinariesDirectory)\Doc\htmlhelp"
|
||||
# iwr "https://www.python.org/ftp/python/3.8.0/python380.chm" -OutFile "$(Build.BinariesDirectory)\Doc\htmlhelp\python390a0.chm"
|
||||
# displayName: 'Cheat at building CHM docs'
|
||||
|
||||
- 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-2019
|
||||
|
||||
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-2019
|
||||
|
||||
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-2019
|
||||
|
||||
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"
|
||||
|
||||
- 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
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
jobs:
|
||||
- job: Make_Embed_Layout
|
||||
displayName: Make embeddable layout
|
||||
condition: and(succeeded(), eq(variables['DoEmbed'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
|
||||
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,75 +0,0 @@
|
|||
jobs:
|
||||
- job: Make_Layouts
|
||||
displayName: Make layouts
|
||||
condition: and(succeeded(), eq(variables['DoLayout'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
|
||||
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)
|
||||
|
||||
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,97 +0,0 @@
|
|||
jobs:
|
||||
- job: Make_MSIX_Layout
|
||||
displayName: Make MSIX layout
|
||||
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
|
||||
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)
|
||||
|
||||
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-2019
|
||||
|
||||
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,36 +0,0 @@
|
|||
jobs:
|
||||
- job: Make_MSI
|
||||
displayName: Make MSI
|
||||
condition: and(succeeded(), not(variables['SigningCertificate']))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
|
||||
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
|
||||
|
||||
- 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
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
jobs:
|
||||
- job: Pack_MSIX
|
||||
displayName: Pack MSIX bundles
|
||||
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
|
||||
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
|
||||
- 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,51 +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
|
||||
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,46 +0,0 @@
|
|||
jobs:
|
||||
- job: Publish_Nuget
|
||||
displayName: Publish Nuget packages
|
||||
condition: and(succeeded(), eq(variables['DoNuget'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: nuget'
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
inputs:
|
||||
artifactName: nuget
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: nuget'
|
||||
condition: and(succeeded(), variables['BuildToPublish'])
|
||||
inputs:
|
||||
artifactName: nuget
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
buildType: specific
|
||||
project: cpython
|
||||
pipeline: Windows-Release
|
||||
buildVersionToDownload: specific
|
||||
buildId: $(BuildToPublish)
|
||||
|
||||
- powershell: 'gci pythonarm*.nupkg | %{ Write-Host "Not publishing: $($_.Name)"; gi $_ } | del'
|
||||
displayName: 'Prevent publishing ARM/ARM64 packages'
|
||||
workingDirectory: '$(Build.BinariesDirectory)\nuget'
|
||||
condition: and(succeeded(), not(variables['PublishArmPackages']))
|
||||
|
||||
- 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,158 +0,0 @@
|
|||
jobs:
|
||||
- job: Publish_Python
|
||||
displayName: Publish python.org packages
|
||||
condition: and(succeeded(), and(eq(variables['DoMSI'], 'true'), eq(variables['DoEmbed'], 'true')))
|
||||
|
||||
pool:
|
||||
#vmImage: windows-2019
|
||||
name: 'Windows Release'
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- template: ./checkout.yml
|
||||
|
||||
- task: UsePythonVersion@0
|
||||
displayName: 'Use Python 3.6 or later'
|
||||
inputs:
|
||||
versionSpec: '>=3.6'
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: Doc'
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
inputs:
|
||||
artifactName: Doc
|
||||
targetPath: $(Build.BinariesDirectory)\Doc
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact: msi'
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
inputs:
|
||||
artifactName: msi
|
||||
targetPath: $(Build.BinariesDirectory)\msi
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: embed'
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
inputs:
|
||||
artifactName: embed
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact from $(BuildToPublish): Doc'
|
||||
condition: and(succeeded(), variables['BuildToPublish'])
|
||||
inputs:
|
||||
artifactName: Doc
|
||||
targetPath: $(Build.BinariesDirectory)\Doc
|
||||
buildType: specific
|
||||
project: cpython
|
||||
pipeline: 21
|
||||
buildVersionToDownload: specific
|
||||
buildId: $(BuildToPublish)
|
||||
|
||||
- task: DownloadPipelineArtifact@1
|
||||
displayName: 'Download artifact from $(BuildToPublish): msi'
|
||||
condition: and(succeeded(), variables['BuildToPublish'])
|
||||
inputs:
|
||||
artifactName: msi
|
||||
targetPath: $(Build.BinariesDirectory)\msi
|
||||
buildType: specific
|
||||
project: cpython
|
||||
pipeline: 21
|
||||
buildVersionToDownload: specific
|
||||
buildId: $(BuildToPublish)
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact from $(BuildToPublish): embed'
|
||||
condition: and(succeeded(), variables['BuildToPublish'])
|
||||
inputs:
|
||||
artifactName: embed
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
buildType: specific
|
||||
project: cpython
|
||||
pipeline: Windows-Release
|
||||
buildVersionToDownload: specific
|
||||
buildId: $(BuildToPublish)
|
||||
|
||||
- powershell: 'gci *embed-arm*.zip | %{ Write-Host "Not publishing: $($_.Name)"; gi $_ } | del'
|
||||
displayName: 'Prevent publishing ARM/ARM64 packages'
|
||||
workingDirectory: '$(Build.BinariesDirectory)\embed'
|
||||
condition: and(succeeded(), not(variables['PublishArmPackages']))
|
||||
|
||||
|
||||
- template: ./gpg-sign.yml
|
||||
parameters:
|
||||
GPGKeyFile: 'python-signing.key'
|
||||
Files: 'doc\htmlhelp\*.chm, msi\*\*, embed\*.zip'
|
||||
|
||||
- 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)
|
||||
displayName: 'Purge CDN'
|
||||
|
||||
- powershell: |
|
||||
$failures = 0
|
||||
gci "msi\*\*-webinstall.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: |
|
||||
$hashes = gci doc\htmlhelp\python*.chm, msi\*\*.exe, embed\*.zip | `
|
||||
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:"
|
||||
(gci msi\*\python*.asc, doc\htmlhelp\*.asc, embed\*.asc).FullName
|
||||
$d = mkdir "$(Build.ArtifactStagingDirectory)\hashes" -Force
|
||||
move msi\*\python*.asc, doc\htmlhelp\*.asc, embed\*.asc $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,35 +0,0 @@
|
|||
jobs:
|
||||
- job: Publish_Store
|
||||
displayName: Publish Store packages
|
||||
condition: and(succeeded(), eq(variables['DoMSIX'], 'true'))
|
||||
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: msixupload'
|
||||
condition: and(succeeded(), not(variables['BuildToPublish']))
|
||||
inputs:
|
||||
artifactName: msixupload
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: 'Download artifact: msixupload'
|
||||
condition: and(succeeded(), variables['BuildToPublish'])
|
||||
inputs:
|
||||
artifactName: msixupload
|
||||
downloadPath: $(Build.BinariesDirectory)
|
||||
buildType: specific
|
||||
project: cpython
|
||||
pipeline: Windows-Release
|
||||
buildVersionToDownload: specific
|
||||
buildId: $(BuildToPublish)
|
||||
|
||||
# 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 } | `
|
||||
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-2019
|
||||
|
||||
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-2019
|
||||
|
||||
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-2019
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
win32_User:
|
||||
ExeMatch: 'python-[\dabrc.]+-webinstall\.exe'
|
||||
Logs: $(Build.ArtifactStagingDirectory)\logs\win32_User
|
||||
InstallAllUsers: 0
|
||||
win32_Machine:
|
||||
ExeMatch: 'python-[\dabrc.]+-webinstall\.exe'
|
||||
Logs: $(Build.ArtifactStagingDirectory)\logs\win32_Machine
|
||||
InstallAllUsers: 1
|
||||
amd64_User:
|
||||
ExeMatch: 'python-[\dabrc.]+-amd64-webinstall\.exe'
|
||||
Logs: $(Build.ArtifactStagingDirectory)\logs\amd64_User
|
||||
InstallAllUsers: 0
|
||||
amd64_Machine:
|
||||
ExeMatch: 'python-[\dabrc.]+-amd64-webinstall\.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-2019
|
||||
|
||||
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'
|
||||
29
.cirrus-DISABLED.yml
Normal file
29
.cirrus-DISABLED.yml
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# gh-91960: Job disabled since Python is out of free credit (September 2023):
|
||||
# https://discuss.python.org/t/freebsd-gets-a-new-cirrus-ci-github-action-job-and-a-new-buildbot/33122/26
|
||||
|
||||
freebsd_task:
|
||||
freebsd_instance:
|
||||
matrix:
|
||||
- image: freebsd-13-2-release-amd64
|
||||
# Turn off TCP and UDP blackhole. It is not enabled by default in FreeBSD,
|
||||
# but it is in the FreeBSD GCE images as used by Cirrus-CI. It causes even
|
||||
# local local connections to fail with ETIMEDOUT instead of ECONNREFUSED.
|
||||
# For more information see https://reviews.freebsd.org/D41751 and
|
||||
# https://github.com/cirruslabs/cirrus-ci-docs/issues/483.
|
||||
sysctl_script:
|
||||
- sysctl net.inet.tcp.blackhole=0
|
||||
- sysctl net.inet.udp.blackhole=0
|
||||
configure_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --with-pydebug
|
||||
build_script:
|
||||
- cd build
|
||||
- make -j$(sysctl -n hw.ncpu)
|
||||
pythoninfo_script:
|
||||
- cd build
|
||||
- make pythoninfo
|
||||
test_script:
|
||||
- cd build
|
||||
# dtrace fails to build on FreeBSD - see gh-73263
|
||||
- make buildbottest TESTOPTS="-j0 -x test_dtrace --timeout=600"
|
||||
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:37
|
||||
|
||||
ENV CC=clang
|
||||
|
||||
ENV WASI_SDK_VERSION=20
|
||||
ENV WASI_SDK_PATH=/opt/wasi-sdk
|
||||
|
||||
ENV WASMTIME_HOME=/opt/wasmtime
|
||||
ENV WASMTIME_VERSION=14.0.4
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,5 +8,8 @@ indent_style = space
|
|||
[*.{py,c,cpp,h}]
|
||||
indent_size = 4
|
||||
|
||||
[*.rst]
|
||||
indent_size = 3
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
|
|
|
|||
101
.gitattributes
vendored
101
.gitattributes
vendored
|
|
@ -18,48 +18,34 @@
|
|||
*.zip binary
|
||||
|
||||
# Specific binary files
|
||||
Lib/test/sndhdrdata/sndhdr.* binary
|
||||
PC/classicAppCompat.* binary
|
||||
|
||||
# Text files that should not be subject to eol conversion
|
||||
Lib/test/cjkencodings/* -text
|
||||
Lib/test/decimaltestdata/*.decTest -text
|
||||
Lib/test/test_email/data/*.txt -text
|
||||
Lib/test/xmltestdata/* -text
|
||||
Lib/test/coding20731.py -text
|
||||
Lib/test/test_importlib/data01/* -text
|
||||
Lib/test/test_importlib/namespacedata01/* -text
|
||||
[attr]noeol -text
|
||||
|
||||
Lib/test/cjkencodings/* noeol
|
||||
Lib/test/tokenizedata/coding20731.py noeol
|
||||
Lib/test/decimaltestdata/*.decTest noeol
|
||||
Lib/test/test_email/data/*.txt 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
|
||||
*.bat text eol=crlf
|
||||
*.ps1 text eol=crlf
|
||||
*.sln text eol=crlf
|
||||
*.vcxproj* text eol=crlf
|
||||
*.props text eol=crlf
|
||||
*.proj text eol=crlf
|
||||
PCbuild/readme.txt text eol=crlf
|
||||
PC/readme.txt text eol=crlf
|
||||
[attr]dos text eol=crlf
|
||||
|
||||
# Generated files
|
||||
# https://github.com/github/linguist#generated-code
|
||||
Modules/clinic/*.h linguist-generated=true
|
||||
Objects/clinic/*.h linguist-generated=true
|
||||
PC/clinic/*.h linguist-generated=true
|
||||
Python/clinic/*.h linguist-generated=true
|
||||
Python/deepfreeze/*.c linguist-generated=true
|
||||
Python/frozen_modules/*.h linguist-generated=true
|
||||
Python/frozen_modules/MANIFEST linguist-generated=true
|
||||
Include/internal/pycore_ast.h linguist-generated=true
|
||||
Python/Python-ast.c linguist-generated=true
|
||||
Include/opcode.h linguist-generated=true
|
||||
Python/opcode_targets.h linguist-generated=true
|
||||
Objects/typeslots.inc linguist-generated=true
|
||||
*_db.h linguist-generated=true
|
||||
Doc/library/token-list.inc linguist-generated=true
|
||||
Include/token.h linguist-generated=true
|
||||
Lib/token.py linguist-generated=true
|
||||
Parser/token.c linguist-generated=true
|
||||
Programs/test_frozenmain.h linguist-generated=true
|
||||
*.bat dos
|
||||
*.proj dos
|
||||
*.props dos
|
||||
*.ps1 dos
|
||||
*.sln dos
|
||||
*.vcxproj* dos
|
||||
PC/readme.txt dos
|
||||
PCbuild/readme.txt dos
|
||||
|
||||
# Language aware diff headers
|
||||
# https://tekin.co.uk/2020/10/better-git-diff-output-for-ruby-python-elixir-and-more
|
||||
|
|
@ -70,3 +56,46 @@ Programs/test_frozenmain.h linguist-generated=true
|
|||
*.html diff=html
|
||||
*.py diff=python
|
||||
*.md diff=markdown
|
||||
|
||||
# Generated files
|
||||
# https://github.com/github/linguist/blob/master/docs/overrides.md
|
||||
#
|
||||
# To always hide generated files in local diffs, mark them as binary:
|
||||
# $ git config diff.generated.binary true
|
||||
#
|
||||
[attr]generated linguist-generated=true diff=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/opcode.h generated
|
||||
Include/opcode_ids.h generated
|
||||
Include/token.h generated
|
||||
Lib/_opcode_metadata.py generated
|
||||
Lib/keyword.py 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/opcode_targets.h generated
|
||||
Python/stdlib_module_names.h generated
|
||||
Tools/peg_generator/pegen/grammar_parser.py generated
|
||||
aclocal.m4 generated
|
||||
configure generated
|
||||
|
|
|
|||
122
.github/CODEOWNERS
vendored
122
.github/CODEOWNERS
vendored
|
|
@ -4,31 +4,59 @@
|
|||
# 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
|
||||
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
|
||||
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
|
||||
|
||||
# Exceptions
|
||||
Lib/traceback.py @iritkatriel
|
||||
Lib/test/test_except*.py @iritkatriel
|
||||
Lib/test/test_traceback.py @iritkatriel
|
||||
Objects/exceptions.c @iritkatriel
|
||||
Python/traceback.c @iritkatriel
|
||||
|
||||
# Hashing
|
||||
**/*hashlib* @python/crypto-team @tiran
|
||||
**/*pyhash* @python/crypto-team @tiran
|
||||
**/*sha* @python/crypto-team @tiran
|
||||
**/*md5* @python/crypto-team @tiran
|
||||
**/*blake* @python/crypto-team @tiran
|
||||
/Modules/_blake2/** @python/crypto-team @tiran
|
||||
/Modules/_sha3/** @python/crypto-team @tiran
|
||||
**/*hashlib* @tiran
|
||||
**/*pyhash* @tiran
|
||||
**/*sha* @tiran
|
||||
**/*md5* @tiran
|
||||
**/*blake* @tiran
|
||||
/Modules/_blake2/** @tiran
|
||||
/Modules/_sha3/** @tiran
|
||||
|
||||
# logging
|
||||
**/*logging* @vsajip
|
||||
|
|
@ -43,21 +71,13 @@ Python/ast_opt.c @isidentical
|
|||
/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
|
||||
|
||||
|
||||
# SSL
|
||||
**/*ssl* @python/crypto-team
|
||||
**/*.pem @python/crypto-team
|
||||
|
||||
# CSPRNG
|
||||
Python/bootstrap_hash.c @python/crypto-team
|
||||
**/*import* @brettcannon @ericsnowcurrently @ncoghlan @warsaw
|
||||
/Python/import.c @kumaraditya303
|
||||
**/*importlib/resources/* @jaraco @warsaw @FFY00
|
||||
**/importlib/metadata/* @jaraco @warsaw
|
||||
|
||||
# Dates and times
|
||||
**/*datetime* @pganssle @abalkin
|
||||
|
|
@ -66,7 +86,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
|
||||
|
|
@ -84,6 +104,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
|
||||
|
|
@ -93,16 +118,22 @@ Lib/ast.py @isidentical
|
|||
|
||||
# Mock
|
||||
/Lib/unittest/mock.py @cjw296
|
||||
/Lib/unittest/test/testmock/* @cjw296
|
||||
/Lib/test/test_unittest/testmock/* @cjw296
|
||||
|
||||
# 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
|
||||
|
|
@ -122,16 +153,16 @@ Lib/ast.py @isidentical
|
|||
**/*bisect* @rhettinger
|
||||
**/*heapq* @rhettinger
|
||||
**/*functools* @rhettinger
|
||||
**/*decimal* @rhettinger @skrah
|
||||
**/*decimal* @rhettinger
|
||||
|
||||
**/*dataclasses* @ericvsmith
|
||||
|
||||
**/*ensurepip* @pfmoore @pradyunsg
|
||||
|
||||
**/*idlelib* @terryjreedy
|
||||
|
||||
**/*typing* @gvanrossum @Fidget-Spinner
|
||||
**/*typing* @JelleZijlstra @AlexWaygood
|
||||
|
||||
**/*asyncore @giampaolo
|
||||
**/*asynchat @giampaolo
|
||||
**/*ftplib @giampaolo
|
||||
**/*shutil @giampaolo
|
||||
|
||||
|
|
@ -139,6 +170,35 @@ Lib/ast.py @isidentical
|
|||
**/*cgi* @ethanfurman
|
||||
**/*tarfile* @ethanfurman
|
||||
|
||||
**/*tomllib* @encukou @hauntsaninja
|
||||
|
||||
**/*sysconfig* @FFY00
|
||||
|
||||
**/*cjkcodecs* @corona10
|
||||
|
||||
# macOS
|
||||
/Mac/ @python/macos-team
|
||||
**/*osx_support* @python/macos-team
|
||||
|
||||
# pathlib
|
||||
**/*pathlib* @barneygale
|
||||
|
||||
# zipfile.Path
|
||||
**/*zipfile/_path/* @jaraco
|
||||
|
||||
# Argument Clinic
|
||||
/Tools/clinic/** @erlend-aasland @AlexWaygood
|
||||
/Lib/test/test_clinic.py @erlend-aasland @AlexWaygood
|
||||
Doc/howto/clinic.rst @erlend-aasland
|
||||
|
||||
# Subinterpreters
|
||||
Lib/test/support/interpreters/ @ericsnowcurrently
|
||||
Modules/_xx*interp*module.c @ericsnowcurrently
|
||||
Lib/test/test_interpreters/ @ericsnowcurrently
|
||||
|
||||
# WebAssembly
|
||||
/Tools/wasm/ @brettcannon
|
||||
|
||||
# SBOM
|
||||
/Misc/sbom.spdx.json @sethmlarson
|
||||
/Tools/build/generate_sbom.py @sethmlarson
|
||||
|
|
|
|||
20
.github/CONTRIBUTING.rst
vendored
20
.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,13 +26,13 @@ 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:
|
||||
|
||||
- All discussions that are not directly related to the code in the pull request
|
||||
should happen on bugs.python.org
|
||||
should happen on `GitHub Issues <https://github.com/python/cpython/issues>`_.
|
||||
- Upon your first non-trivial pull request (which includes documentation changes),
|
||||
feel free to add yourself to ``Misc/ACKS``
|
||||
|
||||
|
|
|
|||
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
|
|
@ -1,2 +0,0 @@
|
|||
custom: https://www.python.org/psf/donations/python-dev/
|
||||
github: [python]
|
||||
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
|
||||
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
contact_links:
|
||||
- name: "Getting help"
|
||||
about: "Ask questions about using Python and debugging errors on Discourse."
|
||||
url: "https://discuss.python.org/c/users/7"
|
||||
- name: "Proposing new features"
|
||||
about: "Submit major feature proposal (e.g. syntax changes) to an ideas forum first."
|
||||
url: "https://discuss.python.org/c/ideas/6"
|
||||
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
|
||||
9
.github/ISSUE_TEMPLATE/documentation.md
vendored
Normal file
9
.github/ISSUE_TEMPLATE/documentation.md
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: Documentation
|
||||
about: Report a problem with the documentation
|
||||
labels: "docs"
|
||||
---
|
||||
|
||||
# Documentation
|
||||
|
||||
(A clear and concise description of the issue.)
|
||||
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
|
||||
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
|
@ -7,10 +7,10 @@ Please read this comment in its entirety. It's quite important.
|
|||
It should be in the following format:
|
||||
|
||||
```
|
||||
bpo-NNNN: Summary of the changes made
|
||||
gh-NNNNN: Summary of the changes made
|
||||
```
|
||||
|
||||
Where: bpo-NNNN refers to the issue number in the https://bugs.python.org.
|
||||
Where: gh-NNNNN refers to the GitHub issue number.
|
||||
|
||||
Most PRs will require an issue number. Trivial changes, like fixing a typo, do not need an issue.
|
||||
|
||||
|
|
|
|||
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', '')}`
|
||||
});
|
||||
}
|
||||
519
.github/workflows/build.yml
vendored
519
.github/workflows/build.yml
vendored
|
|
@ -1,6 +1,6 @@
|
|||
name: Tests
|
||||
|
||||
# bpo-40548: "paths-ignore" is not used to skip documentation-only PRs, because
|
||||
# gh-84728: "paths-ignore" is not used to skip documentation-only PRs, because
|
||||
# it prevents to mark a job as mandatory. A PR cannot be merged if a job is
|
||||
# mandatory but not scheduled because of "paths-ignore".
|
||||
on:
|
||||
|
|
@ -8,33 +8,45 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- '3.12'
|
||||
- '3.11'
|
||||
- '3.10'
|
||||
- '3.9'
|
||||
- '3.8'
|
||||
- '3.7'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
- '3.12'
|
||||
- '3.11'
|
||||
- '3.10'
|
||||
- '3.9'
|
||||
- '3.8'
|
||||
- '3.7'
|
||||
|
||||
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,24 +62,101 @@ 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.2.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: Restore config.cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: config.cache
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }}-${{ env.pythonLocation }}
|
||||
- name: Install Dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: Build CPython
|
||||
- name: Add ccache to PATH
|
||||
run: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
- name: Check Autoconf and aclocal versions
|
||||
run: |
|
||||
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
|
||||
./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: |
|
||||
make -j4 regen-all
|
||||
make regen-stdlib-module-names
|
||||
- name: Check for changes
|
||||
|
|
@ -75,131 +164,103 @@ jobs:
|
|||
git add -u
|
||||
changes=$(git status --porcelain)
|
||||
# Check for changes in regenerated files
|
||||
if ! test -z "$changes"
|
||||
then
|
||||
echo "Generated files not up to date. Perhaps you forgot to run make regen-all or build.bat --regen ;)"
|
||||
if test -n "$changes"; then
|
||||
echo "Generated files not up to date."
|
||||
echo "Perhaps you forgot to run make regen-all or build.bat --regen. ;)"
|
||||
echo "configure files must be regenerated with a specific version of autoconf."
|
||||
echo "$changes"
|
||||
echo ""
|
||||
git diff --staged || true
|
||||
exit 1
|
||||
fi
|
||||
- name: Check exported libpython symbols
|
||||
run: make smelly
|
||||
- name: Check limited ABI symbols
|
||||
run: make check-limited-abi
|
||||
- name: Check Autoconf version 2.69
|
||||
run: |
|
||||
grep "Generated by GNU Autoconf 2.69" configure
|
||||
grep "PKG_PROG_PKG_CONFIG" aclocal.m4
|
||||
- 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'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build CPython
|
||||
run: .\PCbuild\build.bat -e -p Win32
|
||||
- name: Display build info
|
||||
run: .\python.bat -m test.pythoninfo
|
||||
- name: Tests
|
||||
run: .\PCbuild\rt.bat -p Win32 -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'
|
||||
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 -p x64
|
||||
- name: Display build info
|
||||
run: .\python.bat -m test.pythoninfo
|
||||
- name: Tests
|
||||
run: .\PCbuild\rt.bat -p x64 -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 }}
|
||||
|
||||
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
|
||||
|
||||
build_ubuntu:
|
||||
name: 'Ubuntu'
|
||||
runs-on: ubuntu-20.04
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
env:
|
||||
OPENSSL_VER: 1.1.1l
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
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.6
|
||||
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
|
||||
- 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: Tests
|
||||
run: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu"
|
||||
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-20.04
|
||||
timeout-minutes: 60
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true' && needs.check_source.outputs.run_ssl_tests == 'true'
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
openssl_ver: [1.1.1l, 3.0.0]
|
||||
openssl_ver: [1.1.1w, 3.0.11, 3.1.3]
|
||||
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
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore config.cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: config.cache
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }}
|
||||
- name: Register gcc problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
|
||||
- name: Install Dependencies
|
||||
|
|
@ -211,7 +272,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.6
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
|
||||
|
|
@ -222,9 +283,9 @@ 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
|
||||
- name: Configure CPython
|
||||
run: ./configure --with-pydebug --with-openssl=$OPENSSL_DIR
|
||||
run: ./configure --config-cache --with-pydebug --with-openssl=$OPENSSL_DIR
|
||||
- name: Build CPython
|
||||
run: make -j4
|
||||
- name: Display build info
|
||||
|
|
@ -232,18 +293,17 @@ jobs:
|
|||
- name: SSL tests
|
||||
run: ./python Lib/test/ssltests.py
|
||||
|
||||
|
||||
build_asan:
|
||||
name: 'Address sanitizer'
|
||||
test_hypothesis:
|
||||
name: "Hypothesis tests on Ubuntu"
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 60
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
if: needs.check_source.outputs.run_tests == 'true' && needs.check_source.outputs.run_hypothesis == 'true'
|
||||
env:
|
||||
OPENSSL_VER: 1.1.1l
|
||||
OPENSSL_VER: 3.0.11
|
||||
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: Register gcc problem matcher
|
||||
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
|
||||
- name: Install Dependencies
|
||||
|
|
@ -255,7 +315,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.6
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
|
||||
|
|
@ -266,12 +326,239 @@ 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
|
||||
- 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: Restore config.cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.CPYTHON_BUILDDIR }}/config.cache
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ needs.check_source.outputs.config_hash }}
|
||||
- name: Configure CPython out-of-tree
|
||||
working-directory: ${{ env.CPYTHON_BUILDDIR }}
|
||||
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
|
||||
- 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: 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: |
|
||||
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@v3
|
||||
with:
|
||||
path: ./hypothesis
|
||||
key: hypothesis-database-${{ github.head_ref || github.run_id }}
|
||||
restore-keys: |
|
||||
- hypothesis-database-
|
||||
- name: "Run tests"
|
||||
working-directory: ${{ env.CPYTHON_BUILDDIR }}
|
||||
run: |
|
||||
# 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
|
||||
timeout-minutes: 60
|
||||
needs: check_source
|
||||
if: needs.check_source.outputs.run_tests == 'true'
|
||||
env:
|
||||
OPENSSL_VER: 3.0.11
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore config.cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: config.cache
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ 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
|
||||
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@v3
|
||||
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
|
||||
- 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 -x test_ctypes test_crypt test_decimal test_faulthandler test_interpreters test___all__ test_idle test_tix test_tk test_ttk_guionly test_ttk_textonly test_multiprocessing_fork test_multiprocessing_forkserver test_multiprocessing_spawn"
|
||||
run: xvfb-run make test
|
||||
|
||||
# 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_windows
|
||||
- build_windows_free_threading
|
||||
- test_hypothesis
|
||||
- build_asan
|
||||
- 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_windows,
|
||||
build_windows_free_threading,
|
||||
build_asan,
|
||||
'
|
||||
|| ''
|
||||
}}
|
||||
${{
|
||||
!fromJSON(needs.check_source.outputs.run_cifuzz)
|
||||
&& '
|
||||
cifuzz,
|
||||
'
|
||||
|| ''
|
||||
}}
|
||||
${{
|
||||
!fromJSON(needs.check_source.outputs.run_hypothesis)
|
||||
&& '
|
||||
test_hypothesis,
|
||||
'
|
||||
|| ''
|
||||
}}
|
||||
jobs: ${{ toJSON(needs) }}
|
||||
|
|
|
|||
39
.github/workflows/build_msi.yml
vendored
39
.github/workflows/build_msi.yml
vendored
|
|
@ -5,35 +5,34 @@ 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]
|
||||
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
|
||||
run: .\Tools\msi\build.bat --doc -${{ matrix.type }}
|
||||
|
|
|
|||
47
.github/workflows/doc.yml
vendored
47
.github/workflows/doc.yml
vendored
|
|
@ -1,47 +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
|
||||
- name: 'Build documentation'
|
||||
run: xvfb-run make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W --keep-going -j4" doctest html
|
||||
- name: 'Upload'
|
||||
uses: actions/upload-artifact@v2.2.4
|
||||
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"
|
||||
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.0
|
||||
55
.github/workflows/mypy.yml
vendored
Normal file
55
.github/workflows/mypy.yml
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# 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/test/libregrtest/**"
|
||||
- "Tools/build/generate_sbom.py"
|
||||
- "Tools/cases_generator/**"
|
||||
- "Tools/clinic/**"
|
||||
- "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:
|
||||
matrix:
|
||||
target: [
|
||||
"Lib/test/libregrtest",
|
||||
"Tools/build/",
|
||||
"Tools/cases_generator",
|
||||
"Tools/clinic",
|
||||
"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
|
||||
60
.github/workflows/new-bugs-announce-notifier.yml
vendored
Normal file
60
.github/workflows/new-bugs-announce-notifier.yml
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
name: new-bugs-announce notifier
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
|
||||
permissions:
|
||||
issues: read
|
||||
|
||||
jobs:
|
||||
notify-new-bugs-announce:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: npm install mailgun.js form-data
|
||||
- name: Send notification
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
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 = "mailgun.python.org";
|
||||
const mg = mailgun.client({username: 'api', key: process.env.MAILGUN_API_KEY});
|
||||
github.rest.issues.get({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
.then(function(issue) {
|
||||
const payload = {
|
||||
author : issue.data.user.login,
|
||||
issue : issue.data.number,
|
||||
title : issue.data.title,
|
||||
url : issue.data.html_url,
|
||||
labels : issue.data.labels.map(label => { return label.name }).join(", "),
|
||||
assignee : issue.data.assignees.map(assignee => { return assignee.login }),
|
||||
// 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@mailgun.python.org>",
|
||||
to: "new-bugs-announce@python.org",
|
||||
subject: `[Issue ${issue.data.number}] ${issue.data.title}`,
|
||||
template: "new-github-issue",
|
||||
'o:tracking-clicks': 'no',
|
||||
'h:X-Mailgun-Variables': JSON.stringify(payload)
|
||||
};
|
||||
return mg.messages.create(DOMAIN, data)
|
||||
})
|
||||
.then(msg => console.log(msg));
|
||||
4
.github/workflows/posix-deps-apt.sh
vendored
4
.github/workflows/posix-deps-apt.sh
vendored
|
|
@ -1,12 +1,15 @@
|
|||
#!/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 \
|
||||
libb2-dev \
|
||||
libbz2-dev \
|
||||
libffi-dev \
|
||||
libgdbm-dev \
|
||||
|
|
@ -18,6 +21,7 @@ apt-get -yq install \
|
|||
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@v0.1.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
|
||||
22
.github/workflows/require-pr-label.yml
vendored
Normal file
22
.github/workflows/require-pr-label.yml
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
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
|
||||
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"
|
||||
108
.github/workflows/reusable-docs.yml
vendored
Normal file
108
.github/workflows/reusable-docs.yml
vendored
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
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
|
||||
|
||||
# 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.11' # known to work with Sphinx 4.2
|
||||
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@v3
|
||||
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
|
||||
46
.github/workflows/reusable-macos.yml
vendored
Normal file
46
.github/workflows/reusable-macos.yml
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
config_hash:
|
||||
required: true
|
||||
type: string
|
||||
free-threading:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build_macos:
|
||||
name: 'build and test'
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
HOMEBREW_NO_ANALYTICS: 1
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
HOMEBREW_NO_INSTALL_CLEANUP: 1
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore config.cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: config.cache
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ 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 -j4
|
||||
- name: Display build info
|
||||
run: make pythoninfo
|
||||
- name: Tests
|
||||
run: make test
|
||||
71
.github/workflows/reusable-ubuntu.yml
vendored
Normal file
71
.github/workflows/reusable-ubuntu.yml
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
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-20.04
|
||||
env:
|
||||
OPENSSL_VER: 3.0.11
|
||||
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@v3
|
||||
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
|
||||
- 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: Restore config.cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.CPYTHON_BUILDDIR }}/config.cache
|
||||
key: ${{ github.job }}-${{ runner.os }}-${{ 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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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' || '' }}
|
||||
10
.github/workflows/stale.yml
vendored
10
.github/workflows/stale.yml
vendored
|
|
@ -9,14 +9,20 @@ permissions:
|
|||
|
||||
jobs:
|
||||
stale:
|
||||
if: github.repository_owner == 'python'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v4
|
||||
- name: "Check PRs"
|
||||
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
|
||||
25
.gitignore
vendored
25
.gitignore
vendored
|
|
@ -5,11 +5,14 @@
|
|||
*.cover
|
||||
*.iml
|
||||
*.o
|
||||
*.lto
|
||||
*.a
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
*.dSYM
|
||||
*.dll
|
||||
*.wasm
|
||||
*.orig
|
||||
*.pyc
|
||||
*.pyd
|
||||
|
|
@ -20,6 +23,10 @@
|
|||
*.gc??
|
||||
*.profclang?
|
||||
*.profraw
|
||||
# Copies of binaries before BOLT optimizations.
|
||||
*.prebolt
|
||||
# BOLT profile data.
|
||||
*.fdata
|
||||
*.dyn
|
||||
.gdb_history
|
||||
.purify
|
||||
|
|
@ -35,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
|
||||
|
|
@ -55,8 +62,8 @@ 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/*
|
||||
!Lib/test/data/README
|
||||
/_bootstrap_python
|
||||
|
|
@ -74,8 +81,10 @@ Mac/pythonw
|
|||
Misc/python.pc
|
||||
Misc/python-embed.pc
|
||||
Misc/python-config.sh
|
||||
Modules/Setup.bootstrap
|
||||
Modules/Setup.config
|
||||
Modules/Setup.local
|
||||
Modules/Setup.stdlib
|
||||
Modules/config.c
|
||||
Modules/ld_so_aix
|
||||
Programs/_freeze_module
|
||||
|
|
@ -109,13 +118,18 @@ 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/
|
||||
/platform
|
||||
/profile-clean-stamp
|
||||
/profile-run-stamp
|
||||
/profile-bolt-stamp
|
||||
/Python/deepfreeze/*.c
|
||||
/pybuilddir.txt
|
||||
/pyconfig.h
|
||||
|
|
@ -134,7 +148,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
|
||||
|
|
@ -143,3 +157,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>
|
||||
36
.pre-commit-config.yaml
Normal file
36
.pre-commit-config.yaml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.1.7
|
||||
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/pre-commit/pre-commit-hooks
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
- 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/next/
|
||||
|
||||
- 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
|
||||
|
||||
169
.travis.yml
169
.travis.yml
|
|
@ -1,169 +0,0 @@
|
|||
language: c
|
||||
dist: bionic
|
||||
|
||||
# To cache doc-building dependencies and C compiler output.
|
||||
cache:
|
||||
- pip
|
||||
- ccache
|
||||
- directories:
|
||||
- $HOME/multissl
|
||||
|
||||
env:
|
||||
global:
|
||||
- OPENSSL=1.1.1k
|
||||
- OPENSSL_DIR="$HOME/multissl/openssl/${OPENSSL}"
|
||||
- PATH="${OPENSSL_DIR}/bin:$PATH"
|
||||
- CFLAGS="-I${OPENSSL_DIR}/include"
|
||||
- LDFLAGS="-L${OPENSSL_DIR}/lib"
|
||||
# Set rpath with env var instead of -Wl,-rpath linker flag
|
||||
# OpenSSL ignores LDFLAGS when linking bin/openssl
|
||||
- LD_RUN_PATH="${OPENSSL_DIR}/lib"
|
||||
- PYTHONSTRICTEXTENSIONBUILD=1
|
||||
|
||||
branches:
|
||||
only:
|
||||
- main
|
||||
- /^\d\.\d+$/
|
||||
- buildbot-custom
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- env: OPTIONAL=true
|
||||
include:
|
||||
- name: "CPython tests"
|
||||
os: linux
|
||||
language: c
|
||||
compiler: clang
|
||||
# gcc also works, but to keep the # of concurrent builds down, we use one C
|
||||
# compiler here and the other to run the coverage build. Clang is preferred
|
||||
# in this instance for its better error messages.
|
||||
env: TESTING=cpython
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gdb
|
||||
- xvfb
|
||||
- name: "Documentation build"
|
||||
os: linux
|
||||
language: python
|
||||
# Build the docs against a stable version of Python so code bugs don't hold up doc-related PRs.
|
||||
python: 3.6
|
||||
env: TESTING=docs
|
||||
before_script:
|
||||
- cd Doc
|
||||
- make venv PYTHON=python
|
||||
script:
|
||||
- make check html SPHINXOPTS="-q -W -j4"
|
||||
- name: "Documentation tests"
|
||||
os: linux
|
||||
language: c
|
||||
compiler: clang
|
||||
env: TESTING=doctest
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- xvfb
|
||||
before_script:
|
||||
- ./configure
|
||||
- make -j4
|
||||
- make -C Doc/ PYTHON=../python venv
|
||||
script:
|
||||
xvfb-run make -C Doc/ PYTHON=../python SPHINXOPTS="-q -W -j4" doctest
|
||||
|
||||
|
||||
before_install:
|
||||
- set -e
|
||||
- |
|
||||
# Check short-circuit conditions
|
||||
if [[ "${TESTING}" != "docs" && "${TESTING}" != "doctest" ]]
|
||||
then
|
||||
if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]
|
||||
then
|
||||
echo "Not a PR, doing full build."
|
||||
else
|
||||
# Pull requests are slightly complicated because $TRAVIS_COMMIT_RANGE
|
||||
# may include more changes than desired if the history is convoluted.
|
||||
# Instead, explicitly fetch the base branch and compare against the
|
||||
# merge-base commit.
|
||||
git fetch -q origin +refs/heads/$TRAVIS_BRANCH
|
||||
changes=$(git diff --name-only HEAD $(git merge-base HEAD FETCH_HEAD))
|
||||
echo "Files changed:"
|
||||
echo "$changes"
|
||||
if ! echo "$changes" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)'
|
||||
then
|
||||
echo "Only docs were updated, stopping build process."
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
install:
|
||||
- |
|
||||
# Install OpenSSL as necessary
|
||||
# Note: doctest needs OpenSSL
|
||||
if [[ "${TESTING}" != "docs" ]]
|
||||
then
|
||||
# clang complains about unused-parameter a lot, redirect stderr
|
||||
python3 Tools/ssl/multissltests.py --steps=library \
|
||||
--base-directory ${HOME}/multissl \
|
||||
--openssl ${OPENSSL} >/dev/null 2>&1
|
||||
fi
|
||||
- openssl version
|
||||
|
||||
# Travis provides only 2 cores, so don't overdo the parallelism and waste memory.
|
||||
before_script:
|
||||
# -Og is much faster than -O0
|
||||
- CFLAGS="${CFLAGS} -Og" ./configure --with-pydebug
|
||||
- eval "$(pyenv init -)"
|
||||
- pyenv global 3.8
|
||||
- PYTHON_FOR_REGEN=python3.8 make -j4 regen-all
|
||||
- make regen-stdlib-module-names
|
||||
- changes=`git status --porcelain`
|
||||
- |
|
||||
# Check for changes in regenerated files
|
||||
if ! test -z "$changes"
|
||||
then
|
||||
echo "Generated files not up to date"
|
||||
echo "$changes"
|
||||
exit 1
|
||||
fi
|
||||
- make -j4
|
||||
- make pythoninfo
|
||||
|
||||
script:
|
||||
# Using the built Python as patchcheck.py is built around the idea of using
|
||||
# a checkout-build of CPython to know things like what base branch the changes
|
||||
# should be compared against.
|
||||
# Only run on Linux as the check only needs to be run once.
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./python Tools/scripts/patchcheck.py --travis $TRAVIS_PULL_REQUEST; fi
|
||||
# Check that all symbols exported by libpython start with "Py" or "_Py"
|
||||
- make smelly
|
||||
# Check that all symbols in the limited abi are present
|
||||
- make check-limited-abi
|
||||
# `-r -w` implicitly provided through `make buildbottest`.
|
||||
- |
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
XVFB_RUN=xvfb-run;
|
||||
fi
|
||||
$XVFB_RUN make buildbottest TESTOPTS="-j4 -uall,-cpu"
|
||||
notifications:
|
||||
email: false
|
||||
irc:
|
||||
channels:
|
||||
# This is set to a secure variable to prevent forks from notifying the
|
||||
# IRC channel whenever they fail a build. This can be removed when travis
|
||||
# implements https://github.com/travis-ci/travis-ci/issues/1094.
|
||||
# The actual value here is: irc.freenode.net#python-dev
|
||||
- secure: "s7kAkpcom2yUJ8XqyjFI0obJmhAGrn1xmoivdaPdgBIA++X47TBp1x4pgDsbEsoalef7bEwa4l07KdT4qa+DOd/c4QxaWom7fbN3BuLVsZuVfODnl79+gYq/TAbGfyH+yDs18DXrUfPgwD7C5aW32ugsqAOd4iWzfGJQ5OrOZzqzGjYdYQUEkJFXgxDEIb4aHvxNDWGO3Po9uKISrhb5saQ0l776yLo1Ur7M4oxl8RTbCdgX0vf5TzPg52BgvZpOgt3DHOUYPeiJLKNjAE6ibg0U95sEvMfHX77nz4aFY4/3UI6FFaRla34rZ+mYKrn0TdxOhera1QOgPmM6HzdO4K44FpfK1DS0Xxk9U9/uApq+cG0bU3W+cVUHDBe5+90lpRBAXHeHCgT7TI8gec614aiT8lEr3+yH8OBRYGzkjNK8E2LJZ/SxnVxDe7aLF6AWcoWLfS6/ziAIBFQ5Nc4U72CT8fGVSkl8ywPiRlvixKdvTODMSZo0jMqlfZSNaAPTsNRx4wu5Uis4qekwe32Fz4aB6KGpsuuVjBi+H6v0RKxNJNGY3JKDiEH2TK0UE2auJ5GvLW48aUVFcQMB7euCWYXlSWVRHh3WLU8QXF29Dw4JduRZqUpOdRgMHU79UHRq+mkE0jAS/nBcS6CvsmxCpTSrfVYuMOu32yt18QQoTyU="
|
||||
on_success: change
|
||||
on_failure: always
|
||||
skip_join: true
|
||||
webhooks:
|
||||
urls:
|
||||
# For the same reasons as above for IRC, we encrypt the webhook address
|
||||
# for Zulip. The actual value is:
|
||||
# https://python.zulipchat.com/api/v1/external/travis?api_key=<api-key-redacted>&stream=core%2Ftest+runs
|
||||
- secure: "vLz2TodSL7wQ8DsIu86koRS9i4dsK40PH8+wzY93PBCCAzJAz113LTxK3/9PamMv+ObDRUSe5OpXcquE3d5Gwpu8IymF113qK0I3uNr+O3FtmKlj/Kd1P/V+z4pTpS3zh3lW9gyKV9EMWXIWS0IYKKZQU144XqUlIiucWK2jHJF/cSz2cRAx/6Kx68X4mZwEC7hiMOF4ZsWUMbCglM89ybeS0pr0kK9mmh88qsPyRQov3mRKswmVPlePk7clVLNAL43qSe3SzmrmACZfQ9KJYmpYnr/cjo2b6svYHcQBAwAUarZZ9KBMXeV7HwGWsSXAvHH2ynR0P++braBHGEMTGMSitdVWzFTmeiHnrkp08WAB+uFs54iEx3VklTk9bCzozTm2S94TRxbrsG9SypMvQxG570JV6P2XYuR+taCb/GMtMqrtGQm2e1Ht+nDLtiUb+/+rwEbicJJ13knptOQZI4tPOZESI/kXkORkSNwFfLSNLSl9jTlMmO7KjAAPApURHEdx26RbItAn8mIX2NcHTRjKn2qV4h3C54nmHmKWn/ZudHHJc6ieZSEUBoaLGAYmcWJRqrM6jiy2h9I9TRrCKAiGh5jT47FYKLwosTtV245l/ZhDb6eTVfEFT6TSLEoyfx9cCtTUvfMtXYl8eN9wlFYYpH8MSWbMD14eEkKBTWg="
|
||||
on_success: change
|
||||
on_failure: always
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
# Code of Conduct
|
||||
|
||||
Please note that all interactions on
|
||||
[Python Software Foundation](https://www.python.org/psf-landing/)-supported
|
||||
infrastructure is [covered](https://www.python.org/psf/records/board/minutes/2014-01-06/#management-of-the-psfs-web-properties)
|
||||
by the [PSF Code of Conduct](https://www.python.org/psf/codeofconduct/),
|
||||
which includes all the infrastructure used in the development of Python itself
|
||||
(e.g. mailing lists, issue trackers, GitHub, etc.).
|
||||
|
||||
In general, this means that everyone is expected to be **open**, **considerate**, and
|
||||
**respectful** of others no matter what their position is within the project.
|
||||
|
||||
68
Doc/Makefile
68
Doc/Makefile
|
|
@ -8,28 +8,32 @@ PYTHON = python3
|
|||
VENVDIR = ./venv
|
||||
SPHINXBUILD = PATH=$(VENVDIR)/bin:$$PATH sphinx-build
|
||||
BLURB = PATH=$(VENVDIR)/bin:$$PATH blurb
|
||||
JOBS = auto
|
||||
PAPER =
|
||||
SOURCES =
|
||||
DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py)
|
||||
REQUIREMENTS = requirements.txt
|
||||
SPHINXERRORHANDLING = -W
|
||||
|
||||
# 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 " 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"
|
||||
|
|
@ -41,10 +45,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
|
||||
|
|
@ -71,38 +74,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) || { \
|
||||
|
|
@ -110,18 +121,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; }
|
||||
|
||||
.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) || { \
|
||||
|
|
@ -129,31 +134,42 @@ 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"
|
||||
|
||||
.PHONY: htmlview
|
||||
htmlview: html
|
||||
$(PYTHON) -c "import webbrowser; webbrowser.open('build/html/index.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 \
|
||||
$(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
|
||||
|
|
@ -208,12 +224,14 @@ dist:
|
|||
rm -r dist/python-$(DISTVERSION)-docs-texinfo
|
||||
rm dist/python-$(DISTVERSION)-docs-texinfo.tar
|
||||
|
||||
check:
|
||||
$(PYTHON) tools/rstlint.py -i tools -i $(VENVDIR) -i README.rst
|
||||
$(PYTHON) tools/rstlint.py ../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
|
||||
@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.
|
||||
|
|
@ -223,15 +241,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."; \
|
||||
|
|
@ -239,6 +260,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).
|
||||
|
||||
|
|
@ -91,10 +91,7 @@ Available make targets are:
|
|||
|
||||
* "pydoc-topics", which builds a Python module containing a dictionary with
|
||||
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.
|
||||
``tools/pyspecific.py`` -- pydoc needs these to show topic and keyword help.
|
||||
|
||||
* "check", which checks for frequent markup errors.
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
46
Doc/bugs.rst
46
Doc/bugs.rst
|
|
@ -19,6 +19,9 @@ 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'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,43 +38,48 @@ 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/documentation/translating/>`_
|
||||
A list of GitHub pages for documentation translation and their primary contacts.
|
||||
|
||||
|
||||
.. _using-the-tracker:
|
||||
|
||||
Using the Python issue tracker
|
||||
==============================
|
||||
|
||||
Bug reports for Python itself should be submitted via the Python Bug Tracker
|
||||
(https://bugs.python.org/). The bug tracker offers a web form which allows
|
||||
pertinent information to be entered and submitted to the developers.
|
||||
Issue reports for Python itself should be submitted via the GitHub issues
|
||||
tracker (https://github.com/python/cpython/issues).
|
||||
The GitHub issues tracker offers a web form which allows pertinent information
|
||||
to be entered and submitted to the developers.
|
||||
|
||||
The first step in filing a report is to determine whether the problem has
|
||||
already been reported. The advantage in doing so, aside from saving the
|
||||
developers time, is that you learn what has been done to fix it; it may be that
|
||||
developers' time, is that you learn what has been done to fix it; it may be that
|
||||
the problem has already been fixed for the next release, or additional
|
||||
information is needed (in which case you are welcome to provide it if you can!).
|
||||
To do this, search the bug database using the search box on the top of the page.
|
||||
To do this, search the tracker using the search box at the top of the page.
|
||||
|
||||
If the problem you're reporting is not already in the bug tracker, go back to
|
||||
the Python Bug Tracker and log in. If you don't already have a tracker account,
|
||||
select the "Register" link or, if you use OpenID, one of the OpenID provider
|
||||
logos in the sidebar. It is not possible to submit a bug report anonymously.
|
||||
If the problem you're reporting is not already in the list, log in to GitHub.
|
||||
If you don't already have a GitHub account, create a new account using the
|
||||
"Sign up" link.
|
||||
It is not possible to submit a bug report anonymously.
|
||||
|
||||
Being now logged in, you can submit a bug. Select the "Create New" link in the
|
||||
sidebar to open the bug reporting form.
|
||||
Being now logged in, you can submit an issue.
|
||||
Click on the "New issue" button in the top bar to report a new issue.
|
||||
|
||||
The submission form has a number of fields. For the "Title" field, enter a
|
||||
*very* short description of the problem; less than ten words is good. In the
|
||||
"Type" field, select the type of your problem; also select the "Component" and
|
||||
"Versions" to which the bug relates.
|
||||
The submission form has two fields, "Title" and "Comment".
|
||||
|
||||
For the "Title" field, enter a *very* short description of the problem;
|
||||
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
|
||||
extension modules were involved, and what hardware and software platform you
|
||||
were using (including version information as appropriate).
|
||||
|
||||
Each bug report will be assigned to a developer who will determine what needs to
|
||||
be done to correct the problem. You will receive an update each time action is
|
||||
taken on the bug.
|
||||
Each issue report will be reviewed by a developer who will determine what needs to
|
||||
be done to correct the problem. You will receive an update each time an action is
|
||||
taken on the issue.
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
|
@ -95,6 +103,6 @@ patching Python in the `Python Developer's Guide`_. If you have questions,
|
|||
the `core-mentorship mailing list`_ is a friendly place to get answers to
|
||||
any and all questions pertaining to the process of fixing issues in Python.
|
||||
|
||||
.. _Documentation bugs: https://bugs.python.org/issue?@filter=status&@filter=components&components=4&status=1&@columns=id,activity,title,status&@sort=-activity
|
||||
.. _Documentation bugs: https://github.com/python/cpython/issues?q=is%3Aissue+is%3Aopen+label%3Adocs
|
||||
.. _Python Developer's Guide: https://devguide.python.org/
|
||||
.. _core-mentorship mailing list: https://mail.python.org/mailman3/lists/core-mentorship.python.org/
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -58,5 +58,16 @@ See :ref:`stable` for a discussion of API and ABI stability across versions.
|
|||
Thus ``3.4.1a2`` is hexversion ``0x030401a2`` and ``3.10.0`` is
|
||||
hexversion ``0x030a00f0``.
|
||||
|
||||
Use this for numeric comparisons, e.g. ``#if PY_VERSION_HEX >= ...``.
|
||||
|
||||
This version is also available via the symbol :c:var:`Py_Version`.
|
||||
|
||||
.. c:var:: const unsigned long Py_Version
|
||||
|
||||
The Python runtime version number encoded in a single constant integer, with
|
||||
the same format as the :c:macro:`PY_VERSION_HEX` macro.
|
||||
This contains the Python version used at run time.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
All the given macros are defined in :source:`Include/patchlevel.h`.
|
||||
|
|
|
|||
|
|
@ -27,40 +27,55 @@ unit; the entry in (round) parentheses is the Python object type that matches
|
|||
the format unit; and the entry in [square] brackets is the type of the C
|
||||
variable(s) whose address should be passed.
|
||||
|
||||
.. _arg-parsing-string-and-buffers:
|
||||
|
||||
Strings and buffers
|
||||
-------------------
|
||||
|
||||
.. note::
|
||||
|
||||
On Python 3.12 and older, the macro :c:macro:`!PY_SSIZE_T_CLEAN` must be
|
||||
defined before including :file:`Python.h` to use all ``#`` variants of
|
||||
formats (``s#``, ``y#``, etc.) explained below.
|
||||
This is not necessary on Python 3.13 and later.
|
||||
|
||||
These formats allow accessing an object as a contiguous chunk of memory.
|
||||
You don't have to provide raw storage for the returned unicode or bytes
|
||||
area.
|
||||
|
||||
In general, when a format sets a pointer to a buffer, the buffer is
|
||||
managed by the corresponding Python object, and the buffer shares
|
||||
the lifetime of this object. You won't have to release any memory yourself.
|
||||
The only exceptions are ``es``, ``es#``, ``et`` and ``et#``.
|
||||
|
||||
However, when a :c:type:`Py_buffer` structure gets filled, the underlying
|
||||
buffer is locked so that the caller can subsequently use the buffer even
|
||||
inside a :c:type:`Py_BEGIN_ALLOW_THREADS` block without the risk of mutable data
|
||||
being resized or destroyed. As a result, **you have to call**
|
||||
:c:func:`PyBuffer_Release` after you have finished processing the data (or
|
||||
in any early abort case).
|
||||
|
||||
Unless otherwise stated, buffers are not NUL-terminated.
|
||||
|
||||
Some formats require a read-only :term:`bytes-like object`, and set a
|
||||
pointer instead of a buffer structure. They work by checking that
|
||||
the object's :c:member:`PyBufferProcs.bf_releasebuffer` field is ``NULL``,
|
||||
which disallows mutable objects such as :class:`bytearray`.
|
||||
There are three ways strings and buffers can be converted to C:
|
||||
|
||||
.. note::
|
||||
* Formats such as ``y*`` and ``s*`` fill a :c:type:`Py_buffer` structure.
|
||||
This locks the underlying buffer so that the caller can subsequently use
|
||||
the buffer even inside a :c:type:`Py_BEGIN_ALLOW_THREADS`
|
||||
block without the risk of mutable data being resized or destroyed.
|
||||
As a result, **you have to call** :c:func:`PyBuffer_Release` after you have
|
||||
finished processing the data (or in any early abort case).
|
||||
|
||||
For all ``#`` variants of formats (``s#``, ``y#``, etc.), the macro
|
||||
:c:macro:`PY_SSIZE_T_CLEAN` must be defined before including
|
||||
:file:`Python.h`. On Python 3.9 and older, the type of the length argument
|
||||
is :c:type:`Py_ssize_t` if the :c:macro:`PY_SSIZE_T_CLEAN` macro is defined,
|
||||
or int otherwise.
|
||||
* The ``es``, ``es#``, ``et`` and ``et#`` formats allocate the result buffer.
|
||||
**You have to call** :c:func:`PyMem_Free` after you have finished
|
||||
processing the data (or in any early abort case).
|
||||
|
||||
* .. _c-arg-borrowed-buffer:
|
||||
|
||||
Other formats take a :class:`str` or a read-only :term:`bytes-like object`,
|
||||
such as :class:`bytes`, and provide a ``const char *`` pointer to
|
||||
its buffer.
|
||||
In this case the buffer is "borrowed": it is managed by the corresponding
|
||||
Python object, and shares the lifetime of this object.
|
||||
You won't have to release any memory yourself.
|
||||
|
||||
To ensure that the underlying buffer may be safely borrowed, the object's
|
||||
:c:member:`PyBufferProcs.bf_releasebuffer` field must be ``NULL``.
|
||||
This disallows common mutable objects such as :class:`bytearray`,
|
||||
but also some read-only objects such as :class:`memoryview` of
|
||||
:class:`bytes`.
|
||||
|
||||
Besides this ``bf_releasebuffer`` requirement, there is no check to verify
|
||||
whether the input object is immutable (e.g. whether it would honor a request
|
||||
for a writable buffer, or whether another thread can mutate the data).
|
||||
|
||||
``s`` (:class:`str`) [const char \*]
|
||||
Convert a Unicode object to a C pointer to a character string.
|
||||
|
|
@ -89,7 +104,7 @@ which disallows mutable objects such as :class:`bytearray`.
|
|||
Unicode objects are converted to C strings using ``'utf-8'`` encoding.
|
||||
|
||||
``s#`` (:class:`str`, read-only :term:`bytes-like object`) [const char \*, :c:type:`Py_ssize_t`]
|
||||
Like ``s*``, except that it doesn't accept mutable objects.
|
||||
Like ``s*``, except that it provides a :ref:`borrowed buffer <c-arg-borrowed-buffer>`.
|
||||
The result is stored into two C variables,
|
||||
the first one a pointer to a C string, the second one its length.
|
||||
The string may contain embedded null bytes. Unicode objects are converted
|
||||
|
|
@ -108,8 +123,9 @@ which disallows mutable objects such as :class:`bytearray`.
|
|||
pointer is set to ``NULL``.
|
||||
|
||||
``y`` (read-only :term:`bytes-like object`) [const char \*]
|
||||
This format converts a bytes-like object to a C pointer to a character
|
||||
string; it does not accept Unicode objects. The bytes buffer must not
|
||||
This format converts a bytes-like object to a C pointer to a
|
||||
:ref:`borrowed <c-arg-borrowed-buffer>` character string;
|
||||
it does not accept Unicode objects. The bytes buffer must not
|
||||
contain embedded null bytes; if it does, a :exc:`ValueError`
|
||||
exception is raised.
|
||||
|
||||
|
|
@ -129,59 +145,17 @@ which disallows mutable objects such as :class:`bytearray`.
|
|||
``S`` (:class:`bytes`) [PyBytesObject \*]
|
||||
Requires that the Python object is a :class:`bytes` object, without
|
||||
attempting any conversion. Raises :exc:`TypeError` if the object is not
|
||||
a bytes object. The C variable may also be declared as :c:type:`PyObject*`.
|
||||
a bytes object. The C variable may also be declared as :c:expr:`PyObject*`.
|
||||
|
||||
``Y`` (:class:`bytearray`) [PyByteArrayObject \*]
|
||||
Requires that the Python object is a :class:`bytearray` object, without
|
||||
attempting any conversion. Raises :exc:`TypeError` if the object is not
|
||||
a :class:`bytearray` object. The C variable may also be declared as :c:type:`PyObject*`.
|
||||
|
||||
``u`` (:class:`str`) [const Py_UNICODE \*]
|
||||
Convert a Python Unicode object to a C pointer to a NUL-terminated buffer of
|
||||
Unicode characters. You must pass the address of a :c:type:`Py_UNICODE`
|
||||
pointer variable, which will be filled with the pointer to an existing
|
||||
Unicode buffer. Please note that the width of a :c:type:`Py_UNICODE`
|
||||
character depends on compilation options (it is either 16 or 32 bits).
|
||||
The Python string must not contain embedded null code points; if it does,
|
||||
a :exc:`ValueError` exception is raised.
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
Previously, :exc:`TypeError` was raised when embedded null code points
|
||||
were encountered in the Python string.
|
||||
|
||||
.. deprecated-removed:: 3.3 3.12
|
||||
Part of the old-style :c:type:`Py_UNICODE` API; please migrate to using
|
||||
:c:func:`PyUnicode_AsWideCharString`.
|
||||
|
||||
``u#`` (:class:`str`) [const Py_UNICODE \*, :c:type:`Py_ssize_t`]
|
||||
This variant on ``u`` stores into two C variables, the first one a pointer to a
|
||||
Unicode data buffer, the second one its length. This variant allows
|
||||
null code points.
|
||||
|
||||
.. deprecated-removed:: 3.3 3.12
|
||||
Part of the old-style :c:type:`Py_UNICODE` API; please migrate to using
|
||||
:c:func:`PyUnicode_AsWideCharString`.
|
||||
|
||||
``Z`` (:class:`str` or ``None``) [const Py_UNICODE \*]
|
||||
Like ``u``, but the Python object may also be ``None``, in which case the
|
||||
:c:type:`Py_UNICODE` pointer is set to ``NULL``.
|
||||
|
||||
.. deprecated-removed:: 3.3 3.12
|
||||
Part of the old-style :c:type:`Py_UNICODE` API; please migrate to using
|
||||
:c:func:`PyUnicode_AsWideCharString`.
|
||||
|
||||
``Z#`` (:class:`str` or ``None``) [const Py_UNICODE \*, :c:type:`Py_ssize_t`]
|
||||
Like ``u#``, but the Python object may also be ``None``, in which case the
|
||||
:c:type:`Py_UNICODE` pointer is set to ``NULL``.
|
||||
|
||||
.. deprecated-removed:: 3.3 3.12
|
||||
Part of the old-style :c:type:`Py_UNICODE` API; please migrate to using
|
||||
:c:func:`PyUnicode_AsWideCharString`.
|
||||
a :class:`bytearray` object. The C variable may also be declared as :c:expr:`PyObject*`.
|
||||
|
||||
``U`` (:class:`str`) [PyObject \*]
|
||||
Requires that the Python object is a Unicode object, without attempting
|
||||
any conversion. Raises :exc:`TypeError` if the object is not a Unicode
|
||||
object. The C variable may also be declared as :c:type:`PyObject*`.
|
||||
object. The C variable may also be declared as :c:expr:`PyObject*`.
|
||||
|
||||
``w*`` (read-write :term:`bytes-like object`) [Py_buffer]
|
||||
This format accepts any object which implements the read-write buffer
|
||||
|
|
@ -194,10 +168,10 @@ which disallows mutable objects such as :class:`bytearray`.
|
|||
It only works for encoded data without embedded NUL bytes.
|
||||
|
||||
This format requires two arguments. The first is only used as input, and
|
||||
must be a :c:type:`const char*` which points to the name of an encoding as a
|
||||
must be a :c:expr:`const char*` which points to the name of an encoding as a
|
||||
NUL-terminated string, or ``NULL``, in which case ``'utf-8'`` encoding is used.
|
||||
An exception is raised if the named encoding is not known to Python. The
|
||||
second argument must be a :c:type:`char**`; the value of the pointer it
|
||||
second argument must be a :c:expr:`char**`; the value of the pointer it
|
||||
references will be set to a buffer with the contents of the argument text.
|
||||
The text will be encoded in the encoding specified by the first argument.
|
||||
|
||||
|
|
@ -217,10 +191,10 @@ which disallows mutable objects such as :class:`bytearray`.
|
|||
characters.
|
||||
|
||||
It requires three arguments. The first is only used as input, and must be a
|
||||
:c:type:`const char*` which points to the name of an encoding as a
|
||||
:c:expr:`const char*` which points to the name of an encoding as a
|
||||
NUL-terminated string, or ``NULL``, in which case ``'utf-8'`` encoding is used.
|
||||
An exception is raised if the named encoding is not known to Python. The
|
||||
second argument must be a :c:type:`char**`; the value of the pointer it
|
||||
second argument must be a :c:expr:`char**`; the value of the pointer it
|
||||
references will be set to a buffer with the contents of the argument text.
|
||||
The text will be encoded in the encoding specified by the first argument.
|
||||
The third argument must be a pointer to an integer; the referenced integer
|
||||
|
|
@ -247,64 +221,69 @@ which disallows mutable objects such as :class:`bytearray`.
|
|||
them. Instead, the implementation assumes that the byte string object uses the
|
||||
encoding passed in as parameter.
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
``u``, ``u#``, ``Z``, and ``Z#`` are removed because they used a legacy
|
||||
``Py_UNICODE*`` representation.
|
||||
|
||||
|
||||
Numbers
|
||||
-------
|
||||
|
||||
``b`` (:class:`int`) [unsigned char]
|
||||
Convert a nonnegative Python integer to an unsigned tiny int, stored in a C
|
||||
:c:type:`unsigned char`.
|
||||
:c:expr:`unsigned char`.
|
||||
|
||||
``B`` (:class:`int`) [unsigned char]
|
||||
Convert a Python integer to a tiny int without overflow checking, stored in a C
|
||||
:c:type:`unsigned char`.
|
||||
:c:expr:`unsigned char`.
|
||||
|
||||
``h`` (:class:`int`) [short int]
|
||||
Convert a Python integer to a C :c:type:`short int`.
|
||||
Convert a Python integer to a C :c:expr:`short int`.
|
||||
|
||||
``H`` (:class:`int`) [unsigned short int]
|
||||
Convert a Python integer to a C :c:type:`unsigned short int`, without overflow
|
||||
Convert a Python integer to a C :c:expr:`unsigned short int`, without overflow
|
||||
checking.
|
||||
|
||||
``i`` (:class:`int`) [int]
|
||||
Convert a Python integer to a plain C :c:type:`int`.
|
||||
Convert a Python integer to a plain C :c:expr:`int`.
|
||||
|
||||
``I`` (:class:`int`) [unsigned int]
|
||||
Convert a Python integer to a C :c:type:`unsigned int`, without overflow
|
||||
Convert a Python integer to a C :c:expr:`unsigned int`, without overflow
|
||||
checking.
|
||||
|
||||
``l`` (:class:`int`) [long int]
|
||||
Convert a Python integer to a C :c:type:`long int`.
|
||||
Convert a Python integer to a C :c:expr:`long int`.
|
||||
|
||||
``k`` (:class:`int`) [unsigned long]
|
||||
Convert a Python integer to a C :c:type:`unsigned long` without
|
||||
Convert a Python integer to a C :c:expr:`unsigned long` without
|
||||
overflow checking.
|
||||
|
||||
``L`` (:class:`int`) [long long]
|
||||
Convert a Python integer to a C :c:type:`long long`.
|
||||
Convert a Python integer to a C :c:expr:`long long`.
|
||||
|
||||
``K`` (:class:`int`) [unsigned long long]
|
||||
Convert a Python integer to a C :c:type:`unsigned long long`
|
||||
Convert a Python integer to a C :c:expr:`unsigned long long`
|
||||
without overflow checking.
|
||||
|
||||
``n`` (:class:`int`) [Py_ssize_t]
|
||||
``n`` (:class:`int`) [:c:type:`Py_ssize_t`]
|
||||
Convert a Python integer to a C :c:type:`Py_ssize_t`.
|
||||
|
||||
``c`` (:class:`bytes` or :class:`bytearray` of length 1) [char]
|
||||
Convert a Python byte, represented as a :class:`bytes` or
|
||||
:class:`bytearray` object of length 1, to a C :c:type:`char`.
|
||||
:class:`bytearray` object of length 1, to a C :c:expr:`char`.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
Allow :class:`bytearray` objects.
|
||||
|
||||
``C`` (:class:`str` of length 1) [int]
|
||||
Convert a Python character, represented as a :class:`str` object of
|
||||
length 1, to a C :c:type:`int`.
|
||||
length 1, to a C :c:expr:`int`.
|
||||
|
||||
``f`` (:class:`float`) [float]
|
||||
Convert a Python floating point number to a C :c:type:`float`.
|
||||
Convert a Python floating point number to a C :c:expr:`float`.
|
||||
|
||||
``d`` (:class:`float`) [double]
|
||||
Convert a Python floating point number to a C :c:type:`double`.
|
||||
Convert a Python floating point number to a C :c:expr:`double`.
|
||||
|
||||
``D`` (:class:`complex`) [Py_complex]
|
||||
Convert a Python complex number to a C :c:type:`Py_complex` structure.
|
||||
|
|
@ -314,13 +293,15 @@ Other objects
|
|||
|
||||
``O`` (object) [PyObject \*]
|
||||
Store a Python object (without any conversion) in a C object pointer. The C
|
||||
program thus receives the actual object that was passed. The object's reference
|
||||
count is not increased. The pointer stored is not ``NULL``.
|
||||
program thus receives the actual object that was passed. A new
|
||||
:term:`strong reference` to the object is not created
|
||||
(i.e. its reference count is not increased).
|
||||
The pointer stored is not ``NULL``.
|
||||
|
||||
``O!`` (object) [*typeobject*, PyObject \*]
|
||||
Store a Python object in a C object pointer. This is similar to ``O``, but
|
||||
takes two C arguments: the first is the address of a Python type object, the
|
||||
second is the address of the C variable (of type :c:type:`PyObject*`) into which
|
||||
second is the address of the C variable (of type :c:expr:`PyObject*`) into which
|
||||
the object pointer is stored. If the Python object does not have the required
|
||||
type, :exc:`TypeError` is raised.
|
||||
|
||||
|
|
@ -329,13 +310,13 @@ Other objects
|
|||
``O&`` (object) [*converter*, *anything*]
|
||||
Convert a Python object to a C variable through a *converter* function. This
|
||||
takes two arguments: the first is a function, the second is the address of a C
|
||||
variable (of arbitrary type), converted to :c:type:`void *`. The *converter*
|
||||
variable (of arbitrary type), converted to :c:expr:`void *`. The *converter*
|
||||
function in turn is called as follows::
|
||||
|
||||
status = converter(object, address);
|
||||
|
||||
where *object* is the Python object to be converted and *address* is the
|
||||
:c:type:`void*` argument that was passed to the :c:func:`PyArg_Parse\*` function.
|
||||
:c:expr:`void*` argument that was passed to the ``PyArg_Parse*`` function.
|
||||
The returned *status* should be ``1`` for a successful conversion and ``0`` if
|
||||
the conversion has failed. When the conversion fails, the *converter* function
|
||||
should raise an exception and leave the content of *address* unmodified.
|
||||
|
|
@ -364,7 +345,7 @@ Other objects
|
|||
*items*. Format units for sequences may be nested.
|
||||
|
||||
It is possible to pass "long" integers (integers whose value exceeds the
|
||||
platform's :const:`LONG_MAX`) however no proper range checking is done --- the
|
||||
platform's :c:macro:`LONG_MAX`) however no proper range checking is done --- the
|
||||
most significant bits are silently truncated when the receiving field is too
|
||||
small to receive the value (actually, the semantics are inherited from downcasts
|
||||
in C --- your mileage may vary).
|
||||
|
|
@ -399,7 +380,8 @@ inside nested parentheses. They are:
|
|||
mutually exclude each other.
|
||||
|
||||
Note that any Python object references which are provided to the caller are
|
||||
*borrowed* references; do not decrement their reference count!
|
||||
*borrowed* references; do not release them
|
||||
(i.e. do not decrement their reference count)!
|
||||
|
||||
Additional arguments passed to these functions must be addresses of variables
|
||||
whose type is determined by the format string; these are used to store values
|
||||
|
|
@ -409,9 +391,9 @@ what is specified for the corresponding format unit in that case.
|
|||
|
||||
For the conversion to succeed, the *arg* object must match the format
|
||||
and the format must be exhausted. On success, the
|
||||
:c:func:`PyArg_Parse\*` functions return true, otherwise they return
|
||||
``PyArg_Parse*`` functions return true, otherwise they return
|
||||
false and raise an appropriate exception. When the
|
||||
:c:func:`PyArg_Parse\*` functions fail due to conversion failure in one
|
||||
``PyArg_Parse*`` functions fail due to conversion failure in one
|
||||
of the format units, the variables at the addresses corresponding to that
|
||||
and the following format units are left untouched.
|
||||
|
||||
|
|
@ -431,21 +413,35 @@ API Functions
|
|||
than a variable number of arguments.
|
||||
|
||||
|
||||
.. c:function:: int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], ...)
|
||||
.. c:function:: int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char * const *keywords, ...)
|
||||
|
||||
Parse the parameters of a function that takes both positional and keyword
|
||||
parameters into local variables. The *keywords* argument is a
|
||||
``NULL``-terminated array of keyword parameter names. Empty names denote
|
||||
parameters into local variables.
|
||||
The *keywords* argument is a ``NULL``-terminated array of keyword parameter
|
||||
names specified as null-terminated ASCII or UTF-8 encoded C strings.
|
||||
Empty names denote
|
||||
:ref:`positional-only parameters <positional-only_parameter>`.
|
||||
Returns true on success; on failure, it returns false and raises the
|
||||
appropriate exception.
|
||||
|
||||
.. note::
|
||||
|
||||
The *keywords* parameter declaration is :c:expr:`char * const *` in C and
|
||||
:c:expr:`const char * const *` in C++.
|
||||
This can be overridden with the :c:macro:`PY_CXX_CONST` macro.
|
||||
|
||||
.. versionchanged:: 3.6
|
||||
Added support for :ref:`positional-only parameters
|
||||
<positional-only_parameter>`.
|
||||
|
||||
.. versionchanged:: 3.13
|
||||
The *keywords* parameter has now type :c:expr:`char * const *` in C and
|
||||
:c:expr:`const char * const *` in C++, instead of :c:expr:`char **`.
|
||||
Added support for non-ASCII keyword parameter names.
|
||||
|
||||
.. c:function:: int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], va_list vargs)
|
||||
|
||||
|
||||
.. c:function:: int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char * const *keywords, va_list vargs)
|
||||
|
||||
Identical to :c:func:`PyArg_ParseTupleAndKeywords`, except that it accepts a
|
||||
va_list rather than a variable number of arguments.
|
||||
|
|
@ -460,28 +456,36 @@ API Functions
|
|||
.. versionadded:: 3.2
|
||||
|
||||
|
||||
.. XXX deprecated, will be removed
|
||||
.. c:function:: int PyArg_Parse(PyObject *args, const char *format, ...)
|
||||
|
||||
Function used to deconstruct the argument lists of "old-style" functions ---
|
||||
these are functions which use the :const:`METH_OLDARGS` parameter parsing
|
||||
method, which has been removed in Python 3. This is not recommended for use
|
||||
in parameter parsing in new code, and most code in the standard interpreter
|
||||
has been modified to no longer use this for that purpose. It does remain a
|
||||
convenient way to decompose other tuples, however, and may continue to be
|
||||
used for that purpose.
|
||||
Parse the parameter of a function that takes a single positional parameter
|
||||
into a local variable. Returns true on success; on failure, it returns
|
||||
false and raises the appropriate exception.
|
||||
|
||||
Example::
|
||||
|
||||
// Function using METH_O calling convention
|
||||
static PyObject*
|
||||
my_function(PyObject *module, PyObject *arg)
|
||||
{
|
||||
int value;
|
||||
if (!PyArg_Parse(arg, "i:my_function", &value)) {
|
||||
return NULL;
|
||||
}
|
||||
// ... use value ...
|
||||
}
|
||||
|
||||
|
||||
.. c:function:: int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)
|
||||
|
||||
A simpler form of parameter retrieval which does not use a format string to
|
||||
specify the types of the arguments. Functions which use this method to retrieve
|
||||
their parameters should be declared as :const:`METH_VARARGS` in function or
|
||||
their parameters should be declared as :c:macro:`METH_VARARGS` in function or
|
||||
method tables. The tuple containing the actual parameters should be passed as
|
||||
*args*; it must actually be a tuple. The length of the tuple must be at least
|
||||
*min* and no more than *max*; *min* and *max* may be equal. Additional
|
||||
arguments must be passed to the function, each of which should be a pointer to a
|
||||
:c:type:`PyObject*` variable; these will be filled in with the values from
|
||||
:c:expr:`PyObject*` variable; these will be filled in with the values from
|
||||
*args*; they will contain :term:`borrowed references <borrowed reference>`.
|
||||
The variables which correspond
|
||||
to optional parameters not given by *args* will not be filled in; these should
|
||||
|
|
@ -490,7 +494,7 @@ API Functions
|
|||
will be set if there was a failure.
|
||||
|
||||
This is an example of the use of this function, taken from the sources for the
|
||||
:mod:`_weakref` helper module for weak references::
|
||||
:mod:`!_weakref` helper module for weak references::
|
||||
|
||||
static PyObject *
|
||||
weakref_ref(PyObject *self, PyObject *args)
|
||||
|
|
@ -510,6 +514,19 @@ API Functions
|
|||
|
||||
PyArg_ParseTuple(args, "O|O:ref", &object, &callback)
|
||||
|
||||
.. c:macro:: PY_CXX_CONST
|
||||
|
||||
The value to be inserted, if any, before :c:expr:`char * const *`
|
||||
in the *keywords* parameter declaration of
|
||||
:c:func:`PyArg_ParseTupleAndKeywords` and
|
||||
:c:func:`PyArg_VaParseTupleAndKeywords`.
|
||||
Default empty for C and ``const`` for C++
|
||||
(:c:expr:`const char * const *`).
|
||||
To override, define it to the desired value before including
|
||||
:file:`Python.h`.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
---------------
|
||||
Building values
|
||||
|
|
@ -518,7 +535,7 @@ Building values
|
|||
.. c:function:: PyObject* Py_BuildValue(const char *format, ...)
|
||||
|
||||
Create a new value based on a format string similar to those accepted by the
|
||||
:c:func:`PyArg_Parse\*` family of functions and a sequence of values. Returns
|
||||
``PyArg_Parse*`` family of functions and a sequence of values. Returns
|
||||
the value or ``NULL`` in the case of an error; an exception will be raised if
|
||||
``NULL`` is returned.
|
||||
|
||||
|
|
@ -584,58 +601,60 @@ Building values
|
|||
Same as ``s#``.
|
||||
|
||||
``i`` (:class:`int`) [int]
|
||||
Convert a plain C :c:type:`int` to a Python integer object.
|
||||
Convert a plain C :c:expr:`int` to a Python integer object.
|
||||
|
||||
``b`` (:class:`int`) [char]
|
||||
Convert a plain C :c:type:`char` to a Python integer object.
|
||||
Convert a plain C :c:expr:`char` to a Python integer object.
|
||||
|
||||
``h`` (:class:`int`) [short int]
|
||||
Convert a plain C :c:type:`short int` to a Python integer object.
|
||||
Convert a plain C :c:expr:`short int` to a Python integer object.
|
||||
|
||||
``l`` (:class:`int`) [long int]
|
||||
Convert a C :c:type:`long int` to a Python integer object.
|
||||
Convert a C :c:expr:`long int` to a Python integer object.
|
||||
|
||||
``B`` (:class:`int`) [unsigned char]
|
||||
Convert a C :c:type:`unsigned char` to a Python integer object.
|
||||
Convert a C :c:expr:`unsigned char` to a Python integer object.
|
||||
|
||||
``H`` (:class:`int`) [unsigned short int]
|
||||
Convert a C :c:type:`unsigned short int` to a Python integer object.
|
||||
Convert a C :c:expr:`unsigned short int` to a Python integer object.
|
||||
|
||||
``I`` (:class:`int`) [unsigned int]
|
||||
Convert a C :c:type:`unsigned int` to a Python integer object.
|
||||
Convert a C :c:expr:`unsigned int` to a Python integer object.
|
||||
|
||||
``k`` (:class:`int`) [unsigned long]
|
||||
Convert a C :c:type:`unsigned long` to a Python integer object.
|
||||
Convert a C :c:expr:`unsigned long` to a Python integer object.
|
||||
|
||||
``L`` (:class:`int`) [long long]
|
||||
Convert a C :c:type:`long long` to a Python integer object.
|
||||
Convert a C :c:expr:`long long` to a Python integer object.
|
||||
|
||||
``K`` (:class:`int`) [unsigned long long]
|
||||
Convert a C :c:type:`unsigned long long` to a Python integer object.
|
||||
Convert a C :c:expr:`unsigned long long` to a Python integer object.
|
||||
|
||||
``n`` (:class:`int`) [Py_ssize_t]
|
||||
``n`` (:class:`int`) [:c:type:`Py_ssize_t`]
|
||||
Convert a C :c:type:`Py_ssize_t` to a Python integer.
|
||||
|
||||
``c`` (:class:`bytes` of length 1) [char]
|
||||
Convert a C :c:type:`int` representing a byte to a Python :class:`bytes` object of
|
||||
Convert a C :c:expr:`int` representing a byte to a Python :class:`bytes` object of
|
||||
length 1.
|
||||
|
||||
``C`` (:class:`str` of length 1) [int]
|
||||
Convert a C :c:type:`int` representing a character to Python :class:`str`
|
||||
Convert a C :c:expr:`int` representing a character to Python :class:`str`
|
||||
object of length 1.
|
||||
|
||||
``d`` (:class:`float`) [double]
|
||||
Convert a C :c:type:`double` to a Python floating point number.
|
||||
Convert a C :c:expr:`double` to a Python floating point number.
|
||||
|
||||
``f`` (:class:`float`) [float]
|
||||
Convert a C :c:type:`float` to a Python floating point number.
|
||||
Convert a C :c:expr:`float` to a Python floating point number.
|
||||
|
||||
``D`` (:class:`complex`) [Py_complex \*]
|
||||
Convert a C :c:type:`Py_complex` structure to a Python complex number.
|
||||
|
||||
``O`` (object) [PyObject \*]
|
||||
Pass a Python object untouched (except for its reference count, which is
|
||||
incremented by one). If the object passed in is a ``NULL`` pointer, it is assumed
|
||||
Pass a Python object untouched but create a new
|
||||
:term:`strong reference` to it
|
||||
(i.e. its reference count is incremented by one).
|
||||
If the object passed in is a ``NULL`` pointer, it is assumed
|
||||
that this was caused because the call producing the argument found an error and
|
||||
set an exception. Therefore, :c:func:`Py_BuildValue` will return ``NULL`` but won't
|
||||
raise an exception. If no exception has been raised yet, :exc:`SystemError` is
|
||||
|
|
@ -645,13 +664,13 @@ Building values
|
|||
Same as ``O``.
|
||||
|
||||
``N`` (object) [PyObject \*]
|
||||
Same as ``O``, except it doesn't increment the reference count on the object.
|
||||
Same as ``O``, except it doesn't create a new :term:`strong reference`.
|
||||
Useful when the object is created by a call to an object constructor in the
|
||||
argument list.
|
||||
|
||||
``O&`` (object) [*converter*, *anything*]
|
||||
Convert *anything* to a Python object through a *converter* function. The
|
||||
function is called with *anything* (which should be compatible with :c:type:`void*`)
|
||||
function is called with *anything* (which should be compatible with :c:expr:`void*`)
|
||||
as its argument and should return a "new" Python object, or ``NULL`` if an
|
||||
error occurred.
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,17 @@ Boolean Objects
|
|||
---------------
|
||||
|
||||
Booleans in Python are implemented as a subclass of integers. There are only
|
||||
two booleans, :const:`Py_False` and :const:`Py_True`. As such, the normal
|
||||
two booleans, :c:data:`Py_False` and :c:data:`Py_True`. As such, the normal
|
||||
creation and deletion functions don't apply to booleans. The following macros
|
||||
are available, however.
|
||||
|
||||
|
||||
.. c:var:: PyTypeObject PyBool_Type
|
||||
|
||||
This instance of :c:type:`PyTypeObject` represents the Python boolean type; it
|
||||
is the same object as :class:`bool` in the Python layer.
|
||||
|
||||
|
||||
.. c:function:: int PyBool_Check(PyObject *o)
|
||||
|
||||
Return true if *o* is of type :c:data:`PyBool_Type`. This function always
|
||||
|
|
@ -19,29 +25,32 @@ are available, however.
|
|||
|
||||
.. c:var:: PyObject* Py_False
|
||||
|
||||
The Python ``False`` object. This object has no methods. It needs to be
|
||||
treated just like any other object with respect to reference counts.
|
||||
The Python ``False`` object. This object has no methods and is
|
||||
:term:`immortal`.
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
:c:data:`Py_False` is :term:`immortal`.
|
||||
|
||||
|
||||
.. c:var:: PyObject* Py_True
|
||||
|
||||
The Python ``True`` object. This object has no methods. It needs to be treated
|
||||
just like any other object with respect to reference counts.
|
||||
The Python ``True`` object. This object has no methods and is
|
||||
:term:`immortal`.
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
:c:data:`Py_True` is :term:`immortal`.
|
||||
|
||||
|
||||
.. c:macro:: Py_RETURN_FALSE
|
||||
|
||||
Return :const:`Py_False` from a function, properly incrementing its reference
|
||||
count.
|
||||
Return :c:data:`Py_False` from a function.
|
||||
|
||||
|
||||
.. c:macro:: Py_RETURN_TRUE
|
||||
|
||||
Return :const:`Py_True` from a function, properly incrementing its reference
|
||||
count.
|
||||
Return :c:data:`Py_True` from a function.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyBool_FromLong(long v)
|
||||
|
||||
Return a new reference to :const:`Py_True` or :const:`Py_False` depending on the
|
||||
truth value of *v*.
|
||||
Return :c:data:`Py_True` or :c:data:`Py_False`, depending on the truth value of *v*.
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ the elements exposed by an :class:`array.array` can be multi-byte values.
|
|||
|
||||
An example consumer of the buffer interface is the :meth:`~io.BufferedIOBase.write`
|
||||
method of file objects: any object that can export a series of bytes through
|
||||
the buffer interface can be written to a file. While :meth:`write` only
|
||||
the buffer interface can be written to a file. While :meth:`!write` only
|
||||
needs read-only access to the internal contents of the object passed to it,
|
||||
other methods such as :meth:`~io.BufferedIOBase.readinto` need write access
|
||||
to the contents of their argument. The buffer interface allows objects to
|
||||
|
|
@ -99,10 +99,12 @@ a buffer, see :c:func:`PyObject_GetBuffer`.
|
|||
For :term:`contiguous` arrays, the value points to the beginning of
|
||||
the memory block.
|
||||
|
||||
.. c:member:: void *obj
|
||||
.. c:member:: PyObject *obj
|
||||
|
||||
A new reference to the exporting object. The reference is owned by
|
||||
the consumer and automatically decremented and set to ``NULL`` by
|
||||
the consumer and automatically released
|
||||
(i.e. reference count decremented)
|
||||
and set to ``NULL`` by
|
||||
:c:func:`PyBuffer_Release`. The field is the equivalent of the return
|
||||
value of any standard C-API function.
|
||||
|
||||
|
|
@ -159,10 +161,7 @@ a buffer, see :c:func:`PyObject_GetBuffer`.
|
|||
If it is ``0``, :c:member:`~Py_buffer.buf` points to a single item representing
|
||||
a scalar. In this case, :c:member:`~Py_buffer.shape`, :c:member:`~Py_buffer.strides`
|
||||
and :c:member:`~Py_buffer.suboffsets` MUST be ``NULL``.
|
||||
|
||||
The macro :c:macro:`PyBUF_MAX_NDIM` limits the maximum number of dimensions
|
||||
to 64. Exporters MUST respect this limit, consumers of multi-dimensional
|
||||
buffers SHOULD be able to handle up to :c:macro:`PyBUF_MAX_NDIM` dimensions.
|
||||
The maximum number of dimensions is given by :c:macro:`PyBUF_MAX_NDIM`.
|
||||
|
||||
.. c:member:: Py_ssize_t *shape
|
||||
|
||||
|
|
@ -215,6 +214,17 @@ a buffer, see :c:func:`PyObject_GetBuffer`.
|
|||
freed when the buffer is released. The consumer MUST NOT alter this
|
||||
value.
|
||||
|
||||
|
||||
Constants:
|
||||
|
||||
.. c:macro:: PyBUF_MAX_NDIM
|
||||
|
||||
The maximum number of dimensions the memory represents.
|
||||
Exporters MUST respect this limit, consumers of multi-dimensional
|
||||
buffers SHOULD be able to handle up to :c:macro:`!PyBUF_MAX_NDIM` dimensions.
|
||||
Currently set to 64.
|
||||
|
||||
|
||||
.. _buffer-request-types:
|
||||
|
||||
Buffer request types
|
||||
|
|
@ -225,7 +235,7 @@ object via :c:func:`PyObject_GetBuffer`. Since the complexity of the logical
|
|||
structure of the memory can vary drastically, the consumer uses the *flags*
|
||||
argument to specify the exact buffer type it can handle.
|
||||
|
||||
All :c:data:`Py_buffer` fields are unambiguously defined by the request
|
||||
All :c:type:`Py_buffer` fields are unambiguously defined by the request
|
||||
type.
|
||||
|
||||
request-independent fields
|
||||
|
|
@ -438,7 +448,7 @@ Buffer-related functions
|
|||
|
||||
Send a request to *exporter* to fill in *view* as specified by *flags*.
|
||||
If the exporter cannot provide a buffer of the exact type, it MUST raise
|
||||
:c:data:`PyExc_BufferError`, set ``view->obj`` to ``NULL`` and
|
||||
:exc:`BufferError`, set ``view->obj`` to ``NULL`` and
|
||||
return ``-1``.
|
||||
|
||||
On success, fill in *view*, set ``view->obj`` to a new reference
|
||||
|
|
@ -454,7 +464,8 @@ Buffer-related functions
|
|||
|
||||
.. c:function:: void PyBuffer_Release(Py_buffer *view)
|
||||
|
||||
Release the buffer *view* and decrement the reference count for
|
||||
Release the buffer *view* and release the :term:`strong reference`
|
||||
(i.e. decrement the reference count) to the view's supporting object,
|
||||
``view->obj``. This function MUST be called when the buffer
|
||||
is no longer being used, otherwise reference leaks may occur.
|
||||
|
||||
|
|
@ -464,33 +475,33 @@ Buffer-related functions
|
|||
|
||||
.. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *format)
|
||||
|
||||
Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`.
|
||||
Return the implied :c:member:`~Py_buffer.itemsize` from :c:member:`~Py_buffer.format`.
|
||||
On error, raise an exception and return -1.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
.. c:function:: int PyBuffer_IsContiguous(Py_buffer *view, char order)
|
||||
.. c:function:: int PyBuffer_IsContiguous(const Py_buffer *view, char order)
|
||||
|
||||
Return ``1`` if the memory defined by the *view* is C-style (*order* is
|
||||
``'C'``) or Fortran-style (*order* is ``'F'``) :term:`contiguous` or either one
|
||||
(*order* is ``'A'``). Return ``0`` otherwise. This function always succeeds.
|
||||
|
||||
|
||||
.. c:function:: void* PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices)
|
||||
.. c:function:: void* PyBuffer_GetPointer(const Py_buffer *view, const Py_ssize_t *indices)
|
||||
|
||||
Get the memory area pointed to by the *indices* inside the given *view*.
|
||||
*indices* must point to an array of ``view->ndim`` indices.
|
||||
|
||||
|
||||
.. c:function:: int PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort)
|
||||
.. c:function:: int PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char fort)
|
||||
|
||||
Copy contiguous *len* bytes from *buf* to *view*.
|
||||
*fort* can be ``'C'`` or ``'F'`` (for C-style or Fortran-style ordering).
|
||||
``0`` is returned on success, ``-1`` on error.
|
||||
|
||||
|
||||
.. c:function:: int PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
|
||||
.. c:function:: int PyBuffer_ToContiguous(void *buf, const Py_buffer *src, Py_ssize_t len, char order)
|
||||
|
||||
Copy *len* bytes from *src* to its contiguous representation in *buf*.
|
||||
*order* can be ``'C'`` or ``'F'`` or ``'A'`` (for C-style or Fortran-style
|
||||
|
|
@ -499,6 +510,13 @@ Buffer-related functions
|
|||
This function fails if *len* != *src->len*.
|
||||
|
||||
|
||||
.. c:function:: int PyObject_CopyData(PyObject *dest, PyObject *src)
|
||||
|
||||
Copy data from *src* to *dest* buffer. Can convert between C-style and
|
||||
or Fortran-style buffers.
|
||||
|
||||
``0`` is returned on success, ``-1`` on error.
|
||||
|
||||
.. c:function:: void PyBuffer_FillContiguousStrides(int ndims, Py_ssize_t *shape, Py_ssize_t *strides, int itemsize, char order)
|
||||
|
||||
Fill the *strides* array with byte-strides of a :term:`contiguous` (C-style if
|
||||
|
|
@ -517,7 +535,7 @@ Buffer-related functions
|
|||
and :c:macro:`PyBUF_WRITABLE` is set in *flags*.
|
||||
|
||||
On success, set ``view->obj`` to a new reference to *exporter* and
|
||||
return 0. Otherwise, raise :c:data:`PyExc_BufferError`, set
|
||||
return 0. Otherwise, raise :exc:`BufferError`, set
|
||||
``view->obj`` to ``NULL`` and return ``-1``;
|
||||
|
||||
If this function is used as part of a :ref:`getbufferproc <buffer-structs>`,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
Byte Array Objects
|
||||
------------------
|
||||
|
||||
.. index:: object: bytearray
|
||||
.. index:: pair: object; bytearray
|
||||
|
||||
|
||||
.. c:type:: PyByteArrayObject
|
||||
|
|
@ -42,8 +42,6 @@ Direct API functions
|
|||
Return a new bytearray object from any object, *o*, that implements the
|
||||
:ref:`buffer protocol <bufferobjects>`.
|
||||
|
||||
.. XXX expand about the buffer protocol, at least somewhere
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyByteArray_FromStringAndSize(const char *string, Py_ssize_t len)
|
||||
|
||||
|
|
@ -79,9 +77,9 @@ These macros trade safety for speed and they don't check pointers.
|
|||
|
||||
.. c:function:: char* PyByteArray_AS_STRING(PyObject *bytearray)
|
||||
|
||||
Macro version of :c:func:`PyByteArray_AsString`.
|
||||
Similar to :c:func:`PyByteArray_AsString`, but without error checking.
|
||||
|
||||
|
||||
.. c:function:: Py_ssize_t PyByteArray_GET_SIZE(PyObject *bytearray)
|
||||
|
||||
Macro version of :c:func:`PyByteArray_Size`.
|
||||
Similar to :c:func:`PyByteArray_Size`, but without error checking.
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@
|
|||
Bytes Objects
|
||||
-------------
|
||||
|
||||
These functions raise :exc:`TypeError` when expecting a bytes parameter and are
|
||||
These functions raise :exc:`TypeError` when expecting a bytes parameter and
|
||||
called with a non-bytes parameter.
|
||||
|
||||
.. index:: object: bytes
|
||||
.. index:: pair: object; bytes
|
||||
|
||||
|
||||
.. c:type:: PyBytesObject
|
||||
|
|
@ -58,48 +58,45 @@ called with a non-bytes parameter.
|
|||
|
||||
.. % XXX: This should be exactly the same as the table in PyErr_Format.
|
||||
.. % One should just refer to the other.
|
||||
.. % XXX: The descriptions for %zd and %zu are wrong, but the truth is complicated
|
||||
.. % because not all compilers support the %z width modifier -- we fake it
|
||||
.. % when necessary via interpolating PY_FORMAT_SIZE_T.
|
||||
|
||||
.. tabularcolumns:: |l|l|L|
|
||||
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| Format Characters | Type | Comment |
|
||||
+===================+===============+================================+
|
||||
| :attr:`%%` | *n/a* | The literal % character. |
|
||||
| ``%%`` | *n/a* | The literal % character. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%c` | int | A single byte, |
|
||||
| ``%c`` | int | A single byte, |
|
||||
| | | represented as a C int. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%d` | int | Equivalent to |
|
||||
| ``%d`` | int | Equivalent to |
|
||||
| | | ``printf("%d")``. [1]_ |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%u` | unsigned int | Equivalent to |
|
||||
| ``%u`` | unsigned int | Equivalent to |
|
||||
| | | ``printf("%u")``. [1]_ |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%ld` | long | Equivalent to |
|
||||
| ``%ld`` | long | Equivalent to |
|
||||
| | | ``printf("%ld")``. [1]_ |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%lu` | unsigned long | Equivalent to |
|
||||
| ``%lu`` | unsigned long | Equivalent to |
|
||||
| | | ``printf("%lu")``. [1]_ |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%zd` | Py_ssize_t | Equivalent to |
|
||||
| | | ``printf("%zd")``. [1]_ |
|
||||
| ``%zd`` | :c:type:`\ | Equivalent to |
|
||||
| | Py_ssize_t` | ``printf("%zd")``. [1]_ |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%zu` | size_t | Equivalent to |
|
||||
| ``%zu`` | size_t | Equivalent to |
|
||||
| | | ``printf("%zu")``. [1]_ |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%i` | int | Equivalent to |
|
||||
| ``%i`` | int | Equivalent to |
|
||||
| | | ``printf("%i")``. [1]_ |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%x` | int | Equivalent to |
|
||||
| ``%x`` | int | Equivalent to |
|
||||
| | | ``printf("%x")``. [1]_ |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%s` | const char\* | A null-terminated C character |
|
||||
| ``%s`` | const char\* | A null-terminated C character |
|
||||
| | | array. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%p` | const void\* | The hex representation of a C |
|
||||
| ``%p`` | const void\* | The hex representation of a C |
|
||||
| | | pointer. Mostly equivalent to |
|
||||
| | | ``printf("%p")`` except that |
|
||||
| | | it is guaranteed to start with |
|
||||
|
|
@ -134,7 +131,7 @@ called with a non-bytes parameter.
|
|||
|
||||
.. c:function:: Py_ssize_t PyBytes_GET_SIZE(PyObject *o)
|
||||
|
||||
Macro form of :c:func:`PyBytes_Size` but without error checking.
|
||||
Similar to :c:func:`PyBytes_Size`, but without error checking.
|
||||
|
||||
|
||||
.. c:function:: char* PyBytes_AsString(PyObject *o)
|
||||
|
|
@ -151,13 +148,14 @@ called with a non-bytes parameter.
|
|||
|
||||
.. c:function:: char* PyBytes_AS_STRING(PyObject *string)
|
||||
|
||||
Macro form of :c:func:`PyBytes_AsString` but without error checking.
|
||||
Similar to :c:func:`PyBytes_AsString`, but without error checking.
|
||||
|
||||
|
||||
.. c:function:: int PyBytes_AsStringAndSize(PyObject *obj, char **buffer, Py_ssize_t *length)
|
||||
|
||||
Return the null-terminated contents of the object *obj*
|
||||
through the output variables *buffer* and *length*.
|
||||
Returns ``0`` on success.
|
||||
|
||||
If *length* is ``NULL``, the bytes object
|
||||
may not contain embedded null bytes;
|
||||
|
|
@ -187,8 +185,8 @@ called with a non-bytes parameter.
|
|||
.. c:function:: void PyBytes_ConcatAndDel(PyObject **bytes, PyObject *newpart)
|
||||
|
||||
Create a new bytes object in *\*bytes* containing the contents of *newpart*
|
||||
appended to *bytes*. This version decrements the reference count of
|
||||
*newpart*.
|
||||
appended to *bytes*. This version releases the :term:`strong reference`
|
||||
to *newpart* (i.e. decrements its reference count).
|
||||
|
||||
|
||||
.. c:function:: int _PyBytes_Resize(PyObject **bytes, Py_ssize_t newsize)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ This convention is not only used by *tp_call*:
|
|||
:c:member:`~PyTypeObject.tp_new` and :c:member:`~PyTypeObject.tp_init`
|
||||
also pass arguments this way.
|
||||
|
||||
To call an object, use :c:func:`PyObject_Call` or other
|
||||
To call an object, use :c:func:`PyObject_Call` or another
|
||||
:ref:`call API <capi-call>`.
|
||||
|
||||
|
||||
|
|
@ -57,13 +57,22 @@ This bears repeating:
|
|||
A class supporting vectorcall **must** also implement
|
||||
:c:member:`~PyTypeObject.tp_call` with the same semantics.
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
|
||||
The :c:macro:`Py_TPFLAGS_HAVE_VECTORCALL` flag is now removed from a class
|
||||
when the class's :py:meth:`~object.__call__` method is reassigned.
|
||||
(This internally sets :c:member:`~PyTypeObject.tp_call` only, and thus
|
||||
may make it behave differently than the vectorcall function.)
|
||||
In earlier Python versions, vectorcall should only be used with
|
||||
:c:macro:`immutable <Py_TPFLAGS_IMMUTABLETYPE>` or static types.
|
||||
|
||||
A class should not implement vectorcall if that would be slower
|
||||
than *tp_call*. For example, if the callee needs to convert
|
||||
the arguments to an args tuple and kwargs dict anyway, then there is no point
|
||||
in implementing vectorcall.
|
||||
|
||||
Classes can implement the vectorcall protocol by enabling the
|
||||
:const:`Py_TPFLAGS_HAVE_VECTORCALL` flag and setting
|
||||
:c:macro:`Py_TPFLAGS_HAVE_VECTORCALL` flag and setting
|
||||
:c:member:`~PyTypeObject.tp_vectorcall_offset` to the offset inside the
|
||||
object structure where a *vectorcallfunc* appears.
|
||||
This is a pointer to a function with the following signature:
|
||||
|
|
@ -75,7 +84,7 @@ This is a pointer to a function with the following signature:
|
|||
values of the keyword arguments.
|
||||
This can be *NULL* if there are no arguments.
|
||||
- *nargsf* is the number of positional arguments plus possibly the
|
||||
:const:`PY_VECTORCALL_ARGUMENTS_OFFSET` flag.
|
||||
:c:macro:`PY_VECTORCALL_ARGUMENTS_OFFSET` flag.
|
||||
To get the actual number of positional arguments from *nargsf*,
|
||||
use :c:func:`PyVectorcall_NARGS`.
|
||||
- *kwnames* is a tuple containing the names of the keyword arguments;
|
||||
|
|
@ -95,28 +104,17 @@ This is a pointer to a function with the following signature:
|
|||
``args[0]`` may be changed.
|
||||
|
||||
Whenever they can do so cheaply (without additional allocation), callers
|
||||
are encouraged to use :const:`PY_VECTORCALL_ARGUMENTS_OFFSET`.
|
||||
are encouraged to use :c:macro:`PY_VECTORCALL_ARGUMENTS_OFFSET`.
|
||||
Doing so will allow callables such as bound methods to make their onward
|
||||
calls (which include a prepended *self* argument) very efficiently.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
To call an object that implements vectorcall, use a :ref:`call API <capi-call>`
|
||||
function as with any other callable.
|
||||
:c:func:`PyObject_Vectorcall` will usually be most efficient.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
In CPython 3.8, the vectorcall API and related functions were available
|
||||
provisionally under names with a leading underscore:
|
||||
``_PyObject_Vectorcall``, ``_Py_TPFLAGS_HAVE_VECTORCALL``,
|
||||
``_PyObject_VectorcallMethod``, ``_PyVectorcall_Function``,
|
||||
``_PyObject_CallOneArg``, ``_PyObject_CallMethodNoArgs``,
|
||||
``_PyObject_CallMethodOneArg``.
|
||||
Additionally, ``PyObject_VectorcallDict`` was available as
|
||||
``_PyObject_FastCallDict``.
|
||||
The old names are still defined as aliases of the new, non-underscored names.
|
||||
|
||||
|
||||
Recursion Control
|
||||
.................
|
||||
|
||||
|
|
@ -144,8 +142,6 @@ Vectorcall Support API
|
|||
However, the function ``PyVectorcall_NARGS`` should be used to allow
|
||||
for future extensions.
|
||||
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
.. c:function:: vectorcallfunc PyVectorcall_Function(PyObject *op)
|
||||
|
|
@ -158,9 +154,7 @@ Vectorcall Support API
|
|||
This is mostly useful to check whether or not *op* supports vectorcall,
|
||||
which can be done by checking ``PyVectorcall_Function(op) != NULL``.
|
||||
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
.. versionadded:: 3.9
|
||||
|
||||
.. c:function:: PyObject* PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict)
|
||||
|
||||
|
|
@ -169,11 +163,9 @@ Vectorcall Support API
|
|||
|
||||
This is a specialized function, intended to be put in the
|
||||
:c:member:`~PyTypeObject.tp_call` slot or be used in an implementation of ``tp_call``.
|
||||
It does not check the :const:`Py_TPFLAGS_HAVE_VECTORCALL` flag
|
||||
It does not check the :c:macro:`Py_TPFLAGS_HAVE_VECTORCALL` flag
|
||||
and it does not fall back to ``tp_call``.
|
||||
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
|
||||
|
|
@ -256,8 +248,6 @@ please see individual documentation for details.
|
|||
Return the result of the call on success, or raise an exception and return
|
||||
*NULL* on failure.
|
||||
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
|
|
@ -283,7 +273,7 @@ please see individual documentation for details.
|
|||
|
||||
This is the equivalent of the Python expression: ``callable(*args)``.
|
||||
|
||||
Note that if you only pass :c:type:`PyObject *` args,
|
||||
Note that if you only pass :c:expr:`PyObject *` args,
|
||||
:c:func:`PyObject_CallFunctionObjArgs` is a faster alternative.
|
||||
|
||||
.. versionchanged:: 3.4
|
||||
|
|
@ -304,7 +294,7 @@ please see individual documentation for details.
|
|||
This is the equivalent of the Python expression:
|
||||
``obj.name(arg1, arg2, ...)``.
|
||||
|
||||
Note that if you only pass :c:type:`PyObject *` args,
|
||||
Note that if you only pass :c:expr:`PyObject *` args,
|
||||
:c:func:`PyObject_CallMethodObjArgs` is a faster alternative.
|
||||
|
||||
.. versionchanged:: 3.4
|
||||
|
|
@ -314,7 +304,7 @@ please see individual documentation for details.
|
|||
.. c:function:: PyObject* PyObject_CallFunctionObjArgs(PyObject *callable, ...)
|
||||
|
||||
Call a callable Python object *callable*, with a variable number of
|
||||
:c:type:`PyObject *` arguments. The arguments are provided as a variable number
|
||||
:c:expr:`PyObject *` arguments. The arguments are provided as a variable number
|
||||
of parameters followed by *NULL*.
|
||||
|
||||
Return the result of the call on success, or raise an exception and return
|
||||
|
|
@ -328,7 +318,7 @@ please see individual documentation for details.
|
|||
|
||||
Call a method of the Python object *obj*, where the name of the method is given as a
|
||||
Python string object in *name*. It is called with a variable number of
|
||||
:c:type:`PyObject *` arguments. The arguments are provided as a variable number
|
||||
:c:expr:`PyObject *` arguments. The arguments are provided as a variable number
|
||||
of parameters followed by *NULL*.
|
||||
|
||||
Return the result of the call on success, or raise an exception and return
|
||||
|
|
@ -343,8 +333,6 @@ please see individual documentation for details.
|
|||
Return the result of the call on success, or raise an exception and return
|
||||
*NULL* on failure.
|
||||
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
|
|
@ -357,8 +345,6 @@ please see individual documentation for details.
|
|||
Return the result of the call on success, or raise an exception and return
|
||||
*NULL* on failure.
|
||||
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
|
|
@ -372,8 +358,6 @@ please see individual documentation for details.
|
|||
Return the result of the call on success, or raise an exception and return
|
||||
*NULL* on failure.
|
||||
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
.. c:function:: PyObject* PyObject_VectorcallDict(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwdict)
|
||||
|
|
@ -388,8 +372,6 @@ please see individual documentation for details.
|
|||
already has a dictionary ready to use for the keyword arguments,
|
||||
but not a tuple for the positional arguments.
|
||||
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
.. c:function:: PyObject* PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||
|
|
@ -399,19 +381,17 @@ please see individual documentation for details.
|
|||
*args[0]*, and the *args* array starting at *args[1]* represents the arguments
|
||||
of the call. There must be at least one positional argument.
|
||||
*nargsf* is the number of positional arguments including *args[0]*,
|
||||
plus :const:`PY_VECTORCALL_ARGUMENTS_OFFSET` if the value of ``args[0]`` may
|
||||
plus :c:macro:`PY_VECTORCALL_ARGUMENTS_OFFSET` if the value of ``args[0]`` may
|
||||
temporarily be changed. Keyword arguments can be passed just like in
|
||||
:c:func:`PyObject_Vectorcall`.
|
||||
|
||||
If the object has the :const:`Py_TPFLAGS_METHOD_DESCRIPTOR` feature,
|
||||
If the object has the :c:macro:`Py_TPFLAGS_METHOD_DESCRIPTOR` feature,
|
||||
this will call the unbound method object with the full
|
||||
*args* vector as arguments.
|
||||
|
||||
Return the result of the call on success, or raise an exception and return
|
||||
*NULL* on failure.
|
||||
|
||||
This function is not part of the :ref:`limited API <stable>`.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
Capsules
|
||||
--------
|
||||
|
||||
.. index:: object: Capsule
|
||||
.. index:: pair: object; Capsule
|
||||
|
||||
Refer to :ref:`using-capsules` for more information on using these objects.
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ Refer to :ref:`using-capsules` for more information on using these objects.
|
|||
.. c:type:: PyCapsule
|
||||
|
||||
This subtype of :c:type:`PyObject` represents an opaque value, useful for C
|
||||
extension modules who need to pass an opaque value (as a :c:type:`void*`
|
||||
extension modules who need to pass an opaque value (as a :c:expr:`void*`
|
||||
pointer) through Python code to other C code. It is often used to make a C
|
||||
function pointer defined in one module available to other modules, so the
|
||||
regular import mechanism can be used to access C APIs defined in dynamically
|
||||
|
|
@ -64,7 +64,7 @@ Refer to :ref:`using-capsules` for more information on using these objects.
|
|||
|
||||
The *name* parameter must compare exactly to the name stored in the capsule.
|
||||
If the name stored in the capsule is ``NULL``, the *name* passed in must also
|
||||
be ``NULL``. Python uses the C function :c:func:`strcmp` to compare capsule
|
||||
be ``NULL``. Python uses the C function :c:func:`!strcmp` to compare capsule
|
||||
names.
|
||||
|
||||
|
||||
|
|
@ -103,13 +103,14 @@ Refer to :ref:`using-capsules` for more information on using these objects.
|
|||
Import a pointer to a C object from a capsule attribute in a module. The
|
||||
*name* parameter should specify the full name to the attribute, as in
|
||||
``module.attribute``. The *name* stored in the capsule must match this
|
||||
string exactly. If *no_block* is true, import the module without blocking
|
||||
(using :c:func:`PyImport_ImportModuleNoBlock`). If *no_block* is false,
|
||||
import the module conventionally (using :c:func:`PyImport_ImportModule`).
|
||||
string exactly.
|
||||
|
||||
Return the capsule's internal *pointer* on success. On failure, set an
|
||||
exception and return ``NULL``.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
*no_block* has no effect anymore.
|
||||
|
||||
|
||||
.. c:function:: int PyCapsule_IsValid(PyObject *capsule, const char *name)
|
||||
|
||||
|
|
@ -120,7 +121,7 @@ Refer to :ref:`using-capsules` for more information on using these objects.
|
|||
compared.)
|
||||
|
||||
In other words, if :c:func:`PyCapsule_IsValid` returns a true value, calls to
|
||||
any of the accessors (any function starting with :c:func:`PyCapsule_Get`) are
|
||||
any of the accessors (any function starting with ``PyCapsule_Get``) are
|
||||
guaranteed to succeed.
|
||||
|
||||
Return a nonzero value if the object is valid and matches the name passed in.
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ Cell objects are not likely to be useful elsewhere.
|
|||
The type object corresponding to cell objects.
|
||||
|
||||
|
||||
.. c:function:: int PyCell_Check(ob)
|
||||
.. c:function:: int PyCell_Check(PyObject *ob)
|
||||
|
||||
Return true if *ob* is a cell object; *ob* must not be ``NULL``. This
|
||||
function always succeeds.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
.. highlight:: c
|
||||
|
||||
.. _codeobjects:
|
||||
|
||||
.. index:: object; code, code object
|
||||
|
||||
.. _codeobjects:
|
||||
|
||||
Code Objects
|
||||
------------
|
||||
|
||||
|
|
@ -33,24 +33,52 @@ bound into a function.
|
|||
|
||||
Return the number of free variables in *co*.
|
||||
|
||||
.. c:function:: PyCodeObject* PyCode_New(int argcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, int firstlineno, PyObject *lnotab)
|
||||
.. c:function:: PyCodeObject* PyUnstable_Code_New(int argcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, PyObject *qualname, int firstlineno, PyObject *linetable, PyObject *exceptiontable)
|
||||
|
||||
Return a new code object. If you need a dummy code object to create a frame,
|
||||
use :c:func:`PyCode_NewEmpty` instead. Calling :c:func:`PyCode_New` directly
|
||||
can bind you to a precise Python version since the definition of the bytecode
|
||||
changes often.
|
||||
use :c:func:`PyCode_NewEmpty` instead.
|
||||
|
||||
.. c:function:: PyCodeObject* PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, int firstlineno, PyObject *lnotab)
|
||||
Since the definition of the bytecode changes often, calling
|
||||
:c:func:`PyUnstable_Code_New` directly can bind you to a precise Python version.
|
||||
|
||||
Similar to :c:func:`PyCode_New`, but with an extra "posonlyargcount" for positional-only arguments.
|
||||
The many arguments of this function are inter-dependent in complex
|
||||
ways, meaning that subtle changes to values are likely to result in incorrect
|
||||
execution or VM crashes. Use this function only with extreme care.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
.. versionchanged:: 3.11
|
||||
Added ``qualname`` and ``exceptiontable`` parameters.
|
||||
|
||||
.. index:: single: PyCode_New
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
|
||||
Renamed from ``PyCode_New`` as part of :ref:`unstable-c-api`.
|
||||
The old name is deprecated, but will remain available until the
|
||||
signature changes again.
|
||||
|
||||
.. c:function:: PyCodeObject* PyUnstable_Code_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, PyObject *qualname, int firstlineno, PyObject *linetable, PyObject *exceptiontable)
|
||||
|
||||
Similar to :c:func:`PyUnstable_Code_New`, but with an extra "posonlyargcount" for positional-only arguments.
|
||||
The same caveats that apply to ``PyUnstable_Code_New`` also apply to this function.
|
||||
|
||||
.. index:: single: PyCode_NewWithPosOnlyArgs
|
||||
|
||||
.. versionadded:: 3.8 as ``PyCode_NewWithPosOnlyArgs``
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
Added ``qualname`` and ``exceptiontable`` parameters.
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
|
||||
Renamed to ``PyUnstable_Code_NewWithPosOnlyArgs``.
|
||||
The old name is deprecated, but will remain available until the
|
||||
signature changes again.
|
||||
|
||||
.. c:function:: PyCodeObject* PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
|
||||
|
||||
Return a new empty code object with the specified filename,
|
||||
function name, and first line number. It is illegal to
|
||||
:func:`exec` or :func:`eval` the resulting code object.
|
||||
function name, and first line number. The resulting code
|
||||
object will raise an ``Exception`` if executed.
|
||||
|
||||
.. c:function:: int PyCode_Addr2Line(PyCodeObject *co, int byte_offset)
|
||||
|
||||
|
|
@ -58,7 +86,7 @@ bound into a function.
|
|||
If you just need the line number of a frame, use :c:func:`PyFrame_GetLineNumber` instead.
|
||||
|
||||
For efficiently iterating over the line numbers in a code object, use `the API described in PEP 626
|
||||
<https://www.python.org/dev/peps/pep-0626/#out-of-process-debuggers-and-profilers>`_.
|
||||
<https://peps.python.org/pep-0626/#out-of-process-debuggers-and-profilers>`_.
|
||||
|
||||
.. c:function:: int PyCode_Addr2Location(PyObject *co, int byte_offset, int *start_line, int *start_column, int *end_line, int *end_column)
|
||||
|
||||
|
|
@ -67,3 +95,170 @@ bound into a function.
|
|||
information is not available for any particular element.
|
||||
|
||||
Returns ``1`` if the function succeeds and 0 otherwise.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
.. c:function:: PyObject* PyCode_GetCode(PyCodeObject *co)
|
||||
|
||||
Equivalent to the Python code ``getattr(co, 'co_code')``.
|
||||
Returns a strong reference to a :c:type:`PyBytesObject` representing the
|
||||
bytecode in a code object. On error, ``NULL`` is returned and an exception
|
||||
is raised.
|
||||
|
||||
This ``PyBytesObject`` may be created on-demand by the interpreter and does
|
||||
not necessarily represent the bytecode actually executed by CPython. The
|
||||
primary use case for this function is debuggers and profilers.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
.. c:function:: PyObject* PyCode_GetVarnames(PyCodeObject *co)
|
||||
|
||||
Equivalent to the Python code ``getattr(co, 'co_varnames')``.
|
||||
Returns a new reference to a :c:type:`PyTupleObject` containing the names of
|
||||
the local variables. On error, ``NULL`` is returned and an exception
|
||||
is raised.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
.. c:function:: PyObject* PyCode_GetCellvars(PyCodeObject *co)
|
||||
|
||||
Equivalent to the Python code ``getattr(co, 'co_cellvars')``.
|
||||
Returns a new reference to a :c:type:`PyTupleObject` containing the names of
|
||||
the local variables that are referenced by nested functions. On error, ``NULL``
|
||||
is returned and an exception is raised.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
.. c:function:: PyObject* PyCode_GetFreevars(PyCodeObject *co)
|
||||
|
||||
Equivalent to the Python code ``getattr(co, 'co_freevars')``.
|
||||
Returns a new reference to a :c:type:`PyTupleObject` containing the names of
|
||||
the free variables. On error, ``NULL`` is returned and an exception is raised.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
.. c:function:: int PyCode_AddWatcher(PyCode_WatchCallback callback)
|
||||
|
||||
Register *callback* as a code object watcher for the current interpreter.
|
||||
Return an ID which may be passed to :c:func:`PyCode_ClearWatcher`.
|
||||
In case of error (e.g. no more watcher IDs available),
|
||||
return ``-1`` and set an exception.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
.. c:function:: int PyCode_ClearWatcher(int watcher_id)
|
||||
|
||||
Clear watcher identified by *watcher_id* previously returned from
|
||||
:c:func:`PyCode_AddWatcher` for the current interpreter.
|
||||
Return ``0`` on success, or ``-1`` and set an exception on error
|
||||
(e.g. if the given *watcher_id* was never registered.)
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
.. c:type:: PyCodeEvent
|
||||
|
||||
Enumeration of possible code object watcher events:
|
||||
- ``PY_CODE_EVENT_CREATE``
|
||||
- ``PY_CODE_EVENT_DESTROY``
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
.. c:type:: int (*PyCode_WatchCallback)(PyCodeEvent event, PyCodeObject* co)
|
||||
|
||||
Type of a code object watcher callback function.
|
||||
|
||||
If *event* is ``PY_CODE_EVENT_CREATE``, then the callback is invoked
|
||||
after `co` has been fully initialized. Otherwise, the callback is invoked
|
||||
before the destruction of *co* takes place, so the prior state of *co*
|
||||
can be inspected.
|
||||
|
||||
If *event* is ``PY_CODE_EVENT_DESTROY``, taking a reference in the callback
|
||||
to the about-to-be-destroyed code object will resurrect it and prevent it
|
||||
from being freed at this time. When the resurrected object is destroyed
|
||||
later, any watcher callbacks active at that time will be called again.
|
||||
|
||||
Users of this API should not rely on internal runtime implementation
|
||||
details. Such details may include, but are not limited to, the exact
|
||||
order and timing of creation and destruction of code objects. While
|
||||
changes in these details may result in differences observable by watchers
|
||||
(including whether a callback is invoked or not), it does not change
|
||||
the semantics of the Python code being executed.
|
||||
|
||||
If the callback sets an exception, it must return ``-1``; this exception will
|
||||
be printed as an unraisable exception using :c:func:`PyErr_WriteUnraisable`.
|
||||
Otherwise it should return ``0``.
|
||||
|
||||
There may already be a pending exception set on entry to the callback. In
|
||||
this case, the callback should return ``0`` with the same exception still
|
||||
set. This means the callback may not call any other API that can set an
|
||||
exception unless it saves and clears the exception state first, and restores
|
||||
it before returning.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
|
||||
Extra information
|
||||
-----------------
|
||||
|
||||
To support low-level extensions to frame evaluation, such as external
|
||||
just-in-time compilers, it is possible to attach arbitrary extra data to
|
||||
code objects.
|
||||
|
||||
These functions are part of the unstable C API tier:
|
||||
this functionality is a CPython implementation detail, and the API
|
||||
may change without deprecation warnings.
|
||||
|
||||
.. c:function:: Py_ssize_t PyUnstable_Eval_RequestCodeExtraIndex(freefunc free)
|
||||
|
||||
Return a new an opaque index value used to adding data to code objects.
|
||||
|
||||
You generally call this function once (per interpreter) and use the result
|
||||
with ``PyCode_GetExtra`` and ``PyCode_SetExtra`` to manipulate
|
||||
data on individual code objects.
|
||||
|
||||
If *free* is not ``NULL``: when a code object is deallocated,
|
||||
*free* will be called on non-``NULL`` data stored under the new index.
|
||||
Use :c:func:`Py_DecRef` when storing :c:type:`PyObject`.
|
||||
|
||||
.. index:: single: _PyEval_RequestCodeExtraIndex
|
||||
|
||||
.. versionadded:: 3.6 as ``_PyEval_RequestCodeExtraIndex``
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
|
||||
Renamed to ``PyUnstable_Eval_RequestCodeExtraIndex``.
|
||||
The old private name is deprecated, but will be available until the API
|
||||
changes.
|
||||
|
||||
.. c:function:: int PyUnstable_Code_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
|
||||
|
||||
Set *extra* to the extra data stored under the given index.
|
||||
Return 0 on success. Set an exception and return -1 on failure.
|
||||
|
||||
If no data was set under the index, set *extra* to ``NULL`` and return
|
||||
0 without setting an exception.
|
||||
|
||||
.. index:: single: _PyCode_GetExtra
|
||||
|
||||
.. versionadded:: 3.6 as ``_PyCode_GetExtra``
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
|
||||
Renamed to ``PyUnstable_Code_GetExtra``.
|
||||
The old private name is deprecated, but will be available until the API
|
||||
changes.
|
||||
|
||||
.. c:function:: int PyUnstable_Code_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
|
||||
|
||||
Set the extra data stored under the given index to *extra*.
|
||||
Return 0 on success. Set an exception and return -1 on failure.
|
||||
|
||||
.. index:: single: _PyCode_SetExtra
|
||||
|
||||
.. versionadded:: 3.6 as ``_PyCode_SetExtra``
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
|
||||
Renamed to ``PyUnstable_Code_SetExtra``.
|
||||
The old private name is deprecated, but will be available until the API
|
||||
changes.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ Codec registry and support functions
|
|||
|
||||
Register a new codec search function.
|
||||
|
||||
As side effect, this tries to load the :mod:`encodings` package, if not yet
|
||||
As side effect, this tries to load the :mod:`!encodings` package, if not yet
|
||||
done, to make sure that it is always first in the list of search functions.
|
||||
|
||||
.. c:function:: int PyCodec_Unregister(PyObject *search_function)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
Complex Number Objects
|
||||
----------------------
|
||||
|
||||
.. index:: object: complex number
|
||||
.. index:: pair: object; complex number
|
||||
|
||||
Python's complex number objects are implemented as two distinct types when
|
||||
viewed from the C API: one is the Python object exposed to Python programs, and
|
||||
|
|
@ -64,7 +64,7 @@ pointers. This is consistent throughout the API.
|
|||
representation.
|
||||
|
||||
If *divisor* is null, this method returns zero and sets
|
||||
:c:data:`errno` to :c:data:`EDOM`.
|
||||
:c:data:`errno` to :c:macro:`!EDOM`.
|
||||
|
||||
|
||||
.. c:function:: Py_complex _Py_c_pow(Py_complex num, Py_complex exp)
|
||||
|
|
@ -73,7 +73,7 @@ pointers. This is consistent throughout the API.
|
|||
representation.
|
||||
|
||||
If *num* is null and *exp* is not a positive real number,
|
||||
this method returns zero and sets :c:data:`errno` to :c:data:`EDOM`.
|
||||
this method returns zero and sets :c:data:`errno` to :c:macro:`!EDOM`.
|
||||
|
||||
|
||||
Complex Numbers as Python Objects
|
||||
|
|
@ -115,24 +115,24 @@ Complex Numbers as Python Objects
|
|||
|
||||
.. c:function:: double PyComplex_RealAsDouble(PyObject *op)
|
||||
|
||||
Return the real part of *op* as a C :c:type:`double`.
|
||||
Return the real part of *op* as a C :c:expr:`double`.
|
||||
|
||||
|
||||
.. c:function:: double PyComplex_ImagAsDouble(PyObject *op)
|
||||
|
||||
Return the imaginary part of *op* as a C :c:type:`double`.
|
||||
Return the imaginary part of *op* as a C :c:expr:`double`.
|
||||
|
||||
|
||||
.. c:function:: Py_complex PyComplex_AsCComplex(PyObject *op)
|
||||
|
||||
Return the :c:type:`Py_complex` value of the complex number *op*.
|
||||
|
||||
If *op* is not a Python complex number object but has a :meth:`__complex__`
|
||||
If *op* is not a Python complex number object but has a :meth:`~object.__complex__`
|
||||
method, this method will first be called to convert *op* to a Python complex
|
||||
number object. If ``__complex__()`` is not defined then it falls back to
|
||||
:meth:`__float__`. If ``__float__()`` is not defined then it falls back
|
||||
to :meth:`__index__`. Upon failure, this method returns ``-1.0`` as a real
|
||||
number object. If :meth:`!__complex__` is not defined then it falls back to
|
||||
:meth:`~object.__float__`. If :meth:`!__float__` is not defined then it falls back
|
||||
to :meth:`~object.__index__`. Upon failure, this method returns ``-1.0`` as a real
|
||||
value.
|
||||
|
||||
.. versionchanged:: 3.8
|
||||
Use :meth:`__index__` if available.
|
||||
Use :meth:`~object.__index__` if available.
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ This section describes Python type objects and the singleton object ``None``.
|
|||
Numeric Objects
|
||||
===============
|
||||
|
||||
.. index:: object: numeric
|
||||
.. index:: pair: object; numeric
|
||||
|
||||
.. toctree::
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ Numeric Objects
|
|||
Sequence Objects
|
||||
================
|
||||
|
||||
.. index:: object: sequence
|
||||
.. index:: pair: object; sequence
|
||||
|
||||
Generic operations on sequence objects were discussed in the previous chapter;
|
||||
this section deals with the specific kinds of sequence objects that are
|
||||
|
|
@ -77,7 +77,7 @@ intrinsic to the Python language.
|
|||
Container Objects
|
||||
=================
|
||||
|
||||
.. index:: object: mapping
|
||||
.. index:: pair: object; mapping
|
||||
|
||||
.. toctree::
|
||||
|
||||
|
|
@ -111,6 +111,7 @@ Other Objects
|
|||
memoryview.rst
|
||||
weakref.rst
|
||||
capsule.rst
|
||||
frame.rst
|
||||
gen.rst
|
||||
coro.rst
|
||||
contextvars.rst
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ not.
|
|||
The wrappers ensure that ``str[size-1]`` is always ``'\0'`` upon return. They
|
||||
never write more than *size* bytes (including the trailing ``'\0'``) into str.
|
||||
Both functions require that ``str != NULL``, ``size > 0``, ``format != NULL``
|
||||
and ``size < INT_MAX``.
|
||||
and ``size < INT_MAX``. Note that this means there is no equivalent to the C99
|
||||
``n = snprintf(NULL, 0, ...)`` which would determine the necessary buffer size.
|
||||
|
||||
The return value (*rv*) for these functions should be interpreted as follows:
|
||||
|
||||
|
|
@ -49,7 +50,7 @@ The following functions provide locale-independent string to number conversions.
|
|||
|
||||
.. c:function:: double PyOS_string_to_double(const char *s, char **endptr, PyObject *overflow_exception)
|
||||
|
||||
Convert a string ``s`` to a :c:type:`double`, raising a Python
|
||||
Convert a string ``s`` to a :c:expr:`double`, raising a Python
|
||||
exception on failure. The set of accepted strings corresponds to
|
||||
the set of strings accepted by Python's :func:`float` constructor,
|
||||
except that ``s`` must not have leading or trailing whitespace.
|
||||
|
|
@ -83,7 +84,7 @@ The following functions provide locale-independent string to number conversions.
|
|||
|
||||
.. c:function:: char* PyOS_double_to_string(double val, char format_code, int precision, int flags, int *ptype)
|
||||
|
||||
Convert a :c:type:`double` *val* to a string using supplied
|
||||
Convert a :c:expr:`double` *val* to a string using supplied
|
||||
*format_code*, *precision*, and *flags*.
|
||||
|
||||
*format_code* must be one of ``'e'``, ``'E'``, ``'f'``, ``'F'``,
|
||||
|
|
@ -118,10 +119,10 @@ The following functions provide locale-independent string to number conversions.
|
|||
.. c:function:: int PyOS_stricmp(const char *s1, const char *s2)
|
||||
|
||||
Case insensitive comparison of strings. The function works almost
|
||||
identically to :c:func:`strcmp` except that it ignores the case.
|
||||
identically to :c:func:`!strcmp` except that it ignores the case.
|
||||
|
||||
|
||||
.. c:function:: int PyOS_strnicmp(const char *s1, const char *s2, Py_ssize_t size)
|
||||
|
||||
Case insensitive comparison of strings. The function works almost
|
||||
identically to :c:func:`strncmp` except that it ignores the case.
|
||||
identically to :c:func:`!strncmp` except that it ignores the case.
|
||||
|
|
|
|||
|
|
@ -8,11 +8,54 @@ DateTime Objects
|
|||
Various date and time objects are supplied by the :mod:`datetime` module.
|
||||
Before using any of these functions, the header file :file:`datetime.h` must be
|
||||
included in your source (note that this is not included by :file:`Python.h`),
|
||||
and the macro :c:macro:`PyDateTime_IMPORT` must be invoked, usually as part of
|
||||
and the macro :c:macro:`!PyDateTime_IMPORT` must be invoked, usually as part of
|
||||
the module initialisation function. The macro puts a pointer to a C structure
|
||||
into a static variable, :c:data:`PyDateTimeAPI`, that is used by the following
|
||||
into a static variable, :c:data:`!PyDateTimeAPI`, that is used by the following
|
||||
macros.
|
||||
|
||||
.. c:type:: PyDateTime_Date
|
||||
|
||||
This subtype of :c:type:`PyObject` represents a Python date object.
|
||||
|
||||
.. c:type:: PyDateTime_DateTime
|
||||
|
||||
This subtype of :c:type:`PyObject` represents a Python datetime object.
|
||||
|
||||
.. c:type:: PyDateTime_Time
|
||||
|
||||
This subtype of :c:type:`PyObject` represents a Python time object.
|
||||
|
||||
.. c:type:: PyDateTime_Delta
|
||||
|
||||
This subtype of :c:type:`PyObject` represents the difference between two datetime values.
|
||||
|
||||
.. c:var:: PyTypeObject PyDateTime_DateType
|
||||
|
||||
This instance of :c:type:`PyTypeObject` represents the Python date type;
|
||||
it is the same object as :class:`datetime.date` in the Python layer.
|
||||
|
||||
.. c:var:: PyTypeObject PyDateTime_DateTimeType
|
||||
|
||||
This instance of :c:type:`PyTypeObject` represents the Python datetime type;
|
||||
it is the same object as :class:`datetime.datetime` in the Python layer.
|
||||
|
||||
.. c:var:: PyTypeObject PyDateTime_TimeType
|
||||
|
||||
This instance of :c:type:`PyTypeObject` represents the Python time type;
|
||||
it is the same object as :class:`datetime.time` in the Python layer.
|
||||
|
||||
.. c:var:: PyTypeObject PyDateTime_DeltaType
|
||||
|
||||
This instance of :c:type:`PyTypeObject` represents Python type for
|
||||
the difference between two datetime values;
|
||||
it is the same object as :class:`datetime.timedelta` in the Python layer.
|
||||
|
||||
.. c:var:: PyTypeObject PyDateTime_TZInfoType
|
||||
|
||||
This instance of :c:type:`PyTypeObject` represents the Python time zone info type;
|
||||
it is the same object as :class:`datetime.tzinfo` in the Python layer.
|
||||
|
||||
|
||||
Macro for access to the UTC singleton:
|
||||
|
||||
.. c:var:: PyObject* PyDateTime_TimeZone_UTC
|
||||
|
|
@ -28,7 +71,7 @@ Type-check macros:
|
|||
.. c:function:: int PyDate_Check(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :c:data:`PyDateTime_DateType` or a subtype of
|
||||
:c:data:`PyDateTime_DateType`. *ob* must not be ``NULL``. This function always
|
||||
:c:data:`!PyDateTime_DateType`. *ob* must not be ``NULL``. This function always
|
||||
succeeds.
|
||||
|
||||
|
||||
|
|
@ -41,7 +84,7 @@ Type-check macros:
|
|||
.. c:function:: int PyDateTime_Check(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :c:data:`PyDateTime_DateTimeType` or a subtype of
|
||||
:c:data:`PyDateTime_DateTimeType`. *ob* must not be ``NULL``. This function always
|
||||
:c:data:`!PyDateTime_DateTimeType`. *ob* must not be ``NULL``. This function always
|
||||
succeeds.
|
||||
|
||||
|
||||
|
|
@ -54,7 +97,7 @@ Type-check macros:
|
|||
.. c:function:: int PyTime_Check(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :c:data:`PyDateTime_TimeType` or a subtype of
|
||||
:c:data:`PyDateTime_TimeType`. *ob* must not be ``NULL``. This function always
|
||||
:c:data:`!PyDateTime_TimeType`. *ob* must not be ``NULL``. This function always
|
||||
succeeds.
|
||||
|
||||
|
||||
|
|
@ -67,7 +110,7 @@ Type-check macros:
|
|||
.. c:function:: int PyDelta_Check(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :c:data:`PyDateTime_DeltaType` or a subtype of
|
||||
:c:data:`PyDateTime_DeltaType`. *ob* must not be ``NULL``. This function always
|
||||
:c:data:`!PyDateTime_DeltaType`. *ob* must not be ``NULL``. This function always
|
||||
succeeds.
|
||||
|
||||
|
||||
|
|
@ -80,7 +123,7 @@ Type-check macros:
|
|||
.. c:function:: int PyTZInfo_Check(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :c:data:`PyDateTime_TZInfoType` or a subtype of
|
||||
:c:data:`PyDateTime_TZInfoType`. *ob* must not be ``NULL``. This function always
|
||||
:c:data:`!PyDateTime_TZInfoType`. *ob* must not be ``NULL``. This function always
|
||||
succeeds.
|
||||
|
||||
|
||||
|
|
@ -132,14 +175,16 @@ Macros to create objects:
|
|||
resulting number of microseconds and seconds lie in the ranges documented for
|
||||
:class:`datetime.timedelta` objects.
|
||||
|
||||
.. c:function:: PyObject* PyTimeZone_FromOffset(PyDateTime_DeltaType* offset)
|
||||
|
||||
.. c:function:: PyObject* PyTimeZone_FromOffset(PyObject *offset)
|
||||
|
||||
Return a :class:`datetime.timezone` object with an unnamed fixed offset
|
||||
represented by the *offset* argument.
|
||||
|
||||
.. versionadded:: 3.7
|
||||
|
||||
.. c:function:: PyObject* PyTimeZone_FromOffsetAndName(PyDateTime_DeltaType* offset, PyUnicode* name)
|
||||
|
||||
.. c:function:: PyObject* PyTimeZone_FromOffsetAndName(PyObject *offset, PyObject *name)
|
||||
|
||||
Return a :class:`datetime.timezone` object with a fixed offset represented
|
||||
by the *offset* argument and with tzname *name*.
|
||||
|
|
@ -148,8 +193,8 @@ Macros to create objects:
|
|||
|
||||
|
||||
Macros to extract fields from date objects. The argument must be an instance of
|
||||
:c:data:`PyDateTime_Date`, including subclasses (such as
|
||||
:c:data:`PyDateTime_DateTime`). The argument must not be ``NULL``, and the type is
|
||||
:c:type:`PyDateTime_Date`, including subclasses (such as
|
||||
:c:type:`PyDateTime_DateTime`). The argument must not be ``NULL``, and the type is
|
||||
not checked:
|
||||
|
||||
.. c:function:: int PyDateTime_GET_YEAR(PyDateTime_Date *o)
|
||||
|
|
@ -168,7 +213,7 @@ not checked:
|
|||
|
||||
|
||||
Macros to extract fields from datetime objects. The argument must be an
|
||||
instance of :c:data:`PyDateTime_DateTime`, including subclasses. The argument
|
||||
instance of :c:type:`PyDateTime_DateTime`, including subclasses. The argument
|
||||
must not be ``NULL``, and the type is not checked:
|
||||
|
||||
.. c:function:: int PyDateTime_DATE_GET_HOUR(PyDateTime_DateTime *o)
|
||||
|
|
@ -190,14 +235,23 @@ must not be ``NULL``, and the type is not checked:
|
|||
|
||||
Return the microsecond, as an int from 0 through 999999.
|
||||
|
||||
|
||||
.. c:function:: int PyDateTime_DATE_GET_FOLD(PyDateTime_DateTime *o)
|
||||
|
||||
Return the fold, as an int from 0 through 1.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDateTime_DATE_GET_TZINFO(PyDateTime_DateTime *o)
|
||||
|
||||
Return the tzinfo (which may be ``None``).
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
|
||||
Macros to extract fields from time objects. The argument must be an instance of
|
||||
:c:data:`PyDateTime_Time`, including subclasses. The argument must not be ``NULL``,
|
||||
:c:type:`PyDateTime_Time`, including subclasses. The argument must not be ``NULL``,
|
||||
and the type is not checked:
|
||||
|
||||
.. c:function:: int PyDateTime_TIME_GET_HOUR(PyDateTime_Time *o)
|
||||
|
|
@ -219,6 +273,14 @@ and the type is not checked:
|
|||
|
||||
Return the microsecond, as an int from 0 through 999999.
|
||||
|
||||
|
||||
.. c:function:: int PyDateTime_TIME_GET_FOLD(PyDateTime_Time *o)
|
||||
|
||||
Return the fold, as an int from 0 through 1.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDateTime_TIME_GET_TZINFO(PyDateTime_Time *o)
|
||||
|
||||
Return the tzinfo (which may be ``None``).
|
||||
|
|
@ -227,7 +289,7 @@ and the type is not checked:
|
|||
|
||||
|
||||
Macros to extract fields from time delta objects. The argument must be an
|
||||
instance of :c:data:`PyDateTime_Delta`, including subclasses. The argument must
|
||||
instance of :c:type:`PyDateTime_Delta`, including subclasses. The argument must
|
||||
not be ``NULL``, and the type is not checked:
|
||||
|
||||
.. c:function:: int PyDateTime_DELTA_GET_DAYS(PyDateTime_Delta *o)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
Dictionary Objects
|
||||
------------------
|
||||
|
||||
.. index:: object: dictionary
|
||||
.. index:: pair: object; dictionary
|
||||
|
||||
|
||||
.. c:type:: PyDictObject
|
||||
|
|
@ -55,6 +55,15 @@ Dictionary Objects
|
|||
This is equivalent to the Python expression ``key in p``.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_ContainsString(PyObject *p, const char *key)
|
||||
|
||||
This is the same as :c:func:`PyDict_Contains`, but *key* is specified as a
|
||||
:c:expr:`const char*` UTF-8 encoded bytes string, rather than a
|
||||
:c:expr:`PyObject*`.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDict_Copy(PyObject *p)
|
||||
|
||||
Return a new dictionary that contains the same key-value pairs as *p*.
|
||||
|
|
@ -70,17 +79,14 @@ Dictionary Objects
|
|||
|
||||
.. c:function:: int PyDict_SetItemString(PyObject *p, const char *key, PyObject *val)
|
||||
|
||||
.. index:: single: PyUnicode_FromString()
|
||||
|
||||
Insert *val* into the dictionary *p* using *key* as a key. *key* should
|
||||
be a :c:type:`const char*`. The key object is created using
|
||||
``PyUnicode_FromString(key)``. Return ``0`` on success or ``-1`` on
|
||||
failure. This function *does not* steal a reference to *val*.
|
||||
This is the same as :c:func:`PyDict_SetItem`, but *key* is
|
||||
specified as a :c:expr:`const char*` UTF-8 encoded bytes string,
|
||||
rather than a :c:expr:`PyObject*`.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_DelItem(PyObject *p, PyObject *key)
|
||||
|
||||
Remove the entry in dictionary *p* with key *key*. *key* must be hashable;
|
||||
Remove the entry in dictionary *p* with key *key*. *key* must be :term:`hashable`;
|
||||
if it isn't, :exc:`TypeError` is raised.
|
||||
If *key* is not in the dictionary, :exc:`KeyError` is raised.
|
||||
Return ``0`` on success or ``-1`` on failure.
|
||||
|
|
@ -88,19 +94,37 @@ Dictionary Objects
|
|||
|
||||
.. c:function:: int PyDict_DelItemString(PyObject *p, const char *key)
|
||||
|
||||
Remove the entry in dictionary *p* which has a key specified by the string *key*.
|
||||
If *key* is not in the dictionary, :exc:`KeyError` is raised.
|
||||
Return ``0`` on success or ``-1`` on failure.
|
||||
This is the same as :c:func:`PyDict_DelItem`, but *key* is
|
||||
specified as a :c:expr:`const char*` UTF-8 encoded bytes string,
|
||||
rather than a :c:expr:`PyObject*`.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_GetItemRef(PyObject *p, PyObject *key, PyObject **result)
|
||||
|
||||
Return a new :term:`strong reference` to the object from dictionary *p*
|
||||
which has a key *key*:
|
||||
|
||||
* If the key is present, set *\*result* to a new :term:`strong reference`
|
||||
to the value and return ``1``.
|
||||
* If the key is missing, set *\*result* to ``NULL`` and return ``0``.
|
||||
* On error, raise an exception and return ``-1``.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
See also the :c:func:`PyObject_GetItem` function.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDict_GetItem(PyObject *p, PyObject *key)
|
||||
|
||||
Return the object from dictionary *p* which has a key *key*. Return ``NULL``
|
||||
if the key *key* is not present, but *without* setting an exception.
|
||||
Return a :term:`borrowed reference` to the object from dictionary *p* which
|
||||
has a key *key*. Return ``NULL`` if the key *key* is missing *without*
|
||||
setting an exception.
|
||||
|
||||
Note that exceptions which occur while calling :meth:`__hash__` and
|
||||
:meth:`__eq__` methods will get suppressed.
|
||||
To get error reporting use :c:func:`PyDict_GetItemWithError()` instead.
|
||||
.. note::
|
||||
|
||||
Exceptions that occur while this calls :meth:`~object.__hash__` and
|
||||
:meth:`~object.__eq__` methods are silently ignored.
|
||||
Prefer the :c:func:`PyDict_GetItemWithError` function instead.
|
||||
|
||||
.. versionchanged:: 3.10
|
||||
Calling this API without :term:`GIL` held had been allowed for historical
|
||||
|
|
@ -118,12 +142,25 @@ Dictionary Objects
|
|||
.. c:function:: PyObject* PyDict_GetItemString(PyObject *p, const char *key)
|
||||
|
||||
This is the same as :c:func:`PyDict_GetItem`, but *key* is specified as a
|
||||
:c:type:`const char*`, rather than a :c:type:`PyObject*`.
|
||||
:c:expr:`const char*` UTF-8 encoded bytes string, rather than a
|
||||
:c:expr:`PyObject*`.
|
||||
|
||||
Note that exceptions which occur while calling :meth:`__hash__` and
|
||||
:meth:`__eq__` methods and creating a temporary string object
|
||||
will get suppressed.
|
||||
To get error reporting use :c:func:`PyDict_GetItemWithError()` instead.
|
||||
.. note::
|
||||
|
||||
Exceptions that occur while this calls :meth:`~object.__hash__` and
|
||||
:meth:`~object.__eq__` methods or while creating the temporary :class:`str`
|
||||
object are silently ignored.
|
||||
Prefer using the :c:func:`PyDict_GetItemWithError` function with your own
|
||||
:c:func:`PyUnicode_FromString` *key* instead.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_GetItemStringRef(PyObject *p, const char *key, PyObject **result)
|
||||
|
||||
Similar than :c:func:`PyDict_GetItemRef`, but *key* is specified as a
|
||||
:c:expr:`const char*` UTF-8 encoded bytes string, rather than a
|
||||
:c:expr:`PyObject*`.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *defaultobj)
|
||||
|
|
@ -136,6 +173,33 @@ Dictionary Objects
|
|||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
|
||||
.. c:function:: int PyDict_Pop(PyObject *p, PyObject *key, PyObject **result)
|
||||
|
||||
Remove *key* from dictionary *p* and optionally return the removed value.
|
||||
Do not raise :exc:`KeyError` if the key missing.
|
||||
|
||||
- If the key is present, set *\*result* to a new reference to the removed
|
||||
value if *result* is not ``NULL``, and return ``1``.
|
||||
- If the key is missing, set *\*result* to ``NULL`` if *result* is not
|
||||
``NULL``, and return ``0``.
|
||||
- On error, raise an exception and return ``-1``.
|
||||
|
||||
This is similar to :meth:`dict.pop`, but without the default value and
|
||||
not raising :exc:`KeyError` if the key missing.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. c:function:: int PyDict_PopString(PyObject *p, const char *key, PyObject **result)
|
||||
|
||||
Similar to :c:func:`PyDict_Pop`, but *key* is specified as a
|
||||
:c:expr:`const char*` UTF-8 encoded bytes string, rather than a
|
||||
:c:expr:`PyObject*`.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDict_Items(PyObject *p)
|
||||
|
||||
Return a :c:type:`PyListObject` containing all the items from the dictionary.
|
||||
|
|
@ -154,7 +218,7 @@ Dictionary Objects
|
|||
|
||||
.. c:function:: Py_ssize_t PyDict_Size(PyObject *p)
|
||||
|
||||
.. index:: builtin: len
|
||||
.. index:: pair: built-in function; len
|
||||
|
||||
Return the number of items in the dictionary. This is equivalent to
|
||||
``len(p)`` on a dictionary.
|
||||
|
|
@ -167,7 +231,7 @@ Dictionary Objects
|
|||
prior to the first call to this function to start the iteration; the
|
||||
function returns true for each pair in the dictionary, and false once all
|
||||
pairs have been reported. The parameters *pkey* and *pvalue* should either
|
||||
point to :c:type:`PyObject*` variables that will be filled in with each key
|
||||
point to :c:expr:`PyObject*` variables that will be filled in with each key
|
||||
and value, respectively, or may be ``NULL``. Any references returned through
|
||||
them are borrowed. *ppos* should not be altered during iteration. Its
|
||||
value represents offsets within the internal dictionary structure, and
|
||||
|
|
@ -238,3 +302,86 @@ Dictionary Objects
|
|||
for key, value in seq2:
|
||||
if override or key not in a:
|
||||
a[key] = value
|
||||
|
||||
.. c:function:: int PyDict_AddWatcher(PyDict_WatchCallback callback)
|
||||
|
||||
Register *callback* as a dictionary watcher. Return a non-negative integer
|
||||
id which must be passed to future calls to :c:func:`PyDict_Watch`. In case
|
||||
of error (e.g. no more watcher IDs available), return ``-1`` and set an
|
||||
exception.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
.. c:function:: int PyDict_ClearWatcher(int watcher_id)
|
||||
|
||||
Clear watcher identified by *watcher_id* previously returned from
|
||||
:c:func:`PyDict_AddWatcher`. Return ``0`` on success, ``-1`` on error (e.g.
|
||||
if the given *watcher_id* was never registered.)
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
.. c:function:: int PyDict_Watch(int watcher_id, PyObject *dict)
|
||||
|
||||
Mark dictionary *dict* as watched. The callback granted *watcher_id* by
|
||||
:c:func:`PyDict_AddWatcher` will be called when *dict* is modified or
|
||||
deallocated. Return ``0`` on success or ``-1`` on error.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
.. c:function:: int PyDict_Unwatch(int watcher_id, PyObject *dict)
|
||||
|
||||
Mark dictionary *dict* as no longer watched. The callback granted
|
||||
*watcher_id* by :c:func:`PyDict_AddWatcher` will no longer be called when
|
||||
*dict* is modified or deallocated. The dict must previously have been
|
||||
watched by this watcher. Return ``0`` on success or ``-1`` on error.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
.. c:type:: PyDict_WatchEvent
|
||||
|
||||
Enumeration of possible dictionary watcher events: ``PyDict_EVENT_ADDED``,
|
||||
``PyDict_EVENT_MODIFIED``, ``PyDict_EVENT_DELETED``, ``PyDict_EVENT_CLONED``,
|
||||
``PyDict_EVENT_CLEARED``, or ``PyDict_EVENT_DEALLOCATED``.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
.. c:type:: int (*PyDict_WatchCallback)(PyDict_WatchEvent event, PyObject *dict, PyObject *key, PyObject *new_value)
|
||||
|
||||
Type of a dict watcher callback function.
|
||||
|
||||
If *event* is ``PyDict_EVENT_CLEARED`` or ``PyDict_EVENT_DEALLOCATED``, both
|
||||
*key* and *new_value* will be ``NULL``. If *event* is ``PyDict_EVENT_ADDED``
|
||||
or ``PyDict_EVENT_MODIFIED``, *new_value* will be the new value for *key*.
|
||||
If *event* is ``PyDict_EVENT_DELETED``, *key* is being deleted from the
|
||||
dictionary and *new_value* will be ``NULL``.
|
||||
|
||||
``PyDict_EVENT_CLONED`` occurs when *dict* was previously empty and another
|
||||
dict is merged into it. To maintain efficiency of this operation, per-key
|
||||
``PyDict_EVENT_ADDED`` events are not issued in this case; instead a
|
||||
single ``PyDict_EVENT_CLONED`` is issued, and *key* will be the source
|
||||
dictionary.
|
||||
|
||||
The callback may inspect but must not modify *dict*; doing so could have
|
||||
unpredictable effects, including infinite recursion. Do not trigger Python
|
||||
code execution in the callback, as it could modify the dict as a side effect.
|
||||
|
||||
If *event* is ``PyDict_EVENT_DEALLOCATED``, taking a new reference in the
|
||||
callback to the about-to-be-destroyed dictionary will resurrect it and
|
||||
prevent it from being freed at this time. When the resurrected object is
|
||||
destroyed later, any watcher callbacks active at that time will be called
|
||||
again.
|
||||
|
||||
Callbacks occur before the notified modification to *dict* takes place, so
|
||||
the prior state of *dict* can be inspected.
|
||||
|
||||
If the callback sets an exception, it must return ``-1``; this exception will
|
||||
be printed as an unraisable exception using :c:func:`PyErr_WriteUnraisable`.
|
||||
Otherwise it should return ``0``.
|
||||
|
||||
There may already be a pending exception set on entry to the callback. In
|
||||
this case, the callback should return ``0`` with the same exception still
|
||||
set. This means the callback may not call any other API that can set an
|
||||
exception unless it saves and clears the exception state first, and restores
|
||||
it before returning.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ there is a global indicator (per thread) of the last error that occurred. Most
|
|||
C API functions don't clear this on success, but will set it to indicate the
|
||||
cause of the error on failure. Most C API functions also return an error
|
||||
indicator, usually ``NULL`` if they are supposed to return a pointer, or ``-1``
|
||||
if they return an integer (exception: the :c:func:`PyArg_\*` functions
|
||||
if they return an integer (exception: the ``PyArg_*`` functions
|
||||
return ``1`` for success and ``0`` for failure).
|
||||
|
||||
Concretely, the error indicator consists of three object pointers: the
|
||||
|
|
@ -60,9 +60,14 @@ Printing and clearing
|
|||
Call this function **only** when the error indicator is set. Otherwise it
|
||||
will cause a fatal error!
|
||||
|
||||
If *set_sys_last_vars* is nonzero, the variables :data:`sys.last_type`,
|
||||
:data:`sys.last_value` and :data:`sys.last_traceback` will be set to the
|
||||
type, value and traceback of the printed exception, respectively.
|
||||
If *set_sys_last_vars* is nonzero, the variable :data:`sys.last_exc` is
|
||||
set to the printed exception. For backwards compatibility, the
|
||||
deprecated variables :data:`sys.last_type`, :data:`sys.last_value` and
|
||||
:data:`sys.last_traceback` are also set to the type, value and traceback
|
||||
of this exception, respectively.
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
The setting of :data:`sys.last_exc` was added.
|
||||
|
||||
|
||||
.. c:function:: void PyErr_Print()
|
||||
|
|
@ -78,14 +83,41 @@ Printing and clearing
|
|||
This utility function prints a warning message to ``sys.stderr`` when an
|
||||
exception has been set but it is impossible for the interpreter to actually
|
||||
raise the exception. It is used, for example, when an exception occurs in an
|
||||
:meth:`__del__` method.
|
||||
:meth:`~object.__del__` method.
|
||||
|
||||
The function is called with a single argument *obj* that identifies the context
|
||||
in which the unraisable exception occurred. If possible,
|
||||
the repr of *obj* will be printed in the warning message.
|
||||
If *obj* is ``NULL``, only the traceback is printed.
|
||||
|
||||
An exception must be set when calling this function.
|
||||
|
||||
.. versionchanged:: 3.4
|
||||
Print a traceback. Print only traceback if *obj* is ``NULL``.
|
||||
|
||||
.. versionchanged:: 3.8
|
||||
Use :func:`sys.unraisablehook`.
|
||||
|
||||
|
||||
.. c:function:: void PyErr_FormatUnraisable(const char *format, ...)
|
||||
|
||||
Similar to :c:func:`PyErr_WriteUnraisable`, but the *format* and subsequent
|
||||
parameters help format the warning message; they have the same meaning and
|
||||
values as in :c:func:`PyUnicode_FromFormat`.
|
||||
``PyErr_WriteUnraisable(obj)`` is roughtly equivalent to
|
||||
``PyErr_FormatUnraisable("Exception ignored in: %R, obj)``.
|
||||
If *format* is ``NULL``, only the traceback is printed.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. c:function:: void PyErr_DisplayException(PyObject *exc)
|
||||
|
||||
Print the standard traceback display of ``exc`` to ``sys.stderr``, including
|
||||
chained exceptions and notes.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
|
||||
Raising exceptions
|
||||
==================
|
||||
|
|
@ -99,7 +131,8 @@ For convenience, some of these functions will always return a
|
|||
|
||||
This is the most common way to set the error indicator. The first argument
|
||||
specifies the exception type; it is normally one of the standard exceptions,
|
||||
e.g. :c:data:`PyExc_RuntimeError`. You need not increment its reference count.
|
||||
e.g. :c:data:`PyExc_RuntimeError`. You need not create a new
|
||||
:term:`strong reference` to it (e.g. with :c:func:`Py_INCREF`).
|
||||
The second argument is an error message; it is decoded from ``'utf-8'``.
|
||||
|
||||
|
||||
|
|
@ -152,9 +185,9 @@ For convenience, some of these functions will always return a
|
|||
This is a convenience function to raise an exception when a C library function
|
||||
has returned an error and set the C variable :c:data:`errno`. It constructs a
|
||||
tuple object whose first item is the integer :c:data:`errno` value and whose
|
||||
second item is the corresponding error message (gotten from :c:func:`strerror`),
|
||||
second item is the corresponding error message (gotten from :c:func:`!strerror`),
|
||||
and then calls ``PyErr_SetObject(type, object)``. On Unix, when the
|
||||
:c:data:`errno` value is :const:`EINTR`, indicating an interrupted system call,
|
||||
:c:data:`errno` value is :c:macro:`!EINTR`, indicating an interrupted system call,
|
||||
this calls :c:func:`PyErr_CheckSignals`, and if that set the error indicator,
|
||||
leaves it set to that. The function always returns ``NULL``, so a wrapper
|
||||
function around a system call can write ``return PyErr_SetFromErrno(type);``
|
||||
|
|
@ -166,7 +199,7 @@ For convenience, some of these functions will always return a
|
|||
Similar to :c:func:`PyErr_SetFromErrno`, with the additional behavior that if
|
||||
*filenameObject* is not ``NULL``, it is passed to the constructor of *type* as
|
||||
a third parameter. In the case of :exc:`OSError` exception,
|
||||
this is used to define the :attr:`filename` attribute of the
|
||||
this is used to define the :attr:`!filename` attribute of the
|
||||
exception instance.
|
||||
|
||||
|
||||
|
|
@ -189,12 +222,12 @@ For convenience, some of these functions will always return a
|
|||
.. c:function:: PyObject* PyErr_SetFromWindowsErr(int ierr)
|
||||
|
||||
This is a convenience function to raise :exc:`WindowsError`. If called with
|
||||
*ierr* of :c:data:`0`, the error code returned by a call to :c:func:`GetLastError`
|
||||
is used instead. It calls the Win32 function :c:func:`FormatMessage` to retrieve
|
||||
the Windows description of error code given by *ierr* or :c:func:`GetLastError`,
|
||||
*ierr* of ``0``, the error code returned by a call to :c:func:`!GetLastError`
|
||||
is used instead. It calls the Win32 function :c:func:`!FormatMessage` to retrieve
|
||||
the Windows description of error code given by *ierr* or :c:func:`!GetLastError`,
|
||||
then it constructs a tuple object whose first item is the *ierr* value and whose
|
||||
second item is the corresponding error message (gotten from
|
||||
:c:func:`FormatMessage`), and then calls ``PyErr_SetObject(PyExc_WindowsError,
|
||||
:c:func:`!FormatMessage`), and then calls ``PyErr_SetObject(PyExc_WindowsError,
|
||||
object)``. This function always returns ``NULL``.
|
||||
|
||||
.. availability:: Windows.
|
||||
|
|
@ -210,17 +243,21 @@ For convenience, some of these functions will always return a
|
|||
|
||||
.. c:function:: PyObject* PyErr_SetFromWindowsErrWithFilename(int ierr, const char *filename)
|
||||
|
||||
Similar to :c:func:`PyErr_SetFromWindowsErrWithFilenameObject`, but the
|
||||
filename is given as a C string. *filename* is decoded from the filesystem
|
||||
encoding (:func:`os.fsdecode`).
|
||||
Similar to :c:func:`PyErr_SetFromWindowsErr`, with the additional behavior
|
||||
that if *filename* is not ``NULL``, it is decoded from the filesystem
|
||||
encoding (:func:`os.fsdecode`) and passed to the constructor of
|
||||
:exc:`OSError` as a third parameter to be used to define the
|
||||
:attr:`!filename` attribute of the exception instance.
|
||||
|
||||
.. availability:: Windows.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilenameObject(PyObject *type, int ierr, PyObject *filename)
|
||||
|
||||
Similar to :c:func:`PyErr_SetFromWindowsErrWithFilenameObject`, with an
|
||||
additional parameter specifying the exception type to be raised.
|
||||
Similar to :c:func:`PyErr_SetExcFromWindowsErr`, with the additional behavior
|
||||
that if *filename* is not ``NULL``, it is passed to the constructor of
|
||||
:exc:`OSError` as a third parameter to be used to define the
|
||||
:attr:`!filename` attribute of the exception instance.
|
||||
|
||||
.. availability:: Windows.
|
||||
|
||||
|
|
@ -253,6 +290,14 @@ For convenience, some of these functions will always return a
|
|||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyErr_SetImportErrorSubclass(PyObject *exception, PyObject *msg, PyObject *name, PyObject *path)
|
||||
|
||||
Much like :c:func:`PyErr_SetImportError` but this function allows for
|
||||
specifying a subclass of :exc:`ImportError` to raise.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
|
||||
|
||||
.. c:function:: void PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset)
|
||||
|
||||
Set file, line, and offset information for the current exception. If the
|
||||
|
|
@ -273,7 +318,7 @@ For convenience, some of these functions will always return a
|
|||
|
||||
.. c:function:: void PyErr_SyntaxLocation(const char *filename, int lineno)
|
||||
|
||||
Like :c:func:`PyErr_SyntaxLocationEx`, but the col_offset parameter is
|
||||
Like :c:func:`PyErr_SyntaxLocationEx`, but the *col_offset* parameter is
|
||||
omitted.
|
||||
|
||||
|
||||
|
|
@ -320,19 +365,12 @@ an error value).
|
|||
:mod:`warnings` module and the :option:`-W` option in the command line
|
||||
documentation. There is no C API for warning control.
|
||||
|
||||
.. c:function:: PyObject* PyErr_SetImportErrorSubclass(PyObject *exception, PyObject *msg, PyObject *name, PyObject *path)
|
||||
|
||||
Much like :c:func:`PyErr_SetImportError` but this function allows for
|
||||
specifying a subclass of :exc:`ImportError` to raise.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
|
||||
|
||||
.. c:function:: int PyErr_WarnExplicitObject(PyObject *category, PyObject *message, PyObject *filename, int lineno, PyObject *module, PyObject *registry)
|
||||
|
||||
Issue a warning message with explicit control over all warning attributes. This
|
||||
is a straightforward wrapper around the Python function
|
||||
:func:`warnings.warn_explicit`, see there for more information. The *module*
|
||||
:func:`warnings.warn_explicit`; see there for more information. The *module*
|
||||
and *registry* arguments may be set to ``NULL`` to get the default effect
|
||||
described there.
|
||||
|
||||
|
|
@ -369,7 +407,7 @@ Querying the error indicator
|
|||
.. c:function:: PyObject* PyErr_Occurred()
|
||||
|
||||
Test whether the error indicator is set. If set, return the exception *type*
|
||||
(the first argument to the last call to one of the :c:func:`PyErr_Set\*`
|
||||
(the first argument to the last call to one of the ``PyErr_Set*``
|
||||
functions or to :c:func:`PyErr_Restore`). If not set, return ``NULL``. You do not
|
||||
own a reference to the return value, so you do not need to :c:func:`Py_DECREF`
|
||||
it.
|
||||
|
|
@ -399,8 +437,48 @@ Querying the error indicator
|
|||
recursively in subtuples) are searched for a match.
|
||||
|
||||
|
||||
.. c:function:: PyObject *PyErr_GetRaisedException(void)
|
||||
|
||||
Return the exception currently being raised, clearing the error indicator at
|
||||
the same time. Return ``NULL`` if the error indicator is not set.
|
||||
|
||||
This function is used by code that needs to catch exceptions,
|
||||
or code that needs to save and restore the error indicator temporarily.
|
||||
|
||||
For example::
|
||||
|
||||
{
|
||||
PyObject *exc = PyErr_GetRaisedException();
|
||||
|
||||
/* ... code that might produce other errors ... */
|
||||
|
||||
PyErr_SetRaisedException(exc);
|
||||
}
|
||||
|
||||
.. seealso:: :c:func:`PyErr_GetHandledException`,
|
||||
to save the exception currently being handled.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
|
||||
.. c:function:: void PyErr_SetRaisedException(PyObject *exc)
|
||||
|
||||
Set *exc* as the exception currently being raised,
|
||||
clearing the existing exception if one is set.
|
||||
|
||||
.. warning::
|
||||
|
||||
This call steals a reference to *exc*, which must be a valid exception.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
|
||||
.. c:function:: void PyErr_Fetch(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback)
|
||||
|
||||
.. deprecated:: 3.12
|
||||
|
||||
Use :c:func:`PyErr_GetRaisedException` instead.
|
||||
|
||||
Retrieve the error indicator into three variables whose addresses are passed.
|
||||
If the error indicator is not set, set all three variables to ``NULL``. If it is
|
||||
set, it will be cleared and you own a reference to each object retrieved. The
|
||||
|
|
@ -408,8 +486,10 @@ Querying the error indicator
|
|||
|
||||
.. note::
|
||||
|
||||
This function is normally only used by code that needs to catch exceptions or
|
||||
by code that needs to save and restore the error indicator temporarily, e.g.::
|
||||
This function is normally only used by legacy code that needs to catch
|
||||
exceptions or save and restore the error indicator temporarily.
|
||||
|
||||
For example::
|
||||
|
||||
{
|
||||
PyObject *type, *value, *traceback;
|
||||
|
|
@ -423,8 +503,14 @@ Querying the error indicator
|
|||
|
||||
.. c:function:: void PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)
|
||||
|
||||
Set the error indicator from the three objects. If the error indicator is
|
||||
already set, it is cleared first. If the objects are ``NULL``, the error
|
||||
.. deprecated:: 3.12
|
||||
|
||||
Use :c:func:`PyErr_SetRaisedException` instead.
|
||||
|
||||
Set the error indicator from the three objects,
|
||||
*type*, *value*, and *traceback*,
|
||||
clearing the existing exception if one is set.
|
||||
If the objects are ``NULL``, the error
|
||||
indicator is cleared. Do not pass a ``NULL`` type and non-``NULL`` value or
|
||||
traceback. The exception type should be a class. Do not pass an invalid
|
||||
exception type or value. (Violating these rules will cause subtle problems
|
||||
|
|
@ -435,12 +521,17 @@ Querying the error indicator
|
|||
|
||||
.. note::
|
||||
|
||||
This function is normally only used by code that needs to save and restore the
|
||||
error indicator temporarily. Use :c:func:`PyErr_Fetch` to save the current
|
||||
error indicator.
|
||||
This function is normally only used by legacy code that needs to
|
||||
save and restore the error indicator temporarily.
|
||||
Use :c:func:`PyErr_Fetch` to save the current error indicator.
|
||||
|
||||
|
||||
.. c:function:: void PyErr_NormalizeException(PyObject**exc, PyObject**val, PyObject**tb)
|
||||
.. c:function:: void PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
|
||||
|
||||
.. deprecated:: 3.12
|
||||
|
||||
Use :c:func:`PyErr_GetRaisedException` instead,
|
||||
to avoid any possible de-normalization.
|
||||
|
||||
Under certain circumstances, the values returned by :c:func:`PyErr_Fetch` below
|
||||
can be "unnormalized", meaning that ``*exc`` is a class object but ``*val`` is
|
||||
|
|
@ -450,7 +541,8 @@ Querying the error indicator
|
|||
|
||||
.. note::
|
||||
|
||||
This function *does not* implicitly set the ``__traceback__``
|
||||
This function *does not* implicitly set the
|
||||
:attr:`~BaseException.__traceback__`
|
||||
attribute on the exception value. If setting the traceback
|
||||
appropriately is desired, the following additional snippet is needed::
|
||||
|
||||
|
|
@ -459,12 +551,46 @@ Querying the error indicator
|
|||
}
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyErr_GetHandledException(void)
|
||||
|
||||
Retrieve the active exception instance, as would be returned by :func:`sys.exception`.
|
||||
This refers to an exception that was *already caught*, not to an exception that was
|
||||
freshly raised. Returns a new reference to the exception or ``NULL``.
|
||||
Does not modify the interpreter's exception state.
|
||||
|
||||
.. note::
|
||||
|
||||
This function is not normally used by code that wants to handle exceptions.
|
||||
Rather, it can be used when code needs to save and restore the exception
|
||||
state temporarily. Use :c:func:`PyErr_SetHandledException` to restore or
|
||||
clear the exception state.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
.. c:function:: void PyErr_SetHandledException(PyObject *exc)
|
||||
|
||||
Set the active exception, as known from ``sys.exception()``. This refers
|
||||
to an exception that was *already caught*, not to an exception that was
|
||||
freshly raised.
|
||||
To clear the exception state, pass ``NULL``.
|
||||
|
||||
.. note::
|
||||
|
||||
This function is not normally used by code that wants to handle exceptions.
|
||||
Rather, it can be used when code needs to save and restore the exception
|
||||
state temporarily. Use :c:func:`PyErr_GetHandledException` to get the exception
|
||||
state.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
.. c:function:: void PyErr_GetExcInfo(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback)
|
||||
|
||||
Retrieve the exception info, as known from ``sys.exc_info()``. This refers
|
||||
to an exception that was *already caught*, not to an exception that was
|
||||
freshly raised. Returns new references for the three objects, any of which
|
||||
may be ``NULL``. Does not modify the exception info state.
|
||||
Retrieve the old-style representation of the exception info, as known from
|
||||
:func:`sys.exc_info`. This refers to an exception that was *already caught*,
|
||||
not to an exception that was freshly raised. Returns new references for the
|
||||
three objects, any of which may be ``NULL``. Does not modify the exception
|
||||
info state. This function is kept for backwards compatibility. Prefer using
|
||||
:c:func:`PyErr_GetHandledException`.
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
@ -482,7 +608,8 @@ Querying the error indicator
|
|||
to an exception that was *already caught*, not to an exception that was
|
||||
freshly raised. This function steals the references of the arguments.
|
||||
To clear the exception state, pass ``NULL`` for all three arguments.
|
||||
For general rules about the three arguments, see :c:func:`PyErr_Restore`.
|
||||
This function is kept for backwards compatibility. Prefer using
|
||||
:c:func:`PyErr_SetHandledException`.
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
@ -493,6 +620,12 @@ Querying the error indicator
|
|||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
The ``type`` and ``traceback`` arguments are no longer used and
|
||||
can be NULL. The interpreter now derives them from the exception
|
||||
instance (the ``value`` argument). The function still steals
|
||||
references of all three arguments.
|
||||
|
||||
|
||||
Signal Handling
|
||||
===============
|
||||
|
|
@ -501,7 +634,7 @@ Signal Handling
|
|||
.. c:function:: int PyErr_CheckSignals()
|
||||
|
||||
.. index::
|
||||
module: signal
|
||||
pair: module; signal
|
||||
single: SIGINT
|
||||
single: KeyboardInterrupt (built-in exception)
|
||||
|
||||
|
|
@ -525,18 +658,18 @@ Signal Handling
|
|||
be interruptible by user requests (such as by pressing Ctrl-C).
|
||||
|
||||
.. note::
|
||||
The default Python signal handler for :const:`SIGINT` raises the
|
||||
The default Python signal handler for :c:macro:`!SIGINT` raises the
|
||||
:exc:`KeyboardInterrupt` exception.
|
||||
|
||||
|
||||
.. c:function:: void PyErr_SetInterrupt()
|
||||
|
||||
.. index::
|
||||
module: signal
|
||||
pair: module; signal
|
||||
single: SIGINT
|
||||
single: KeyboardInterrupt (built-in exception)
|
||||
|
||||
Simulate the effect of a :const:`SIGINT` signal arriving.
|
||||
Simulate the effect of a :c:macro:`!SIGINT` signal arriving.
|
||||
This is equivalent to ``PyErr_SetInterruptEx(SIGINT)``.
|
||||
|
||||
.. note::
|
||||
|
|
@ -547,7 +680,7 @@ Signal Handling
|
|||
.. c:function:: int PyErr_SetInterruptEx(int signum)
|
||||
|
||||
.. index::
|
||||
module: signal
|
||||
pair: module; signal
|
||||
single: KeyboardInterrupt (built-in exception)
|
||||
|
||||
Simulate the effect of a signal arriving. The next time
|
||||
|
|
@ -560,7 +693,7 @@ Signal Handling
|
|||
to interrupt an operation).
|
||||
|
||||
If the given signal isn't handled by Python (it was set to
|
||||
:data:`signal.SIG_DFL` or :data:`signal.SIG_IGN`), it will be ignored.
|
||||
:py:const:`signal.SIG_DFL` or :py:const:`signal.SIG_IGN`), it will be ignored.
|
||||
|
||||
If *signum* is outside of the allowed range of signal numbers, ``-1``
|
||||
is returned. Otherwise, ``0`` is returned. The error indicator is
|
||||
|
|
@ -621,7 +754,8 @@ Exception Objects
|
|||
.. c:function:: PyObject* PyException_GetTraceback(PyObject *ex)
|
||||
|
||||
Return the traceback associated with the exception as a new reference, as
|
||||
accessible from Python through :attr:`__traceback__`. If there is no
|
||||
accessible from Python through the :attr:`~BaseException.__traceback__`
|
||||
attribute. If there is no
|
||||
traceback associated, this returns ``NULL``.
|
||||
|
||||
|
||||
|
|
@ -635,8 +769,8 @@ Exception Objects
|
|||
|
||||
Return the context (another exception instance during whose handling *ex* was
|
||||
raised) associated with the exception as a new reference, as accessible from
|
||||
Python through :attr:`__context__`. If there is no context associated, this
|
||||
returns ``NULL``.
|
||||
Python through the :attr:`~BaseException.__context__` attribute.
|
||||
If there is no context associated, this returns ``NULL``.
|
||||
|
||||
|
||||
.. c:function:: void PyException_SetContext(PyObject *ex, PyObject *ctx)
|
||||
|
|
@ -648,20 +782,44 @@ Exception Objects
|
|||
|
||||
.. c:function:: PyObject* PyException_GetCause(PyObject *ex)
|
||||
|
||||
Return the cause (either an exception instance, or :const:`None`,
|
||||
Return the cause (either an exception instance, or ``None``,
|
||||
set by ``raise ... from ...``) associated with the exception as a new
|
||||
reference, as accessible from Python through :attr:`__cause__`.
|
||||
reference, as accessible from Python through the
|
||||
:attr:`~BaseException.__cause__` attribute.
|
||||
|
||||
|
||||
.. c:function:: void PyException_SetCause(PyObject *ex, PyObject *cause)
|
||||
|
||||
Set the cause associated with the exception to *cause*. Use ``NULL`` to clear
|
||||
it. There is no type check to make sure that *cause* is either an exception
|
||||
instance or :const:`None`. This steals a reference to *cause*.
|
||||
instance or ``None``. This steals a reference to *cause*.
|
||||
|
||||
:attr:`__suppress_context__` is implicitly set to ``True`` by this function.
|
||||
The :attr:`~BaseException.__suppress_context__` attribute is implicitly set
|
||||
to ``True`` by this function.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyException_GetArgs(PyObject *ex)
|
||||
|
||||
Return :attr:`~BaseException.args` of exception *ex*.
|
||||
|
||||
|
||||
.. c:function:: void PyException_SetArgs(PyObject *ex, PyObject *args)
|
||||
|
||||
Set :attr:`~BaseException.args` of exception *ex* to *args*.
|
||||
|
||||
.. c:function:: PyObject* PyUnstable_Exc_PrepReraiseStar(PyObject *orig, PyObject *excs)
|
||||
|
||||
Implement part of the interpreter's implementation of :keyword:`!except*`.
|
||||
*orig* is the original exception that was caught, and *excs* is the list of
|
||||
the exceptions that need to be raised. This list contains the unhandled
|
||||
part of *orig*, if any, as well as the exceptions that were raised from the
|
||||
:keyword:`!except*` clauses (so they have a different traceback from *orig*) and
|
||||
those that were reraised (and have the same traceback as *orig*).
|
||||
Return the :exc:`ExceptionGroup` that needs to be reraised in the end, or
|
||||
``None`` if there is nothing to reraise.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
.. _unicodeexceptions:
|
||||
|
||||
Unicode Exception Objects
|
||||
|
|
@ -746,7 +904,7 @@ because the :ref:`call protocol <call>` takes care of recursion handling.
|
|||
|
||||
Marks a point where a recursive C-level call is about to be performed.
|
||||
|
||||
If :const:`USE_STACKCHECK` is defined, this function checks if the OS
|
||||
If :c:macro:`USE_STACKCHECK` is defined, this function checks if the OS
|
||||
stack overflowed using :c:func:`PyOS_CheckStack`. In this is the case, it
|
||||
sets a :exc:`MemoryError` and returns a nonzero value.
|
||||
|
||||
|
|
@ -759,7 +917,7 @@ because the :ref:`call protocol <call>` takes care of recursion handling.
|
|||
depth limit.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
This function is now also available in the limited API.
|
||||
This function is now also available in the :ref:`limited API <limited-c-api>`.
|
||||
|
||||
.. c:function:: void Py_LeaveRecursiveCall(void)
|
||||
|
||||
|
|
@ -767,7 +925,7 @@ because the :ref:`call protocol <call>` takes care of recursion handling.
|
|||
*successful* invocation of :c:func:`Py_EnterRecursiveCall`.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
This function is now also available in the limited API.
|
||||
This function is now also available in the :ref:`limited API <limited-c-api>`.
|
||||
|
||||
Properly implementing :c:member:`~PyTypeObject.tp_repr` for container types requires
|
||||
special recursion handling. In addition to protecting the stack,
|
||||
|
|
@ -806,7 +964,7 @@ Standard Exceptions
|
|||
|
||||
All standard Python exceptions are available as global variables whose names are
|
||||
``PyExc_`` followed by the Python exception name. These have the type
|
||||
:c:type:`PyObject*`; they are all class objects. For completeness, here are all
|
||||
:c:expr:`PyObject*`; they are all class objects. For completeness, here are all
|
||||
the variables:
|
||||
|
||||
.. index::
|
||||
|
|
@ -867,11 +1025,11 @@ the variables:
|
|||
+-----------------------------------------+---------------------------------+----------+
|
||||
| C Name | Python Name | Notes |
|
||||
+=========================================+=================================+==========+
|
||||
| :c:data:`PyExc_BaseException` | :exc:`BaseException` | \(1) |
|
||||
| :c:data:`PyExc_BaseException` | :exc:`BaseException` | [1]_ |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_Exception` | :exc:`Exception` | \(1) |
|
||||
| :c:data:`PyExc_Exception` | :exc:`Exception` | [1]_ |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_ArithmeticError` | :exc:`ArithmeticError` | \(1) |
|
||||
| :c:data:`PyExc_ArithmeticError` | :exc:`ArithmeticError` | [1]_ |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_AssertionError` | :exc:`AssertionError` | |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
|
|
@ -917,7 +1075,7 @@ the variables:
|
|||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_KeyboardInterrupt` | :exc:`KeyboardInterrupt` | |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_LookupError` | :exc:`LookupError` | \(1) |
|
||||
| :c:data:`PyExc_LookupError` | :exc:`LookupError` | [1]_ |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_MemoryError` | :exc:`MemoryError` | |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
|
|
@ -929,7 +1087,7 @@ the variables:
|
|||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_NotImplementedError` | :exc:`NotImplementedError` | |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_OSError` | :exc:`OSError` | \(1) |
|
||||
| :c:data:`PyExc_OSError` | :exc:`OSError` | [1]_ |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_OverflowError` | :exc:`OverflowError` | |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
|
|
@ -939,7 +1097,7 @@ the variables:
|
|||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_RecursionError` | :exc:`RecursionError` | |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_ReferenceError` | :exc:`ReferenceError` | \(2) |
|
||||
| :c:data:`PyExc_ReferenceError` | :exc:`ReferenceError` | |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_RuntimeError` | :exc:`RuntimeError` | |
|
||||
+-----------------------------------------+---------------------------------+----------+
|
||||
|
|
@ -1004,7 +1162,7 @@ These are compatibility aliases to :c:data:`PyExc_OSError`:
|
|||
+-------------------------------------+----------+
|
||||
| :c:data:`PyExc_IOError` | |
|
||||
+-------------------------------------+----------+
|
||||
| :c:data:`PyExc_WindowsError` | \(3) |
|
||||
| :c:data:`PyExc_WindowsError` | [2]_ |
|
||||
+-------------------------------------+----------+
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
|
|
@ -1012,10 +1170,10 @@ These are compatibility aliases to :c:data:`PyExc_OSError`:
|
|||
|
||||
Notes:
|
||||
|
||||
(1)
|
||||
.. [1]
|
||||
This is a base class for other standard exceptions.
|
||||
|
||||
(2)
|
||||
.. [2]
|
||||
Only defined on Windows; protect code that uses this by testing that the
|
||||
preprocessor macro ``MS_WINDOWS`` is defined.
|
||||
|
||||
|
|
@ -1026,7 +1184,7 @@ Standard Warning Categories
|
|||
|
||||
All standard Python warning categories are available as global variables whose
|
||||
names are ``PyExc_`` followed by the Python exception name. These have the type
|
||||
:c:type:`PyObject*`; they are all class objects. For completeness, here are all
|
||||
:c:expr:`PyObject*`; they are all class objects. For completeness, here are all
|
||||
the variables:
|
||||
|
||||
.. index::
|
||||
|
|
@ -1045,7 +1203,7 @@ the variables:
|
|||
+------------------------------------------+---------------------------------+----------+
|
||||
| C Name | Python Name | Notes |
|
||||
+==========================================+=================================+==========+
|
||||
| :c:data:`PyExc_Warning` | :exc:`Warning` | \(1) |
|
||||
| :c:data:`PyExc_Warning` | :exc:`Warning` | [3]_ |
|
||||
+------------------------------------------+---------------------------------+----------+
|
||||
| :c:data:`PyExc_BytesWarning` | :exc:`BytesWarning` | |
|
||||
+------------------------------------------+---------------------------------+----------+
|
||||
|
|
@ -1073,5 +1231,5 @@ the variables:
|
|||
|
||||
Notes:
|
||||
|
||||
(1)
|
||||
.. [3]
|
||||
This is a base class for other standard warning categories.
|
||||
|
|
|
|||
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