Compare commits

..

No commits in common. "main" and "v3.15.0a1" have entirely different histories.

1157 changed files with 31230 additions and 130486 deletions

View file

@ -1,73 +0,0 @@
{
"image": "ghcr.io/python/wasicontainer:latest",
"onCreateCommand": [
// Install common tooling.
"dnf",
"install",
"-y",
// For umask fix below.
"/usr/bin/setfacl"
],
"updateContentCommand": {
// Using the shell for `nproc` usage.
"python": "python3 Tools/wasm/wasi build --quiet -- --with-pydebug -C"
},
"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",
// 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"
],
"[restructuredtext]": {
"editor.tabSize": 3
}
}
}
}
}

5
.gitattributes vendored
View file

@ -68,7 +68,6 @@ PCbuild/readme.txt dos
**/clinic/*.cpp.h generated
**/clinic/*.h.h generated
*_db.h generated
Doc/_static/tachyon-example-*.html generated
Doc/c-api/lifecycle.dot.svg generated
Doc/data/stable_abi.dat generated
Doc/library/token-list.inc generated
@ -83,15 +82,11 @@ Include/opcode.h generated
Include/opcode_ids.h generated
Include/token.h generated
Lib/_opcode_metadata.py generated
Lib/idlelib/help.html generated
Lib/keyword.py generated
Lib/pydoc_data/topics.py generated
Lib/pydoc_data/module_docs.py generated
Lib/test/certdata/*.pem generated
Lib/test/certdata/*.0 generated
Lib/test/levenshtein_examples.json generated
Lib/test/test_stable_abi_ctypes.py generated
Lib/test/test_zoneinfo/data/*.json generated
Lib/token.py generated
Misc/sbom.spdx.json generated
Objects/typeslots.inc generated

14
.github/CODEOWNERS vendored
View file

@ -126,9 +126,6 @@ Doc/howto/clinic.rst @erlend-aasland @AA-Turner
# C Analyser
Tools/c-analyzer/ @ericsnowcurrently
# C API Documentation Checks
Tools/check-c-api-docs/ @ZeroIntensity
# Fuzzing
Modules/_xxtestfuzz/ @ammaraskar
@ -289,10 +286,10 @@ Tools/jit/ @brandtbucher @savannahostrowski @diegorusso
InternalDocs/jit.md @brandtbucher @savannahostrowski @diegorusso @AA-Turner
# Micro-op / μop / Tier 2 Optimiser
Python/optimizer.c @markshannon @Fidget-Spinner
Python/optimizer.c @markshannon
Python/optimizer_analysis.c @markshannon @tomasr8 @Fidget-Spinner
Python/optimizer_bytecodes.c @markshannon @tomasr8 @Fidget-Spinner
Python/optimizer_symbols.c @markshannon @tomasr8 @Fidget-Spinner
Python/optimizer_symbols.c @markshannon @tomasr8
# Parser, Lexer, and Grammar
Grammar/python.gram @pablogsal @lysnikolaou
@ -322,7 +319,7 @@ Tools/build/generate_global_objects.py @ericsnowcurrently
# Remote Debugging
Python/remote_debug.h @pablogsal
Python/remote_debugging.c @pablogsal
Modules/_remote_debugging/ @pablogsal
Modules/_remote_debugging_module.c @pablogsal @ambv @1st1
# Sub-Interpreters
**/*crossinterp* @ericsnowcurrently
@ -537,11 +534,6 @@ Lib/pydoc.py @AA-Turner
Lib/pydoc_data/ @AA-Turner
Lib/test/test_pydoc/ @AA-Turner
# Profiling (Sampling)
Doc/library/profiling*.rst @pablogsal
Lib/profiling/ @pablogsal
Lib/test/test_profiling/ @pablogsal
# PyREPL
Lib/_pyrepl/ @pablogsal @lysnikolaou @ambv
Lib/test/test_pyrepl/ @pablogsal @lysnikolaou @ambv

View file

@ -28,12 +28,13 @@ 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/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.
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:
The final key part of our workflow is that all discussions that are not
directly related to the code in the pull request should happen on
`GitHub Issues <https://github.com/python/cpython/issues>`__, generally in the
pull request's parent issue.
- All discussions that are not directly related to the code in the pull request
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``.
Setting Expectations

View file

@ -5,6 +5,3 @@ contact_links:
- 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"
- name: "Python Install Manager issues"
about: "Report issues with the Python Install Manager (for Windows)"
url: "https://github.com/python/pymanager/issues"

View file

@ -12,11 +12,6 @@ updates:
update-types:
- "version-update:semver-minor"
- "version-update:semver-patch"
cooldown:
# https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns
# Cooldowns protect against supply chain attacks by avoiding the
# highest-risk window immediately after new releases.
default-days: 14
- package-ecosystem: "pip"
directory: "/Tools/"
schedule:
@ -24,5 +19,3 @@ updates:
labels:
- "skip issue"
- "skip news"
cooldown:
default-days: 14

View file

@ -109,10 +109,20 @@ jobs:
python-version: '3.x'
- name: Runner image version
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
- name: Restore config.cache
uses: actions/cache@v4
with:
path: config.cache
# Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.build-context.outputs.config-hash }}-${{ env.pythonLocation }}
- name: Install dependencies
run: sudo ./.github/workflows/posix-deps-apt.sh
- name: Add ccache to PATH
run: echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
- name: Configure ccache action
uses: hendrikmuhs/ccache-action@v1.2
with:
save: false
- name: Configure CPython
run: |
# Build Python with the libpython dynamic library
@ -142,9 +152,6 @@ jobs:
- name: Check for unsupported C global variables
if: github.event_name == 'pull_request' # $GITHUB_EVENT_NAME
run: make check-c-globals
- name: Check for undocumented C APIs
run: make check-c-api-docs
build-windows:
name: >-
@ -191,7 +198,7 @@ jobs:
macOS
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
needs: build-context
if: needs.build-context.outputs.run-macos == 'true'
if: needs.build-context.outputs.run-tests == 'true'
strategy:
fail-fast: false
matrix:
@ -208,6 +215,7 @@ jobs:
free-threading: true
uses: ./.github/workflows/reusable-macos.yml
with:
config_hash: ${{ needs.build-context.outputs.config-hash }}
free-threading: ${{ matrix.free-threading }}
os: ${{ matrix.os }}
@ -217,7 +225,7 @@ jobs:
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
${{ fromJSON(matrix.bolt) && '(bolt)' || '' }}
needs: build-context
if: needs.build-context.outputs.run-ubuntu == 'true'
if: needs.build-context.outputs.run-tests == 'true'
strategy:
fail-fast: false
matrix:
@ -239,6 +247,7 @@ jobs:
bolt: true
uses: ./.github/workflows/reusable-ubuntu.yml
with:
config_hash: ${{ needs.build-context.outputs.config-hash }}
bolt-optimizations: ${{ matrix.bolt }}
free-threading: ${{ matrix.free-threading }}
os: ${{ matrix.os }}
@ -248,7 +257,7 @@ jobs:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
needs: build-context
if: needs.build-context.outputs.run-ubuntu == 'true'
if: needs.build-context.outputs.run-tests == 'true'
strategy:
fail-fast: false
matrix:
@ -269,6 +278,11 @@ jobs:
persist-credentials: false
- name: Runner image version
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
- name: Restore config.cache
uses: actions/cache@v4
with:
path: config.cache
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.build-context.outputs.config-hash }}
- name: Register gcc problem matcher
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
- name: Install dependencies
@ -290,6 +304,10 @@ jobs:
- name: Add ccache to PATH
run: |
echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
- name: Configure ccache action
uses: hendrikmuhs/ccache-action@v1.2
with:
save: false
- name: Configure CPython
run: ./configure CFLAGS="-fdiagnostics-format=json" --config-cache --enable-slower-safety --with-pydebug --with-openssl="$OPENSSL_DIR"
- name: Build CPython
@ -304,7 +322,7 @@ jobs:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
needs: build-context
if: needs.build-context.outputs.run-ubuntu == 'true'
if: needs.build-context.outputs.run-tests == 'true'
strategy:
fail-fast: false
matrix:
@ -321,6 +339,11 @@ jobs:
persist-credentials: false
- name: Runner image version
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
- name: Restore config.cache
uses: actions/cache@v4
with:
path: config.cache
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.build-context.outputs.config-hash }}
- name: Register gcc problem matcher
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
- name: Install dependencies
@ -347,6 +370,10 @@ jobs:
- name: Add ccache to PATH
run: |
echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
- name: Configure ccache action
uses: hendrikmuhs/ccache-action@v1.2
with:
save: false
- name: Configure CPython
run: |
./configure CFLAGS="-fdiagnostics-format=json" \
@ -368,7 +395,7 @@ jobs:
build-android:
name: Android (${{ matrix.arch }})
needs: build-context
if: needs.build-context.outputs.run-android == 'true'
if: needs.build-context.outputs.run-tests == 'true'
timeout-minutes: 60
strategy:
fail-fast: false
@ -387,41 +414,20 @@ jobs:
- name: Build and test
run: ./Android/android.py ci --fast-ci ${{ matrix.arch }}-linux-android
build-ios:
name: iOS
needs: build-context
if: needs.build-context.outputs.run-ios == 'true'
timeout-minutes: 60
runs-on: macos-14
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
# GitHub recommends explicitly selecting the desired Xcode version:
# https://github.com/actions/runner-images/issues/12541#issuecomment-3083850140
# This became a necessity as a result of
# https://github.com/actions/runner-images/issues/12541 and
# https://github.com/actions/runner-images/issues/12751.
- name: Select Xcode version
run: |
sudo xcode-select --switch /Applications/Xcode_15.4.app
- name: Build and test
run: python3 Apple ci iOS --fast-ci --simulator 'iPhone SE (3rd generation),OS=17.5'
build-wasi:
name: 'WASI'
needs: build-context
if: needs.build-context.outputs.run-wasi == 'true'
if: needs.build-context.outputs.run-tests == 'true'
uses: ./.github/workflows/reusable-wasi.yml
with:
config_hash: ${{ needs.build-context.outputs.config-hash }}
test-hypothesis:
name: "Hypothesis tests on Ubuntu"
runs-on: ubuntu-24.04
timeout-minutes: 60
needs: build-context
if: needs.build-context.outputs.run-ubuntu == 'true'
if: needs.build-context.outputs.run-tests == 'true'
env:
OPENSSL_VER: 3.0.18
PYTHONSTRICTEXTENSIONBUILD: 1
@ -450,6 +456,10 @@ jobs:
- name: Add ccache to PATH
run: |
echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
- name: Configure ccache action
uses: hendrikmuhs/ccache-action@v1.2
with:
save: false
- name: Setup directory envs for out-of-tree builds
run: |
echo "CPYTHON_RO_SRCDIR=$(realpath -m "${GITHUB_WORKSPACE}"/../cpython-ro-srcdir)" >> "$GITHUB_ENV"
@ -460,6 +470,11 @@ jobs:
run: sudo mount --bind -o ro "$GITHUB_WORKSPACE" "$CPYTHON_RO_SRCDIR"
- name: Runner image version
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
- name: Restore config.cache
uses: actions/cache@v4
with:
path: ${{ env.CPYTHON_BUILDDIR }}/config.cache
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.build-context.outputs.config-hash }}
- name: Configure CPython out-of-tree
working-directory: ${{ env.CPYTHON_BUILDDIR }}
run: |
@ -528,7 +543,7 @@ jobs:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
needs: build-context
if: needs.build-context.outputs.run-ubuntu == 'true'
if: needs.build-context.outputs.run-tests == 'true'
strategy:
fail-fast: false
matrix:
@ -543,6 +558,11 @@ jobs:
persist-credentials: false
- name: Runner image version
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
- name: Restore config.cache
uses: actions/cache@v4
with:
path: config.cache
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.build-context.outputs.config-hash }}
- name: Register gcc problem matcher
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
- name: Install dependencies
@ -568,6 +588,11 @@ jobs:
- name: Add ccache to PATH
run: |
echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
- name: Configure ccache action
uses: hendrikmuhs/ccache-action@v1.2
with:
save: ${{ github.event_name == 'push' }}
max-size: "200M"
- name: Configure CPython
run: ./configure --config-cache --with-address-sanitizer --without-pymalloc
- name: Build CPython
@ -581,7 +606,7 @@ jobs:
# ${{ '' } is a hack to nest jobs under the same sidebar category.
name: Sanitizers${{ '' }} # zizmor: ignore[obfuscation]
needs: build-context
if: needs.build-context.outputs.run-ubuntu == 'true'
if: needs.build-context.outputs.run-tests == 'true'
strategy:
fail-fast: false
matrix:
@ -599,6 +624,7 @@ jobs:
uses: ./.github/workflows/reusable-san.yml
with:
sanitizer: ${{ matrix.sanitizer }}
config_hash: ${{ needs.build-context.outputs.config-hash }}
free-threading: ${{ matrix.free-threading }}
cross-build-linux:
@ -606,13 +632,18 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 60
needs: build-context
if: needs.build-context.outputs.run-ubuntu == 'true'
if: needs.build-context.outputs.run-tests == 'true'
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Runner image version
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
- name: Restore config.cache
uses: actions/cache@v4
with:
path: config.cache
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.build-context.outputs.config-hash }}
- name: Register gcc problem matcher
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
- name: Set build dir
@ -692,7 +723,6 @@ jobs:
- build-ubuntu-ssltests-awslc
- build-ubuntu-ssltests-openssl
- build-android
- build-ios
- build-wasi
- test-hypothesis
- build-asan
@ -712,24 +742,24 @@ jobs:
test-hypothesis,
cifuzz,
allowed-skips: >-
${{ !fromJSON(needs.build-context.outputs.run-docs) && 'check-docs,' || '' }}
${{
!fromJSON(needs.build-context.outputs.run-docs)
&& '
check-docs,
'
|| ''
}}
${{
needs.build-context.outputs.run-tests != 'true'
&& '
check-autoconf-regen,
check-generated-files,
'
|| ''
}}
${{ !fromJSON(needs.build-context.outputs.run-windows-tests) && 'build-windows,' || '' }}
${{ !fromJSON(needs.build-context.outputs.run-ci-fuzz) && 'cifuzz,' || '' }}
${{ !fromJSON(needs.build-context.outputs.run-macos) && 'build-macos,' || '' }}
${{
!fromJSON(needs.build-context.outputs.run-ubuntu)
&& '
build-macos,
build-ubuntu,
build-ubuntu-ssltests-awslc,
build-ubuntu-ssltests-openssl,
build-android,
build-wasi,
test-hypothesis,
build-asan,
build-san,
@ -737,7 +767,18 @@ jobs:
'
|| ''
}}
${{ !fromJSON(needs.build-context.outputs.run-android) && 'build-android,' || '' }}
${{ !fromJSON(needs.build-context.outputs.run-ios) && 'build-ios,' || '' }}
${{ !fromJSON(needs.build-context.outputs.run-wasi) && 'build-wasi,' || '' }}
${{
!fromJSON(needs.build-context.outputs.run-windows-tests)
&& '
build-windows,
'
|| ''
}}
${{
!fromJSON(needs.build-context.outputs.run-ci-fuzz)
&& '
cifuzz,
'
|| ''
}}
jobs: ${{ toJSON(needs) }}

View file

@ -68,7 +68,7 @@ jobs:
- true
- false
llvm:
- 21
- 19
include:
- target: i686-pc-windows-msvc/msvc
architecture: Win32
@ -138,7 +138,7 @@ jobs:
fail-fast: false
matrix:
llvm:
- 21
- 19
steps:
- uses: actions/checkout@v4
with:
@ -166,7 +166,7 @@ jobs:
fail-fast: false
matrix:
llvm:
- 21
- 19
steps:
- uses: actions/checkout@v4
with:
@ -183,27 +183,3 @@ jobs:
- name: Run tests without optimizations
run: |
PYTHON_UOPS_OPTIMIZE=0 ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
tail-call-jit:
name: JIT with tail calling interpreter
needs: interpreter
runs-on: ubuntu-24.04
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
llvm:
- 21
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Build with JIT and tailcall
run: |
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
CC=clang-${{ matrix.llvm }} ./configure --enable-experimental-jit --with-tail-call-interp --with-pydebug
make all --jobs 4

View file

@ -16,7 +16,6 @@ on:
- "Tools/build/check_extension_modules.py"
- "Tools/build/check_warnings.py"
- "Tools/build/compute-changes.py"
- "Tools/build/consts_getter.py"
- "Tools/build/deepfreeze.py"
- "Tools/build/generate-build-details.py"
- "Tools/build/generate_sbom.py"
@ -26,7 +25,6 @@ on:
- "Tools/build/update_file.py"
- "Tools/build/verify_ensurepip_wheels.py"
- "Tools/cases_generator/**"
- "Tools/check-c-api-docs/**"
- "Tools/clinic/**"
- "Tools/jit/**"
- "Tools/peg_generator/**"
@ -59,7 +57,6 @@ jobs:
"Lib/tomllib",
"Tools/build",
"Tools/cases_generator",
"Tools/check-c-api-docs",
"Tools/clinic",
"Tools/jit",
"Tools/peg_generator",

View file

@ -17,36 +17,24 @@ on: # yamllint disable-line rule:truthy
# || 'falsy-branch'
# }}
#
run-android:
description: Whether to run the Android tests
value: ${{ jobs.compute-changes.outputs.run-android }} # bool
run-ci-fuzz:
description: Whether to run the CIFuzz job
value: ${{ jobs.compute-changes.outputs.run-ci-fuzz }} # bool
config-hash:
description: Config hash value for use in cache keys
value: ${{ jobs.compute-changes.outputs.config-hash }} # str
run-docs:
description: Whether to build the docs
value: ${{ jobs.compute-changes.outputs.run-docs }} # bool
run-ios:
description: Whether to run the iOS tests
value: ${{ jobs.compute-changes.outputs.run-ios }} # bool
run-macos:
description: Whether to run the macOS tests
value: ${{ jobs.compute-changes.outputs.run-macos }} # bool
run-tests:
description: Whether to run the regular tests
value: ${{ jobs.compute-changes.outputs.run-tests }} # bool
run-ubuntu:
description: Whether to run the Ubuntu tests
value: ${{ jobs.compute-changes.outputs.run-ubuntu }} # bool
run-wasi:
description: Whether to run the WASI tests
value: ${{ jobs.compute-changes.outputs.run-wasi }} # bool
run-windows-msi:
description: Whether to run the MSI installer smoke tests
value: ${{ jobs.compute-changes.outputs.run-windows-msi }} # bool
run-windows-tests:
description: Whether to run the Windows tests
value: ${{ jobs.compute-changes.outputs.run-windows-tests }} # bool
run-windows-msi:
description: Whether to run the MSI installer smoke tests
value: ${{ jobs.compute-changes.outputs.run-windows-msi }} # bool
run-ci-fuzz:
description: Whether to run the CIFuzz job
value: ${{ jobs.compute-changes.outputs.run-ci-fuzz }} # bool
jobs:
compute-changes:
@ -54,14 +42,10 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
run-android: ${{ steps.changes.outputs.run-android }}
config-hash: ${{ steps.config-hash.outputs.hash }}
run-ci-fuzz: ${{ steps.changes.outputs.run-ci-fuzz }}
run-docs: ${{ steps.changes.outputs.run-docs }}
run-ios: ${{ steps.changes.outputs.run-ios }}
run-macos: ${{ steps.changes.outputs.run-macos }}
run-tests: ${{ steps.changes.outputs.run-tests }}
run-ubuntu: ${{ steps.changes.outputs.run-ubuntu }}
run-wasi: ${{ steps.changes.outputs.run-wasi }}
run-windows-msi: ${{ steps.changes.outputs.run-windows-msi }}
run-windows-tests: ${{ steps.changes.outputs.run-windows-tests }}
steps:
@ -116,3 +100,8 @@ jobs:
GITHUB_EVENT_NAME: ${{ github.event_name }}
CCF_TARGET_REF: ${{ github.base_ref || github.event.repository.default_branch }}
CCF_HEAD_REF: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Compute hash for config cache key
id: config-hash
run: |
echo "hash=${{ hashFiles('configure', 'configure.ac', '.github/workflows/build.yml') }}" >> "$GITHUB_OUTPUT"

View file

@ -3,6 +3,9 @@ name: Reusable macOS
on:
workflow_call:
inputs:
config_hash:
required: true
type: string
free-threading:
required: false
type: boolean
@ -33,6 +36,11 @@ jobs:
persist-credentials: false
- name: Runner image version
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
- name: Restore config.cache
uses: actions/cache@v4
with:
path: config.cache
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ inputs.config_hash }}
- name: Install Homebrew dependencies
run: |
brew install pkg-config openssl@3.0 xz gdbm tcl-tk@9 make

View file

@ -6,6 +6,9 @@ on:
sanitizer:
required: true
type: string
config_hash:
required: true
type: string
free-threading:
description: Whether to use free-threaded mode
required: false
@ -31,6 +34,11 @@ jobs:
persist-credentials: false
- name: Runner image version
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
- name: Restore config.cache
uses: actions/cache@v4
with:
path: config.cache
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ inputs.sanitizer }}-${{ inputs.config_hash }}
- name: Install dependencies
run: |
sudo ./.github/workflows/posix-deps-apt.sh
@ -69,6 +77,11 @@ jobs:
- name: Add ccache to PATH
run: |
echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
- name: Configure ccache action
uses: hendrikmuhs/ccache-action@v1.2
with:
save: ${{ github.event_name == 'push' }}
max-size: "200M"
- name: Configure CPython
run: >-
./configure

View file

@ -3,6 +3,9 @@ name: Reusable Ubuntu
on:
workflow_call:
inputs:
config_hash:
required: true
type: string
bolt-optimizations:
description: Whether to enable BOLT optimizations
required: false
@ -61,6 +64,11 @@ jobs:
- name: Add ccache to PATH
run: |
echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
- name: Configure ccache action
uses: hendrikmuhs/ccache-action@v1.2
with:
save: ${{ github.event_name == 'push' }}
max-size: "200M"
- name: Setup directory envs for out-of-tree builds
run: |
echo "CPYTHON_RO_SRCDIR=$(realpath -m "${GITHUB_WORKSPACE}"/../cpython-ro-srcdir)" >> "$GITHUB_ENV"
@ -71,6 +79,11 @@ jobs:
run: sudo mount --bind -o ro "$GITHUB_WORKSPACE" "$CPYTHON_RO_SRCDIR"
- name: Runner image version
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
- name: Restore config.cache
uses: actions/cache@v4
with:
path: ${{ env.CPYTHON_BUILDDIR }}/config.cache
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ inputs.config_hash }}
- name: Configure CPython out-of-tree
working-directory: ${{ env.CPYTHON_BUILDDIR }}
# `test_unpickle_module_race` writes to the source directory, which is

View file

@ -2,6 +2,10 @@ name: Reusable WASI
on:
workflow_call:
inputs:
config_hash:
required: true
type: string
env:
FORCE_COLOR: 1
@ -9,11 +13,11 @@ env:
jobs:
build-wasi-reusable:
name: 'build and test'
runs-on: ubuntu-24.04-arm
runs-on: ubuntu-24.04
timeout-minutes: 60
env:
WASMTIME_VERSION: 38.0.3
WASI_SDK_VERSION: 29
WASMTIME_VERSION: 22.0.0
WASI_SDK_VERSION: 24
WASI_SDK_PATH: /opt/wasi-sdk
CROSS_BUILD_PYTHON: cross-build/build
CROSS_BUILD_WASI: cross-build/wasm32-wasip1
@ -36,8 +40,13 @@ jobs:
if: steps.cache-wasi-sdk.outputs.cache-hit != 'true'
run: |
mkdir "${WASI_SDK_PATH}" && \
curl -s -S --location "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-arm64-linux.tar.gz" | \
curl -s -S --location "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-x86_64-linux.tar.gz" | \
tar --strip-components 1 --directory "${WASI_SDK_PATH}" --extract --gunzip
- name: "Configure ccache action"
uses: hendrikmuhs/ccache-action@v1.2
with:
save: ${{ github.event_name == 'push' }}
max-size: "200M"
- name: "Add ccache to PATH"
run: echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
- name: "Install Python"
@ -46,15 +55,29 @@ jobs:
python-version: '3.x'
- name: "Runner image version"
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
- name: "Restore Python build config.cache"
uses: actions/cache@v4
with:
path: ${{ env.CROSS_BUILD_PYTHON }}/config.cache
# Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python.
# Include the hash of `Tools/wasm/wasi.py` as it may change the environment variables.
# (Make sure to keep the key in sync with the other config.cache step below.)
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ env.WASI_SDK_VERSION }}-${{ env.WASMTIME_VERSION }}-${{ inputs.config_hash }}-${{ hashFiles('Tools/wasm/wasi.py') }}-${{ env.pythonLocation }}
- name: "Configure build Python"
run: python3 Tools/wasm/wasi configure-build-python -- --config-cache --with-pydebug
run: python3 Tools/wasm/wasi.py configure-build-python -- --config-cache --with-pydebug
- name: "Make build Python"
run: python3 Tools/wasm/wasi make-build-python
run: python3 Tools/wasm/wasi.py make-build-python
- name: "Restore host config.cache"
uses: actions/cache@v4
with:
path: ${{ env.CROSS_BUILD_WASI }}/config.cache
# Should be kept in sync with the other config.cache step above.
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ env.WASI_SDK_VERSION }}-${{ env.WASMTIME_VERSION }}-${{ inputs.config_hash }}-${{ hashFiles('Tools/wasm/wasi.py') }}-${{ env.pythonLocation }}
- name: "Configure host"
# `--with-pydebug` inferred from configure-build-python
run: python3 Tools/wasm/wasi configure-host -- --config-cache
run: python3 Tools/wasm/wasi.py configure-host -- --config-cache
- name: "Make host"
run: python3 Tools/wasm/wasi make-host
run: python3 Tools/wasm/wasi.py make-host
- name: "Display build info"
run: make --directory "${CROSS_BUILD_WASI}" pythoninfo
- name: "Test"

View file

@ -79,17 +79,19 @@ jobs:
with:
python-version: '3.11'
- name: Native Windows MSVC (release)
- name: Native Windows (debug)
if: runner.os == 'Windows' && matrix.architecture != 'ARM64'
shell: cmd
run: |
choco install visualstudio2026buildtools --no-progress -y --force --params "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --locale en-US --passive"
$env:PATH = "C:\Program Files (x86)\Microsoft Visual Studio\18\BuildTools\MSBuild\Current\bin;$env:PATH"
./PCbuild/build.bat --tail-call-interp -c Release -p ${{ matrix.architecture }} "/p:PlatformToolset=v145"
./PCbuild/rt.bat -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}.1.0
set PlatformToolset=clangcl
set LLVMToolsVersion=${{ matrix.llvm }}.1.0
set LLVMInstallDir=C:\Program Files\LLVM
call ./PCbuild/build.bat --tail-call-interp -d -p ${{ matrix.architecture }}
call ./PCbuild/rt.bat -d -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
# No tests (yet):
- name: Emulated Windows Clang (release)
- name: Emulated Windows (release)
if: runner.os == 'Windows' && matrix.architecture == 'ARM64'
shell: cmd
run: |

2
.gitignore vendored
View file

@ -45,7 +45,6 @@ gmon.out
.pytest_cache/
.ruff_cache/
.DS_Store
.pixi/
*.exe
@ -136,6 +135,7 @@ Tools/unicode/data/
/config.log
/config.status
/config.status.lineno
# hendrikmuhs/ccache-action@v1
/.ccache
/cross-build/
/jit_stencils*.h

View file

@ -2,10 +2,6 @@ repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.13.2
hooks:
- id: ruff-check
name: Run Ruff (lint) on Apple/
args: [--exit-non-zero-on-fix, --config=Apple/.ruff.toml]
files: ^Apple/
- id: ruff-check
name: Run Ruff (lint) on Doc/
args: [--exit-non-zero-on-fix]
@ -34,21 +30,17 @@ repos:
name: Run Ruff (lint) on Tools/wasm/
args: [--exit-non-zero-on-fix, --config=Tools/wasm/.ruff.toml]
files: ^Tools/wasm/
- id: ruff-format
name: Run Ruff (format) on Apple/
args: [--exit-non-zero-on-fix, --config=Apple/.ruff.toml]
files: ^Apple
- id: ruff-format
name: Run Ruff (format) on Doc/
args: [--exit-non-zero-on-fix]
args: [--check]
files: ^Doc/
- id: ruff-format
name: Run Ruff (format) on Tools/build/check_warnings.py
args: [--exit-non-zero-on-fix, --config=Tools/build/.ruff.toml]
args: [--check, --config=Tools/build/.ruff.toml]
files: ^Tools/build/check_warnings.py
- id: ruff-format
name: Run Ruff (format) on Tools/wasm/
args: [--exit-non-zero-on-fix, --config=Tools/wasm/.ruff.toml]
args: [--check, --config=Tools/wasm/.ruff.toml]
files: ^Tools/wasm/
- repo: https://github.com/psf/black-pre-commit-mirror

View file

@ -29,7 +29,6 @@ in_source_tree = (
ANDROID_DIR.name == "Android" and (PYTHON_DIR / "pyconfig.h.in").exists()
)
ENV_SCRIPT = ANDROID_DIR / "android-env.sh"
TESTBED_DIR = ANDROID_DIR / "testbed"
CROSS_BUILD_DIR = PYTHON_DIR / "cross-build"
@ -130,11 +129,12 @@ def android_env(host):
sysconfig_filename = next(sysconfig_files).name
host = re.fullmatch(r"_sysconfigdata__android_(.+).py", sysconfig_filename)[1]
env_script = ANDROID_DIR / "android-env.sh"
env_output = subprocess.run(
f"set -eu; "
f"HOST={host}; "
f"PREFIX={prefix}; "
f". {ENV_SCRIPT}; "
f". {env_script}; "
f"export",
check=True, shell=True, capture_output=True, encoding='utf-8',
).stdout
@ -151,7 +151,7 @@ def android_env(host):
env[key] = value
if not env:
raise ValueError(f"Found no variables in {ENV_SCRIPT.name} output:\n"
raise ValueError(f"Found no variables in {env_script.name} output:\n"
+ env_output)
return env
@ -281,30 +281,15 @@ def clean_all(context):
def setup_ci():
if "GITHUB_ACTIONS" in os.environ:
# Enable emulator hardware acceleration
# (https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/).
if platform.system() == "Linux":
run(
["sudo", "tee", "/etc/udev/rules.d/99-kvm4all.rules"],
input='KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"\n',
text=True,
)
run(["sudo", "udevadm", "control", "--reload-rules"])
run(["sudo", "udevadm", "trigger", "--name-match=kvm"])
# Free up disk space by deleting unused versions of the NDK
# (https://github.com/freakboy3742/pyspamsum/pull/108).
for line in ENV_SCRIPT.read_text().splitlines():
if match := re.fullmatch(r"ndk_version=(.+)", line):
ndk_version = match[1]
break
else:
raise ValueError(f"Failed to find NDK version in {ENV_SCRIPT.name}")
for item in (android_home / "ndk").iterdir():
if item.name[0].isdigit() and item.name != ndk_version:
delete_glob(item)
# https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/
if "GITHUB_ACTIONS" in os.environ and platform.system() == "Linux":
run(
["sudo", "tee", "/etc/udev/rules.d/99-kvm4all.rules"],
input='KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"\n',
text=True,
)
run(["sudo", "udevadm", "control", "--reload-rules"])
run(["sudo", "udevadm", "trigger", "--name-match=kvm"])
def setup_sdk():

View file

@ -47,7 +47,7 @@ for ((i, prefix) in prefixes.withIndex()) {
val libDir = file("$prefix/lib")
val version = run {
for (filename in libDir.list()!!) {
"""python(\d+\.\d+[a-z]*)""".toRegex().matchEntire(filename)?.let {
"""python(\d+\.\d+)""".toRegex().matchEntire(filename)?.let {
return@run it.groupValues[1]
}
}
@ -64,10 +64,9 @@ for ((i, prefix) in prefixes.withIndex()) {
val libPythonDir = file("$libDir/python$pythonVersion")
val triplet = run {
for (filename in libPythonDir.list()!!) {
"""_sysconfigdata_[a-z]*_android_(.+).py""".toRegex()
.matchEntire(filename)?.let {
return@run it.groupValues[1]
}
"""_sysconfigdata__android_(.+).py""".toRegex().matchEntire(filename)?.let {
return@run it.groupValues[1]
}
}
throw GradleException("Failed to find Python triplet in $libPythonDir")
}
@ -79,7 +78,7 @@ android {
val androidEnvFile = file("../../android-env.sh").absoluteFile
namespace = "org.python.testbed"
compileSdk = 35
compileSdk = 34
defaultConfig {
applicationId = "org.python.testbed"
@ -92,7 +91,7 @@ android {
}
throw GradleException("Failed to find API level in $androidEnvFile")
}
targetSdk = 35
targetSdk = 34
versionCode = 1
versionName = "1.0"

View file

@ -1,22 +0,0 @@
extend = "../.ruff.toml" # Inherit the project-wide settings
[format]
preview = true
docstring-code-format = true
[lint]
select = [
"C4", # flake8-comprehensions
"E", # pycodestyle
"F", # pyflakes
"I", # isort
"ISC", # flake8-implicit-str-concat
"LOG", # flake8-logging
"PGH", # pygrep-hooks
"PT", # flake8-pytest-style
"PYI", # flake8-pyi
"RUF100", # Ban unused `# noqa` comments
"UP", # pyupgrade
"W", # pycodestyle
"YTT", # flake8-2020
]

View file

@ -46,12 +46,13 @@ import subprocess
import sys
import sysconfig
import time
from collections.abc import Callable, Sequence
from collections.abc import Sequence
from contextlib import contextmanager
from datetime import datetime, timezone
from os.path import basename, relpath
from pathlib import Path
from subprocess import CalledProcessError
from typing import Callable
EnvironmentT = dict[str, str]
ArgsT = Sequence[str | Path]
@ -139,15 +140,17 @@ def print_env(env: EnvironmentT) -> None:
def apple_env(host: str) -> EnvironmentT:
"""Construct an Apple development environment for the given host."""
env = {
"PATH": ":".join([
str(PYTHON_DIR / "Apple/iOS/Resources/bin"),
str(subdir(host) / "prefix"),
"/usr/bin",
"/bin",
"/usr/sbin",
"/sbin",
"/Library/Apple/usr/bin",
]),
"PATH": ":".join(
[
str(PYTHON_DIR / "Apple/iOS/Resources/bin"),
str(subdir(host) / "prefix"),
"/usr/bin",
"/bin",
"/usr/sbin",
"/sbin",
"/Library/Apple/usr/bin",
]
),
}
return env
@ -193,10 +196,14 @@ def clean(context: argparse.Namespace, target: str = "all") -> None:
paths.append(target)
if target in {"all", "hosts", "test"}:
paths.extend([
path.name
for path in CROSS_BUILD_DIR.glob(f"{context.platform}-testbed.*")
])
paths.extend(
[
path.name
for path in CROSS_BUILD_DIR.glob(
f"{context.platform}-testbed.*"
)
]
)
for path in paths:
delete_path(path)
@ -345,16 +352,18 @@ def download(url: str, target_dir: Path) -> Path:
out_path = target_path / basename(url)
if not Path(out_path).is_file():
run([
"curl",
"-Lf",
"--retry",
"5",
"--retry-all-errors",
"-o",
out_path,
url,
])
run(
[
"curl",
"-Lf",
"--retry",
"5",
"--retry-all-errors",
"-o",
out_path,
url,
]
)
else:
print(f"Using cached version of {basename(url)}")
return out_path
@ -459,7 +468,8 @@ def package_version(prefix_path: Path) -> str:
def lib_platform_files(dirname, names):
"""A file filter that ignores platform-specific files in lib."""
"""A file filter that ignores platform-specific files in the lib directory.
"""
path = Path(dirname)
if (
path.parts[-3] == "lib"
@ -468,7 +478,7 @@ def lib_platform_files(dirname, names):
):
return names
elif path.parts[-2] == "lib" and path.parts[-1].startswith("python"):
ignored_names = {
ignored_names = set(
name
for name in names
if (
@ -476,13 +486,7 @@ def lib_platform_files(dirname, names):
or name.startswith("_sysconfig_vars_")
or name == "build-details.json"
)
}
elif path.parts[-1] == "lib":
ignored_names = {
name
for name in names
if name.startswith("libpython") and name.endswith(".dylib")
}
)
else:
ignored_names = set()
@ -495,9 +499,7 @@ def lib_non_platform_files(dirname, names):
"""
path = Path(dirname)
if path.parts[-2] == "lib" and path.parts[-1].startswith("python"):
return (
set(names) - lib_platform_files(dirname, names) - {"lib-dynload"}
)
return set(names) - lib_platform_files(dirname, names) - {"lib-dynload"}
else:
return set()
@ -505,15 +507,14 @@ def lib_non_platform_files(dirname, names):
def create_xcframework(platform: str) -> str:
"""Build an XCframework from the component parts for the platform.
:return: The version number of the Python version that was packaged.
:return: The version number of the Python verion that was packaged.
"""
package_path = CROSS_BUILD_DIR / platform
try:
package_path.mkdir()
except FileExistsError:
raise RuntimeError(
f"{platform} XCframework already exists; do you need to run "
"with --clean?"
f"{platform} XCframework already exists; do you need to run with --clean?"
) from None
frameworks = []
@ -606,7 +607,7 @@ def create_xcframework(platform: str) -> str:
print(f" - {slice_name} binaries")
shutil.copytree(first_path / "bin", slice_path / "bin")
# Copy the include path (a symlink to the framework headers)
# Copy the include path (this will be a symlink to the framework headers)
print(f" - {slice_name} include files")
shutil.copytree(
first_path / "include",
@ -620,12 +621,6 @@ def create_xcframework(platform: str) -> str:
slice_framework / "Headers/pyconfig.h",
)
print(f" - {slice_name} shared library")
# Create a simlink for the fat library
shared_lib = slice_path / f"lib/libpython{version_tag}.dylib"
shared_lib.parent.mkdir()
shared_lib.symlink_to("../Python.framework/Python")
print(f" - {slice_name} architecture-specific files")
for host_triple, multiarch in slice_parts.items():
print(f" - {multiarch} standard library")
@ -637,7 +632,6 @@ def create_xcframework(platform: str) -> str:
framework_path(host_triple, multiarch) / "lib",
package_path / "Python.xcframework/lib",
ignore=lib_platform_files,
symlinks=True,
)
has_common_stdlib = True
@ -645,7 +639,6 @@ def create_xcframework(platform: str) -> str:
framework_path(host_triple, multiarch) / "lib",
slice_path / f"lib-{arch}",
ignore=lib_non_platform_files,
symlinks=True,
)
# Copy the host's pyconfig.h to an architecture-specific name.
@ -666,8 +659,7 @@ def create_xcframework(platform: str) -> str:
# statically link those libraries into a Framework, you become
# responsible for providing a privacy manifest for that framework.
xcprivacy_file = {
"OpenSSL": subdir(host_triple)
/ "prefix/share/OpenSSL.xcprivacy"
"OpenSSL": subdir(host_triple) / "prefix/share/OpenSSL.xcprivacy"
}
print(f" - {multiarch} xcprivacy files")
for module, lib in [
@ -677,8 +669,7 @@ def create_xcframework(platform: str) -> str:
shutil.copy(
xcprivacy_file[lib],
slice_path
/ f"lib-{arch}/python{version_tag}"
/ f"lib-dynload/{module}.xcprivacy",
/ f"lib-{arch}/python{version_tag}/lib-dynload/{module}.xcprivacy",
)
print(" - build tools")
@ -701,16 +692,18 @@ def package(context: argparse.Namespace) -> None:
# Clone testbed
print()
run([
sys.executable,
"Apple/testbed",
"clone",
"--platform",
context.platform,
"--framework",
CROSS_BUILD_DIR / context.platform / "Python.xcframework",
CROSS_BUILD_DIR / context.platform / "testbed",
])
run(
[
sys.executable,
"Apple/testbed",
"clone",
"--platform",
context.platform,
"--framework",
CROSS_BUILD_DIR / context.platform / "Python.xcframework",
CROSS_BUILD_DIR / context.platform / "testbed",
]
)
# Build the final archive
archive_name = (
@ -764,7 +757,7 @@ def build(context: argparse.Namespace, host: str | None = None) -> None:
package(context)
def test(context: argparse.Namespace, host: str | None = None) -> None: # noqa: PT028
def test(context: argparse.Namespace, host: str | None = None) -> None:
"""The implementation of the "test" command."""
if host is None:
host = context.host
@ -802,16 +795,18 @@ def test(context: argparse.Namespace, host: str | None = None) -> None: # noqa:
/ f"Frameworks/{apple_multiarch(host)}"
)
run([
sys.executable,
"Apple/testbed",
"clone",
"--platform",
context.platform,
"--framework",
framework_path,
testbed_dir,
])
run(
[
sys.executable,
"Apple/testbed",
"clone",
"--platform",
context.platform,
"--framework",
framework_path,
testbed_dir,
]
)
run(
[
@ -828,7 +823,7 @@ def test(context: argparse.Namespace, host: str | None = None) -> None: # noqa:
+ [
"--",
"test",
f"--{context.ci_mode}-ci",
"--slow-ci" if context.slow else "--fast-ci",
"--single-process",
"--no-randomize",
# Timeout handling requires subprocesses; explicitly setting
@ -841,39 +836,11 @@ def test(context: argparse.Namespace, host: str | None = None) -> None: # noqa:
)
def apple_sim_host(platform_name: str) -> str:
"""Determine the native simulator target for this platform."""
for _, slice_parts in HOSTS[platform_name].items():
for host_triple in slice_parts:
parts = host_triple.split("-")
if parts[0] == platform.machine() and parts[-1] == "simulator":
return host_triple
raise KeyError(platform_name)
def ci(context: argparse.Namespace) -> None:
"""The implementation of the "ci" command.
In "Fast" mode, this compiles the build python, and the simulator for the
build machine's architecture; and runs the test suite with `--fast-ci`
configuration.
In "Slow" mode, it compiles the build python, plus all candidate
architectures (both device and simulator); then runs the test suite with
`--slow-ci` configuration.
"""
"""The implementation of the "ci" command."""
clean(context, "all")
if context.ci_mode == "slow":
# In slow mode, build and test the full XCframework
build(context, host="all")
test(context, host="all")
else:
# In fast mode, just build the simulator platform.
sim_host = apple_sim_host(context.platform)
build(context, host="build")
build(context, host=sim_host)
test(context, host=sim_host)
build(context, host="all")
test(context, host="all")
def parse_args() -> argparse.Namespace:
@ -973,28 +940,17 @@ def parse_args() -> argparse.Namespace:
cmd.add_argument(
"--simulator",
help=(
"The name of the simulator to use (eg: 'iPhone 16e'). "
"Defaults to the most recently released 'entry level' "
"iPhone device. Device architecture and OS version can also "
"be specified; e.g., "
"`--simulator 'iPhone 16 Pro,arch=arm64,OS=26.0'` would "
"run on an ARM64 iPhone 16 Pro simulator running iOS 26.0."
"The name of the simulator to use (eg: 'iPhone 16e'). Defaults to "
"the most recently released 'entry level' iPhone device. Device "
"architecture and OS version can also be specified; e.g., "
"`--simulator 'iPhone 16 Pro,arch=arm64,OS=26.0'` would run on "
"an ARM64 iPhone 16 Pro simulator running iOS 26.0."
),
)
group = cmd.add_mutually_exclusive_group()
group.add_argument(
"--fast-ci",
action="store_const",
dest="ci_mode",
const="fast",
help="Add test arguments for GitHub Actions",
)
group.add_argument(
"--slow-ci",
action="store_const",
dest="ci_mode",
const="slow",
help="Add test arguments for buildbots",
cmd.add_argument(
"--slow",
action="store_true",
help="Run tests with --slow-ci options.",
)
for subcommand in [configure_build, configure_host, build, ci]:
@ -1056,10 +1012,4 @@ def main() -> None:
if __name__ == "__main__":
# Under the buildbot, stdout is not a TTY, but we must still flush after
# every line to make sure our output appears in the correct order relative
# to the output of our subprocesses.
for stream in [sys.stdout, sys.stderr]:
stream.reconfigure(line_buffering=True)
main()

View file

@ -224,17 +224,6 @@ Once you have a built an XCframework, you can test that framework by running:
$ python Apple test iOS
This test will attempt to find an "SE-class" simulator (i.e., an iPhone SE, or
iPhone 16e, or similar), and run the test suite on the most recent version of
iOS that is available. You can specify a simulator using the `--simulator`
command line argument, providing the name of the simulator (e.g., `--simulator
'iPhone 16 Pro'`). You can also use this argument to control the OS version used
for testing; `--simulator 'iPhone 16 Pro,OS=18.2'` would attempt to run the
tests on an iPhone 16 Pro running iOS 18.2.
If the test runner is executed on GitHub Actions, the `GITHUB_ACTIONS`
environment variable will be exposed to the iOS process at runtime.
### Testing a single-architecture framework
The `Apple/testbed` folder that contains an Xcode project that is able to run

View file

@ -46,8 +46,7 @@ install_stdlib() {
rsync -au --delete "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/"
rsync -au "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/$SLICE_FOLDER/lib-$ARCHS/" "$CODESIGNING_FOLDER_PATH/python/lib/"
else
# A single-arch framework will have a libpython symlink; that can't be included at runtime
rsync -au --delete "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/$SLICE_FOLDER/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/" --exclude 'libpython*.dylib'
rsync -au --delete "$PROJECT_DIR/$PYTHON_XCFRAMEWORK_PATH/$SLICE_FOLDER/lib/" "$CODESIGNING_FOLDER_PATH/python/lib/"
fi
}

View file

@ -35,9 +35,6 @@
setenv("NO_COLOR", "1", true);
setenv("PYTHON_COLORS", "0", true);
if (getenv("GITHUB_ACTIONS")) {
NSLog(@"Running in a GitHub Actions environment");
}
// Arguments to pass into the test suite runner.
// argv[0] must identify the process; any subsequent arg
// will be handled as if it were an argument to `python -m test`

View file

@ -1,8 +1,6 @@
import argparse
import json
import os
import re
import shlex
import shutil
import subprocess
import sys
@ -32,15 +30,15 @@ def select_simulator_device(platform):
json_data = json.loads(raw_json)
if platform == "iOS":
# Any iOS device will do; we'll look for "SE" devices - but the name
# isn't consistent over time. Older Xcode versions will use "iPhone SE
# (Nth generation)"; As of 2025, they've started using "iPhone 16e".
# Any iOS device will do; we'll look for "SE" devices - but the name isn't
# consistent over time. Older Xcode versions will use "iPhone SE (Nth
# generation)"; As of 2025, they've started using "iPhone 16e".
#
# When Xcode is updated after a new release, new devices will be
# available and old ones will be dropped from the set available on the
# latest iOS version. Select the one with the highest minimum runtime
# version - this is an indicator of the "newest" released device, which
# should always be supported on the "most recent" iOS version.
# When Xcode is updated after a new release, new devices will be available
# and old ones will be dropped from the set available on the latest iOS
# version. Select the one with the highest minimum runtime version - this
# is an indicator of the "newest" released device, which should always be
# supported on the "most recent" iOS version.
se_simulators = sorted(
(devicetype["minRuntimeVersion"], devicetype["name"])
for devicetype in json_data["devicetypes"]
@ -80,13 +78,6 @@ def xcode_test(location: Path, platform: str, simulator: str, verbose: bool):
check=True,
)
# Any environment variable prefixed with TEST_RUNNER_ is exposed into the
# test runner environment. There are some variables (like those identifying
# CI platforms) that can be useful to have access to.
test_env = os.environ.copy()
if "GITHUB_ACTIONS" in os.environ:
test_env["TEST_RUNNER_GITHUB_ACTIONS"] = os.environ["GITHUB_ACTIONS"]
print("Running test project...")
# Test execution *can't* be run -quiet; verbose mode
# is how we see the output of the test output.
@ -94,7 +85,6 @@ def xcode_test(location: Path, platform: str, simulator: str, verbose: bool):
["xcodebuild", "test-without-building"] + args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
env=test_env,
)
while line := (process.stdout.readline()).decode(*DECODE_ARGS):
# Strip the timestamp/process prefix from each log line
@ -253,7 +243,7 @@ def update_test_plan(testbed_path, platform, args):
test_plan = json.load(f)
test_plan["defaultOptions"]["commandLineArgumentEntries"] = [
{"argument": shlex.quote(arg)} for arg in args
{"argument": arg} for arg in args
]
with test_plan_path.open("w", encoding="utf-8") as f:
@ -295,8 +285,7 @@ def main():
parser = argparse.ArgumentParser(
description=(
"Manages the process of testing an Apple Python project "
"through Xcode."
"Manages the process of testing an Apple Python project through Xcode."
),
)
@ -337,10 +326,7 @@ def main():
run = subcommands.add_parser(
"run",
usage=(
"%(prog)s [-h] [--simulator SIMULATOR] -- "
"<test arg> [<test arg> ...]"
),
usage="%(prog)s [-h] [--simulator SIMULATOR] -- <test arg> [<test arg> ...]",
description=(
"Run a testbed project. The arguments provided after `--` will be "
"passed to the running iOS process as if they were arguments to "
@ -401,9 +387,9 @@ def main():
/ "bin"
).is_dir():
print(
"Testbed does not contain a compiled Python framework. "
f"Use `python {sys.argv[0]} clone ...` to create a "
"runnable clone of this testbed."
f"Testbed does not contain a compiled Python framework. Use "
f"`python {sys.argv[0]} clone ...` to create a runnable "
f"clone of this testbed."
)
sys.exit(20)
@ -415,8 +401,7 @@ def main():
)
else:
print(
"Must specify test arguments "
f"(e.g., {sys.argv[0]} run -- test)"
f"Must specify test arguments (e.g., {sys.argv[0]} run -- test)"
)
print()
parser.print_help(sys.stderr)
@ -427,9 +412,4 @@ def main():
if __name__ == "__main__":
# Under the buildbot, stdout is not a TTY, but we must still flush after
# every line to make sure our output appears in the correct order relative
# to the output of our subprocesses.
for stream in [sys.stdout, sys.stderr]:
stream.reconfigure(line_buffering=True)
main()

View file

@ -140,8 +140,7 @@ doctest:
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" \
"&& cp build/pydoc-topics/module_docs.py ../Lib/pydoc_data/module_docs.py"
"cp build/pydoc-topics/topics.py ../Lib/pydoc_data/topics.py"
.PHONY: gettext
gettext: BUILDER = gettext
@ -242,8 +241,7 @@ dist-pdf:
# as otherwise the full latexmk process is run twice.
# ($$ is needed to escape the $; https://www.gnu.org/software/make/manual/make.html#Basics-of-Variable-References)
-sed -i 's/: all-$$(FMT)/:/' build/latex/Makefile
if [ -n "$(filter output-sync,$(value .FEATURES))" ]; then OUTPUTSYNC=--output-sync; else OUTPUTSYNC=; fi && \
(cd build/latex; $(MAKE) clean && $(MAKE) --jobs=$$((`getconf _NPROCESSORS_ONLN`+1)) $$OUTPUTSYNC LATEXMKOPTS='-quiet' all-pdf && $(MAKE) FMT=pdf zip bz2)
(cd build/latex; $(MAKE) clean && $(MAKE) --jobs=$$((`nproc`+1)) --output-sync LATEXMKOPTS='-quiet' all-pdf && $(MAKE) FMT=pdf zip bz2)
cp build/latex/docs-pdf.zip dist/python-$(DISTVERSION)-docs-pdf-a4.zip
cp build/latex/docs-pdf.tar.bz2 dist/python-$(DISTVERSION)-docs-pdf-a4.tar.bz2
@echo "Build finished and archived!"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -32,9 +32,8 @@ Contributors to the Python documentation
----------------------------------------
Many people have contributed to the Python language, the Python standard
library, and the Python documentation. See the `CPython
GitHub repository <https://github.com/python/cpython/graphs/contributors>`__
for a partial list of contributors.
library, and the Python documentation. See :source:`Misc/ACKS` in the Python
source distribution for a partial list of contributors.
It is only with the input and contributions of the Python community
that Python has such wonderful documentation -- Thank You!

View file

@ -19,12 +19,6 @@ If you find a bug in this documentation or would like to propose an improvement,
please submit a bug report on the :ref:`issue tracker <using-the-tracker>`. If you
have a suggestion on how to fix it, include that as well.
.. only:: translation
If the bug or suggested improvement concerns the translation of this
documentation, submit the report to the
`translations repository <TRANSLATION_REPO_>`_ instead.
You can also open a discussion item on our
`Documentation Discourse forum <https://discuss.python.org/c/documentation/26>`_.

View file

@ -140,6 +140,10 @@ Allocating Objects on the Heap
* :c:member:`~PyTypeObject.tp_alloc`
.. c:function:: void PyObject_Del(void *op)
Same as :c:func:`PyObject_Free`.
.. c:var:: PyObject _Py_NoneStruct
Object which is visible in Python as ``None``. This should only be accessed
@ -152,35 +156,3 @@ Allocating Objects on the Heap
:ref:`moduleobjects`
To allocate and create extension modules.
Deprecated aliases
^^^^^^^^^^^^^^^^^^
These are :term:`soft deprecated` aliases to existing functions and macros.
They exist solely for backwards compatibility.
.. list-table::
:widths: auto
:header-rows: 1
* * Deprecated alias
* Function
* * .. c:macro:: PyObject_NEW(type, typeobj)
* :c:macro:`PyObject_New`
* * .. c:macro:: PyObject_NEW_VAR(type, typeobj, n)
* :c:macro:`PyObject_NewVar`
* * .. c:macro:: PyObject_INIT(op, typeobj)
* :c:func:`PyObject_Init`
* * .. c:macro:: PyObject_INIT_VAR(op, typeobj, n)
* :c:func:`PyObject_InitVar`
* * .. c:macro:: PyObject_MALLOC(n)
* :c:func:`PyObject_Malloc`
* * .. c:macro:: PyObject_REALLOC(p, n)
* :c:func:`PyObject_Realloc`
* * .. c:macro:: PyObject_FREE(p)
* :c:func:`PyObject_Free`
* * .. c:macro:: PyObject_DEL(p)
* :c:func:`PyObject_Free`
* * .. c:macro:: PyObject_Del(p)
* :c:func:`PyObject_Free`

View file

@ -160,7 +160,7 @@ There are three ways strings and buffers can be converted to C:
``w*`` (read-write :term:`bytes-like object`) [Py_buffer]
This format accepts any object which implements the read-write buffer
interface. It fills a :c:type:`Py_buffer` structure provided by the caller.
The buffer may contain embedded null bytes. The caller has to call
The buffer may contain embedded null bytes. The caller have to call
:c:func:`PyBuffer_Release` when it is done with the buffer.
``es`` (:class:`str`) [const char \*encoding, char \*\*buffer]

View file

@ -261,10 +261,6 @@ readonly, format
MUST be consistent for all consumers. For example, :c:expr:`PyBUF_SIMPLE | PyBUF_WRITABLE`
can be used to request a simple writable buffer.
.. c:macro:: PyBUF_WRITEABLE
This is a :term:`soft deprecated` alias to :c:macro:`PyBUF_WRITABLE`.
.. c:macro:: PyBUF_FORMAT
Controls the :c:member:`~Py_buffer.format` field. If set, this field MUST

View file

@ -228,42 +228,6 @@ called with a non-bytes parameter.
The function is :term:`soft deprecated`,
use the :c:type:`PyBytesWriter` API instead.
.. c:function:: PyObject *PyBytes_Repr(PyObject *bytes, int smartquotes)
Get the string representation of *bytes*. This function is currently used to
implement :meth:`!bytes.__repr__` in Python.
This function does not do type checking; it is undefined behavior to pass
*bytes* as a non-bytes object or ``NULL``.
If *smartquotes* is true, the representation will use a double-quoted string
instead of single-quoted string when single-quotes are present in *bytes*.
For example, the byte string ``'Python'`` would be represented as
``b"'Python'"`` when *smartquotes* is true, or ``b'\'Python\''`` when it is
false.
On success, this function returns a :term:`strong reference` to a
:class:`str` object containing the representation. On failure, this
returns ``NULL`` with an exception set.
.. c:function:: PyObject *PyBytes_DecodeEscape(const char *s, Py_ssize_t len, const char *errors, Py_ssize_t unicode, const char *recode_encoding)
Unescape a backslash-escaped string *s*. *s* must not be ``NULL``.
*len* must be the size of *s*.
*errors* must be one of ``"strict"``, ``"replace"``, or ``"ignore"``. If
*errors* is ``NULL``, then ``"strict"`` is used by default.
On success, this function returns a :term:`strong reference` to a Python
:class:`bytes` object containing the unescaped string. On failure, this
function returns ``NULL`` with an exception set.
.. versionchanged:: 3.9
*unicode* and *recode_encoding* are now unused.
.. _pybyteswriter:
PyBytesWriter
@ -295,7 +259,6 @@ Create, Finish, Discard
If *size* is greater than zero, allocate *size* bytes, and set the
writer size to *size*. The caller is responsible to write *size*
bytes using :c:func:`PyBytesWriter_GetData`.
This function does not overallocate.
On error, set an exception and return ``NULL``.
@ -386,8 +349,6 @@ Low-level API
Resize the writer to *size* bytes. It can be used to enlarge or to
shrink the writer.
This function typically overallocates to achieve amortized performance when
resizing multiple times.
Newly allocated bytes are left uninitialized.
@ -399,8 +360,6 @@ Low-level API
.. c:function:: int PyBytesWriter_Grow(PyBytesWriter *writer, Py_ssize_t grow)
Resize the writer by adding *grow* bytes to the current writer size.
This function typically overallocates to achieve amortized performance when
resizing multiple times.
Newly allocated bytes are left uninitialized.

View file

@ -15,19 +15,13 @@ 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 which need to pass an opaque value (as a :c:expr:`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
loaded modules.
.. c:var:: PyTypeObject PyCapsule_Type
The type object corresponding to capsule objects. This is the same object
as :class:`types.CapsuleType` in the Python layer.
.. c:type:: PyCapsule_Destructor
The type of a destructor callback for a capsule. Defined as::

View file

@ -7,7 +7,7 @@ Cell Objects
"Cell" objects are used to implement variables referenced by multiple scopes.
For each such variable, a cell object is created to store the value; the local
variables of each stack frame that references the value contain a reference to
variables of each stack frame that references the value contains a reference to
the cells from outer scopes which also use that variable. When the value is
accessed, the value contained in the cell is used instead of the cell object
itself. This de-referencing of the cell object requires support from the

View file

@ -211,17 +211,6 @@ bound into a function.
.. versionadded:: 3.12
.. c:function:: PyObject *PyCode_Optimize(PyObject *code, PyObject *consts, PyObject *names, PyObject *lnotab_obj)
This is a :term:`soft deprecated` function that does nothing.
Prior to Python 3.10, this function would perform basic optimizations to a
code object.
.. versionchanged:: 3.10
This function now does nothing.
.. _c_codeobject_flags:
Code Object Flags
@ -300,7 +289,7 @@ may change without deprecation warnings.
.. c:function:: Py_ssize_t PyUnstable_Eval_RequestCodeExtraIndex(freefunc free)
Return a new opaque index value used to adding data to code objects.
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

View file

@ -7,7 +7,7 @@ Codec registry and support functions
Register a new codec search function.
As a 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)
@ -39,7 +39,7 @@ Codec registry and support functions
*object* is passed through the decoder function found for the given
*encoding* using the error handling method defined by *errors*. *errors* may
be ``NULL`` to use the default method defined for the codec. Raises a
:exc:`LookupError` if no decoder can be found.
:exc:`LookupError` if no encoder can be found.
Codec lookup API
@ -129,13 +129,3 @@ Registry API for Unicode encoding error handlers
Replace the unicode encode error with ``\N{...}`` escapes.
.. versionadded:: 3.5
Codec utility variables
-----------------------
.. c:var:: const char *Py_hexdigits
A string constant containing the lowercase hexadecimal digits: ``"0123456789abcdef"``.
.. versionadded:: 3.3

View file

@ -82,7 +82,7 @@ Complex Number Objects
.. c:type:: Py_complex
This C structure defines an export format for a Python complex
This C structure defines export format for a Python complex
number object.
.. c:member:: double real

View file

@ -109,20 +109,11 @@ Other Objects
descriptor.rst
slice.rst
memoryview.rst
picklebuffer.rst
weakref.rst
capsule.rst
frame.rst
gen.rst
coro.rst
contextvars.rst
typehints.rst
C API for extension modules
===========================
.. toctree::
curses.rst
datetime.rst
typehints.rst

View file

@ -41,7 +41,7 @@ The return value (*rv*) for these functions should be interpreted as follows:
``rv + 1`` bytes would have been needed to succeed. ``str[size-1]`` is ``'\0'``
in this case.
* When ``rv < 0``, the output conversion failed and ``str[size-1]`` is ``'\0'`` in
* When ``rv < 0``, "something bad happened." ``str[size-1]`` is ``'\0'`` in
this case too, but the rest of *str* is undefined. The exact cause of the error
depends on the underlying platform.
@ -105,7 +105,7 @@ The following functions provide locale-independent string to number conversions.
If ``s`` represents a value that is too large to store in a float
(for example, ``"1e500"`` is such a string on many platforms) then
if ``overflow_exception`` is ``NULL`` return :c:macro:`!INFINITY` (with
if ``overflow_exception`` is ``NULL`` return ``Py_INFINITY`` (with
an appropriate sign) and don't set any exception. Otherwise,
``overflow_exception`` must point to a Python exception object;
raise that exception and return ``-1.0``. In both cases, set
@ -128,28 +128,18 @@ The following functions provide locale-independent string to number conversions.
must be 0 and is ignored. The ``'r'`` format code specifies the
standard :func:`repr` format.
*flags* can be zero or more of the following values or-ed together:
*flags* can be zero or more of the values ``Py_DTSF_SIGN``,
``Py_DTSF_ADD_DOT_0``, or ``Py_DTSF_ALT``, or-ed together:
.. c:macro:: Py_DTSF_SIGN
* ``Py_DTSF_SIGN`` means to always precede the returned string with a sign
character, even if *val* is non-negative.
Always precede the returned string with a sign
character, even if *val* is non-negative.
* ``Py_DTSF_ADD_DOT_0`` means to ensure that the returned string will not look
like an integer.
.. c:macro:: Py_DTSF_ADD_DOT_0
Ensure that the returned string will not look like an integer.
.. c:macro:: Py_DTSF_ALT
Apply "alternate" formatting rules.
See the documentation for the :c:func:`PyOS_snprintf` ``'#'`` specifier for
details.
.. c:macro:: Py_DTSF_NO_NEG_0
Negative zero is converted to positive zero.
.. versionadded:: 3.11
* ``Py_DTSF_ALT`` means to apply "alternate" formatting rules. See the
documentation for the :c:func:`PyOS_snprintf` ``'#'`` specifier for
details.
If *ptype* is non-``NULL``, then the value it points to will be set to one of
``Py_DTST_FINITE``, ``Py_DTST_INFINITE``, or ``Py_DTST_NAN``, signifying that
@ -162,85 +152,13 @@ The following functions provide locale-independent string to number conversions.
.. versionadded:: 3.1
.. c:function:: int PyOS_mystricmp(const char *str1, const char *str2)
int PyOS_mystrnicmp(const char *str1, const char *str2, Py_ssize_t size)
.. c:function:: int PyOS_stricmp(const char *s1, const char *s2)
Case insensitive comparison of strings. These functions work almost
identically to :c:func:`!strcmp` and :c:func:`!strncmp` (respectively),
except that they ignore the case of ASCII characters.
Return ``0`` if the strings are equal, a negative value if *str1* sorts
lexicographically before *str2*, or a positive value if it sorts after.
In the *str1* or *str2* arguments, a NUL byte marks the end of the string.
For :c:func:`!PyOS_mystrnicmp`, the *size* argument gives the maximum size
of the string, as if NUL was present at the index given by *size*.
These functions do not use the locale.
Case insensitive comparison of strings. The function works almost
identically to :c:func:`!strcmp` except that it ignores the case.
.. c:function:: int PyOS_stricmp(const char *str1, const char *str2)
int PyOS_strnicmp(const char *str1, const char *str2, Py_ssize_t size)
.. c:function:: int PyOS_strnicmp(const char *s1, const char *s2, Py_ssize_t size)
Case insensitive comparison of strings.
On Windows, these are aliases of :c:func:`!stricmp` and :c:func:`!strnicmp`,
respectively.
On other platforms, they are aliases of :c:func:`PyOS_mystricmp` and
:c:func:`PyOS_mystrnicmp`, respectively.
Character classification and conversion
=======================================
The following macros provide locale-independent (unlike the C standard library
``ctype.h``) character classification and conversion.
The argument must be a signed or unsigned :c:expr:`char`.
.. c:macro:: Py_ISALNUM(c)
Return true if the character *c* is an alphanumeric character.
.. c:macro:: Py_ISALPHA(c)
Return true if the character *c* is an alphabetic character (``a-z`` and ``A-Z``).
.. c:macro:: Py_ISDIGIT(c)
Return true if the character *c* is a decimal digit (``0-9``).
.. c:macro:: Py_ISLOWER(c)
Return true if the character *c* is a lowercase ASCII letter (``a-z``).
.. c:macro:: Py_ISUPPER(c)
Return true if the character *c* is an uppercase ASCII letter (``A-Z``).
.. c:macro:: Py_ISSPACE(c)
Return true if the character *c* is a whitespace character (space, tab,
carriage return, newline, vertical tab, or form feed).
.. c:macro:: Py_ISXDIGIT(c)
Return true if the character *c* is a hexadecimal digit (``0-9``, ``a-f``, and
``A-F``).
.. c:macro:: Py_TOLOWER(c)
Return the lowercase equivalent of the character *c*.
.. c:macro:: Py_TOUPPER(c)
Return the uppercase equivalent of the character *c*.
Case insensitive comparison of strings. The function works almost
identically to :c:func:`!strncmp` except that it ignores the case.

View file

@ -1,138 +0,0 @@
.. highlight:: c
Curses C API
------------
:mod:`curses` exposes a small C interface for extension modules.
Consumers must include the header file :file:`py_curses.h` (which is not
included by default by :file:`Python.h`) and :c:func:`import_curses` must
be invoked, usually as part of the module initialisation function, to populate
:c:var:`PyCurses_API`.
.. warning::
Neither the C API nor the pure Python :mod:`curses` module are compatible
with subinterpreters.
.. c:macro:: import_curses()
Import the curses C API. The macro does not need a semi-colon to be called.
On success, populate the :c:var:`PyCurses_API` pointer.
On failure, set :c:var:`PyCurses_API` to NULL and set an exception.
The caller must check if an error occurred via :c:func:`PyErr_Occurred`:
.. code-block::
import_curses(); // semi-colon is optional but recommended
if (PyErr_Occurred()) { /* cleanup */ }
.. c:var:: void **PyCurses_API
Dynamically allocated object containing the curses C API.
This variable is only available once :c:macro:`import_curses` succeeds.
``PyCurses_API[0]`` corresponds to :c:data:`PyCursesWindow_Type`.
``PyCurses_API[1]``, ``PyCurses_API[2]``, and ``PyCurses_API[3]``
are pointers to predicate functions of type ``int (*)(void)``.
When called, these predicates return whether :func:`curses.setupterm`,
:func:`curses.initscr`, and :func:`curses.start_color` have been called
respectively.
See also the convenience macros :c:macro:`PyCursesSetupTermCalled`,
:c:macro:`PyCursesInitialised`, and :c:macro:`PyCursesInitialisedColor`.
.. note::
The number of entries in this structure is subject to changes.
Consider using :c:macro:`PyCurses_API_pointers` to check if
new fields are available or not.
.. c:macro:: PyCurses_API_pointers
The number of accessible fields (``4``) in :c:var:`PyCurses_API`.
This number is incremented whenever new fields are added.
.. c:var:: PyTypeObject PyCursesWindow_Type
The :ref:`heap type <heap-types>` corresponding to :class:`curses.window`.
.. c:function:: int PyCursesWindow_Check(PyObject *op)
Return true if *op* is a :class:`curses.window` instance, false otherwise.
The following macros are convenience macros expanding into C statements.
In particular, they can only be used as ``macro;`` or ``macro``, but not
``macro()`` or ``macro();``.
.. c:macro:: PyCursesSetupTermCalled
Macro checking if :func:`curses.setupterm` has been called.
The macro expansion is roughly equivalent to:
.. code-block::
{
typedef int (*predicate_t)(void);
predicate_t was_setupterm_called = (predicate_t)PyCurses_API[1];
if (!was_setupterm_called()) {
return NULL;
}
}
.. c:macro:: PyCursesInitialised
Macro checking if :func:`curses.initscr` has been called.
The macro expansion is roughly equivalent to:
.. code-block::
{
typedef int (*predicate_t)(void);
predicate_t was_initscr_called = (predicate_t)PyCurses_API[2];
if (!was_initscr_called()) {
return NULL;
}
}
.. c:macro:: PyCursesInitialisedColor
Macro checking if :func:`curses.start_color` has been called.
The macro expansion is roughly equivalent to:
.. code-block::
{
typedef int (*predicate_t)(void);
predicate_t was_start_color_called = (predicate_t)PyCurses_API[3];
if (!was_start_color_called()) {
return NULL;
}
}
Internal data
-------------
The following objects are exposed by the C API but should be considered
internal-only.
.. c:macro:: PyCurses_CAPSULE_NAME
Name of the curses capsule to pass to :c:func:`PyCapsule_Import`.
Internal usage only. Use :c:macro:`import_curses` instead.

View file

@ -8,42 +8,11 @@ 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:macro:: PyDateTime_IMPORT()
Import the datetime C API.
On success, populate the :c:var:`PyDateTimeAPI` pointer.
On failure, set :c:var:`PyDateTimeAPI` to ``NULL`` and set an exception.
The caller must check if an error occurred via :c:func:`PyErr_Occurred`:
.. code-block::
PyDateTime_IMPORT;
if (PyErr_Occurred()) { /* cleanup */ }
.. warning::
This is not compatible with subinterpreters.
.. c:type:: PyDateTime_CAPI
Structure containing the fields for the datetime C API.
The fields of this structure are private and subject to change.
Do not use this directly; prefer ``PyDateTime_*`` APIs instead.
.. c:var:: PyDateTime_CAPI *PyDateTimeAPI
Dynamically allocated object containing the datetime C API.
This variable is only available once :c:macro:`PyDateTime_IMPORT` succeeds.
.. c:type:: PyDateTime_Date
This subtype of :c:type:`PyObject` represents a Python date object.
@ -77,7 +46,7 @@ macros.
.. c:var:: PyTypeObject PyDateTime_DeltaType
This instance of :c:type:`PyTypeObject` represents the Python type for
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.
@ -356,16 +325,3 @@ Macros for the convenience of modules implementing the DB API:
Create and return a new :class:`datetime.date` object given an argument
tuple suitable for passing to :meth:`datetime.date.fromtimestamp`.
Internal data
-------------
The following symbols are exposed by the C API but should be considered
internal-only.
.. c:macro:: PyDateTime_CAPSULE_NAME
Name of the datetime capsule to pass to :c:func:`PyCapsule_Import`.
Internal usage only. Use :c:macro:`PyDateTime_IMPORT` instead.

View file

@ -21,104 +21,20 @@ found in the dictionary of type objects.
.. c:function:: PyObject* PyDescr_NewMember(PyTypeObject *type, struct PyMemberDef *meth)
.. c:var:: PyTypeObject PyMemberDescr_Type
The type object for member descriptor objects created from
:c:type:`PyMemberDef` structures. These descriptors expose fields of a
C struct as attributes on a type, and correspond
to :class:`types.MemberDescriptorType` objects in Python.
.. c:var:: PyTypeObject PyGetSetDescr_Type
The type object for get/set descriptor objects created from
:c:type:`PyGetSetDef` structures. These descriptors implement attributes
whose value is computed by C getter and setter functions, and are used
for many built-in type attributes.
.. c:function:: PyObject* PyDescr_NewMethod(PyTypeObject *type, struct PyMethodDef *meth)
.. c:var:: PyTypeObject PyMethodDescr_Type
The type object for method descriptor objects created from
:c:type:`PyMethodDef` structures. These descriptors expose C functions as
methods on a type, and correspond to :class:`types.MemberDescriptorType`
objects in Python.
.. c:function:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *wrapper, void *wrapped)
.. c:var:: PyTypeObject PyWrapperDescr_Type
The type object for wrapper descriptor objects created by
:c:func:`PyDescr_NewWrapper` and :c:func:`PyWrapper_New`. Wrapper
descriptors are used internally to expose special methods implemented
via wrapper structures, and appear in Python as
:class:`types.WrapperDescriptorType` objects.
.. c:function:: PyObject* PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
.. c:function:: int PyDescr_IsData(PyObject *descr)
Return non-zero if the descriptor object *descr* describes a data attribute, or
Return non-zero if the descriptor objects *descr* describes a data attribute, or
``0`` if it describes a method. *descr* must be a descriptor object; there is
no error checking.
.. c:function:: PyObject* PyWrapper_New(PyObject *, PyObject *)
Built-in descriptors
^^^^^^^^^^^^^^^^^^^^
.. c:var:: PyTypeObject PySuper_Type
The type object for super objects. This is the same object as
:class:`super` in the Python layer.
.. c:var:: PyTypeObject PyClassMethod_Type
The type of class method objects. This is the same object as
:class:`classmethod` in the Python layer.
.. c:var:: PyTypeObject PyClassMethodDescr_Type
The type object for C-level class method descriptor objects.
This is the type of the descriptors created for :func:`classmethod` defined in
C extension types, and is the same object as :class:`classmethod`
in Python.
.. c:function:: PyObject *PyClassMethod_New(PyObject *callable)
Create a new :class:`classmethod` object wrapping *callable*.
*callable* must be a callable object and must not be ``NULL``.
On success, this function returns a :term:`strong reference` to a new class
method descriptor. On failure, this function returns ``NULL`` with an
exception set.
.. c:var:: PyTypeObject PyStaticMethod_Type
The type of static method objects. This is the same object as
:class:`staticmethod` in the Python layer.
.. c:function:: PyObject *PyStaticMethod_New(PyObject *callable)
Create a new :class:`staticmethod` object wrapping *callable*.
*callable* must be a callable object and must not be ``NULL``.
On success, this function returns a :term:`strong reference` to a new static
method descriptor. On failure, this function returns ``NULL`` with an
exception set.

View file

@ -43,17 +43,6 @@ Dictionary Objects
prevent modification of the dictionary for non-dynamic class types.
.. c:var:: PyTypeObject PyDictProxy_Type
The type object for mapping proxy objects created by
:c:func:`PyDictProxy_New` and for the read-only ``__dict__`` attribute
of many built-in types. A :c:type:`PyDictProxy_Type` instance provides a
dynamic, read-only view of an underlying dictionary: changes to the
underlying dictionary are reflected in the proxy, but the proxy itself
does not support mutation operations. This corresponds to
:class:`types.MappingProxyType` in Python.
.. c:function:: void PyDict_Clear(PyObject *p)
Empty an existing dictionary of all key-value pairs.
@ -61,7 +50,7 @@ Dictionary Objects
.. c:function:: int PyDict_Contains(PyObject *p, PyObject *key)
Determine if dictionary *p* contains *key*. If an item in *p* matches
Determine if dictionary *p* contains *key*. If an item in *p* is matches
*key*, return ``1``, otherwise return ``0``. On error, return ``-1``.
This is equivalent to the Python expression ``key in p``.
@ -209,7 +198,7 @@ Dictionary Objects
.. 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 is missing.
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``.
@ -218,7 +207,7 @@ Dictionary Objects
- On error, raise an exception and return ``-1``.
Similar to :meth:`dict.pop`, but without the default value and
not raising :exc:`KeyError` if the key is missing.
not raising :exc:`KeyError` if the key missing.
.. versionadded:: 3.13
@ -256,11 +245,6 @@ Dictionary Objects
``len(p)`` on a dictionary.
.. c:function:: Py_ssize_t PyDict_GET_SIZE(PyObject *p)
Similar to :c:func:`PyDict_Size`, but without error checking.
.. c:function:: int PyDict_Next(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
Iterate over all key-value pairs in the dictionary *p*. The
@ -442,138 +426,3 @@ Dictionary Objects
it before returning.
.. versionadded:: 3.12
Dictionary View Objects
^^^^^^^^^^^^^^^^^^^^^^^
.. c:function:: int PyDictViewSet_Check(PyObject *op)
Return true if *op* is a view of a set inside a dictionary. This is currently
equivalent to :c:expr:`PyDictKeys_Check(op) || PyDictItems_Check(op)`. This
function always succeeds.
.. c:var:: PyTypeObject PyDictKeys_Type
Type object for a view of dictionary keys. In Python, this is the type of
the object returned by :meth:`dict.keys`.
.. c:function:: int PyDictKeys_Check(PyObject *op)
Return true if *op* is an instance of a dictionary keys view. This function
always succeeds.
.. c:var:: PyTypeObject PyDictValues_Type
Type object for a view of dictionary values. In Python, this is the type of
the object returned by :meth:`dict.values`.
.. c:function:: int PyDictValues_Check(PyObject *op)
Return true if *op* is an instance of a dictionary values view. This function
always succeeds.
.. c:var:: PyTypeObject PyDictItems_Type
Type object for a view of dictionary items. In Python, this is the type of
the object returned by :meth:`dict.items`.
.. c:function:: int PyDictItems_Check(PyObject *op)
Return true if *op* is an instance of a dictionary items view. This function
always succeeds.
Ordered Dictionaries
^^^^^^^^^^^^^^^^^^^^
Python's C API provides interface for :class:`collections.OrderedDict` from C.
Since Python 3.7, dictionaries are ordered by default, so there is usually
little need for these functions; prefer ``PyDict*`` where possible.
.. c:var:: PyTypeObject PyODict_Type
Type object for ordered dictionaries. This is the same object as
:class:`collections.OrderedDict` in the Python layer.
.. c:function:: int PyODict_Check(PyObject *od)
Return true if *od* is an ordered dictionary object or an instance of a
subtype of the :class:`~collections.OrderedDict` type. This function
always succeeds.
.. c:function:: int PyODict_CheckExact(PyObject *od)
Return true if *od* is an ordered dictionary object, but not an instance of
a subtype of the :class:`~collections.OrderedDict` type.
This function always succeeds.
.. c:var:: PyTypeObject PyODictKeys_Type
Analogous to :c:type:`PyDictKeys_Type` for ordered dictionaries.
.. c:var:: PyTypeObject PyODictValues_Type
Analogous to :c:type:`PyDictValues_Type` for ordered dictionaries.
.. c:var:: PyTypeObject PyODictItems_Type
Analogous to :c:type:`PyDictItems_Type` for ordered dictionaries.
.. c:function:: PyObject *PyODict_New(void)
Return a new empty ordered dictionary, or ``NULL`` on failure.
This is analogous to :c:func:`PyDict_New`.
.. c:function:: int PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
Insert *value* into the ordered dictionary *od* with a key of *key*.
Return ``0`` on success or ``-1`` with an exception set on failure.
This is analogous to :c:func:`PyDict_SetItem`.
.. c:function:: int PyODict_DelItem(PyObject *od, PyObject *key)
Remove the entry in the ordered dictionary *od* with key *key*.
Return ``0`` on success or ``-1`` with an exception set on failure.
This is analogous to :c:func:`PyDict_DelItem`.
These are :term:`soft deprecated` aliases to ``PyDict`` APIs:
.. list-table::
:widths: auto
:header-rows: 1
* * ``PyODict``
* ``PyDict``
* * .. c:macro:: PyODict_GetItem(od, key)
* :c:func:`PyDict_GetItem`
* * .. c:macro:: PyODict_GetItemWithError(od, key)
* :c:func:`PyDict_GetItemWithError`
* * .. c:macro:: PyODict_GetItemString(od, key)
* :c:func:`PyDict_GetItemString`
* * .. c:macro:: PyODict_Contains(od, key)
* :c:func:`PyDict_Contains`
* * .. c:macro:: PyODict_Size(od)
* :c:func:`PyDict_Size`
* * .. c:macro:: PyODict_SIZE(od)
* :c:func:`PyDict_GET_SIZE`

View file

@ -309,14 +309,6 @@ For convenience, some of these functions will always return a
.. versionadded:: 3.4
.. c:function:: void PyErr_RangedSyntaxLocationObject(PyObject *filename, int lineno, int col_offset, int end_lineno, int end_col_offset)
Similar to :c:func:`PyErr_SyntaxLocationObject`, but also sets the
*end_lineno* and *end_col_offset* information for the current exception.
.. versionadded:: 3.10
.. c:function:: void PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)
Like :c:func:`PyErr_SyntaxLocationObject`, but *filename* is a byte string
@ -339,23 +331,6 @@ For convenience, some of these functions will always return a
use.
.. c:function:: PyObject *PyErr_ProgramTextObject(PyObject *filename, int lineno)
Get the source line in *filename* at line *lineno*. *filename* should be a
Python :class:`str` object.
On success, this function returns a Python string object with the found line.
On failure, this function returns ``NULL`` without an exception set.
.. c:function:: PyObject *PyErr_ProgramText(const char *filename, int lineno)
Similar to :c:func:`PyErr_ProgramTextObject`, but *filename* is a
:c:expr:`const char *`, which is decoded with the
:term:`filesystem encoding and error handler`, instead of a
Python object reference.
Issuing warnings
================
@ -419,15 +394,6 @@ an error value).
.. versionadded:: 3.2
.. c:function:: int PyErr_WarnExplicitFormat(PyObject *category, const char *filename, int lineno, const char *module, PyObject *registry, const char *format, ...)
Similar to :c:func:`PyErr_WarnExplicit`, but uses
:c:func:`PyUnicode_FromFormat` to format the warning message. *format* is
an ASCII-encoded string.
.. versionadded:: 3.2
.. c:function:: int PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level, const char *format, ...)
Function similar to :c:func:`PyErr_WarnFormat`, but *category* is
@ -796,17 +762,6 @@ Exception Classes
Exception Objects
=================
.. c:function:: int PyExceptionInstance_Check(PyObject *op)
Return true if *op* is an instance of :class:`BaseException`, false
otherwise. This function always succeeds.
.. c:macro:: PyExceptionInstance_Class(op)
Equivalent to :c:func:`Py_TYPE(op) <Py_TYPE>`.
.. c:function:: PyObject* PyException_GetTraceback(PyObject *ex)
Return the traceback associated with the exception as a new reference, as
@ -984,9 +939,6 @@ because the :ref:`call protocol <call>` takes care of recursion handling.
be concatenated to the :exc:`RecursionError` message caused by the recursion
depth limit.
.. seealso::
The :c:func:`PyUnstable_ThreadState_SetStackProtection` function.
.. versionchanged:: 3.9
This function is now also available in the :ref:`limited API <limited-c-api>`.
@ -1027,27 +979,6 @@ these are the C equivalent to :func:`reprlib.recursive_repr`.
Ends a :c:func:`Py_ReprEnter`. Must be called once for each
invocation of :c:func:`Py_ReprEnter` that returns zero.
.. c:function:: int Py_GetRecursionLimit(void)
Get the recursion limit for the current interpreter. It can be set with
:c:func:`Py_SetRecursionLimit`. The recursion limit prevents the
Python interpreter stack from growing infinitely.
This function cannot fail, and the caller must hold an
:term:`attached thread state`.
.. seealso::
:py:func:`sys.getrecursionlimit`
.. c:function:: void Py_SetRecursionLimit(int new_limit)
Set the recursion limit for the current interpreter.
This function cannot fail, and the caller must hold an
:term:`attached thread state`.
.. seealso::
:py:func:`sys.setrecursionlimit`
.. _standardexceptions:
@ -1276,37 +1207,3 @@ Warning types
.. versionadded:: 3.10
:c:data:`PyExc_EncodingWarning`.
Tracebacks
==========
.. c:var:: PyTypeObject PyTraceBack_Type
Type object for traceback objects. This is available as
:class:`types.TracebackType` in the Python layer.
.. c:function:: int PyTraceBack_Check(PyObject *op)
Return true if *op* is a traceback object, false otherwise. This function
does not account for subtypes.
.. c:function:: int PyTraceBack_Here(PyFrameObject *f)
Replace the :attr:`~BaseException.__traceback__` attribute on the current
exception with a new traceback prepending *f* to the existing chain.
Calling this function without an exception set is undefined behavior.
This function returns ``0`` on success, and returns ``-1`` with an
exception set on failure.
.. c:function:: int PyTraceBack_Print(PyObject *tb, PyObject *f)
Write the traceback *tb* into the file *f*.
This function returns ``0`` on success, and returns ``-1`` with an
exception set on failure.

View file

@ -8,8 +8,7 @@ Defining extension modules
A C extension for CPython is a shared library (for example, a ``.so`` file
on Linux, ``.pyd`` DLL on Windows), which is loadable into the Python process
(for example, it is compiled with compatible compiler settings), and which
exports an :dfn:`export hook` function (or an
old-style :ref:`initialization function <extension-pyinit>`).
exports an :ref:`initialization function <extension-export-hook>`.
To be importable by default (that is, by
:py:class:`importlib.machinery.ExtensionFileLoader`),
@ -24,127 +23,25 @@ and must be named after the module name plus an extension listed in
One suitable tool is Setuptools, whose documentation can be found at
https://setuptools.pypa.io/en/latest/setuptools.html.
.. _extension-export-hook:
Normally, the initialization function returns a module definition initialized
using :c:func:`PyModuleDef_Init`.
This allows splitting the creation process into several phases:
Extension export hook
.....................
.. versionadded:: 3.15
Support for the :samp:`PyModExport_{<name>}` export hook was added in Python
3.15. The older way of defining modules is still available: consult either
the :ref:`extension-pyinit` section or earlier versions of this
documentation if you plan to support earlier Python versions.
The export hook must be an exported function with the following signature:
.. c:function:: PyModuleDef_Slot *PyModExport_modulename(void)
For modules with ASCII-only names, the :ref:`export hook <extension-export-hook>`
must be named :samp:`PyModExport_{<name>}`,
with ``<name>`` replaced by the module's name.
For non-ASCII module names, the export hook must instead be named
:samp:`PyModExportU_{<name>}` (note the ``U``), with ``<name>`` encoded using
Python's *punycode* encoding with hyphens replaced by underscores. In Python:
.. code-block:: python
def hook_name(name):
try:
suffix = b'_' + name.encode('ascii')
except UnicodeEncodeError:
suffix = b'U_' + name.encode('punycode').replace(b'-', b'_')
return b'PyModExport' + suffix
The export hook returns an array of :c:type:`PyModuleDef_Slot` entries,
terminated by an entry with a slot ID of ``0``.
These slots describe how the module should be created and initialized.
This array must remain valid and constant until interpreter shutdown.
Typically, it should use ``static`` storage.
Prefer using the :c:macro:`Py_mod_create` and :c:macro:`Py_mod_exec` slots
for any dynamic behavior.
The export hook may return ``NULL`` with an exception set to signal failure.
It is recommended to define the export hook function using a helper macro:
.. c:macro:: PyMODEXPORT_FUNC
Declare an extension module export hook.
This macro:
* specifies the :c:expr:`PyModuleDef_Slot*` return type,
* adds any special linkage declarations required by the platform, and
* for C++, declares the function as ``extern "C"``.
For example, a module called ``spam`` would be defined like this::
PyABIInfo_VAR(abi_info);
static PyModuleDef_Slot spam_slots[] = {
{Py_mod_abi, &abi_info},
{Py_mod_name, "spam"},
{Py_mod_init, spam_init_function},
...
{0, NULL},
};
PyMODEXPORT_FUNC
PyModExport_spam(void)
{
return spam_slots;
}
The export hook is typically the only non-\ ``static``
item defined in the module's C source.
The hook should be kept short -- ideally, one line as above.
If you do need to use Python C API in this function, it is recommended to call
``PyABIInfo_Check(&abi_info, "modulename")`` first to raise an exception,
rather than crash, in common cases of ABI mismatch.
.. note::
It is possible to export multiple modules from a single shared library by
defining multiple export hooks.
However, importing them requires a custom importer or suitably named
copies/links of the extension file, because Python's import machinery only
finds the function corresponding to the filename.
See the `Multiple modules in one library <https://peps.python.org/pep-0489/#multiple-modules-in-one-library>`__
section in :pep:`489` for details.
.. _multi-phase-initialization:
Multi-phase initialization
..........................
The process of creating an extension module follows several phases:
- Python finds and calls the export hook to get information on how to
create the module.
- Before any substantial code is executed, Python can determine which
capabilities the module supports, and it can adjust the environment or
refuse loading an incompatible extension.
Slots like :c:data:`Py_mod_abi`, :c:data:`Py_mod_gil` and
:c:data:`Py_mod_multiple_interpreters` influence this step.
- By default, Python itself then creates the module object -- that is, it does
the equivalent of calling :py:meth:`~object.__new__` when creating an object.
This step can be overridden using the :c:data:`Py_mod_create` slot.
- Python sets initial module attributes like :attr:`~module.__package__` and
:attr:`~module.__loader__`, and inserts the module object into
:py:attr:`sys.modules`.
- Afterwards, the module object is initialized in an extension-specific way
-- the equivalent of :py:meth:`~object.__init__` when creating an object,
or of executing top-level code in a Python-language module.
The behavior is specified using the :c:data:`Py_mod_exec` slot.
- By default, Python itself creates the module object -- that is, it does
the equivalent of :py:meth:`object.__new__` for classes.
It also sets initial attributes like :attr:`~module.__package__` and
:attr:`~module.__loader__`.
- Afterwards, the module object is initialized using extension-specific
code -- the equivalent of :py:meth:`~object.__init__` on classes.
This is called *multi-phase initialization* to distinguish it from the legacy
(but still supported) :ref:`single-phase initialization <single-phase-initialization>`,
where an initialization function returns a fully constructed module.
(but still supported) *single-phase initialization* scheme,
where the initialization function returns a fully constructed module.
See the :ref:`single-phase-initialization section below <single-phase-initialization>`
for details.
.. versionchanged:: 3.5
@ -156,7 +53,7 @@ Multiple module instances
By default, extension modules are not singletons.
For example, if the :py:attr:`sys.modules` entry is removed and the module
is re-imported, a new module object is created and, typically, populated with
is re-imported, a new module object is created, and typically populated with
fresh method and type objects.
The old module is subject to normal garbage collection.
This mirrors the behavior of pure-Python modules.
@ -186,34 +83,36 @@ A module may also be limited to the main interpreter using
the :c:data:`Py_mod_multiple_interpreters` slot.
.. _extension-pyinit:
.. _extension-export-hook:
``PyInit`` function
...................
Initialization function
.......................
.. deprecated:: 3.15
This functionality is :term:`soft deprecated`.
It will not get new features, but there are no plans to remove it.
Instead of :c:func:`PyModExport_modulename`, an extension module can define
an older-style :dfn:`initialization function` with the signature:
The initialization function defined by an extension module has the
following signature:
.. c:function:: PyObject* PyInit_modulename(void)
Its name should be :samp:`PyInit_{<name>}`, with ``<name>`` replaced by the
name of the module.
For non-ASCII module names, use :samp:`PyInitU_{<name>}` instead, with
``<name>`` encoded in the same way as for the
:ref:`export hook <extension-export-hook>` (that is, using Punycode
with underscores).
If a module exports both :samp:`PyInit_{<name>}` and
:samp:`PyModExport_{<name>}`, the :samp:`PyInit_{<name>}` function
is ignored.
For modules with ASCII-only names, the function must instead be named
:samp:`PyInit_{<name>}`, with ``<name>`` replaced by the name of the module.
When using :ref:`multi-phase-initialization`, non-ASCII module names
are allowed. In this case, the initialization function name is
:samp:`PyInitU_{<name>}`, with ``<name>`` encoded using Python's
*punycode* encoding with hyphens replaced by underscores. In Python:
Like with :c:macro:`PyMODEXPORT_FUNC`, it is recommended to define the
initialization function using a helper macro:
.. code-block:: python
def initfunc_name(name):
try:
suffix = b'_' + name.encode('ascii')
except UnicodeEncodeError:
suffix = b'U_' + name.encode('punycode').replace(b'-', b'_')
return b'PyInit' + suffix
It is recommended to define the initialization function using a helper macro:
.. c:macro:: PyMODINIT_FUNC
@ -224,34 +123,6 @@ initialization function using a helper macro:
* adds any special linkage declarations required by the platform, and
* for C++, declares the function as ``extern "C"``.
Normally, the initialization function (``PyInit_modulename``) returns
a :c:type:`PyModuleDef` instance with non-``NULL``
:c:member:`~PyModuleDef.m_slots`. This allows Python to use
:ref:`multi-phase initialization <multi-phase-initialization>`.
Before it is returned, the ``PyModuleDef`` instance must be initialized
using the following function:
.. c:function:: PyObject* PyModuleDef_Init(PyModuleDef *def)
Ensure a module definition is a properly initialized Python object that
correctly reports its type and a reference count.
Return *def* cast to ``PyObject*``, or ``NULL`` if an error occurred.
Calling this function is required before returning a :c:type:`PyModuleDef`
from a module initialization function.
It should not be used in other contexts.
Note that Python assumes that ``PyModuleDef`` structures are statically
allocated.
This function may return either a new reference or a borrowed one;
this reference must not be released.
.. versionadded:: 3.5
For example, a module called ``spam`` would be defined like this::
static struct PyModuleDef spam_module = {
@ -266,23 +137,59 @@ For example, a module called ``spam`` would be defined like this::
return PyModuleDef_Init(&spam_module);
}
It is possible to export multiple modules from a single shared library by
defining multiple initialization functions. However, importing them requires
using symbolic links or a custom importer, because by default only the
function corresponding to the filename is found.
See the `Multiple modules in one library <https://peps.python.org/pep-0489/#multiple-modules-in-one-library>`__
section in :pep:`489` for details.
The initialization function is typically the only non-\ ``static``
item defined in the module's C source.
.. _multi-phase-initialization:
Multi-phase initialization
..........................
Normally, the :ref:`initialization function <extension-export-hook>`
(``PyInit_modulename``) returns a :c:type:`PyModuleDef` instance with
non-``NULL`` :c:member:`~PyModuleDef.m_slots`.
Before it is returned, the ``PyModuleDef`` instance must be initialized
using the following function:
.. c:function:: PyObject* PyModuleDef_Init(PyModuleDef *def)
Ensure a module definition is a properly initialized Python object that
correctly reports its type and a reference count.
Return *def* cast to ``PyObject*``, or ``NULL`` if an error occurred.
Calling this function is required for :ref:`multi-phase-initialization`.
It should not be used in other contexts.
Note that Python assumes that ``PyModuleDef`` structures are statically
allocated.
This function may return either a new reference or a borrowed one;
this reference must not be released.
.. versionadded:: 3.5
.. _single-phase-initialization:
Legacy single-phase initialization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
..................................
.. deprecated:: 3.15
Single-phase initialization is :term:`soft deprecated`.
It is a legacy mechanism to initialize extension
.. attention::
Single-phase initialization is a legacy mechanism to initialize extension
modules, with known drawbacks and design flaws. Extension module authors
are encouraged to use multi-phase initialization instead.
However, there are no plans to remove support for it.
In single-phase initialization, the old-style
:ref:`initialization function <extension-pyinit>` (``PyInit_modulename``)
In single-phase initialization, the
:ref:`initialization function <extension-export-hook>` (``PyInit_modulename``)
should create, populate and return a module object.
This is typically done using :c:func:`PyModule_Create` and functions like
:c:func:`PyModule_AddObjectRef`.
@ -335,8 +242,6 @@ in the following ways:
* Single-phase modules support module lookup functions like
:c:func:`PyState_FindModule`.
* The module's :c:member:`PyModuleDef.m_slots` must be NULL.
.. [#testsinglephase] ``_testsinglephase`` is an internal module used
in CPython's self-test suite; your installation may or may not
include it.

View file

@ -93,29 +93,6 @@ the :mod:`io` APIs instead.
.. versionadded:: 3.8
.. c:function:: PyObject *PyFile_OpenCodeObject(PyObject *path)
Open *path* with the mode ``'rb'``. *path* must be a Python :class:`str`
object. The behavior of this function may be overridden by
:c:func:`PyFile_SetOpenCodeHook` to allow for some preprocessing of the
text.
This is analogous to :func:`io.open_code` in Python.
On success, this function returns a :term:`strong reference` to a Python
file object. On failure, this function returns ``NULL`` with an exception
set.
.. versionadded:: 3.8
.. c:function:: PyObject *PyFile_OpenCode(const char *path)
Similar to :c:func:`PyFile_OpenCodeObject`, but *path* is a
UTF-8 encoded :c:expr:`const char*`.
.. versionadded:: 3.8
.. c:function:: int PyFile_WriteObject(PyObject *obj, PyObject *p, int flags)

View file

@ -78,111 +78,6 @@ Floating-Point Objects
Return the minimum normalized positive float *DBL_MIN* as C :c:expr:`double`.
.. c:macro:: Py_INFINITY
This macro expands a to constant expression of type :c:expr:`double`, that
represents the positive infinity.
It is equivalent to the :c:macro:`!INFINITY` macro from the C11 standard
``<math.h>`` header.
.. deprecated:: 3.15
The macro is :term:`soft deprecated`.
.. c:macro:: Py_NAN
This macro expands a to constant expression of type :c:expr:`double`, that
represents a quiet not-a-number (qNaN) value.
On most platforms, this is equivalent to the :c:macro:`!NAN` macro from
the C11 standard ``<math.h>`` header.
.. c:macro:: Py_HUGE_VAL
Equivalent to :c:macro:`!INFINITY`.
.. deprecated:: 3.14
The macro is :term:`soft deprecated`.
.. c:macro:: Py_MATH_E
The definition (accurate for a :c:expr:`double` type) of the :data:`math.e` constant.
.. c:macro:: Py_MATH_El
High precision (long double) definition of :data:`~math.e` constant.
.. deprecated-removed:: 3.15 3.20
.. c:macro:: Py_MATH_PI
The definition (accurate for a :c:expr:`double` type) of the :data:`math.pi` constant.
.. c:macro:: Py_MATH_PIl
High precision (long double) definition of :data:`~math.pi` constant.
.. deprecated-removed:: 3.15 3.20
.. c:macro:: Py_MATH_TAU
The definition (accurate for a :c:expr:`double` type) of the :data:`math.tau` constant.
.. versionadded:: 3.6
.. c:macro:: Py_RETURN_NAN
Return :data:`math.nan` from a function.
On most platforms, this is equivalent to ``return PyFloat_FromDouble(NAN)``.
.. c:macro:: Py_RETURN_INF(sign)
Return :data:`math.inf` or :data:`-math.inf <math.inf>` from a function,
depending on the sign of *sign*.
On most platforms, this is equivalent to the following::
return PyFloat_FromDouble(copysign(INFINITY, sign));
.. c:macro:: Py_IS_FINITE(X)
Return ``1`` if the given floating-point number *X* is finite,
that is, it is normal, subnormal or zero, but not infinite or NaN.
Return ``0`` otherwise.
.. deprecated:: 3.14
The macro is :term:`soft deprecated`. Use :c:macro:`!isfinite` instead.
.. c:macro:: Py_IS_INFINITY(X)
Return ``1`` if the given floating-point number *X* is positive or negative
infinity. Return ``0`` otherwise.
.. deprecated:: 3.14
The macro is :term:`soft deprecated`. Use :c:macro:`!isinf` instead.
.. c:macro:: Py_IS_NAN(X)
Return ``1`` if the given floating-point number *X* is a not-a-number (NaN)
value. Return ``0`` otherwise.
.. deprecated:: 3.14
The macro is :term:`soft deprecated`. Use :c:macro:`!isnan` instead.
Pack and Unpack functions
-------------------------
@ -201,8 +96,8 @@ NaNs (if such things exist on the platform) isn't handled correctly, and
attempting to unpack a bytes string containing an IEEE INF or NaN will raise an
exception.
Note that NaNs type may not be preserved on IEEE platforms (signaling NaN become
quiet NaN), for example on x86 systems in 32-bit mode.
Note that NaNs type may not be preserved on IEEE platforms (silent NaN become
quiet), for example on x86 systems in 32-bit mode.
On non-IEEE platforms with more precision, or larger dynamic range, than IEEE
754 supports, not all values can be packed; on non-IEEE platforms with less

View file

@ -29,12 +29,6 @@ See also :ref:`Reflection <reflection>`.
Previously, this type was only available after including
``<frameobject.h>``.
.. c:function:: PyFrameObject *PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, PyObject *locals)
Create a new frame object. This function returns a :term:`strong reference`
to the new frame object on success, and returns ``NULL`` with an exception
set on failure.
.. c:function:: int PyFrame_Check(PyObject *obj)
Return non-zero if *obj* is a frame object.
@ -167,57 +161,6 @@ See :pep:`667` for more information.
Return non-zero if *obj* is a frame :func:`locals` proxy.
Legacy Local Variable APIs
^^^^^^^^^^^^^^^^^^^^^^^^^^
These APIs are :term:`soft deprecated`. As of Python 3.13, they do nothing.
They exist solely for backwards compatibility.
.. c:function:: void PyFrame_LocalsToFast(PyFrameObject *f, int clear)
This function is :term:`soft deprecated` and does nothing.
Prior to Python 3.13, this function would copy the :attr:`~frame.f_locals`
attribute of *f* to the internal "fast" array of local variables, allowing
changes in frame objects to be visible to the interpreter. If *clear* was
true, this function would process variables that were unset in the locals
dictionary.
.. versionchanged:: 3.13
This function now does nothing.
.. c:function:: void PyFrame_FastToLocals(PyFrameObject *f)
This function is :term:`soft deprecated` and does nothing.
Prior to Python 3.13, this function would copy the internal "fast" array
of local variables (which is used by the interpreter) to the
:attr:`~frame.f_locals` attribute of *f*, allowing changes in local
variables to be visible to frame objects.
.. versionchanged:: 3.13
This function now does nothing.
.. c:function:: int PyFrame_FastToLocalsWithError(PyFrameObject *f)
This function is :term:`soft deprecated` and does nothing.
Prior to Python 3.13, this function was similar to
:c:func:`PyFrame_FastToLocals`, but would return ``0`` on success, and
``-1`` with an exception set on failure.
.. versionchanged:: 3.13
This function now does nothing.
.. seealso::
:pep:`667`
Internal Frames
^^^^^^^^^^^^^^^

View file

@ -102,15 +102,6 @@ There are a few functions specific to Python functions.
dictionary of arguments or ``NULL``.
.. c:function:: int PyFunction_SetKwDefaults(PyObject *op, PyObject *defaults)
Set the keyword-only argument default values of the function object *op*.
*defaults* must be a dictionary of keyword-only arguments or ``Py_None``.
This function returns ``0`` on success, and returns ``-1`` with an exception
set on failure.
.. c:function:: PyObject* PyFunction_GetClosure(PyObject *op)
Return the closure associated with the function object *op*. This can be ``NULL``
@ -209,7 +200,7 @@ There are a few functions specific to Python functions.
runtime behavior depending on optimization decisions, it does not change
the semantics of the Python code being executed.
If *event* is ``PyFunction_EVENT_DESTROY``, taking a reference in the
If *event* is ``PyFunction_EVENT_DESTROY``, Taking a reference in the
callback to the about-to-be-destroyed function will resurrect it, preventing
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.

View file

@ -232,10 +232,6 @@ The :c:member:`~PyTypeObject.tp_traverse` handler must have the following type:
object argument. If *visit* returns a non-zero value that value should be
returned immediately.
The traversal function must not have any side effects. Implementations
may not modify the reference counts of any Python objects nor create or
destroy any Python objects.
To simplify writing :c:member:`~PyTypeObject.tp_traverse` handlers, a :c:func:`Py_VISIT` macro is
provided. In order to use this macro, the :c:member:`~PyTypeObject.tp_traverse` implementation
must name its arguments exactly *visit* and *arg*:

View file

@ -44,41 +44,3 @@ than explicitly calling :c:func:`PyGen_New` or :c:func:`PyGen_NewWithQualName`.
with ``__name__`` and ``__qualname__`` set to *name* and *qualname*.
A reference to *frame* is stolen by this function. The *frame* argument
must not be ``NULL``.
.. c:function:: PyCodeObject* PyGen_GetCode(PyGenObject *gen)
Return a new :term:`strong reference` to the code object wrapped by *gen*.
This function always succeeds.
Asynchronous Generator Objects
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. seealso::
:pep:`525`
.. c:var:: PyTypeObject PyAsyncGen_Type
The type object corresponding to asynchronous generator objects. This is
available as :class:`types.AsyncGeneratorType` in the Python layer.
.. versionadded:: 3.6
.. c:function:: PyObject *PyAsyncGen_New(PyFrameObject *frame, PyObject *name, PyObject *qualname)
Create a new asynchronous generator wrapping *frame*, with ``__name__`` and
``__qualname__`` set to *name* and *qualname*. *frame* is stolen by this
function and must not be ``NULL``.
On success, this function returns a :term:`strong reference` to the
new asynchronous generator. On failure, this function returns ``NULL``
with an exception set.
.. versionadded:: 3.6
.. c:function:: int PyAsyncGen_CheckExact(PyObject *op)
Return true if *op* is an asynchronous generator object, false otherwise.
This function always succeeds.
.. versionadded:: 3.6

View file

@ -11,98 +11,42 @@ See also the :c:member:`PyTypeObject.tp_hash` member and :ref:`numeric-hash`.
.. versionadded:: 3.2
.. c:type:: Py_uhash_t
Hash value type: unsigned integer.
.. versionadded:: 3.2
.. c:macro:: Py_HASH_ALGORITHM
A numerical value indicating the algorithm for hashing of :class:`str`,
:class:`bytes`, and :class:`memoryview`.
The algorithm name is exposed by :data:`sys.hash_info.algorithm`.
.. versionadded:: 3.4
.. c:macro:: Py_HASH_FNV
Py_HASH_SIPHASH24
Py_HASH_SIPHASH13
Numerical values to compare to :c:macro:`Py_HASH_ALGORITHM` to determine
which algorithm is used for hashing. The hash algorithm can be configured
via the configure :option:`--with-hash-algorithm` option.
.. versionadded:: 3.4
Add :c:macro:`!Py_HASH_FNV` and :c:macro:`!Py_HASH_SIPHASH24`.
.. versionadded:: 3.11
Add :c:macro:`!Py_HASH_SIPHASH13`.
.. c:macro:: Py_HASH_CUTOFF
Buffers of length in range ``[1, Py_HASH_CUTOFF)`` are hashed using DJBX33A
instead of the algorithm described by :c:macro:`Py_HASH_ALGORITHM`.
- A :c:macro:`!Py_HASH_CUTOFF` of 0 disables the optimization.
- :c:macro:`!Py_HASH_CUTOFF` must be non-negative and less or equal than 7.
32-bit platforms should use a cutoff smaller than 64-bit platforms because
it is easier to create colliding strings. A cutoff of 7 on 64-bit platforms
and 5 on 32-bit platforms should provide a decent safety margin.
This corresponds to the :data:`sys.hash_info.cutoff` constant.
.. versionadded:: 3.4
.. c:macro:: PyHASH_MODULUS
The `Mersenne prime <https://en.wikipedia.org/wiki/Mersenne_prime>`_ ``P = 2**n -1``,
used for numeric hash scheme.
This corresponds to the :data:`sys.hash_info.modulus` constant.
The `Mersenne prime <https://en.wikipedia.org/wiki/Mersenne_prime>`_ ``P = 2**n -1``, used for numeric hash scheme.
.. versionadded:: 3.13
.. c:macro:: PyHASH_BITS
The exponent ``n`` of ``P`` in :c:macro:`PyHASH_MODULUS`.
.. versionadded:: 3.13
.. c:macro:: PyHASH_MULTIPLIER
Prime multiplier used in string and various other hashes.
.. versionadded:: 3.13
.. c:macro:: PyHASH_INF
The hash value returned for a positive infinity.
This corresponds to the :data:`sys.hash_info.inf` constant.
.. versionadded:: 3.13
.. c:macro:: PyHASH_IMAG
The multiplier used for the imaginary part of a complex number.
This corresponds to the :data:`sys.hash_info.imag` constant.
.. versionadded:: 3.13
.. c:type:: PyHash_FuncDef
Hash function definition used by :c:func:`PyHash_GetFuncDef`.
@ -115,20 +59,14 @@ See also the :c:member:`PyTypeObject.tp_hash` member and :ref:`numeric-hash`.
Hash function name (UTF-8 encoded string).
This corresponds to the :data:`sys.hash_info.algorithm` constant.
.. c:member:: const int hash_bits
Internal size of the hash value in bits.
This corresponds to the :data:`sys.hash_info.hash_bits` constant.
.. c:member:: const int seed_bits
Size of seed input in bits.
This corresponds to the :data:`sys.hash_info.seed_bits` constant.
.. versionadded:: 3.4

View file

@ -129,7 +129,8 @@ Importing Modules
of :class:`~importlib.machinery.SourceFileLoader` otherwise.
The module's :attr:`~module.__file__` attribute will be set to the code
object's :attr:`~codeobject.co_filename`.
object's :attr:`~codeobject.co_filename`. If applicable,
:attr:`~module.__cached__` will also be set.
This function will reload the module if it was already imported. See
:c:func:`PyImport_ReloadModule` for the intended way to reload a module.
@ -141,13 +142,10 @@ Importing Modules
:c:func:`PyImport_ExecCodeModuleWithPathnames`.
.. versionchanged:: 3.12
The setting of ``__cached__`` and :attr:`~module.__loader__`
The setting of :attr:`~module.__cached__` and :attr:`~module.__loader__`
is deprecated. See :class:`~importlib.machinery.ModuleSpec` for
alternatives.
.. versionchanged:: 3.15
``__cached__`` is no longer set.
.. c:function:: PyObject* PyImport_ExecCodeModuleEx(const char *name, PyObject *co, const char *pathname)
@ -159,19 +157,16 @@ Importing Modules
.. c:function:: PyObject* PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname, PyObject *cpathname)
Like :c:func:`PyImport_ExecCodeModuleEx`, but the path to any compiled file
via *cpathname* is used appropriately when non-``NULL``. Of the three
functions, this is the preferred one to use.
Like :c:func:`PyImport_ExecCodeModuleEx`, but the :attr:`~module.__cached__`
attribute of the module object is set to *cpathname* if it is
non-``NULL``. Of the three functions, this is the preferred one to use.
.. versionadded:: 3.3
.. versionchanged:: 3.12
Setting ``__cached__`` is deprecated. See
Setting :attr:`~module.__cached__` is deprecated. See
:class:`~importlib.machinery.ModuleSpec` for alternatives.
.. versionchanged:: 3.15
``__cached__`` no longer set.
.. c:function:: PyObject* PyImport_ExecCodeModuleWithPathnames(const char *name, PyObject *co, const char *pathname, const char *cpathname)
@ -319,13 +314,6 @@ Importing Modules
initialization.
.. c:var:: struct _inittab *PyImport_Inittab
The table of built-in modules used by Python initialization. Do not use this directly;
use :c:func:`PyImport_AppendInittab` and :c:func:`PyImport_ExtendInittab`
instead.
.. c:function:: PyObject* PyImport_ImportModuleAttr(PyObject *mod_name, PyObject *attr_name)
Import the module *mod_name* and get its attribute *attr_name*.
@ -345,24 +333,3 @@ Importing Modules
strings instead of Python :class:`str` objects.
.. versionadded:: 3.14
.. c:function:: PyObject* PyImport_CreateModuleFromInitfunc(PyObject *spec, PyObject* (*initfunc)(void))
This function is a building block that enables embedders to implement
the :py:meth:`~importlib.abc.Loader.create_module` step of custom
static extension importers (e.g. of statically-linked extensions).
*spec* must be a :class:`~importlib.machinery.ModuleSpec` object.
*initfunc* must be an :ref:`initialization function <extension-export-hook>`,
the same as for :c:func:`PyImport_AppendInittab`.
On success, create and return a module object.
This module will not be initialized; call :c:func:`PyModule_Exec`
to initialize it.
(Custom importers should do this in their
:py:meth:`~importlib.abc.Loader.exec_module` method.)
On error, return NULL with an exception set.
.. versionadded:: 3.15

View file

@ -1366,43 +1366,6 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
.. versionadded:: 3.11
.. c:function:: int PyUnstable_ThreadState_SetStackProtection(PyThreadState *tstate, void *stack_start_addr, size_t stack_size)
Set the stack protection start address and stack protection size
of a Python thread state.
On success, return ``0``.
On failure, set an exception and return ``-1``.
CPython implements :ref:`recursion control <recursion>` for C code by raising
:py:exc:`RecursionError` when it notices that the machine execution stack is close
to overflow. See for example the :c:func:`Py_EnterRecursiveCall` function.
For this, it needs to know the location of the current thread's stack, which it
normally gets from the operating system.
When the stack is changed, for example using context switching techniques like the
Boost library's ``boost::context``, you must call
:c:func:`~PyUnstable_ThreadState_SetStackProtection` to inform CPython of the change.
Call :c:func:`~PyUnstable_ThreadState_SetStackProtection` either before
or after changing the stack.
Do not call any other Python C API between the call and the stack
change.
See :c:func:`PyUnstable_ThreadState_ResetStackProtection` for undoing this operation.
.. versionadded:: 3.15
.. c:function:: void PyUnstable_ThreadState_ResetStackProtection(PyThreadState *tstate)
Reset the stack protection start address and stack protection size
of a Python thread state to the operating system defaults.
See :c:func:`PyUnstable_ThreadState_SetStackProtection` for an explanation.
.. versionadded:: 3.15
.. c:function:: PyInterpreterState* PyInterpreterState_Get(void)
Get the current interpreter.
@ -1717,8 +1680,7 @@ function. You can create and destroy them using the following functions:
Only C-level static and global variables are shared between these
module objects.
* For modules using legacy
:ref:`single-phase initialization <single-phase-initialization>`,
* For modules using single-phase initialization,
e.g. :c:func:`PyModule_Create`, the first time a particular extension
is imported, it is initialized normally, and a (shallow) copy of its
module's dictionary is squirreled away.
@ -1892,25 +1854,6 @@ pointer and a void pointer argument.
This function now always schedules *func* to be run in the main
interpreter.
.. c:function:: int Py_MakePendingCalls(void)
Execute all pending calls. This is usually executed automatically by the
interpreter.
This function returns ``0`` on success, and returns ``-1`` with an exception
set on failure.
If this is not called in the main thread of the main
interpreter, this function does nothing and returns ``0``.
The caller must hold an :term:`attached thread state`.
.. versionadded:: 3.1
.. versionchanged:: 3.12
This function only runs pending calls in the main interpreter.
.. _profiling:
Profiling and Tracing
@ -2197,7 +2140,7 @@ use a thread key and functions to associate a :c:expr:`void*` value per
thread.
A :term:`thread state` does *not* need to be :term:`attached <attached thread state>`
when calling these functions; they supply their own locking.
when calling these functions; they suppl their own locking.
Note that :file:`Python.h` does not include the declaration of the TLS APIs,
you need to include :file:`pythread.h` to use thread-local storage.
@ -2540,220 +2483,3 @@ code triggered by the finalizer blocks and calls :c:func:`PyEval_SaveThread`.
In the default build, this macro expands to ``}``.
.. versionadded:: 3.13
Legacy Locking APIs
-------------------
These APIs are obsolete since Python 3.13 with the introduction of
:c:type:`PyMutex`.
.. versionchanged:: 3.15
These APIs are now a simple wrapper around ``PyMutex``.
.. c:type:: PyThread_type_lock
A pointer to a mutual exclusion lock.
.. c:type:: PyLockStatus
The result of acquiring a lock with a timeout.
.. c:namespace:: NULL
.. c:enumerator:: PY_LOCK_FAILURE
Failed to acquire the lock.
.. c:enumerator:: PY_LOCK_ACQUIRED
The lock was successfully acquired.
.. c:enumerator:: PY_LOCK_INTR
The lock was interrupted by a signal.
.. c:function:: PyThread_type_lock PyThread_allocate_lock(void)
Allocate a new lock.
On success, this function returns a lock; on failure, this
function returns ``0`` without an exception set.
The caller does not need to hold an :term:`attached thread state`.
.. versionchanged:: 3.15
This function now always uses :c:type:`PyMutex`. In prior versions, this
would use a lock provided by the operating system.
.. c:function:: void PyThread_free_lock(PyThread_type_lock lock)
Destroy *lock*. The lock should not be held by any thread when calling
this.
The caller does not need to hold an :term:`attached thread state`.
.. c:function:: PyLockStatus PyThread_acquire_lock_timed(PyThread_type_lock lock, long long microseconds, int intr_flag)
Acquire *lock* with a timeout.
This will wait for *microseconds* microseconds to acquire the lock. If the
timeout expires, this function returns :c:enumerator:`PY_LOCK_FAILURE`.
If *microseconds* is ``-1``, this will wait indefinitely until the lock has
been released.
If *intr_flag* is ``1``, acquiring the lock may be interrupted by a signal,
in which case this function returns :c:enumerator:`PY_LOCK_INTR`. Upon
interruption, it's generally expected that the caller makes a call to
:c:func:`Py_MakePendingCalls` to propagate an exception to Python code.
If the lock is successfully acquired, this function returns
:c:enumerator:`PY_LOCK_ACQUIRED`.
The caller does not need to hold an :term:`attached thread state`.
.. c:function:: int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
Acquire *lock*.
If *waitflag* is ``1`` and another thread currently holds the lock, this
function will wait until the lock can be acquired and will always return
``1``.
If *waitflag* is ``0`` and another thread holds the lock, this function will
not wait and instead return ``0``. If the lock is not held by any other
thread, then this function will acquire it and return ``1``.
Unlike :c:func:`PyThread_acquire_lock_timed`, acquiring the lock cannot be
interrupted by a signal.
The caller does not need to hold an :term:`attached thread state`.
.. c:function:: int PyThread_release_lock(PyThread_type_lock lock)
Release *lock*. If *lock* is not held, then this function issues a
fatal error.
The caller does not need to hold an :term:`attached thread state`.
Operating System Thread APIs
============================
.. c:macro:: PYTHREAD_INVALID_THREAD_ID
Sentinel value for an invalid thread ID.
This is currently equivalent to ``(unsigned long)-1``.
.. c:function:: unsigned long PyThread_start_new_thread(void (*func)(void *), void *arg)
Start function *func* in a new thread with argument *arg*.
The resulting thread is not intended to be joined.
*func* must not be ``NULL``, but *arg* may be ``NULL``.
On success, this function returns the identifier of the new thread; on failure,
this returns :c:macro:`PYTHREAD_INVALID_THREAD_ID`.
The caller does not need to hold an :term:`attached thread state`.
.. c:function:: unsigned long PyThread_get_thread_ident(void)
Return the identifier of the current thread, which will never be zero.
This function cannot fail, and the caller does not need to hold an
:term:`attached thread state`.
.. seealso::
:py:func:`threading.get_ident`
.. c:function:: PyObject *PyThread_GetInfo(void)
Get general information about the current thread in the form of a
:ref:`struct sequence <struct-sequence-objects>` object. This information is
accessible as :py:attr:`sys.thread_info` in Python.
On success, this returns a new :term:`strong reference` to the thread
information; on failure, this returns ``NULL`` with an exception set.
The caller must hold an :term:`attached thread state`.
.. c:macro:: PY_HAVE_THREAD_NATIVE_ID
This macro is defined when the system supports native thread IDs.
.. c:function:: unsigned long PyThread_get_thread_native_id(void)
Get the native identifier of the current thread as it was assigned by the operating
system's kernel, which will never be less than zero.
This function is only available when :c:macro:`PY_HAVE_THREAD_NATIVE_ID` is
defined.
This function cannot fail, and the caller does not need to hold an
:term:`attached thread state`.
.. seealso::
:py:func:`threading.get_native_id`
.. c:function:: void PyThread_exit_thread(void)
Terminate the current thread. This function is generally considered unsafe
and should be avoided. It is kept solely for backwards compatibility.
This function is only safe to call if all functions in the full call
stack are written to safely allow it.
.. warning::
If the current system uses POSIX threads (also known as "pthreads"),
this calls :manpage:`pthread_exit(3)`, which attempts to unwind the stack
and call C++ destructors on some libc implementations. However, if a
``noexcept`` function is reached, it may terminate the process.
Other systems, such as macOS, do unwinding.
On Windows, this function calls ``_endthreadex()``, which kills the thread
without calling C++ destructors.
In any case, there is a risk of corruption on the thread's stack.
.. deprecated:: 3.14
.. c:function:: void PyThread_init_thread(void)
Initialize ``PyThread*`` APIs. Python executes this function automatically,
so there's little need to call it from an extension module.
.. c:function:: int PyThread_set_stacksize(size_t size)
Set the stack size of the current thread to *size* bytes.
This function returns ``0`` on success, ``-1`` if *size* is invalid, or
``-2`` if the system does not support changing the stack size. This function
does not set exceptions.
The caller does not need to hold an :term:`attached thread state`.
.. c:function:: size_t PyThread_get_stacksize(void)
Return the stack size of the current thread in bytes, or ``0`` if the system's
default stack size is in use.
The caller does not need to hold an :term:`attached thread state`.

View file

@ -102,7 +102,7 @@ Error Handling
* Set *\*err_msg* and return ``1`` if an error is set.
* Set *\*err_msg* to ``NULL`` and return ``0`` otherwise.
An error message is a UTF-8 encoded string.
An error message is an UTF-8 encoded string.
If *config* has an exit code, format the exit code as an error
message.

View file

@ -107,46 +107,6 @@ header files properly declare the entry points to be ``extern "C"``. As a result
there is no need to do anything special to use the API from C++.
.. _capi-system-includes:
System includes
---------------
:file:`Python.h` includes several standard header files.
C extensions should include the standard headers that they use,
and should not rely on these implicit includes.
The implicit includes are:
* ``<assert.h>``
* ``<intrin.h>`` (on Windows)
* ``<inttypes.h>``
* ``<limits.h>``
* ``<math.h>``
* ``<stdarg.h>``
* ``<wchar.h>``
* ``<sys/types.h>`` (if present)
The following are included for backwards compatibility, unless using
:ref:`Limited API <limited-c-api>` 3.13 or newer:
* ``<ctype.h>``
* ``<unistd.h>`` (on POSIX)
The following are included for backwards compatibility, unless using
:ref:`Limited API <limited-c-api>` 3.11 or newer:
* ``<errno.h>``
* ``<stdio.h>``
* ``<stdlib.h>``
* ``<string.h>``
.. note::
Since Python may define some pre-processor definitions which affect the standard
headers on some systems, you *must* include :file:`Python.h` before any standard
headers are included.
Useful macros
=============
@ -161,10 +121,6 @@ complete listing.
Return the absolute value of ``x``.
If the result cannot be represented (for example, if ``x`` has
:c:macro:`!INT_MIN` value for :c:expr:`int` type), the behavior is
undefined.
.. versionadded:: 3.3
.. c:macro:: Py_ALWAYS_INLINE
@ -211,17 +167,6 @@ complete listing.
Like ``getenv(s)``, but returns ``NULL`` if :option:`-E` was passed on the
command line (see :c:member:`PyConfig.use_environment`).
.. c:macro:: Py_LOCAL(type)
Declare a function returning the specified *type* using a fast-calling
qualifier for functions that are local to the current file.
Semantically, this is equivalent to ``static type``.
.. c:macro:: Py_LOCAL_INLINE(type)
Equivalent to :c:macro:`Py_LOCAL` but additionally requests the function
be inlined.
.. c:macro:: Py_MAX(x, y)
Return the maximum value between ``x`` and ``y``.
@ -234,14 +179,6 @@ complete listing.
.. versionadded:: 3.6
.. c:macro:: Py_MEMCPY(dest, src, n)
This is a :term:`soft deprecated` alias to :c:func:`!memcpy`.
Use :c:func:`!memcpy` directly instead.
.. deprecated:: 3.14
The macro is :term:`soft deprecated`.
.. c:macro:: Py_MIN(x, y)
Return the minimum value between ``x`` and ``y``.
@ -296,32 +233,9 @@ complete listing.
.. versionadded:: 3.4
.. c:macro:: Py_BUILD_ASSERT(cond)
Asserts a compile-time condition *cond*, as a statement.
The build will fail if the condition is false or cannot be evaluated at compile time.
For example::
Py_BUILD_ASSERT(sizeof(PyTime_t) == sizeof(int64_t));
.. versionadded:: 3.3
.. c:macro:: Py_BUILD_ASSERT_EXPR(cond)
Asserts a compile-time condition *cond*, as an expression that evaluates to ``0``.
The build will fail if the condition is false or cannot be evaluated at compile time.
For example::
#define foo_to_char(foo) \
((char *)(foo) + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0))
.. versionadded:: 3.3
.. c:macro:: PyDoc_STRVAR(name, str)
Creates a variable with name *name* that can be used in docstrings.
Creates a variable with name ``name`` that can be used in docstrings.
If Python is built without docstrings, the value will be empty.
Use :c:macro:`PyDoc_STRVAR` for docstrings to support building
@ -353,28 +267,6 @@ complete listing.
{NULL, NULL}
};
.. c:macro:: PyDoc_VAR(name)
Declares a static character array variable with the given name *name*.
For example::
PyDoc_VAR(python_doc) = PyDoc_STR("A genus of constricting snakes in the Pythonidae family native "
"to the tropics and subtropics of the Eastern Hemisphere.");
.. c:macro:: Py_ARRAY_LENGTH(array)
Compute the length of a statically allocated C array at compile time.
The *array* argument must be a C array with a size known at compile time.
Passing an array with an unknown size, such as a heap-allocated array,
will result in a compilation error on some compilers, or otherwise produce
incorrect results.
This is roughly equivalent to::
sizeof(array) / sizeof((array)[0])
.. _api-objects:

View file

@ -54,6 +54,6 @@ There are two functions specifically for working with iterators.
- ``PYGEN_RETURN`` if iterator returns. Return value is returned via *presult*.
- ``PYGEN_NEXT`` if iterator yields. Yielded value is returned via *presult*.
- ``PYGEN_ERROR`` if iterator has raised an exception. *presult* is set to ``NULL``.
- ``PYGEN_ERROR`` if iterator has raised and exception. *presult* is set to ``NULL``.
.. versionadded:: 3.10

View file

@ -50,72 +50,3 @@ sentinel value is returned.
callable object that can be called with no parameters; each call to it should
return the next item in the iteration. When *callable* returns a value equal to
*sentinel*, the iteration will be terminated.
Range Objects
^^^^^^^^^^^^^
.. c:var:: PyTypeObject PyRange_Type
The type object for :class:`range` objects.
.. c:function:: int PyRange_Check(PyObject *o)
Return true if the object *o* is an instance of a :class:`range` object.
This function always succeeds.
Builtin Iterator Types
^^^^^^^^^^^^^^^^^^^^^^
These are built-in iteration types that are included in Python's C API, but
provide no additional functions. They are here for completeness.
.. list-table::
:widths: auto
:header-rows: 1
* * C type
* Python type
* * .. c:var:: PyTypeObject PyEnum_Type
* :py:class:`enumerate`
* * .. c:var:: PyTypeObject PyFilter_Type
* :py:class:`filter`
* * .. c:var:: PyTypeObject PyMap_Type
* :py:class:`map`
* * .. c:var:: PyTypeObject PyReversed_Type
* :py:class:`reversed`
* * .. c:var:: PyTypeObject PyZip_Type
* :py:class:`zip`
Other Iterator Objects
^^^^^^^^^^^^^^^^^^^^^^
.. c:var:: PyTypeObject PyByteArrayIter_Type
.. c:var:: PyTypeObject PyBytesIter_Type
.. c:var:: PyTypeObject PyListIter_Type
.. c:var:: PyTypeObject PyListRevIter_Type
.. c:var:: PyTypeObject PySetIter_Type
.. c:var:: PyTypeObject PyTupleIter_Type
.. c:var:: PyTypeObject PyRangeIter_Type
.. c:var:: PyTypeObject PyLongRangeIter_Type
.. c:var:: PyTypeObject PyDictIterKey_Type
.. c:var:: PyTypeObject PyDictRevIterKey_Type
.. c:var:: PyTypeObject PyDictIterValue_Type
.. c:var:: PyTypeObject PyDictRevIterValue_Type
.. c:var:: PyTypeObject PyDictIterItem_Type
.. c:var:: PyTypeObject PyDictRevIterItem_Type
.. c:var:: PyTypeObject PyODictIter_Type
Type objects for iterators of various built-in objects.
Do not create instances of these directly; prefer calling
:c:func:`PyObject_GetIter` instead.
Note that there is no guarantee that a given built-in type uses a given iterator
type. For example, iterating over :class:`range` will use one of two iterator
types depending on the size of the range. Other types may start using a
similar scheme in the future, without warning.

View file

@ -43,7 +43,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
.. impl-detail::
CPython keeps an array of integer objects for all integers
between ``-5`` and ``1024``. When you create an int in that range
between ``-5`` and ``256``. When you create an int in that range
you actually just get back a reference to the existing object.
@ -161,17 +161,6 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
.. versionadded:: 3.13
.. c:macro:: PyLong_FromPid(pid)
Macro for creating a Python integer from a process identifier.
This can be defined as an alias to :c:func:`PyLong_FromLong` or
:c:func:`PyLong_FromLongLong`, depending on the size of the system's
PID type.
.. versionadded:: 3.2
.. c:function:: long PyLong_AsLong(PyObject *obj)
.. index::
@ -586,17 +575,6 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
.. versionadded:: 3.13
.. c:macro:: PyLong_AsPid(pid)
Macro for converting a Python integer into a process identifier.
This can be defined as an alias to :c:func:`PyLong_AsLong`,
:c:func:`PyLong_FromLongLong`, or :c:func:`PyLong_AsInt`, depending on the
size of the system's PID type.
.. versionadded:: 3.2
.. c:function:: int PyLong_GetSign(PyObject *obj, int *sign)
Get the sign of the integer object *obj*.

View file

@ -102,7 +102,7 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and
.. note::
Exceptions which occur when this calls the :meth:`~object.__getitem__`
Exceptions which occur when this calls :meth:`~object.__getitem__`
method are silently ignored.
For proper error handling, use :c:func:`PyMapping_HasKeyWithError`,
:c:func:`PyMapping_GetOptionalItem` or :c:func:`PyObject_GetItem()` instead.
@ -116,7 +116,7 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and
.. note::
Exceptions that occur when this calls the :meth:`~object.__getitem__`
Exceptions that occur when this calls :meth:`~object.__getitem__`
method or while creating the temporary :class:`str`
object are silently ignored.
For proper error handling, use :c:func:`PyMapping_HasKeyStringWithError`,

View file

@ -82,7 +82,7 @@ The following functions allow marshalled values to be read back in.
assumes that no further objects will be read from the file, allowing it to
aggressively load file data into memory so that the de-serialization can
operate from data in memory rather than reading a byte at a time from the
file. Only use this variant if you are certain that you won't be reading
file. Only use these variant if you are certain that you won't be reading
anything else from the file.
On error, sets the appropriate exception (:exc:`EOFError`, :exc:`ValueError`

View file

@ -102,7 +102,7 @@ All allocating functions belong to one of three different "domains" (see also
strategies and are optimized for different purposes. The specific details on
how every domain allocates memory or what internal functions each domain calls
is considered an implementation detail, but for debugging purposes a simplified
table can be found at :ref:`default-memory-allocators`.
table can be found at :ref:`here <default-memory-allocators>`.
The APIs used to allocate and free a block of memory must be from the same domain.
For example, :c:func:`PyMem_Free` must be used to free memory allocated using :c:func:`PyMem_Malloc`.

View file

@ -13,12 +13,6 @@ A :class:`memoryview` object exposes the C level :ref:`buffer interface
any other object.
.. c:var:: PyTypeObject PyMemoryView_Type
This instance of :c:type:`PyTypeObject` represents the Python memoryview
type. This is the same object as :class:`memoryview` in the Python layer.
.. c:function:: PyObject *PyMemoryView_FromObject(PyObject *obj)
Create a memoryview object from an object that provides the buffer interface.

View file

@ -3,16 +3,17 @@
.. _moduleobjects:
Module Objects
==============
--------------
.. index:: pair: object; module
.. c:var:: PyTypeObject PyModule_Type
.. index:: single: ModuleType (in module types)
This instance of :c:type:`PyTypeObject` represents the Python module type. This
is exposed to Python programs as :py:class:`types.ModuleType`.
is exposed to Python programs as ``types.ModuleType``.
.. c:function:: int PyModule_Check(PyObject *p)
@ -70,9 +71,6 @@ Module Objects
``PyObject_*`` functions rather than directly manipulate a module's
:attr:`~object.__dict__`.
The returned reference is borrowed from the module; it is valid until
the module is destroyed.
.. c:function:: PyObject* PyModule_GetNameObject(PyObject *module)
@ -92,19 +90,18 @@ Module Objects
Similar to :c:func:`PyModule_GetNameObject` but return the name encoded to
``'utf-8'``.
The returned buffer is only valid until the module is renamed or destroyed.
Note that Python code may rename a module by setting its :py:attr:`~module.__name__`
attribute.
.. c:function:: void* PyModule_GetState(PyObject *module)
Return the "state" of the module, that is, a pointer to the block of memory
allocated at module creation time, or ``NULL``. See
:c:member:`PyModuleDef.m_size`.
.. c:function:: PyModuleDef* PyModule_GetDef(PyObject *module)
Return a pointer to the :c:type:`PyModuleDef` struct from which the module was
created, or ``NULL`` if the module wasn't created from a definition.
On error, return ``NULL`` with an exception set.
Use :c:func:`PyErr_Occurred` to tell this case apart from a missing
:c:type:`!PyModuleDef`.
.. c:function:: PyObject* PyModule_GetFilenameObject(PyObject *module)
@ -125,116 +122,215 @@ Module Objects
Similar to :c:func:`PyModule_GetFilenameObject` but return the filename
encoded to 'utf-8'.
The returned buffer is only valid until the module's :py:attr:`~module.__file__` attribute
is reassigned or the module is destroyed.
.. deprecated:: 3.2
:c:func:`PyModule_GetFilename` raises :exc:`UnicodeEncodeError` on
unencodable filenames, use :c:func:`PyModule_GetFilenameObject` instead.
.. _pymoduledef_slot:
.. _pymoduledef:
Module definition
-----------------
Module definitions
------------------
Modules created using the C API are typically defined using an
array of :dfn:`slots`.
The slots provide a "description" of how a module should be created.
The functions in the previous section work on any module object, including
modules imported from Python code.
.. versionchanged:: 3.15
Modules defined using the C API typically use a *module definition*,
:c:type:`PyModuleDef` -- a statically allocated, constant “description" of
how a module should be created.
Previously, a :c:type:`PyModuleDef` struct was necessary to define modules.
The older way of defining modules is still available: consult either the
:ref:`pymoduledef` section or earlier versions of this documentation
if you plan to support earlier Python versions.
The definition is usually used to define an extension's “main” module object
(see :ref:`extension-modules` for details).
It is also used to
:ref:`create extension modules dynamically <moduledef-dynamic>`.
The slots array is usually used to define an extension module's “main”
module object (see :ref:`extension-modules` for details).
It can also be used to
:ref:`create extension modules dynamically <module-from-slots>`.
Unlike :c:func:`PyModule_New`, the definition allows management of
*module state* -- a piece of memory that is allocated and cleared together
with the module object.
Unlike the module's Python attributes, Python code cannot replace or delete
data stored in module state.
Unless specified otherwise, the same slot ID may not be repeated
in an array of slots.
.. c:type:: PyModuleDef
The module definition struct, which holds all information needed to create
a module object.
This structure must be statically allocated (or be otherwise guaranteed
to be valid while any modules created from it exist).
Usually, there is only one variable of this type for each extension module.
.. c:member:: PyModuleDef_Base m_base
Always initialize this member to :c:macro:`PyModuleDef_HEAD_INIT`.
.. c:member:: const char *m_name
Name for the new module.
.. c:member:: const char *m_doc
Docstring for the module; usually a docstring variable created with
:c:macro:`PyDoc_STRVAR` is used.
.. c:member:: Py_ssize_t m_size
Module state may be kept in a per-module memory area that can be
retrieved with :c:func:`PyModule_GetState`, rather than in static globals.
This makes modules safe for use in multiple sub-interpreters.
This memory area is allocated based on *m_size* on module creation,
and freed when the module object is deallocated, after the
:c:member:`~PyModuleDef.m_free` function has been called, if present.
Setting it to a non-negative value means that the module can be
re-initialized and specifies the additional amount of memory it requires
for its state.
Setting ``m_size`` to ``-1`` means that the module does not support
sub-interpreters, because it has global state.
Negative ``m_size`` is only allowed when using
:ref:`legacy single-phase initialization <single-phase-initialization>`
or when :ref:`creating modules dynamically <moduledef-dynamic>`.
See :PEP:`3121` for more details.
.. c:member:: PyMethodDef* m_methods
A pointer to a table of module-level functions, described by
:c:type:`PyMethodDef` values. Can be ``NULL`` if no functions are present.
.. c:member:: PyModuleDef_Slot* m_slots
An array of slot definitions for multi-phase initialization, terminated by
a ``{0, NULL}`` entry.
When using legacy single-phase initialization, *m_slots* must be ``NULL``.
.. versionchanged:: 3.5
Prior to version 3.5, this member was always set to ``NULL``,
and was defined as:
.. c:member:: inquiry m_reload
.. c:member:: traverseproc m_traverse
A traversal function to call during GC traversal of the module object, or
``NULL`` if not needed.
This function is not called if the module state was requested but is not
allocated yet. This is the case immediately after the module is created
and before the module is executed (:c:data:`Py_mod_exec` function). More
precisely, this function is not called if :c:member:`~PyModuleDef.m_size` is greater
than 0 and the module state (as returned by :c:func:`PyModule_GetState`)
is ``NULL``.
.. versionchanged:: 3.9
No longer called before the module state is allocated.
.. c:member:: inquiry m_clear
A clear function to call during GC clearing of the module object, or
``NULL`` if not needed.
This function is not called if the module state was requested but is not
allocated yet. This is the case immediately after the module is created
and before the module is executed (:c:data:`Py_mod_exec` function). More
precisely, this function is not called if :c:member:`~PyModuleDef.m_size` is greater
than 0 and the module state (as returned by :c:func:`PyModule_GetState`)
is ``NULL``.
Like :c:member:`PyTypeObject.tp_clear`, this function is not *always*
called before a module is deallocated. For example, when reference
counting is enough to determine that an object is no longer used,
the cyclic garbage collector is not involved and
:c:member:`~PyModuleDef.m_free` is called directly.
.. versionchanged:: 3.9
No longer called before the module state is allocated.
.. c:member:: freefunc m_free
A function to call during deallocation of the module object, or ``NULL``
if not needed.
This function is not called if the module state was requested but is not
allocated yet. This is the case immediately after the module is created
and before the module is executed (:c:data:`Py_mod_exec` function). More
precisely, this function is not called if :c:member:`~PyModuleDef.m_size` is greater
than 0 and the module state (as returned by :c:func:`PyModule_GetState`)
is ``NULL``.
.. versionchanged:: 3.9
No longer called before the module state is allocated.
Module slots
............
.. c:type:: PyModuleDef_Slot
.. c:member:: int slot
A slot ID, chosen from the available ``Py_mod_*`` values explained below.
An ID of 0 marks the end of a :c:type:`!PyModuleDef_Slot` array.
A slot ID, chosen from the available values explained below.
.. c:member:: void* value
Value of the slot, whose meaning depends on the slot ID.
The value may not be NULL.
To leave a slot out, omit the :c:type:`PyModuleDef_Slot` entry entirely.
.. versionadded:: 3.5
The available slot types are:
Metadata slots
..............
.. c:macro:: Py_mod_create
.. c:macro:: Py_mod_name
Specifies a function that is called to create the module object itself.
The *value* pointer of this slot must point to a function of the signature:
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for the name of the new module,
as a NUL-terminated UTF8-encoded ``const char *``.
.. c:function:: PyObject* create_module(PyObject *spec, PyModuleDef *def)
:no-index-entry:
:no-contents-entry:
Note that modules are typically created using a
:py:class:`~importlib.machinery.ModuleSpec`, and when they are, the
name from the spec will be used instead of :c:data:`!Py_mod_name`.
However, it is still recommended to include this slot for introspection
and debugging purposes.
The function receives a :py:class:`~importlib.machinery.ModuleSpec`
instance, as defined in :PEP:`451`, and the module definition.
It should return a new module object, or set an error
and return ``NULL``.
.. versionadded:: 3.15
This function should be kept minimal. In particular, it should not
call arbitrary Python code, as trying to import the same module again may
result in an infinite loop.
Use :c:member:`PyModuleDef.m_name` instead to support previous versions.
Multiple ``Py_mod_create`` slots may not be specified in one module
definition.
.. c:macro:: Py_mod_doc
If ``Py_mod_create`` is not specified, the import machinery will create
a normal module object using :c:func:`PyModule_New`. The name is taken from
*spec*, not the definition, to allow extension modules to dynamically adjust
to their place in the module hierarchy and be imported under different
names through symlinks, all while sharing a single module definition.
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for the docstring of the new
module, as a NUL-terminated UTF8-encoded ``const char *``.
There is no requirement for the returned object to be an instance of
:c:type:`PyModule_Type`. Any type can be used, as long as it supports
setting and getting import-related attributes.
However, only ``PyModule_Type`` instances may be returned if the
``PyModuleDef`` has non-``NULL`` ``m_traverse``, ``m_clear``,
``m_free``; non-zero ``m_size``; or slots other than ``Py_mod_create``.
Usually it is set to a variable created with :c:macro:`PyDoc_STRVAR`.
.. c:macro:: Py_mod_exec
.. versionadded:: 3.15
Specifies a function that is called to *execute* the module.
This is equivalent to executing the code of a Python module: typically,
this function adds classes and constants to the module.
The signature of the function is:
Use :c:member:`PyModuleDef.m_doc` instead to support previous versions.
.. c:function:: int exec_module(PyObject* module)
:no-index-entry:
:no-contents-entry:
Feature slots
.............
.. c:macro:: Py_mod_abi
:c:type:`Slot ID <PyModuleDef_Slot.slot>` whose value points to
a :c:struct:`PyABIInfo` structure describing the ABI that
the extension is using.
A suitable :c:struct:`!PyABIInfo` variable can be defined using the
:c:macro:`PyABIInfo_VAR` macro, as in:
.. code-block:: c
PyABIInfo_VAR(abi_info);
static PyModuleDef_Slot mymodule_slots[] = {
{Py_mod_abi, &abi_info},
...
};
When creating a module, Python checks the value of this slot
using :c:func:`PyABIInfo_Check`.
.. versionadded:: 3.15
If multiple ``Py_mod_exec`` slots are specified, they are processed in the
order they appear in the *m_slots* array.
.. c:macro:: Py_mod_multiple_interpreters
:c:type:`Slot ID <PyModuleDef_Slot.slot>` whose value is one of:
Specifies one of the following values:
.. c:namespace:: NULL
@ -257,6 +353,9 @@ Feature slots
This slot determines whether or not importing this module
in a subinterpreter will fail.
Multiple ``Py_mod_multiple_interpreters`` slots may not be specified
in one module definition.
If ``Py_mod_multiple_interpreters`` is not specified, the import
machinery defaults to ``Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED``.
@ -264,7 +363,7 @@ Feature slots
.. c:macro:: Py_mod_gil
:c:type:`Slot ID <PyModuleDef_Slot.slot>` whose value is one of:
Specifies one of the following values:
.. c:namespace:: NULL
@ -282,482 +381,45 @@ Feature slots
this module will cause the GIL to be automatically enabled. See
:ref:`whatsnew313-free-threaded-cpython` for more detail.
Multiple ``Py_mod_gil`` slots may not be specified in one module definition.
If ``Py_mod_gil`` is not specified, the import machinery defaults to
``Py_MOD_GIL_USED``.
.. versionadded:: 3.13
.. c:macro:: Py_mod_abi
Creation and initialization slots
.................................
A pointer to a :c:struct:`PyABIInfo` structure that describes the ABI that
the extension is using.
.. c:macro:: Py_mod_create
When the module is loaded, the :c:struct:`!PyABIInfo` in this slot is checked
using :c:func:`PyABIInfo_Check`.
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for a function that creates
the module object itself.
The function must have the signature:
A suitable :c:struct:`!PyABIInfo` variable can be defined using the
:c:macro:`PyABIInfo_VAR` macro, as in:
.. c:function:: PyObject* create_module(PyObject *spec, PyModuleDef *def)
:no-index-entry:
:no-contents-entry:
.. code-block:: c
The function will be called with:
PyABIInfo_VAR(abi_info);
- *spec*: a ``ModuleSpec``-like object, meaning that any attributes defined
for :py:class:`importlib.machinery.ModuleSpec` have matching semantics.
However, any of the attributes may be missing.
- *def*: ``NULL``, or the module definition if the module is created from one.
The function should return a new module object, or set an error
and return ``NULL``.
This function should be kept minimal. In particular, it should not
call arbitrary Python code, as trying to import the same module again may
result in an infinite loop.
If ``Py_mod_create`` is not specified, the import machinery will create
a normal module object using :c:func:`PyModule_New`. The name is taken from
*spec*, not the definition, to allow extension modules to dynamically adjust
to their place in the module hierarchy and be imported under different
names through symlinks, all while sharing a single module definition.
There is no requirement for the returned object to be an instance of
:c:type:`PyModule_Type`.
However, some slots may only be used with
:c:type:`!PyModule_Type` instances; in particular:
- :c:macro:`Py_mod_exec`,
- :ref:`module state slots <ext-module-state-slots>` (``Py_mod_state_*``),
- :c:macro:`Py_mod_token`.
.. versionadded:: 3.5
.. versionchanged:: 3.15
The *slots* argument may be a ``ModuleSpec``-like object, rather than
a true :py:class:`~importlib.machinery.ModuleSpec` instance.
Note that previous versions of CPython did not enforce this.
The *def* argument may now be ``NULL``, since modules are not necessarily
made from definitions.
.. c:macro:: Py_mod_exec
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for a function that will
:dfn:`execute`, or initialize, the module.
This function does the equivalent to executing the code of a Python module:
typically, it adds classes and constants to the module.
The signature of the function is:
.. c:function:: int exec_module(PyObject* module)
:no-index-entry:
:no-contents-entry:
See the :ref:`capi-module-support-functions` section for some useful
functions to call.
For backwards compatibility, the :c:type:`PyModuleDef.m_slots` array may
contain multiple :c:macro:`!Py_mod_exec` slots; these are processed in the
order they appear in the array.
Elsewhere (that is, in arguments to :c:func:`PyModule_FromSlotsAndSpec`
and in return values of :samp:`PyModExport_{<name>}`), repeating the slot
is not allowed.
.. versionadded:: 3.5
.. versionchanged:: 3.15
Repeated ``Py_mod_exec`` slots are disallowed, except in
:c:type:`PyModuleDef.m_slots`.
.. c:macro:: Py_mod_methods
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for a table of module-level
functions, as an array of :c:type:`PyMethodDef` values suitable as the
*functions* argument to :c:func:`PyModule_AddFunctions`.
Like other slot IDs, a slots array may only contain one
:c:macro:`!Py_mod_methods` entry.
To add functions from multiple :c:type:`PyMethodDef` arrays, call
:c:func:`PyModule_AddFunctions` in the :c:macro:`Py_mod_exec` function.
The table must be statically allocated (or otherwise guaranteed to outlive
the module object).
static PyModuleDef_Slot mymodule_slots[] = {
{Py_mod_abi, &abi_info},
...
};
.. versionadded:: 3.15
Use :c:member:`PyModuleDef.m_methods` instead to support previous versions.
.. _ext-module-state:
Module state
------------
Extension modules can have *module state* -- a
piece of memory that is allocated on module creation,
and freed when the module object is deallocated.
The module state is specified using :ref:`dedicated slots <ext-module-state-slots>`.
A typical use of module state is storing an exception type -- or indeed *any*
type object defined by the module --
Unlike the module's Python attributes, Python code cannot replace or delete
data stored in module state.
Keeping per-module information in attributes and module state, rather than in
static globals, makes module objects *isolated* and safer for use in
multiple sub-interpreters.
It also helps Python do an orderly clean-up when it shuts down.
Extensions that keep references to Python objects as part of module state must
implement :c:macro:`Py_mod_state_traverse` and :c:macro:`Py_mod_state_clear`
functions to avoid reference leaks.
To retrieve the state from a given module, use the following functions:
.. c:function:: void* PyModule_GetState(PyObject *module)
Return the "state" of the module, that is, a pointer to the block of memory
allocated at module creation time, or ``NULL``. See
:c:macro:`Py_mod_state_size`.
On error, return ``NULL`` with an exception set.
Use :c:func:`PyErr_Occurred` to tell this case apart from missing
module state.
.. c:function:: int PyModule_GetStateSize(PyObject *, Py_ssize_t *result)
Set *\*result* to the size of the module's state, as specified using
:c:macro:`Py_mod_state_size` (or :c:member:`PyModuleDef.m_size`),
and return 0.
On error, set *\*result* to -1, and return -1 with an exception set.
.. versionadded:: 3.15
.. _ext-module-state-slots:
Slots for defining module state
...............................
The following :c:member:`PyModuleDef_Slot.slot` IDs are available for
defining the module state.
.. c:macro:: Py_mod_state_size
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for the size of the module state,
in bytes.
Setting the value to a non-negative value means that the module can be
re-initialized and specifies the additional amount of memory it requires
for its state.
See :PEP:`3121` for more details.
Use :c:func:`PyModule_GetStateSize` to retrieve the size of a given module.
.. versionadded:: 3.15
Use :c:member:`PyModuleDef.m_size` instead to support previous versions.
.. c:macro:: Py_mod_state_traverse
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for a traversal function to call
during GC traversal of the module object.
The signature of the function, and meanings of the arguments,
is similar as for :c:member:`PyTypeObject.tp_traverse`:
.. c:function:: int traverse_module_state(PyObject *module, visitproc visit, void *arg)
:no-index-entry:
:no-contents-entry:
This function is not called if the module state was requested but is not
allocated yet. This is the case immediately after the module is created
and before the module is executed (:c:data:`Py_mod_exec` function). More
precisely, this function is not called if the state size
(:c:data:`Py_mod_state_size`) is greater than 0 and the module state
(as returned by :c:func:`PyModule_GetState`) is ``NULL``.
.. versionadded:: 3.15
Use :c:member:`PyModuleDef.m_size` instead to support previous versions.
.. c:macro:: Py_mod_state_clear
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for a clear function to call
during GC clearing of the module object.
The signature of the function is:
.. c:function:: int clear_module_state(PyObject* module)
:no-index-entry:
:no-contents-entry:
This function is not called if the module state was requested but is not
allocated yet. This is the case immediately after the module is created
and before the module is executed (:c:data:`Py_mod_exec` function). More
precisely, this function is not called if the state size
(:c:data:`Py_mod_state_size`) is greater than 0 and the module state
(as returned by :c:func:`PyModule_GetState`) is ``NULL``.
Like :c:member:`PyTypeObject.tp_clear`, this function is not *always*
called before a module is deallocated. For example, when reference
counting is enough to determine that an object is no longer used,
the cyclic garbage collector is not involved and
the :c:macro:`Py_mod_state_free` function is called directly.
.. versionadded:: 3.15
Use :c:member:`PyModuleDef.m_clear` instead to support previous versions.
.. c:macro:: Py_mod_state_free
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for a function to call during
deallocation of the module object.
The signature of the function is:
.. c:function:: int free_module_state(PyObject* module)
:no-index-entry:
:no-contents-entry:
This function is not called if the module state was requested but is not
allocated yet. This is the case immediately after the module is created
and before the module is executed (:c:data:`Py_mod_exec` function). More
precisely, this function is not called if the state size
(:c:data:`Py_mod_state_size`) is greater than 0 and the module state
(as returned by :c:func:`PyModule_GetState`) is ``NULL``.
.. versionadded:: 3.15
Use :c:member:`PyModuleDef.m_free` instead to support previous versions.
.. _ext-module-token:
Module token
............
Each module may have an associated *token*: a pointer-sized value intended to
identify of the module state's memory layout.
This means that if you have a module object, but you are not sure if it
“belongs” to your extension, you can check using code like this:
.. code-block:: c
PyObject *module = <the module in question>
void *module_token;
if (PyModule_GetToken(module, &module_token) < 0) {
return NULL;
}
if (module_token != your_token) {
PyErr_SetString(PyExc_ValueError, "unexpected module")
return NULL;
}
// This module's state has the expected memory layout; it's safe to cast
struct my_state state = (struct my_state*)PyModule_GetState(module)
A module's token -- and the *your_token* value to use in the above code -- is:
- For modules created with :c:type:`PyModuleDef`: the address of that
:c:type:`PyModuleDef`;
- For modules defined with the :c:macro:`Py_mod_token` slot: the value
of that slot;
- For modules created from an ``PyModExport_*``
:ref:`export hook <extension-export-hook>`: the slots array that the export
hook returned (unless overriden with :c:macro:`Py_mod_token`).
.. c:macro:: Py_mod_token
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for the module token.
If you use this slot to set the module token (rather than rely on the
default), you must ensure that:
* The pointer outlives the class, so it's not reused for something else
while the class exists.
* It "belongs" to the extension module where the class lives, so it will not
clash with other extensions.
* If the token points to a :c:type:`PyModuleDef` struct, the module should
behave as if it was created from that :c:type:`PyModuleDef`.
In particular, the module state must have matching layout and semantics.
Modules created from :c:type:`PyModuleDef` always use the address of
the :c:type:`PyModuleDef` as the token.
This means that :c:macro:`!Py_mod_token` cannot be used in
:c:member:`PyModuleDef.m_slots`.
.. versionadded:: 3.15
.. c:function:: int PyModule_GetToken(PyObject *module, void** result)
Set *\*result* to the module's token and return 0.
On error, set *\*result* to NULL, and return -1 with an exception set.
.. versionadded:: 3.15
See also :c:func:`PyType_GetModuleByToken`.
.. _module-from-slots:
Creating extension modules dynamically
--------------------------------------
The following functions may be used to create an extension module dynamically,
rather than from an extension's :ref:`export hook <extension-export-hook>`.
.. c:function:: PyObject *PyModule_FromSlotsAndSpec(const PyModuleDef_Slot *slots, PyObject *spec)
Create a new module object, given an array of :ref:`slots <pymoduledef_slot>`
and the :py:class:`~importlib.machinery.ModuleSpec` *spec*.
The *slots* argument must point to an array of :c:type:`PyModuleDef_Slot`
structures, terminated by an entry slot with slot ID of 0
(typically written as ``{0}`` or ``{0, NULL}`` in C).
The *slots* argument may not be ``NULL``.
The *spec* argument may be any ``ModuleSpec``-like object, as described
in :c:macro:`Py_mod_create` documentation.
Currently, the *spec* must have a ``name`` attribute.
On success, return the new module.
On error, return ``NULL`` with an exception set.
Note that this does not process the module's execution slot
(:c:data:`Py_mod_exec`).
Both :c:func:`!PyModule_FromSlotsAndSpec` and :c:func:`PyModule_Exec`
must be called to fully initialize a module.
(See also :ref:`multi-phase-initialization`.)
The *slots* array only needs to be valid for the duration of the
:c:func:`!PyModule_FromSlotsAndSpec` call.
In particular, it may be heap-allocated.
.. versionadded:: 3.15
.. c:function:: int PyModule_Exec(PyObject *module)
Execute the :c:data:`Py_mod_exec` slot(s) of the given *module*.
On success, return 0.
On error, return -1 with an exception set.
For clarity: If *module* has no slots, for example if it uses
:ref:`legacy single-phase initialization <single-phase-initialization>`,
this function does nothing and returns 0.
.. versionadded:: 3.15
.. _pymoduledef:
Module definition struct
------------------------
Traditionally, extension modules were defined using a *module definition*
as the “description" of how a module should be created.
Rather than using an array of :ref:`slots <pymoduledef_slot>` directly,
the definition has dedicated members for most common functionality,
and allows additional slots as an extension mechanism.
This way of defining modules is still available and there are no plans to
remove it.
.. c:type:: PyModuleDef
The module definition struct, which holds information needed to create
a module object.
This structure must be statically allocated (or be otherwise guaranteed
to be valid while any modules created from it exist).
Usually, there is only one variable of this type for each extension module
defined this way.
.. c:member:: PyModuleDef_Base m_base
Always initialize this member to :c:macro:`PyModuleDef_HEAD_INIT`:
.. c:namespace:: NULL
.. c:type:: PyModuleDef_Base
The type of :c:member:`!PyModuleDef.m_base`.
.. c:macro:: PyModuleDef_HEAD_INIT
The required initial value for :c:member:`!PyModuleDef.m_base`.
.. c:member:: const char *m_name
Corresponds to the :c:macro:`Py_mod_name` slot.
.. c:member:: const char *m_doc
These members correspond to the :c:macro:`Py_mod_doc` slot.
Setting this to NULL is equivalent to omitting the slot.
.. c:member:: Py_ssize_t m_size
Corresponds to the :c:macro:`Py_mod_state_size` slot.
Setting this to zero is equivalent to omitting the slot.
When using :ref:`legacy single-phase initialization <single-phase-initialization>`
or when creating modules dynamically using :c:func:`PyModule_Create`
or :c:func:`PyModule_Create2`, :c:member:`!m_size` may be set to -1.
This indicates that the module does not support sub-interpreters,
because it has global state.
.. c:member:: PyMethodDef *m_methods
Corresponds to the :c:macro:`Py_mod_methods` slot.
Setting this to NULL is equivalent to omitting the slot.
.. c:member:: PyModuleDef_Slot* m_slots
An array of additional slots, terminated by a ``{0, NULL}`` entry.
This array may not contain slots corresponding to :c:type:`PyModuleDef`
members.
For example, you cannot use :c:macro:`Py_mod_name` in :c:member:`!m_slots`;
the module name must be given as :c:member:`PyModuleDef.m_name`.
.. versionchanged:: 3.5
Prior to version 3.5, this member was always set to ``NULL``,
and was defined as:
.. c:member:: inquiry m_reload
.. c:member:: traverseproc m_traverse
inquiry m_clear
freefunc m_free
These members correspond to the :c:macro:`Py_mod_state_traverse`,
:c:macro:`Py_mod_state_clear`, and :c:macro:`Py_mod_state_free` slots,
respectively.
Setting these members to NULL is equivalent to omitting the
corresponding slots.
.. versionchanged:: 3.9
:c:member:`m_traverse`, :c:member:`m_clear` and :c:member:`m_free`
functions are longer called before the module state is allocated.
.. _moduledef-dynamic:
The following API can be used to create modules from a :c:type:`!PyModuleDef`
struct:
Creating extension modules dynamically
--------------------------------------
The following functions may be used to create a module outside of an
extension's :ref:`initialization function <extension-export-hook>`.
They are also used in
:ref:`single-phase initialization <single-phase-initialization>`.
.. c:function:: PyObject* PyModule_Create(PyModuleDef *def)
@ -834,13 +496,12 @@ struct:
useful for versioning. This may change in the future.
.. _capi-module-support-functions:
Support functions
-----------------
The following functions are provided to help initialize a module object.
They are intended for a module's execution slot (:c:data:`Py_mod_exec`),
The following functions are provided to help initialize a module
state.
They are intended for a module's execution slots (:c:data:`Py_mod_exec`),
the initialization function for legacy :ref:`single-phase initialization <single-phase-initialization>`,
or code that creates modules dynamically.
@ -1006,9 +667,6 @@ or code that creates modules dynamically.
:c:type:`PyMethodDef` arrays; in that case they should call this function
directly.
The *functions* array must be statically allocated (or otherwise guaranteed
to outlive the module object).
.. versionadded:: 3.5
.. c:function:: int PyModule_SetDocString(PyObject *module, const char *docstring)

View file

@ -136,7 +136,7 @@ Managing the Monitoring State
-----------------------------
Monitoring states can be managed with the help of monitoring scopes. A scope
would typically correspond to a Python function.
would typically correspond to a python function.
.. c:function:: int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length)

View file

@ -73,7 +73,7 @@ Object Protocol
Flag to be used with multiple functions that print the object (like
:c:func:`PyObject_Print` and :c:func:`PyFile_WriteObject`).
If passed, these functions use the :func:`str` of the object
If passed, these function would use the :func:`str` of the object
instead of the :func:`repr`.
@ -85,35 +85,6 @@ Object Protocol
instead of the :func:`repr`.
.. c:function:: void PyUnstable_Object_Dump(PyObject *op)
Dump an object *op* to ``stderr``. This should only be used for debugging.
The output is intended to try dumping objects even after memory corruption:
* Information is written starting with fields that are the least likely to
crash when accessed.
* This function can be called without an :term:`attached thread state`, but
it's not recommended to do so: it can cause deadlocks.
* An object that does not belong to the current interpreter may be dumped,
but this may also cause crashes or unintended behavior.
* Implement a heuristic to detect if the object memory has been freed. Don't
display the object contents in this case, only its memory address.
* The output format may change at any time.
Example of output:
.. code-block:: output
object address : 0x7f80124702c0
object refcount : 2
object type : 0x9902e0
object type name: str
object repr : 'abcdef'
.. versionadded:: 3.15
.. c:function:: int PyObject_HasAttrWithError(PyObject *o, PyObject *attr_name)
Returns ``1`` if *o* has the attribute *attr_name*, and ``0`` otherwise.

View file

@ -1,59 +0,0 @@
.. highlight:: c
.. _picklebuffer-objects:
.. index::
pair: object; PickleBuffer
Pickle buffer objects
---------------------
.. versionadded:: 3.8
A :class:`pickle.PickleBuffer` object wraps a :ref:`buffer-providing object
<bufferobjects>` for out-of-band data transfer with the :mod:`pickle` module.
.. c:var:: PyTypeObject PyPickleBuffer_Type
This instance of :c:type:`PyTypeObject` represents the Python pickle buffer type.
This is the same object as :class:`pickle.PickleBuffer` in the Python layer.
.. c:function:: int PyPickleBuffer_Check(PyObject *op)
Return true if *op* is a pickle buffer instance.
This function always succeeds.
.. c:function:: PyObject *PyPickleBuffer_FromObject(PyObject *obj)
Create a pickle buffer from the object *obj*.
This function will fail if *obj* doesn't support the :ref:`buffer protocol <bufferobjects>`.
On success, return a new pickle buffer instance.
On failure, set an exception and return ``NULL``.
Analogous to calling :class:`pickle.PickleBuffer` with *obj* in Python.
.. c:function:: const Py_buffer *PyPickleBuffer_GetBuffer(PyObject *picklebuf)
Get a pointer to the underlying :c:type:`Py_buffer` that the pickle buffer wraps.
The returned pointer is valid as long as *picklebuf* is alive and has not been
released. The caller must not modify or free the returned :c:type:`Py_buffer`.
If the pickle buffer has been released, raise :exc:`ValueError`.
On success, return a pointer to the buffer view.
On failure, set an exception and return ``NULL``.
.. c:function:: int PyPickleBuffer_Release(PyObject *picklebuf)
Release the underlying buffer held by the pickle buffer.
Return ``0`` on success. On failure, set an exception and return ``-1``.
Analogous to calling :meth:`pickle.PickleBuffer.release` in Python.

View file

@ -147,7 +147,7 @@ subtypes but not for instances of :class:`frozenset` or its subtypes.
Return ``1`` if found and removed, ``0`` if not found (no action taken), and ``-1`` if an
error is encountered. Does not raise :exc:`KeyError` for missing keys. Raise a
:exc:`TypeError` if the *key* is unhashable. Unlike the Python :meth:`~set.discard`
:exc:`TypeError` if the *key* is unhashable. Unlike the Python :meth:`~frozenset.discard`
method, this function does not automatically convert unhashable sets into
temporary frozensets. Raise :exc:`SystemError` if *set* is not an
instance of :class:`set` or its subtype.

View file

@ -279,7 +279,7 @@ The full API is described below for advanced use cases.
.. c:member:: uint8_t abiinfo_minor_version
The minor version of :c:struct:`PyABIInfo`.
The major version of :c:struct:`PyABIInfo`.
Must be set to ``0``; larger values are reserved for backwards-compatible
future versions of :c:struct:`!PyABIInfo`.
@ -294,7 +294,7 @@ The full API is described below for advanced use cases.
Default flags, based on current values of macros such as
:c:macro:`Py_LIMITED_API` and :c:macro:`Py_GIL_DISABLED`.
Alternately, the field can be set to the following flags, combined
Alternately, the field can be set to to the following flags, combined
by bitwise OR.
Unused bits must be set to zero.

View file

@ -280,8 +280,6 @@ Implementing functions and methods
Name of the method.
A ``NULL`` *ml_name* marks the end of a :c:type:`!PyMethodDef` array.
.. c:member:: PyCFunction ml_meth
Pointer to the C implementation.
@ -449,25 +447,6 @@ definition with the same method name.
slot. This is helpful because calls to PyCFunctions are optimized more
than wrapper object calls.
.. c:var:: PyTypeObject PyCMethod_Type
The type object corresponding to Python C method objects. This is
available as :class:`types.BuiltinMethodType` in the Python layer.
.. c:function:: int PyCMethod_Check(PyObject *op)
Return true if *op* is an instance of the :c:type:`PyCMethod_Type` type
or a subtype of it. This function always succeeds.
.. c:function:: int PyCMethod_CheckExact(PyObject *op)
This is the same as :c:func:`PyCMethod_Check`, but does not account for
subtypes.
.. c:function:: PyObject * PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *cls)
Turn *ml* into a Python :term:`callable` object.
@ -493,24 +472,6 @@ definition with the same method name.
.. versionadded:: 3.9
.. c:var:: PyTypeObject PyCFunction_Type
The type object corresponding to Python C function objects. This is
available as :class:`types.BuiltinFunctionType` in the Python layer.
.. c:function:: int PyCFunction_Check(PyObject *op)
Return true if *op* is an instance of the :c:type:`PyCFunction_Type` type
or a subtype of it. This function always succeeds.
.. c:function:: int PyCFunction_CheckExact(PyObject *op)
This is the same as :c:func:`PyCFunction_Check`, but does not account for
subtypes.
.. c:function:: PyObject * PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
Equivalent to ``PyCMethod_New(ml, self, module, NULL)``.
@ -521,62 +482,6 @@ definition with the same method name.
Equivalent to ``PyCMethod_New(ml, self, NULL, NULL)``.
.. c:function:: int PyCFunction_GetFlags(PyObject *func)
Get the function's flags on *func* as they were passed to
:c:member:`~PyMethodDef.ml_flags`.
If *func* is not a C function object, this fails with an exception.
*func* must not be ``NULL``.
This function returns the function's flags on success, and ``-1`` with an
exception set on failure.
.. c:function:: int PyCFunction_GET_FLAGS(PyObject *func)
This is the same as :c:func:`PyCFunction_GetFlags`, but without error
or type checking.
.. c:function:: PyCFunction PyCFunction_GetFunction(PyObject *func)
Get the function pointer on *func* as it was passed to
:c:member:`~PyMethodDef.ml_meth`.
If *func* is not a C function object, this fails with an exception.
*func* must not be ``NULL``.
This function returns the function pointer on success, and ``NULL`` with an
exception set on failure.
.. c:function:: int PyCFunction_GET_FUNCTION(PyObject *func)
This is the same as :c:func:`PyCFunction_GetFunction`, but without error
or type checking.
.. c:function:: PyObject *PyCFunction_GetSelf(PyObject *func)
Get the "self" object on *func*. This is the object that would be passed
to the first argument of a :c:type:`PyCFunction`. For C function objects
created through a :c:type:`PyMethodDef` on a :c:type:`PyModuleDef`, this
is the resulting module object.
If *func* is not a C function object, this fails with an exception.
*func* must not be ``NULL``.
This function returns a :term:`borrowed reference` to the "self" object
on success, and ``NULL`` with an exception set on failure.
.. c:function:: PyObject *PyCFunction_GET_SELF(PyObject *func)
This is the same as :c:func:`PyCFunction_GetSelf`, but without error or
type checking.
Accessing attributes of extension types
---------------------------------------
@ -700,12 +605,14 @@ The following flags can be used with :c:member:`PyMemberDef.flags`:
entry indicates an offset from the subclass-specific data, rather than
from ``PyObject``.
Can only be used as part of the :c:data:`Py_tp_members`
Can only be used as part of :c:member:`Py_tp_members <PyTypeObject.tp_members>`
:c:type:`slot <PyType_Slot>` when creating a class using negative
:c:member:`~PyType_Spec.basicsize`.
It is mandatory in that case.
When setting :c:member:`~PyTypeObject.tp_members` from the slot during
class creation, Python clears the flag and sets
This flag is only used in :c:type:`PyType_Slot`.
When setting :c:member:`~PyTypeObject.tp_members` during
class creation, Python clears it and sets
:c:member:`PyMemberDef.offset` to the offset from the ``PyObject`` struct.
.. index::

View file

@ -123,24 +123,6 @@ Operating System Utilities
This is a thin wrapper around either :c:func:`!sigaction` or :c:func:`!signal`. Do
not call those functions directly!
.. c:function:: int PyOS_InterruptOccurred(void)
Check if a :c:macro:`!SIGINT` signal has been received.
Returns ``1`` if a :c:macro:`!SIGINT` has occurred and clears the signal flag,
or ``0`` otherwise.
In most cases, you should prefer :c:func:`PyErr_CheckSignals` over this function.
:c:func:`!PyErr_CheckSignals` invokes the appropriate signal handlers
for all pending signals, allowing Python code to handle the signal properly.
This function only detects :c:macro:`!SIGINT` and does not invoke any Python
signal handlers.
This function is async-signal-safe and this function cannot fail.
The caller must hold an :term:`attached thread state`.
.. c:function:: wchar_t* Py_DecodeLocale(const char* arg, size_t *size)
.. warning::

View file

@ -61,7 +61,7 @@ Tuple Objects
.. c:function:: Py_ssize_t PyTuple_Size(PyObject *p)
Take a pointer to a tuple object, and return the size of that tuple.
On error, return ``-1`` with an exception set.
On error, return ``-1`` and with an exception set.
.. c:function:: Py_ssize_t PyTuple_GET_SIZE(PyObject *p)
@ -148,11 +148,8 @@ Tuple Objects
Struct Sequence Objects
-----------------------
A struct sequence object is a :term:`named tuple`, that is, a sequence
whose items can also be accessed through attributes.
It is similar to :func:`collections.namedtuple`, but provides a slightly
different interface.
Struct sequence objects are the C equivalent of :func:`~collections.namedtuple`
objects, i.e. a sequence whose items can also be accessed through attributes.
To create a struct sequence, you first have to create a specific struct sequence
type.

View file

@ -116,20 +116,6 @@ Type Objects
.. versionadded:: 3.12
.. c:function:: int PyType_Unwatch(int watcher_id, PyObject *type)
Mark *type* as not watched. This undoes a previous call to
:c:func:`PyType_Watch`. *type* must not be ``NULL``.
An extension should never call this function with a *watcher_id* that was
not returned to it by a previous call to :c:func:`PyType_AddWatcher`.
On success, this function returns ``0``. On failure, this function returns
``-1`` with an exception set.
.. versionadded:: 3.12
.. c:type:: int (*PyType_WatchCallback)(PyObject *type)
Type of a type-watcher callback function.
@ -147,18 +133,6 @@ Type Objects
Type features are denoted by single bit flags.
.. c:function:: int PyType_FastSubclass(PyTypeObject *type, int flag)
Return non-zero if the type object *type* sets the subclass flag *flag*.
Subclass flags are denoted by
:c:macro:`Py_TPFLAGS_*_SUBCLASS <Py_TPFLAGS_LONG_SUBCLASS>`.
This function is used by many ``_Check`` functions for common types.
.. seealso::
:c:func:`PyObject_TypeCheck`, which is used as a slower alternative in
``_Check`` functions for types that don't come with subclass flags.
.. c:function:: int PyType_IS_GC(PyTypeObject *o)
Return true if the type object includes support for the cycle detector; this
@ -195,14 +169,12 @@ Type Objects
before initialization) and should be paired with :c:func:`PyObject_Free` in
:c:member:`~PyTypeObject.tp_free`.
.. c:function:: PyObject* PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
Generic handler for the :c:member:`~PyTypeObject.tp_new` slot of a type
object. Creates a new instance using the type's
:c:member:`~PyTypeObject.tp_alloc` slot and returns the resulting object.
.. c:function:: int PyType_Ready(PyTypeObject *type)
Finalize a type object. This should be called on all type objects to finish
@ -219,7 +191,6 @@ Type Objects
GC protocol itself by at least implementing the
:c:member:`~PyTypeObject.tp_traverse` handle.
.. c:function:: PyObject* PyType_GetName(PyTypeObject *type)
Return the type's name. Equivalent to getting the type's
@ -227,7 +198,6 @@ Type Objects
.. versionadded:: 3.11
.. c:function:: PyObject* PyType_GetQualName(PyTypeObject *type)
Return the type's qualified name. Equivalent to getting the
@ -243,7 +213,6 @@ Type Objects
.. versionadded:: 3.13
.. c:function:: PyObject* PyType_GetModuleName(PyTypeObject *type)
Return the type's module name. Equivalent to getting the
@ -251,7 +220,6 @@ Type Objects
.. versionadded:: 3.13
.. c:function:: void* PyType_GetSlot(PyTypeObject *type, int slot)
Return the function pointer stored in the given slot. If the
@ -268,7 +236,6 @@ Type Objects
:c:func:`PyType_GetSlot` can now accept all types.
Previously, it was limited to :ref:`heap types <heap-types>`.
.. c:function:: PyObject* PyType_GetModule(PyTypeObject *type)
Return the module object associated with the given type when the type was
@ -283,12 +250,11 @@ Type Objects
``Py_TYPE(self)`` may be a *subclass* of the intended class, and subclasses
are not necessarily defined in the same module as their superclass.
See :c:type:`PyCMethod` to get the class that defines the method.
See :c:func:`PyType_GetModuleByToken` for cases when :c:type:`!PyCMethod`
cannot be used.
See :c:func:`PyType_GetModuleByDef` for cases when :c:type:`!PyCMethod` cannot
be used.
.. versionadded:: 3.9
.. c:function:: void* PyType_GetModuleState(PyTypeObject *type)
Return the state of the module object associated with the given type.
@ -303,11 +269,10 @@ Type Objects
.. versionadded:: 3.9
.. c:function:: PyObject* PyType_GetModuleByDef(PyTypeObject *type, struct PyModuleDef *def)
.. c:function:: PyObject* PyType_GetModuleByToken(PyTypeObject *type, const void *mod_token)
Find the first superclass whose module has the given
:ref:`module token <ext-module-token>`, and return that module.
Find the first superclass whose module was created from
the given :c:type:`PyModuleDef` *def*, and return that module.
If no module is found, raises a :py:class:`TypeError` and returns ``NULL``.
@ -317,34 +282,16 @@ Type Objects
and other places where a method's defining class cannot be passed using the
:c:type:`PyCMethod` calling convention.
.. versionadded:: 3.15
.. c:function:: PyObject* PyType_GetModuleByDef(PyTypeObject *type, struct PyModuleDef *def)
Find the first superclass whose module was created from the given
:c:type:`PyModuleDef` *def*, or whose :ref:`module token <ext-module-token>`
is equal to *def*, and return that module.
Note that modules created from a :c:type:`PyModuleDef` always have their
token set to the :c:type:`PyModuleDef`'s address.
In other words, this function is equivalent to
:c:func:`PyType_GetModuleByToken`, except that it:
- returns a borrowed reference, and
- has a non-``void*`` argument type (which is a cosmetic difference in C).
The returned reference is :term:`borrowed <borrowed reference>` from *type*,
and will be valid as long as you hold a reference to *type*.
Do not release it with :c:func:`Py_DECREF` or similar.
.. versionadded:: 3.11
.. c:function:: int PyType_GetBaseByToken(PyTypeObject *type, void *tp_token, PyTypeObject **result)
.. c:function:: int PyType_GetBaseByToken(PyTypeObject *type, void *token, PyTypeObject **result)
Find the first superclass in *type*'s :term:`method resolution order` whose
:c:macro:`Py_tp_token` token is equal to *tp_token*.
:c:macro:`Py_tp_token` token is equal to the given one.
* If found, set *\*result* to a new :term:`strong reference`
to it and return ``1``.
@ -355,11 +302,10 @@ Type Objects
The *result* argument may be ``NULL``, in which case *\*result* is not set.
Use this if you need only the return value.
The *tp_token* argument may not be ``NULL``.
The *token* argument may not be ``NULL``.
.. versionadded:: 3.14
.. c:function:: int PyUnstable_Type_AssignVersionTag(PyTypeObject *type)
Attempt to assign a version tag to the given type.
@ -370,16 +316,6 @@ Type Objects
.. versionadded:: 3.12
.. c:function:: int PyType_SUPPORTS_WEAKREFS(PyTypeObject *type)
Return true if instances of *type* support creating weak references, false
otherwise. This function always succeeds. *type* must not be ``NULL``.
.. seealso::
* :ref:`weakrefobjects`
* :py:mod:`weakref`
Creating Heap-Allocated Types
.............................
@ -400,8 +336,8 @@ The following functions and structs are used to create
The *bases* argument can be used to specify base classes; it can either
be only one class or a tuple of classes.
If *bases* is ``NULL``, the :c:data:`Py_tp_bases` slot is used instead.
If that also is ``NULL``, the :c:data:`Py_tp_base` slot is used instead.
If *bases* is ``NULL``, the *Py_tp_bases* slot is used instead.
If that also is ``NULL``, the *Py_tp_base* slot is used instead.
If that also is ``NULL``, the new type derives from :class:`object`.
The *module* argument can be used to record the module in which the new
@ -428,7 +364,6 @@ The following functions and structs are used to create
.. versionadded:: 3.12
.. c:function:: PyObject* PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
Equivalent to ``PyType_FromMetaclass(NULL, module, spec, bases)``.
@ -455,7 +390,6 @@ The following functions and structs are used to create
Creating classes whose metaclass overrides
:c:member:`~PyTypeObject.tp_new` is no longer allowed.
.. c:function:: PyObject* PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
Equivalent to ``PyType_FromMetaclass(NULL, NULL, spec, bases)``.
@ -477,7 +411,6 @@ The following functions and structs are used to create
Creating classes whose metaclass overrides
:c:member:`~PyTypeObject.tp_new` is no longer allowed.
.. c:function:: PyObject* PyType_FromSpec(PyType_Spec *spec)
Equivalent to ``PyType_FromMetaclass(NULL, NULL, spec, NULL)``.
@ -498,7 +431,6 @@ The following functions and structs are used to create
Creating classes whose metaclass overrides
:c:member:`~PyTypeObject.tp_new` is no longer allowed.
.. c:function:: int PyType_Freeze(PyTypeObject *type)
Make a type immutable: set the :c:macro:`Py_TPFLAGS_IMMUTABLETYPE` flag.
@ -607,9 +539,9 @@ The following functions and structs are used to create
:c:type:`PyAsyncMethods` with an added ``Py_`` prefix.
For example, use:
* :c:data:`Py_tp_dealloc` to set :c:member:`PyTypeObject.tp_dealloc`
* :c:data:`Py_nb_add` to set :c:member:`PyNumberMethods.nb_add`
* :c:data:`Py_sq_length` to set :c:member:`PySequenceMethods.sq_length`
* ``Py_tp_dealloc`` to set :c:member:`PyTypeObject.tp_dealloc`
* ``Py_nb_add`` to set :c:member:`PyNumberMethods.nb_add`
* ``Py_sq_length`` to set :c:member:`PySequenceMethods.sq_length`
An additional slot is supported that does not correspond to a
:c:type:`!PyTypeObject` struct field:
@ -628,7 +560,7 @@ The following functions and structs are used to create
If it is not possible to switch to a ``MANAGED`` flag (for example,
for vectorcall or to support Python older than 3.12), specify the
offset in :c:data:`Py_tp_members`.
offset in :c:member:`Py_tp_members <PyTypeObject.tp_members>`.
See :ref:`PyMemberDef documentation <pymemberdef-offsets>`
for details.
@ -655,8 +587,8 @@ The following functions and structs are used to create
under the :ref:`limited API <limited-c-api>`.
.. versionchanged:: 3.14
The field :c:member:`~PyTypeObject.tp_vectorcall` can now be set
using :c:data:`Py_tp_vectorcall`. See the field's documentation
The field :c:member:`~PyTypeObject.tp_vectorcall` can now set
using ``Py_tp_vectorcall``. See the field's documentation
for details.
.. c:member:: void *pfunc
@ -666,11 +598,10 @@ The following functions and structs are used to create
*pfunc* values may not be ``NULL``, except for the following slots:
* :c:data:`Py_tp_doc`
* ``Py_tp_doc``
* :c:data:`Py_tp_token` (for clarity, prefer :c:data:`Py_TP_USE_SPEC`
rather than ``NULL``)
.. c:macro:: Py_tp_token
A :c:member:`~PyType_Slot.slot` that records a static memory layout ID

View file

@ -676,8 +676,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: destructor PyTypeObject.tp_dealloc
.. corresponding-type-slot:: Py_tp_dealloc
A pointer to the instance destructor function. The function signature is::
void tp_dealloc(PyObject *self);
@ -862,8 +860,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: getattrfunc PyTypeObject.tp_getattr
.. corresponding-type-slot:: Py_tp_getattr
An optional pointer to the get-attribute-string function.
This field is deprecated. When it is defined, it should point to a function
@ -881,8 +877,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: setattrfunc PyTypeObject.tp_setattr
.. corresponding-type-slot:: Py_tp_setattr
An optional pointer to the function for setting and deleting attributes.
This field is deprecated. When it is defined, it should point to a function
@ -915,8 +909,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: reprfunc PyTypeObject.tp_repr
.. corresponding-type-slot:: Py_tp_repr
.. index:: pair: built-in function; repr
An optional pointer to a function that implements the built-in function
@ -982,8 +974,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: hashfunc PyTypeObject.tp_hash
.. corresponding-type-slot:: Py_tp_hash
.. index:: pair: built-in function; hash
An optional pointer to a function that implements the built-in function
@ -1025,8 +1015,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: ternaryfunc PyTypeObject.tp_call
.. corresponding-type-slot:: Py_tp_call
An optional pointer to a function that implements calling the object. This
should be ``NULL`` if the object is not callable. The signature is the same as
for :c:func:`PyObject_Call`::
@ -1040,8 +1028,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: reprfunc PyTypeObject.tp_str
.. corresponding-type-slot:: Py_tp_str
An optional pointer to a function that implements the built-in operation
:func:`str`. (Note that :class:`str` is a type now, and :func:`str` calls the
constructor for that type. This constructor calls :c:func:`PyObject_Str` to do
@ -1067,8 +1053,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: getattrofunc PyTypeObject.tp_getattro
.. corresponding-type-slot:: Py_tp_getattro
An optional pointer to the get-attribute function.
The signature is the same as for :c:func:`PyObject_GetAttr`::
@ -1093,8 +1077,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: setattrofunc PyTypeObject.tp_setattro
.. corresponding-type-slot:: Py_tp_setattro
An optional pointer to the function for setting and deleting attributes.
The signature is the same as for :c:func:`PyObject_SetAttr`::
@ -1278,7 +1260,7 @@ and :c:data:`PyType_Type` effectively act as defaults.)
This bit indicates that instances of the class have a :attr:`~object.__dict__`
attribute, and that the space for the dictionary is managed by the VM.
If this flag is set, :c:macro:`Py_TPFLAGS_HAVE_GC` must also be set.
If this flag is set, :c:macro:`Py_TPFLAGS_HAVE_GC` should also be set.
The type traverse function must call :c:func:`PyObject_VisitManagedDict`
and its clear function must call :c:func:`PyObject_ClearManagedDict`.
@ -1296,8 +1278,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
This bit indicates that instances of the class should be weakly
referenceable.
If this flag is set, :c:macro:`Py_TPFLAGS_HAVE_GC` must also be set.
.. versionadded:: 3.12
**Inheritance:**
@ -1351,8 +1331,8 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:macro:: Py_TPFLAGS_BASE_EXC_SUBCLASS
.. c:macro:: Py_TPFLAGS_TYPE_SUBCLASS
Functions such as :c:func:`PyLong_Check` will call :c:func:`PyType_FastSubclass`
with one of these flags to quickly determine if a type is a subclass
These flags are used by functions such as
:c:func:`PyLong_Check` to quickly determine if a type is a subclass
of a built-in type; such specific checks are faster than a generic
check, like :c:func:`PyObject_IsInstance`. Custom types that inherit
from built-ins should have their :c:member:`~PyTypeObject.tp_flags`
@ -1493,8 +1473,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: const char* PyTypeObject.tp_doc
.. corresponding-type-slot:: Py_tp_doc
An optional pointer to a NUL-terminated C string giving the docstring for this
type object. This is exposed as the :attr:`~type.__doc__` attribute on the
type and instances of the type.
@ -1506,8 +1484,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: traverseproc PyTypeObject.tp_traverse
.. corresponding-type-slot:: Py_tp_traverse
An optional pointer to a traversal function for the garbage collector. This is
only used if the :c:macro:`Py_TPFLAGS_HAVE_GC` flag bit is set. The signature is::
@ -1569,11 +1545,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
but the instance has no strong reference to the elements inside it, as they
are allowed to be removed even if the instance is still alive).
.. warning::
The traversal function must not have any side effects. It must not
modify the reference counts of any Python objects nor create or destroy
any Python objects.
Note that :c:func:`Py_VISIT` requires the *visit* and *arg* parameters to
:c:func:`!local_traverse` to have these specific names; don't name them just
anything.
@ -1609,8 +1580,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: inquiry PyTypeObject.tp_clear
.. corresponding-type-slot:: Py_tp_clear
An optional pointer to a clear function. The signature is::
int tp_clear(PyObject *);
@ -1759,8 +1728,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: richcmpfunc PyTypeObject.tp_richcompare
.. corresponding-type-slot:: Py_tp_richcompare
An optional pointer to the rich comparison function, whose signature is::
PyObject *tp_richcompare(PyObject *self, PyObject *other, int op);
@ -1863,8 +1830,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: getiterfunc PyTypeObject.tp_iter
.. corresponding-type-slot:: Py_tp_iter
An optional pointer to a function that returns an :term:`iterator` for the
object. Its presence normally signals that the instances of this type are
:term:`iterable` (although sequences may be iterable without this function).
@ -1880,8 +1845,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: iternextfunc PyTypeObject.tp_iternext
.. corresponding-type-slot:: Py_tp_iternext
An optional pointer to a function that returns the next item in an
:term:`iterator`. The signature is::
@ -1905,8 +1868,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: struct PyMethodDef* PyTypeObject.tp_methods
.. corresponding-type-slot:: Py_tp_methods
An optional pointer to a static ``NULL``-terminated array of :c:type:`PyMethodDef`
structures, declaring regular methods of this type.
@ -1921,8 +1882,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: struct PyMemberDef* PyTypeObject.tp_members
.. corresponding-type-slot:: Py_tp_members
An optional pointer to a static ``NULL``-terminated array of :c:type:`PyMemberDef`
structures, declaring regular data members (fields or slots) of instances of
this type.
@ -1938,8 +1897,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: struct PyGetSetDef* PyTypeObject.tp_getset
.. corresponding-type-slot:: Py_tp_getset
An optional pointer to a static ``NULL``-terminated array of :c:type:`PyGetSetDef`
structures, declaring computed attributes of instances of this type.
@ -1954,8 +1911,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: PyTypeObject* PyTypeObject.tp_base
.. corresponding-type-slot:: Py_tp_base
An optional pointer to a base type from which type properties are inherited. At
this level, only single inheritance is supported; multiple inheritance require
dynamically creating a type object by calling the metatype.
@ -2028,8 +1983,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: descrgetfunc PyTypeObject.tp_descr_get
.. corresponding-type-slot:: Py_tp_descr_get
An optional pointer to a "descriptor get" function.
The function signature is::
@ -2045,8 +1998,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: descrsetfunc PyTypeObject.tp_descr_set
.. corresponding-type-slot:: Py_tp_descr_set
An optional pointer to a function for setting and deleting
a descriptor's value.
@ -2107,8 +2058,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: initproc PyTypeObject.tp_init
.. corresponding-type-slot:: Py_tp_init
An optional pointer to an instance initialization function.
This function corresponds to the :meth:`~object.__init__` method of classes. Like
@ -2144,8 +2093,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: allocfunc PyTypeObject.tp_alloc
.. corresponding-type-slot:: Py_tp_alloc
An optional pointer to an instance allocation function.
The function signature is::
@ -2169,8 +2116,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: newfunc PyTypeObject.tp_new
.. corresponding-type-slot:: Py_tp_new
An optional pointer to an instance creation function.
The function signature is::
@ -2210,8 +2155,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: freefunc PyTypeObject.tp_free
.. corresponding-type-slot:: Py_tp_free
An optional pointer to an instance deallocation function. Its signature is::
void tp_free(void *self);
@ -2241,8 +2184,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: inquiry PyTypeObject.tp_is_gc
.. corresponding-type-slot:: Py_tp_is_gc
An optional pointer to a function called by the garbage collector.
The garbage collector needs to know whether a particular object is collectible
@ -2271,14 +2212,12 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: PyObject* PyTypeObject.tp_bases
.. corresponding-type-slot:: Py_tp_bases
Tuple of base types.
This field should be set to ``NULL`` and treated as read-only.
Python will fill it in when the type is :c:func:`initialized <PyType_Ready>`.
For dynamically created classes, the :c:data:`Py_tp_bases`
For dynamically created classes, the ``Py_tp_bases``
:c:type:`slot <PyType_Slot>` can be used instead of the *bases* argument
of :c:func:`PyType_FromSpecWithBases`.
The argument form is preferred.
@ -2353,8 +2292,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: destructor PyTypeObject.tp_del
.. corresponding-type-slot:: Py_tp_del
This field is deprecated. Use :c:member:`~PyTypeObject.tp_finalize` instead.
@ -2369,8 +2306,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: destructor PyTypeObject.tp_finalize
.. corresponding-type-slot:: Py_tp_finalize
An optional pointer to an instance finalization function. This is the C
implementation of the :meth:`~object.__del__` special method. Its signature
is::
@ -2529,8 +2464,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: vectorcallfunc PyTypeObject.tp_vectorcall
.. corresponding-type-slot:: Py_tp_vectorcall
A :ref:`vectorcall function <vectorcall>` to use for calls of this type
object (rather than instances).
In other words, ``tp_vectorcall`` can be used to optimize ``type.__call__``,
@ -2696,148 +2629,42 @@ Number Object Structures
Python 3.0.1.
.. c:member:: binaryfunc PyNumberMethods.nb_add
.. corresponding-type-slot:: Py_nb_add
.. c:member:: binaryfunc PyNumberMethods.nb_subtract
.. corresponding-type-slot:: Py_nb_subtract
.. c:member:: binaryfunc PyNumberMethods.nb_multiply
.. corresponding-type-slot:: Py_nb_multiply
.. c:member:: binaryfunc PyNumberMethods.nb_remainder
.. corresponding-type-slot:: Py_nb_remainder
.. c:member:: binaryfunc PyNumberMethods.nb_divmod
.. corresponding-type-slot:: Py_nb_divmod
.. c:member:: ternaryfunc PyNumberMethods.nb_power
.. corresponding-type-slot:: Py_nb_power
.. c:member:: unaryfunc PyNumberMethods.nb_negative
.. corresponding-type-slot:: Py_nb_negative
.. c:member:: unaryfunc PyNumberMethods.nb_positive
.. corresponding-type-slot:: Py_nb_positive
.. c:member:: unaryfunc PyNumberMethods.nb_absolute
.. corresponding-type-slot:: Py_nb_absolute
.. c:member:: inquiry PyNumberMethods.nb_bool
.. corresponding-type-slot:: Py_nb_bool
.. c:member:: unaryfunc PyNumberMethods.nb_invert
.. corresponding-type-slot:: Py_nb_invert
.. c:member:: binaryfunc PyNumberMethods.nb_lshift
.. corresponding-type-slot:: Py_nb_lshift
.. c:member:: binaryfunc PyNumberMethods.nb_rshift
.. corresponding-type-slot:: Py_nb_rshift
.. c:member:: binaryfunc PyNumberMethods.nb_and
.. corresponding-type-slot:: Py_nb_and
.. c:member:: binaryfunc PyNumberMethods.nb_xor
.. corresponding-type-slot:: Py_nb_xor
.. c:member:: binaryfunc PyNumberMethods.nb_or
.. corresponding-type-slot:: Py_nb_or
.. c:member:: unaryfunc PyNumberMethods.nb_int
.. corresponding-type-slot:: Py_nb_int
.. c:member:: void *PyNumberMethods.nb_reserved
.. c:member:: unaryfunc PyNumberMethods.nb_float
.. corresponding-type-slot:: Py_nb_float
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_add
.. corresponding-type-slot:: Py_nb_inplace_add
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_subtract
.. corresponding-type-slot:: Py_nb_inplace_subtract
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_multiply
.. corresponding-type-slot:: Py_nb_inplace_multiply
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_remainder
.. corresponding-type-slot:: Py_nb_inplace_remainder
.. c:member:: ternaryfunc PyNumberMethods.nb_inplace_power
.. corresponding-type-slot:: Py_nb_inplace_power
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_lshift
.. corresponding-type-slot:: Py_nb_inplace_lshift
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_rshift
.. corresponding-type-slot:: Py_nb_inplace_rshift
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_and
.. corresponding-type-slot:: Py_nb_inplace_and
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_xor
.. corresponding-type-slot:: Py_nb_inplace_xor
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_or
.. corresponding-type-slot:: Py_nb_inplace_or
.. c:member:: binaryfunc PyNumberMethods.nb_floor_divide
.. corresponding-type-slot:: Py_nb_floor_divide
.. c:member:: binaryfunc PyNumberMethods.nb_true_divide
.. corresponding-type-slot:: Py_nb_true_divide
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_floor_divide
.. corresponding-type-slot:: Py_nb_inplace_floor_divide
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_true_divide
.. corresponding-type-slot:: Py_nb_inplace_true_divide
.. c:member:: unaryfunc PyNumberMethods.nb_index
.. corresponding-type-slot:: Py_nb_index
.. c:member:: binaryfunc PyNumberMethods.nb_matrix_multiply
.. corresponding-type-slot:: Py_nb_matrix_multiply
.. c:member:: binaryfunc PyNumberMethods.nb_inplace_matrix_multiply
.. corresponding-type-slot:: Py_nb_inplace_matrix_multiply
.. _mapping-structs:
@ -2854,16 +2681,12 @@ Mapping Object Structures
.. c:member:: lenfunc PyMappingMethods.mp_length
.. corresponding-type-slot:: Py_mp_length
This function is used by :c:func:`PyMapping_Size` and
:c:func:`PyObject_Size`, and has the same signature. This slot may be set to
``NULL`` if the object has no defined length.
.. c:member:: binaryfunc PyMappingMethods.mp_subscript
.. corresponding-type-slot:: Py_mp_subscript
This function is used by :c:func:`PyObject_GetItem` and
:c:func:`PySequence_GetSlice`, and has the same signature as
:c:func:`!PyObject_GetItem`. This slot must be filled for the
@ -2872,8 +2695,6 @@ Mapping Object Structures
.. c:member:: objobjargproc PyMappingMethods.mp_ass_subscript
.. corresponding-type-slot:: Py_mp_ass_subscript
This function is used by :c:func:`PyObject_SetItem`,
:c:func:`PyObject_DelItem`, :c:func:`PySequence_SetSlice` and
:c:func:`PySequence_DelSlice`. It has the same signature as
@ -2897,8 +2718,6 @@ Sequence Object Structures
.. c:member:: lenfunc PySequenceMethods.sq_length
.. corresponding-type-slot:: Py_sq_length
This function is used by :c:func:`PySequence_Size` and
:c:func:`PyObject_Size`, and has the same signature. It is also used for
handling negative indices via the :c:member:`~PySequenceMethods.sq_item`
@ -2906,24 +2725,18 @@ Sequence Object Structures
.. c:member:: binaryfunc PySequenceMethods.sq_concat
.. corresponding-type-slot:: Py_sq_concat
This function is used by :c:func:`PySequence_Concat` and has the same
signature. It is also used by the ``+`` operator, after trying the numeric
addition via the :c:member:`~PyNumberMethods.nb_add` slot.
.. c:member:: ssizeargfunc PySequenceMethods.sq_repeat
.. corresponding-type-slot:: Py_sq_repeat
This function is used by :c:func:`PySequence_Repeat` and has the same
signature. It is also used by the ``*`` operator, after trying numeric
multiplication via the :c:member:`~PyNumberMethods.nb_multiply` slot.
.. c:member:: ssizeargfunc PySequenceMethods.sq_item
.. corresponding-type-slot:: Py_sq_item
This function is used by :c:func:`PySequence_GetItem` and has the same
signature. It is also used by :c:func:`PyObject_GetItem`, after trying
the subscription via the :c:member:`~PyMappingMethods.mp_subscript` slot.
@ -2937,8 +2750,6 @@ Sequence Object Structures
.. c:member:: ssizeobjargproc PySequenceMethods.sq_ass_item
.. corresponding-type-slot:: Py_sq_ass_item
This function is used by :c:func:`PySequence_SetItem` and has the same
signature. It is also used by :c:func:`PyObject_SetItem` and
:c:func:`PyObject_DelItem`, after trying the item assignment and deletion
@ -2948,8 +2759,6 @@ Sequence Object Structures
.. c:member:: objobjproc PySequenceMethods.sq_contains
.. corresponding-type-slot:: Py_sq_contains
This function may be used by :c:func:`PySequence_Contains` and has the same
signature. This slot may be left to ``NULL``, in this case
:c:func:`!PySequence_Contains` simply traverses the sequence until it
@ -2957,8 +2766,6 @@ Sequence Object Structures
.. c:member:: binaryfunc PySequenceMethods.sq_inplace_concat
.. corresponding-type-slot:: Py_sq_inplace_concat
This function is used by :c:func:`PySequence_InPlaceConcat` and has the same
signature. It should modify its first operand, and return it. This slot
may be left to ``NULL``, in this case :c:func:`!PySequence_InPlaceConcat`
@ -2968,8 +2775,6 @@ Sequence Object Structures
.. c:member:: ssizeargfunc PySequenceMethods.sq_inplace_repeat
.. corresponding-type-slot:: Py_sq_inplace_repeat
This function is used by :c:func:`PySequence_InPlaceRepeat` and has the same
signature. It should modify its first operand, and return it. This slot
may be left to ``NULL``, in this case :c:func:`!PySequence_InPlaceRepeat`
@ -2995,8 +2800,6 @@ Buffer Object Structures
.. c:member:: getbufferproc PyBufferProcs.bf_getbuffer
.. corresponding-type-slot:: Py_bf_getbuffer
The signature of this function is::
int (PyObject *exporter, Py_buffer *view, int flags);
@ -3046,8 +2849,6 @@ Buffer Object Structures
.. c:member:: releasebufferproc PyBufferProcs.bf_releasebuffer
.. corresponding-type-slot:: Py_bf_releasebuffer
The signature of this function is::
void (PyObject *exporter, Py_buffer *view);
@ -3102,8 +2903,6 @@ Async Object Structures
.. c:member:: unaryfunc PyAsyncMethods.am_await
.. corresponding-type-slot:: Py_am_await
The signature of this function is::
PyObject *am_await(PyObject *self);
@ -3115,8 +2914,6 @@ Async Object Structures
.. c:member:: unaryfunc PyAsyncMethods.am_aiter
.. corresponding-type-slot:: Py_am_aiter
The signature of this function is::
PyObject *am_aiter(PyObject *self);
@ -3129,8 +2926,6 @@ Async Object Structures
.. c:member:: unaryfunc PyAsyncMethods.am_anext
.. corresponding-type-slot:: Py_am_anext
The signature of this function is::
PyObject *am_anext(PyObject *self);
@ -3141,8 +2936,6 @@ Async Object Structures
.. c:member:: sendfunc PyAsyncMethods.am_send
.. corresponding-type-slot:: Py_am_send
The signature of this function is::
PySendResult am_send(PyObject *self, PyObject *arg, PyObject **result);

View file

@ -321,22 +321,12 @@ These APIs can be used to work with surrogates:
Check if *ch* is a low surrogate (``0xDC00 <= ch <= 0xDFFF``).
.. c:function:: Py_UCS4 Py_UNICODE_HIGH_SURROGATE(Py_UCS4 ch)
Return the high UTF-16 surrogate (``0xD800`` to ``0xDBFF``) for a Unicode
code point in the range ``[0x10000; 0x10FFFF]``.
.. c:function:: Py_UCS4 Py_UNICODE_LOW_SURROGATE(Py_UCS4 ch)
Return the low UTF-16 surrogate (``0xDC00`` to ``0xDFFF``) for a Unicode
code point in the range ``[0x10000; 0x10FFFF]``.
.. c:function:: Py_UCS4 Py_UNICODE_JOIN_SURROGATES(Py_UCS4 high, Py_UCS4 low)
Join two surrogate code points and return a single :c:type:`Py_UCS4` value.
*high* and *low* are respectively the leading and trailing surrogates in a
surrogate pair. *high* must be in the range ``[0xD800; 0xDBFF]`` and *low* must
be in the range ``[0xDC00; 0xDFFF]``.
surrogate pair. *high* must be in the range [0xD800; 0xDBFF] and *low* must
be in the range [0xDC00; 0xDFFF].
Creating and accessing Unicode strings

View file

@ -13,9 +13,8 @@ the interpreter.
Several of these functions accept a start symbol from the grammar as a
parameter. The available start symbols are :c:data:`Py_eval_input`,
:c:data:`Py_file_input`, :c:data:`Py_single_input`, and
:c:data:`Py_func_type_input`. These are described following the functions
which accept them as parameters.
:c:data:`Py_file_input`, and :c:data:`Py_single_input`. These are described
following the functions which accept them as parameters.
Note also that several of these functions take :c:expr:`FILE*` parameters. One
particular issue which needs to be handled carefully is that the :c:type:`FILE`
@ -100,20 +99,6 @@ the same library that the Python runtime is using.
Otherwise, Python may not handle script file with LF line ending correctly.
.. c:function:: int PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)
Read and execute a single statement from a file associated with an
interactive device according to the *flags* argument. The user will be
prompted using ``sys.ps1`` and ``sys.ps2``. *filename* must be a Python
:class:`str` object.
Returns ``0`` when the input was
executed successfully, ``-1`` if there was an exception, or an error code
from the :file:`errcode.h` include file distributed as part of Python if
there was a parse error. (Note that :file:`errcode.h` is not included by
:file:`Python.h`, so must be included specifically if needed.)
.. c:function:: int PyRun_InteractiveOne(FILE *fp, const char *filename)
This is a simplified interface to :c:func:`PyRun_InteractiveOneFlags` below,
@ -122,10 +107,17 @@ the same library that the Python runtime is using.
.. c:function:: int PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
Similar to :c:func:`PyRun_InteractiveOneObject`, but *filename* is a
:c:expr:`const char*`, which is decoded from the
Read and execute a single statement from a file associated with an
interactive device according to the *flags* argument. The user will be
prompted using ``sys.ps1`` and ``sys.ps2``. *filename* is decoded from the
:term:`filesystem encoding and error handler`.
Returns ``0`` when the input was
executed successfully, ``-1`` if there was an exception, or an error code
from the :file:`errcode.h` include file distributed as part of Python if
there was a parse error. (Note that :file:`errcode.h` is not included by
:file:`Python.h`, so must be included specifically if needed.)
.. c:function:: int PyRun_InteractiveLoop(FILE *fp, const char *filename)
@ -148,7 +140,7 @@ the same library that the Python runtime is using.
interpreter prompt is about to become idle and wait for user input
from the terminal. The return value is ignored. Overriding this
hook can be used to integrate the interpreter's prompt with other
event loops, as done in :file:`Modules/_tkinter.c` in the
event loops, as done in the :file:`Modules/_tkinter.c` in the
Python source code.
.. versionchanged:: 3.12
@ -191,7 +183,8 @@ the same library that the Python runtime is using.
objects *globals* and *locals* with the compiler flags specified by
*flags*. *globals* must be a dictionary; *locals* can be any object
that implements the mapping protocol. The parameter *start* specifies
the start symbol and must one of the :ref:`available start symbols <start-symbols>`.
the start symbol and must one of the following:
:c:data:`Py_eval_input`, :c:data:`Py_file_input`, or :c:data:`Py_single_input`.
Returns the result of executing the code as a Python object, or ``NULL`` if an
exception was raised.
@ -240,8 +233,8 @@ the same library that the Python runtime is using.
Parse and compile the Python source code in *str*, returning the resulting code
object. The start symbol is given by *start*; this can be used to constrain the
code which can be compiled and should be :ref:`available start symbols
<start-symbols>`. The filename specified by
code which can be compiled and should be :c:data:`Py_eval_input`,
:c:data:`Py_file_input`, or :c:data:`Py_single_input`. The filename specified by
*filename* is used to construct the code object and may appear in tracebacks or
:exc:`SyntaxError` exception messages. This returns ``NULL`` if the code
cannot be parsed or compiled.
@ -304,6 +297,32 @@ the same library that the Python runtime is using.
true on success, false on failure.
.. c:var:: int Py_eval_input
.. index:: single: Py_CompileString (C function)
The start symbol from the Python grammar for isolated expressions; for use with
:c:func:`Py_CompileString`.
.. c:var:: int Py_file_input
.. index:: single: Py_CompileString (C function)
The start symbol from the Python grammar for sequences of statements as read
from a file or other source; for use with :c:func:`Py_CompileString`. This is
the symbol to use when compiling arbitrarily long Python source code.
.. c:var:: int Py_single_input
.. index:: single: Py_CompileString (C function)
The start symbol from the Python grammar for a single statement; for use with
:c:func:`Py_CompileString`. This is the symbol used for the interactive
interpreter loop.
.. c:struct:: PyCompilerFlags
This is the structure used to hold compiler flags. In cases where code is only
@ -347,92 +366,3 @@ the same library that the Python runtime is using.
as :c:macro:`CO_FUTURE_ANNOTATIONS` to enable features normally
selectable using :ref:`future statements <future>`.
See :ref:`c_codeobject_flags` for a complete list.
.. _start-symbols:
Available start symbols
^^^^^^^^^^^^^^^^^^^^^^^
.. c:var:: int Py_eval_input
.. index:: single: Py_CompileString (C function)
The start symbol from the Python grammar for isolated expressions; for use with
:c:func:`Py_CompileString`.
.. c:var:: int Py_file_input
.. index:: single: Py_CompileString (C function)
The start symbol from the Python grammar for sequences of statements as read
from a file or other source; for use with :c:func:`Py_CompileString`. This is
the symbol to use when compiling arbitrarily long Python source code.
.. c:var:: int Py_single_input
.. index:: single: Py_CompileString (C function)
The start symbol from the Python grammar for a single statement; for use with
:c:func:`Py_CompileString`. This is the symbol used for the interactive
interpreter loop.
.. c:var:: int Py_func_type_input
.. index:: single: Py_CompileString (C function)
The start symbol from the Python grammar for a function type; for use with
:c:func:`Py_CompileString`. This is used to parse "signature type comments"
from :pep:`484`.
This requires the :c:macro:`PyCF_ONLY_AST` flag to be set.
.. seealso::
* :py:class:`ast.FunctionType`
* :pep:`484`
.. versionadded:: 3.8
Stack Effects
^^^^^^^^^^^^^
.. seealso::
:py:func:`dis.stack_effect`
.. c:macro:: PY_INVALID_STACK_EFFECT
Sentinel value representing an invalid stack effect.
This is currently equivalent to ``INT_MAX``.
.. versionadded:: 3.8
.. c:function:: int PyCompile_OpcodeStackEffect(int opcode, int oparg)
Compute the stack effect of *opcode* with argument *oparg*.
On success, this function returns the stack effect; on failure, this
returns :c:macro:`PY_INVALID_STACK_EFFECT`.
.. versionadded:: 3.4
.. c:function:: int PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump)
Similar to :c:func:`PyCompile_OpcodeStackEffect`, but don't include the
stack effect of jumping if *jump* is zero.
If *jump* is ``0``, this will not include the stack effect of jumping, but
if *jump* is ``1`` or ``-1``, this will include it.
On success, this function returns the stack effect; on failure, this
returns :c:macro:`PY_INVALID_STACK_EFFECT`.
.. versionadded:: 3.8

View file

@ -19,14 +19,7 @@ as much as it can.
.. c:function:: int PyWeakref_CheckRef(PyObject *ob)
Return non-zero if *ob* is a reference object or a subclass of the reference
type. This function always succeeds.
.. c:function:: int PyWeakref_CheckRefExact(PyObject *ob)
Return non-zero if *ob* is a reference object, but not a subclass of the
reference type. This function always succeeds.
Return non-zero if *ob* is a reference object. This function always succeeds.
.. c:function:: int PyWeakref_CheckProxy(PyObject *ob)
@ -45,10 +38,6 @@ as much as it can.
weakly referenceable object, or if *callback* is not callable, ``None``, or
``NULL``, this will return ``NULL`` and raise :exc:`TypeError`.
.. seealso::
:c:func:`PyType_SUPPORTS_WEAKREFS` for checking if *ob* is weakly
referenceable.
.. c:function:: PyObject* PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
@ -61,10 +50,6 @@ as much as it can.
is not a weakly referenceable object, or if *callback* is not callable,
``None``, or ``NULL``, this will return ``NULL`` and raise :exc:`TypeError`.
.. seealso::
:c:func:`PyType_SUPPORTS_WEAKREFS` for checking if *ob* is weakly
referenceable.
.. c:function:: int PyWeakref_GetRef(PyObject *ref, PyObject **pobj)

View file

@ -226,6 +226,9 @@ nitpick_ignore = [
# Temporary undocumented names.
# In future this list must be empty.
nitpick_ignore += [
# Undocumented public C macros
('c:macro', 'Py_BUILD_ASSERT'),
('c:macro', 'Py_BUILD_ASSERT_EXPR'),
# Do not error nit-picky mode builds when _SubParsersAction.add_parser cannot
# be resolved, as the method is currently undocumented. For context, see
# https://github.com/python/cpython/pull/103289.
@ -356,12 +359,11 @@ latex_elements = {
'papersize': 'a4paper',
# The font size ('10pt', '11pt' or '12pt').
'pointsize': '10pt',
'maxlistdepth': '8', # See https://github.com/python/cpython/issues/139588
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
_stdauthor = 'The Python development team'
_stdauthor = 'Guido van Rossum and the Python development team'
latex_documents = [
('c-api/index', 'c-api.tex', 'The Python/C API', _stdauthor, 'manual'),
(
@ -436,36 +438,12 @@ latex_appendices = ['glossary', 'about', 'license', 'copyright']
epub_author = 'Python Documentation Authors'
epub_publisher = 'Python Software Foundation'
epub_exclude_files = (
'index.xhtml',
'download.xhtml',
'_static/tachyon-example-flamegraph.html',
'_static/tachyon-example-heatmap.html',
)
epub_exclude_files = ('index.xhtml', 'download.xhtml')
# index pages are not valid xhtml
# https://github.com/sphinx-doc/sphinx/issues/12359
epub_use_index = False
# translation tag
# ---------------
language_code = None
for arg in sys.argv:
if arg.startswith('language='):
language_code = arg.split('=', 1)[1]
if language_code:
tags.add('translation') # noqa: F821
rst_epilog += f"""\
.. _TRANSLATION_REPO: https://github.com/python/python-docs-{language_code.replace("_", "-").lower()}
""" # noqa: F821
else:
rst_epilog += """\
.. _TRANSLATION_REPO: https://github.com/python
"""
# Options for the coverage checker
# --------------------------------

View file

@ -1472,9 +1472,6 @@ PyModule_Create2:PyObject*::+1:
PyModule_Create2:PyModuleDef*:def::
PyModule_Create2:int:module_api_version::
PyModule_Exec:int:::
PyModule_ExecDef:PyObject*:module:0:
PyModule_ExecDef:int:::
PyModule_ExecDef:PyObject*:module:0:
PyModule_ExecDef:PyModuleDef*:def::
@ -1488,10 +1485,6 @@ PyModule_FromDefAndSpec2:PyModuleDef*:def::
PyModule_FromDefAndSpec2:PyObject*:spec:0:
PyModule_FromDefAndSpec2:int:module_api_version::
PyModule_FromSlotsAndSpec:PyObject*::+1:
PyModule_FromSlotsAndSpec:const PyModuleDef_Slot *:slots::
PyModule_FromSlotsAndSpec:PyObject*:spec:0:
PyModule_GetDef:PyModuleDef*::0:
PyModule_GetDef:PyObject*:module:0:
@ -1513,14 +1506,6 @@ PyModule_GetNameObject:PyObject*:module:0:
PyModule_GetState:void*:::
PyModule_GetState:PyObject*:module:0:
PyModule_GetStateSize:int:::
PyModule_GetStateSize:PyObject*:module:0:
PyModule_GetToken:Py_ssize_t**:result::
PyModule_GetToken:int:::
PyModule_GetToken:PyObject*:module:0:
PyModule_GetToken:void**:result::
PyModule_New:PyObject*::+1:
PyModule_New:char*:name::
@ -2427,10 +2412,6 @@ PyType_GetFlags:PyTypeObject*:type:0:
PyType_GetName:PyObject*::+1:
PyType_GetName:PyTypeObject*:type:0:
PyType_GetModuleByToken:PyObject*::+1:
PyType_GetModuleByToken:PyTypeObject*:type:0:
PyType_GetModuleByToken:PyModuleDef*:def::
PyType_GetModuleByDef:PyObject*::0:
PyType_GetModuleByDef:PyTypeObject*:type:0:
PyType_GetModuleByDef:PyModuleDef*:def::

176
Doc/data/stable_abi.dat generated
View file

@ -1,21 +1,7 @@
role,name,added,ifdef_note,struct_abi_kind
macro,METH_CLASS,3.2,,
macro,METH_COEXIST,3.2,,
macro,METH_FASTCALL,3.7,,
macro,METH_METHOD,3.7,,
macro,METH_NOARGS,3.2,,
macro,METH_O,3.2,,
macro,METH_STATIC,3.2,,
macro,METH_VARARGS,3.2,,
macro,PY_VECTORCALL_ARGUMENTS_OFFSET,3.12,,
type,PyABIInfo,3.15,,full-abi
func,PyABIInfo_Check,3.15,,
macro,PyABIInfo_DEFAULT_ABI_VERSION,3.15,,
macro,PyABIInfo_DEFAULT_FLAGS,3.15,,
macro,PyABIInfo_FREETHREADED,3.15,,
macro,PyABIInfo_FREETHREADING_AGNOSTIC,3.15,,
macro,PyABIInfo_GIL,3.15,,
macro,PyABIInfo_STABLE,3.15,,
macro,PyABIInfo_VAR,3.15,,
func,PyAIter_Check,3.10,,
func,PyArg_Parse,3.2,,
@ -25,26 +11,6 @@ func,PyArg_UnpackTuple,3.2,,
func,PyArg_VaParse,3.2,,
func,PyArg_VaParseTupleAndKeywords,3.2,,
func,PyArg_ValidateKeywordArguments,3.2,,
macro,PyBUF_ANY_CONTIGUOUS,3.11,,
macro,PyBUF_CONTIG,3.11,,
macro,PyBUF_CONTIG_RO,3.11,,
macro,PyBUF_C_CONTIGUOUS,3.11,,
macro,PyBUF_FORMAT,3.11,,
macro,PyBUF_FULL,3.11,,
macro,PyBUF_FULL_RO,3.11,,
macro,PyBUF_F_CONTIGUOUS,3.11,,
macro,PyBUF_INDIRECT,3.11,,
macro,PyBUF_MAX_NDIM,3.11,,
macro,PyBUF_ND,3.11,,
macro,PyBUF_READ,3.11,,
macro,PyBUF_RECORDS,3.11,,
macro,PyBUF_RECORDS_RO,3.11,,
macro,PyBUF_SIMPLE,3.11,,
macro,PyBUF_STRIDED,3.11,,
macro,PyBUF_STRIDED_RO,3.11,,
macro,PyBUF_STRIDES,3.11,,
macro,PyBUF_WRITABLE,3.11,,
macro,PyBUF_WRITE,3.11,,
data,PyBaseObject_Type,3.2,,
func,PyBool_FromLong,3.2,,
data,PyBool_Type,3.2,,
@ -160,7 +126,6 @@ func,PyDict_Merge,3.2,,
func,PyDict_MergeFromSeq2,3.2,,
func,PyDict_New,3.2,,
func,PyDict_Next,3.2,,
func,PyDict_SetDefaultRef,3.15,,
func,PyDict_SetItem,3.2,,
func,PyDict_SetItemString,3.2,,
func,PyDict_Size,3.2,,
@ -426,7 +391,6 @@ func,PyLong_FromUnsignedNativeBytes,3.14,,
func,PyLong_FromVoidPtr,3.2,,
func,PyLong_GetInfo,3.2,,
data,PyLong_Type,3.2,,
macro,PyMODEXPORT_FUNC,3.15,,
data,PyMap_Type,3.2,,
func,PyMapping_Check,3.2,,
func,PyMapping_GetItemString,3.2,,
@ -464,7 +428,6 @@ data,PyMethodDescr_Type,3.2,,
type,PyModuleDef,3.2,,full-abi
type,PyModuleDef_Base,3.2,,full-abi
func,PyModuleDef_Init,3.5,,
type,PyModuleDef_Slot,3.5,,full-abi
data,PyModuleDef_Type,3.5,,
func,PyModule_Add,3.13,,
func,PyModule_AddFunctions,3.7,,
@ -474,10 +437,8 @@ func,PyModule_AddObjectRef,3.10,,
func,PyModule_AddStringConstant,3.2,,
func,PyModule_AddType,3.10,,
func,PyModule_Create2,3.2,,
func,PyModule_Exec,3.15,,
func,PyModule_ExecDef,3.7,,
func,PyModule_FromDefAndSpec2,3.7,,
func,PyModule_FromSlotsAndSpec,3.15,,
func,PyModule_GetDef,3.2,,
func,PyModule_GetDict,3.2,,
func,PyModule_GetFilename,3.2,,
@ -485,8 +446,6 @@ func,PyModule_GetFilenameObject,3.2,,
func,PyModule_GetName,3.2,,
func,PyModule_GetNameObject,3.7,,
func,PyModule_GetState,3.2,,
func,PyModule_GetStateSize,3.15,,
func,PyModule_GetToken,3.15,,
func,PyModule_New,3.2,,
func,PyModule_NewObject,3.7,,
func,PyModule_SetDocString,3.7,,
@ -745,7 +704,6 @@ func,PyType_GetFlags,3.2,,
func,PyType_GetFullyQualifiedName,3.13,,
func,PyType_GetModule,3.10,,
func,PyType_GetModuleByDef,3.13,,
func,PyType_GetModuleByToken,3.15,,
func,PyType_GetModuleName,3.13,,
func,PyType_GetModuleState,3.10,,
func,PyType_GetName,3.11,,
@ -878,14 +836,6 @@ func,PyWeakref_NewRef,3.2,,
data,PyWrapperDescr_Type,3.2,,
func,PyWrapper_New,3.2,,
data,PyZip_Type,3.2,,
macro,Py_ASNATIVEBYTES_ALLOW_INDEX,3.14,,
macro,Py_ASNATIVEBYTES_BIG_ENDIAN,3.14,,
macro,Py_ASNATIVEBYTES_DEFAULTS,3.14,,
macro,Py_ASNATIVEBYTES_LITTLE_ENDIAN,3.14,,
macro,Py_ASNATIVEBYTES_NATIVE_ENDIAN,3.14,,
macro,Py_ASNATIVEBYTES_REJECT_NEGATIVE,3.14,,
macro,Py_ASNATIVEBYTES_UNSIGNED_BUFFER,3.14,,
macro,Py_AUDIT_READ,3.12,,
func,Py_AddPendingCall,3.2,,
func,Py_AtExit,3.2,,
macro,Py_BEGIN_ALLOW_THREADS,3.2,,
@ -916,7 +866,6 @@ func,Py_GetPlatform,3.2,,
func,Py_GetRecursionLimit,3.2,,
func,Py_GetVersion,3.2,,
data,Py_HasFileSystemDefaultEncoding,3.2,,
func,Py_IS_TYPE,3.15,,
func,Py_IncRef,3.2,,
func,Py_Initialize,3.2,,
func,Py_InitializeEx,3.2,,
@ -933,147 +882,22 @@ func,Py_NewInterpreter,3.2,,
func,Py_NewRef,3.10,,
func,Py_PACK_FULL_VERSION,3.14,,
func,Py_PACK_VERSION,3.14,,
macro,Py_READONLY,3.12,,
func,Py_REFCNT,3.14,,
macro,Py_RELATIVE_OFFSET,3.12,,
func,Py_ReprEnter,3.2,,
func,Py_ReprLeave,3.2,,
func,Py_SET_SIZE,3.15,,
func,Py_SIZE,3.15,,
func,Py_SetProgramName,3.2,,
func,Py_SetPythonHome,3.2,,
func,Py_SetRecursionLimit,3.2,,
macro,Py_TPFLAGS_BASETYPE,3.2,,
macro,Py_TPFLAGS_DEFAULT,3.2,,
macro,Py_TPFLAGS_HAVE_GC,3.2,,
macro,Py_TPFLAGS_HAVE_VECTORCALL,3.12,,
macro,Py_TPFLAGS_ITEMS_AT_END,3.12,,
macro,Py_TPFLAGS_METHOD_DESCRIPTOR,3.8,,
macro,Py_TP_USE_SPEC,3.14,,
func,Py_TYPE,3.14,,
macro,Py_T_BOOL,3.12,,
macro,Py_T_BYTE,3.12,,
macro,Py_T_CHAR,3.12,,
macro,Py_T_DOUBLE,3.12,,
macro,Py_T_FLOAT,3.12,,
macro,Py_T_INT,3.12,,
macro,Py_T_LONG,3.12,,
macro,Py_T_LONGLONG,3.12,,
macro,Py_T_OBJECT_EX,3.12,,
macro,Py_T_PYSSIZET,3.12,,
macro,Py_T_SHORT,3.12,,
macro,Py_T_STRING,3.12,,
macro,Py_T_STRING_INPLACE,3.12,,
macro,Py_T_UBYTE,3.12,,
macro,Py_T_UINT,3.12,,
macro,Py_T_ULONG,3.12,,
macro,Py_T_ULONGLONG,3.12,,
macro,Py_T_USHORT,3.12,,
type,Py_UCS4,3.2,,
macro,Py_UNBLOCK_THREADS,3.2,,
data,Py_UTF8Mode,3.8,,
func,Py_VaBuildValue,3.2,,
data,Py_Version,3.11,,
func,Py_XNewRef,3.10,,
macro,Py_am_aiter,3.5,,
macro,Py_am_anext,3.5,,
macro,Py_am_await,3.5,,
macro,Py_am_send,3.10,,
macro,Py_bf_getbuffer,3.11,,
macro,Py_bf_releasebuffer,3.11,,
type,Py_buffer,3.11,,full-abi
type,Py_intptr_t,3.2,,
macro,Py_mod_abi,3.15,,
macro,Py_mod_create,3.5,,
macro,Py_mod_doc,3.15,,
macro,Py_mod_exec,3.5,,
macro,Py_mod_gil,3.13,,
macro,Py_mod_methods,3.15,,
macro,Py_mod_multiple_interpreters,3.12,,
macro,Py_mod_name,3.15,,
macro,Py_mod_state_clear,3.15,,
macro,Py_mod_state_free,3.15,,
macro,Py_mod_state_size,3.15,,
macro,Py_mod_state_traverse,3.15,,
macro,Py_mod_token,3.15,,
macro,Py_mp_ass_subscript,3.2,,
macro,Py_mp_length,3.2,,
macro,Py_mp_subscript,3.2,,
macro,Py_nb_absolute,3.2,,
macro,Py_nb_add,3.2,,
macro,Py_nb_and,3.2,,
macro,Py_nb_bool,3.2,,
macro,Py_nb_divmod,3.2,,
macro,Py_nb_float,3.2,,
macro,Py_nb_floor_divide,3.2,,
macro,Py_nb_index,3.2,,
macro,Py_nb_inplace_add,3.2,,
macro,Py_nb_inplace_and,3.2,,
macro,Py_nb_inplace_floor_divide,3.2,,
macro,Py_nb_inplace_lshift,3.2,,
macro,Py_nb_inplace_matrix_multiply,3.5,,
macro,Py_nb_inplace_multiply,3.2,,
macro,Py_nb_inplace_or,3.2,,
macro,Py_nb_inplace_power,3.2,,
macro,Py_nb_inplace_remainder,3.2,,
macro,Py_nb_inplace_rshift,3.2,,
macro,Py_nb_inplace_subtract,3.2,,
macro,Py_nb_inplace_true_divide,3.2,,
macro,Py_nb_inplace_xor,3.2,,
macro,Py_nb_int,3.2,,
macro,Py_nb_invert,3.2,,
macro,Py_nb_lshift,3.2,,
macro,Py_nb_matrix_multiply,3.5,,
macro,Py_nb_multiply,3.2,,
macro,Py_nb_negative,3.2,,
macro,Py_nb_or,3.2,,
macro,Py_nb_positive,3.2,,
macro,Py_nb_power,3.2,,
macro,Py_nb_remainder,3.2,,
macro,Py_nb_rshift,3.2,,
macro,Py_nb_subtract,3.2,,
macro,Py_nb_true_divide,3.2,,
macro,Py_nb_xor,3.2,,
macro,Py_sq_ass_item,3.2,,
macro,Py_sq_concat,3.2,,
macro,Py_sq_contains,3.2,,
macro,Py_sq_inplace_concat,3.2,,
macro,Py_sq_inplace_repeat,3.2,,
macro,Py_sq_item,3.2,,
macro,Py_sq_length,3.2,,
macro,Py_sq_repeat,3.2,,
type,Py_ssize_t,3.2,,
macro,Py_tp_alloc,3.2,,
macro,Py_tp_base,3.2,,
macro,Py_tp_bases,3.2,,
macro,Py_tp_call,3.2,,
macro,Py_tp_clear,3.2,,
macro,Py_tp_dealloc,3.2,,
macro,Py_tp_del,3.2,,
macro,Py_tp_descr_get,3.2,,
macro,Py_tp_descr_set,3.2,,
macro,Py_tp_doc,3.2,,
macro,Py_tp_finalize,3.5,,
macro,Py_tp_free,3.2,,
macro,Py_tp_getattr,3.2,,
macro,Py_tp_getattro,3.2,,
macro,Py_tp_getset,3.2,,
macro,Py_tp_hash,3.2,,
macro,Py_tp_init,3.2,,
macro,Py_tp_is_gc,3.2,,
macro,Py_tp_iter,3.2,,
macro,Py_tp_iternext,3.2,,
macro,Py_tp_members,3.2,,
macro,Py_tp_methods,3.2,,
macro,Py_tp_new,3.2,,
macro,Py_tp_repr,3.2,,
macro,Py_tp_richcompare,3.2,,
macro,Py_tp_setattr,3.2,,
macro,Py_tp_setattro,3.2,,
macro,Py_tp_str,3.2,,
macro,Py_tp_token,3.14,,
macro,Py_tp_traverse,3.2,,
macro,Py_tp_vectorcall,3.14,,
type,Py_uintptr_t,3.2,,
type,allocfunc,3.2,,
type,binaryfunc,3.2,,

View file

@ -1,16 +1,7 @@
Pending removal in Python 3.20
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* :c:func:`!_PyObject_CallMethodId`, :c:func:`!_PyObject_GetAttrId` and
:c:func:`!_PyUnicode_FromId` are deprecated since 3.15 and will be removed in
3.20. Instead, use :c:func:`PyUnicode_InternFromString()` and cache the result in
the module state, then call :c:func:`PyObject_CallMethod` or
:c:func:`PyObject_GetAttr`.
(Contributed by Victor Stinner in :gh:`141049`.)
* The ``cval`` field in :c:type:`PyComplexObject` (:gh:`128813`).
Use :c:func:`PyComplex_AsCComplex` and :c:func:`PyComplex_FromCComplex`
to convert a Python complex number to/from the C :c:type:`Py_complex`
representation.
* Macros :c:macro:`!Py_MATH_PIl` and :c:macro:`!Py_MATH_El`.

View file

@ -38,3 +38,15 @@ APIs:
* :meth:`!unittest.TestProgram.usageExit` (:gh:`67048`)
* :class:`!webbrowser.MacOSX` (:gh:`86421`)
* :class:`classmethod` descriptor chaining (:gh:`89519`)
* :mod:`importlib.resources` deprecated methods:
* ``contents()``
* ``is_resource()``
* ``open_binary()``
* ``open_text()``
* ``path()``
* ``read_binary()``
* ``read_text()``
Use :func:`importlib.resources.files` instead. Refer to `importlib-resources: Migrating from Legacy
<https://importlib-resources.readthedocs.io/en/latest/using.html#migrating-from-legacy>`_ (:gh:`106531`)

View file

@ -3,9 +3,9 @@ Pending removal in Python 3.15
* The import system:
* Setting ``__cached__`` on a module while
* Setting :attr:`~module.__cached__` on a module while
failing to set :attr:`__spec__.cached <importlib.machinery.ModuleSpec.cached>`
is deprecated. In Python 3.15, ``__cached__`` will cease to be set or
is deprecated. In Python 3.15, :attr:`!__cached__` will cease to be set or
take into consideration by the import system or standard library. (:gh:`97879`)
* Setting :attr:`~module.__package__` on a module while
@ -92,7 +92,7 @@ Pending removal in Python 3.15
Use ``class TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})``
to create a TypedDict with zero field.
* The :func:`!typing.no_type_check_decorator` decorator function
* The :func:`typing.no_type_check_decorator` decorator function
has been deprecated since Python 3.13.
After eight years in the :mod:`typing` module,
it has yet to be supported by any major type checker.

View file

@ -63,9 +63,9 @@ Pending removal in Python 3.16
* :mod:`logging`:
* Support for custom logging handlers with the *strm* argument is deprecated
and scheduled for removal in Python 3.16. Define handlers with the *stream*
argument instead. (Contributed by Mariusz Felisiak in :gh:`115032`.)
Support for custom logging handlers with the *strm* argument is deprecated
and scheduled for removal in Python 3.16. Define handlers with the *stream*
argument instead. (Contributed by Mariusz Felisiak in :gh:`115032`.)
* :mod:`mimetypes`:

View file

@ -23,12 +23,6 @@ Pending removal in Python 3.17
(Contributed by Shantanu Jain in :gh:`91896`.)
* :mod:`encodings`:
- Passing non-ascii *encoding* names to :func:`encodings.normalize_encoding`
is deprecated and scheduled for removal in Python 3.17.
(Contributed by Stan Ulbrych in :gh:`136702`)
* :mod:`typing`:
- Before Python 3.14, old-style unions were implemented using the private class

View file

@ -1,17 +1,13 @@
Pending removal in Python 3.20
------------------------------
* The ``__version__``, ``version`` and ``VERSION`` attributes have been
deprecated in these standard library modules and will be removed in
Python 3.20. Use :py:data:`sys.version_info` instead.
* The ``__version__`` attribute has been deprecated in these standard library
modules and will be removed in Python 3.20.
Use :py:data:`sys.version_info` instead.
- :mod:`argparse`
- :mod:`csv`
- :mod:`ctypes`
- :mod:`!ctypes.macholib`
- :mod:`decimal` (use :data:`decimal.SPEC_VERSION` instead)
- :mod:`http.server`
- :mod:`imaplib`
- :mod:`ipaddress`
- :mod:`json`
- :mod:`logging` (``__date__`` also deprecated)
@ -23,10 +19,5 @@ Pending removal in Python 3.20
- :mod:`tabnanny`
- :mod:`tkinter.font`
- :mod:`tkinter.ttk`
- :mod:`wsgiref.simple_server`
- :mod:`xml.etree.ElementTree`
- :mod:`!xml.sax.expatreader`
- :mod:`xml.sax.handler`
- :mod:`zlib`
(Contributed by Hugo van Kemenade and Stan Ulbrych in :gh:`76007`.)
(Contributed by Hugo van Kemenade in :gh:`76007`.)

View file

@ -76,7 +76,7 @@ although there is currently no date scheduled for their removal.
* :mod:`mailbox`: Use of StringIO input and text mode is deprecated, use
BytesIO and binary mode instead.
* :mod:`os`: Calling :func:`os.register_at_fork` in a multi-threaded process.
* :mod:`os`: Calling :func:`os.register_at_fork` in multi-threaded process.
* :class:`!pydoc.ErrorDuringImport`: A tuple value for *exc_info* parameter is
deprecated, use an exception instance.

View file

@ -3,20 +3,154 @@
.. _extending-intro:
********************************
Using the C API: Assorted topics
********************************
******************************
Extending Python with C or C++
******************************
The :ref:`tutorial <first-extension-module>` walked you through
creating a C API extension module, but left many areas unexplained.
This document looks at several concepts that you'll need to learn
in order to write more complex extensions.
It is quite easy to add new built-in modules to Python, if you know how to
program in C. Such :dfn:`extension modules` can do two things that can't be
done directly in Python: they can implement new built-in object types, and they
can call C library functions and system calls.
To support extensions, the Python API (Application Programmers Interface)
defines a set of functions, macros and variables that provide access to most
aspects of the Python run-time system. The Python API is incorporated in a C
source file by including the header ``"Python.h"``.
The compilation of an extension module depends on its intended use as well as on
your system setup; details are given in later chapters.
.. note::
The C extension interface is specific to CPython, and extension modules do
not work on other Python implementations. In many cases, it is possible to
avoid writing C extensions and preserve portability to other implementations.
For example, if your use case is calling C library functions or system calls,
you should consider using the :mod:`ctypes` module or the `cffi
<https://cffi.readthedocs.io/>`_ library rather than writing
custom C code.
These modules let you write Python code to interface with C code and are more
portable between implementations of Python than writing and compiling a C
extension module.
.. _extending-simpleexample:
A Simple Example
================
Let's create an extension module called ``spam`` (the favorite food of Monty
Python fans...) and let's say we want to create a Python interface to the C
library function :c:func:`system` [#]_. This function takes a null-terminated
character string as argument and returns an integer. We want this function to
be callable from Python as follows:
.. code-block:: pycon
>>> import spam
>>> status = spam.system("ls -l")
Begin by creating a file :file:`spammodule.c`. (Historically, if a module is
called ``spam``, the C file containing its implementation is called
:file:`spammodule.c`; if the module name is very long, like ``spammify``, the
module name can be just :file:`spammify.c`.)
The first two lines of our file can be::
#define PY_SSIZE_T_CLEAN
#include <Python.h>
which pulls in the Python API (you can add a comment describing the purpose of
the module and a copyright notice if you like).
.. note::
Since Python may define some pre-processor definitions which affect the standard
headers on some systems, you *must* include :file:`Python.h` before any standard
headers are included.
``#define PY_SSIZE_T_CLEAN`` was used to indicate that ``Py_ssize_t`` should be
used in some APIs instead of ``int``.
It is not necessary since Python 3.13, but we keep it here for backward compatibility.
See :ref:`arg-parsing-string-and-buffers` for a description of this macro.
All user-visible symbols defined by :file:`Python.h` have a prefix of ``Py`` or
``PY``, except those defined in standard header files.
.. tip::
For backward compatibility, :file:`Python.h` includes several standard header files.
C extensions should include the standard headers that they use,
and should not rely on these implicit includes.
If using the limited C API version 3.13 or newer, the implicit includes are:
* ``<assert.h>``
* ``<intrin.h>`` (on Windows)
* ``<inttypes.h>``
* ``<limits.h>``
* ``<math.h>``
* ``<stdarg.h>``
* ``<wchar.h>``
* ``<sys/types.h>`` (if present)
If :c:macro:`Py_LIMITED_API` is not defined, or is set to version 3.12 or older,
the headers below are also included:
* ``<ctype.h>``
* ``<unistd.h>`` (on POSIX)
If :c:macro:`Py_LIMITED_API` is not defined, or is set to version 3.10 or older,
the headers below are also included:
* ``<errno.h>``
* ``<stdio.h>``
* ``<stdlib.h>``
* ``<string.h>``
The next thing we add to our module file is the C function that will be called
when the Python expression ``spam.system(string)`` is evaluated (we'll see
shortly how it ends up being called)::
static PyObject *
spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
sts = system(command);
return PyLong_FromLong(sts);
}
There is a straightforward translation from the argument list in Python (for
example, the single expression ``"ls -l"``) to the arguments passed to the C
function. The C function always has two arguments, conventionally named *self*
and *args*.
The *self* argument points to the module object for module-level functions;
for a method it would point to the object instance.
The *args* argument will be a pointer to a Python tuple object containing the
arguments. Each item of the tuple corresponds to an argument in the call's
argument list. The arguments are Python objects --- in order to do anything
with them in our C function we have to convert them to C values. The function
:c:func:`PyArg_ParseTuple` in the Python API checks the argument types and
converts them to C values. It uses a template string to determine the required
types of the arguments as well as the types of the C variables into which to
store the converted values. More about this later.
:c:func:`PyArg_ParseTuple` returns true (nonzero) if all arguments have the right
type and its components have been stored in the variables whose addresses are
passed. It returns false (zero) if an invalid argument list was passed. In the
latter case it also raises an appropriate exception so the calling function can
return ``NULL`` immediately (as we saw in the example).
.. _extending-errors:
Errors and Exceptions
=====================
Intermezzo: Errors and Exceptions
=================================
An important convention throughout the Python interpreter is the following: when
a function fails, it should set an exception condition and return an error value
@ -187,14 +321,194 @@ call to :c:func:`PyErr_SetString` as shown below::
}
.. _backtoexample:
Back to the Example
===================
Going back to our example function, you should now be able to understand this
statement::
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
It returns ``NULL`` (the error indicator for functions returning object pointers)
if an error is detected in the argument list, relying on the exception set by
:c:func:`PyArg_ParseTuple`. Otherwise the string value of the argument has been
copied to the local variable :c:data:`!command`. This is a pointer assignment and
you are not supposed to modify the string to which it points (so in Standard C,
the variable :c:data:`!command` should properly be declared as ``const char
*command``).
The next statement is a call to the Unix function :c:func:`system`, passing it
the string we just got from :c:func:`PyArg_ParseTuple`::
sts = system(command);
Our :func:`!spam.system` function must return the value of :c:data:`!sts` as a
Python object. This is done using the function :c:func:`PyLong_FromLong`. ::
return PyLong_FromLong(sts);
In this case, it will return an integer object. (Yes, even integers are objects
on the heap in Python!)
If you have a C function that returns no useful argument (a function returning
:c:expr:`void`), the corresponding Python function must return ``None``. You
need this idiom to do so (which is implemented by the :c:macro:`Py_RETURN_NONE`
macro)::
Py_INCREF(Py_None);
return Py_None;
:c:data:`Py_None` is the C name for the special Python object ``None``. It is a
genuine Python object rather than a ``NULL`` pointer, which means "error" in most
contexts, as we have seen.
.. _methodtable:
The Module's Method Table and Initialization Function
=====================================================
I promised to show how :c:func:`!spam_system` is called from Python programs.
First, we need to list its name and address in a "method table"::
static PyMethodDef spam_methods[] = {
...
{"system", spam_system, METH_VARARGS,
"Execute a shell command."},
...
{NULL, NULL, 0, NULL} /* Sentinel */
};
Note the third entry (``METH_VARARGS``). This is a flag telling the interpreter
the calling convention to be used for the C function. It should normally always
be ``METH_VARARGS`` or ``METH_VARARGS | METH_KEYWORDS``; a value of ``0`` means
that an obsolete variant of :c:func:`PyArg_ParseTuple` is used.
When using only ``METH_VARARGS``, the function should expect the Python-level
parameters to be passed in as a tuple acceptable for parsing via
:c:func:`PyArg_ParseTuple`; more information on this function is provided below.
The :c:macro:`METH_KEYWORDS` bit may be set in the third field if keyword
arguments should be passed to the function. In this case, the C function should
accept a third ``PyObject *`` parameter which will be a dictionary of keywords.
Use :c:func:`PyArg_ParseTupleAndKeywords` to parse the arguments to such a
function.
The method table must be referenced in the module definition structure::
static struct PyModuleDef spam_module = {
...
.m_methods = spam_methods,
...
};
This structure, in turn, must be passed to the interpreter in the module's
initialization function. The initialization function must be named
:c:func:`!PyInit_name`, where *name* is the name of the module, and should be the
only non-\ ``static`` item defined in the module file::
PyMODINIT_FUNC
PyInit_spam(void)
{
return PyModuleDef_Init(&spam_module);
}
Note that :c:macro:`PyMODINIT_FUNC` declares the function as ``PyObject *`` return type,
declares any special linkage declarations required by the platform, and for C++
declares the function as ``extern "C"``.
:c:func:`!PyInit_spam` is called when each interpreter imports its module
:mod:`!spam` for the first time. (See below for comments about embedding Python.)
A pointer to the module definition must be returned via :c:func:`PyModuleDef_Init`,
so that the import machinery can create the module and store it in ``sys.modules``.
When embedding Python, the :c:func:`!PyInit_spam` function is not called
automatically unless there's an entry in the :c:data:`!PyImport_Inittab` table.
To add the module to the initialization table, use :c:func:`PyImport_AppendInittab`,
optionally followed by an import of the module::
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
PyStatus status;
PyConfig config;
PyConfig_InitPythonConfig(&config);
/* Add a built-in module, before Py_Initialize */
if (PyImport_AppendInittab("spam", PyInit_spam) == -1) {
fprintf(stderr, "Error: could not extend in-built modules table\n");
exit(1);
}
/* Pass argv[0] to the Python interpreter */
status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]);
if (PyStatus_Exception(status)) {
goto exception;
}
/* Initialize the Python interpreter. Required.
If this step fails, it will be a fatal error. */
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto exception;
}
PyConfig_Clear(&config);
/* Optionally import the module; alternatively,
import can be deferred until the embedded script
imports it. */
PyObject *pmodule = PyImport_ImportModule("spam");
if (!pmodule) {
PyErr_Print();
fprintf(stderr, "Error: could not import module 'spam'\n");
}
// ... use Python C API here ...
return 0;
exception:
PyConfig_Clear(&config);
Py_ExitStatusException(status);
}
.. note::
If you declare a global variable or a local static one, the module may
experience unintended side-effects on re-initialisation, for example when
removing entries from ``sys.modules`` or importing compiled modules into
multiple interpreters within a process
(or following a :c:func:`fork` without an intervening :c:func:`exec`).
If module state is not yet fully :ref:`isolated <isolating-extensions-howto>`,
authors should consider marking the module as having no support for subinterpreters
(via :c:macro:`Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED`).
A more substantial example module is included in the Python source distribution
as :file:`Modules/xxlimited.c`. This file may be used as a template or simply
read as an example.
.. _compilation:
Embedding an extension
======================
Compilation and Linkage
=======================
If you want to make your module a permanent
There are two more things to do before you can use your new extension: compiling
and linking it with the Python system. If you use dynamic loading, the details
may depend on the style of dynamic loading your system uses; see the chapters
about building extension modules (chapter :ref:`building`) and additional
information that pertains only to building on Windows (chapter
:ref:`building-on-windows`) for more information about this.
If you can't use dynamic loading, or if you want to make your module a permanent
part of the Python interpreter, you will have to change the configuration setup
and rebuild the interpreter. On Unix, place
and rebuild the interpreter. Luckily, this is very simple on Unix: just place
your file (:file:`spammodule.c` for example) in the :file:`Modules/` directory
of an unpacked source distribution, add a line to the file
:file:`Modules/Setup.local` describing your file:
@ -222,7 +536,7 @@ on the line in the configuration file as well, for instance:
Calling Python Functions from C
===============================
The tutorial concentrated on making C functions callable from Python. The
So far we have concentrated on making C functions callable from Python. The
reverse is also useful: calling Python functions from C. This is especially the
case for libraries that support so-called "callback" functions. If a C
interface makes use of callbacks, the equivalent Python often needs to provide a
@ -267,7 +581,7 @@ be part of a module definition::
}
This function must be registered with the interpreter using the
:c:macro:`METH_VARARGS` flag in :c:type:`PyMethodDef.ml_flags`. The
:c:macro:`METH_VARARGS` flag; this is described in section :ref:`methodtable`. The
:c:func:`PyArg_ParseTuple` function and its arguments are documented in section
:ref:`parsetuple`.
@ -362,21 +676,14 @@ the above example, we use :c:func:`Py_BuildValue` to construct the dictionary. :
Py_DECREF(result);
.. index:: single: PyArg_ParseTuple (C function)
.. _parsetuple:
Extracting Parameters in Extension Functions
============================================
The :ref:`tutorial <first-extension-module>` uses a ":c:data:`METH_O`"
function, which is limited to a single Python argument.
If you want more, you can use :c:data:`METH_VARARGS` instead.
With this flag, the C function will receive a :py:class:`tuple` of arguments
instead of a single object.
.. index:: single: PyArg_ParseTuple (C function)
For unpacking the tuple, CPython provides the :c:func:`PyArg_ParseTuple`
function, declared as follows::
The :c:func:`PyArg_ParseTuple` function is declared as follows::
int PyArg_ParseTuple(PyObject *arg, const char *format, ...);
@ -386,19 +693,6 @@ whose syntax is explained in :ref:`arg-parsing` in the Python/C API Reference
Manual. The remaining arguments must be addresses of variables whose type is
determined by the format string.
For example, to receive a single Python :py:class:`str` object and turn it
into a C buffer, you would use ``"s"`` as the format string::
const char *command;
if (!PyArg_ParseTuple(args, "s", &command)) {
return NULL;
}
If an error is detected in the argument list, :c:func:`!PyArg_ParseTuple`
returns ``NULL`` (the error indicator for functions returning object pointers);
your function may return ``NULL``, relying on the exception set by
:c:func:`PyArg_ParseTuple`.
Note that while :c:func:`PyArg_ParseTuple` checks that the Python arguments have
the required types, it cannot check the validity of the addresses of C variables
passed to the call: if you make mistakes there, your code will probably crash or
@ -409,6 +703,7 @@ Note that any Python object references which are provided to the caller are
Some example calls::
#define PY_SSIZE_T_CLEAN
#include <Python.h>
::
@ -478,17 +773,6 @@ Some example calls::
Keyword Parameters for Extension Functions
==========================================
If you also want your function to accept
:term:`keyword arguments <keyword argument>`, use the :c:data:`METH_KEYWORDS`
flag in combination with :c:data:`METH_VARARGS`.
(:c:data:`!METH_KEYWORDS` can also be used with other flags; see its
documentation for the allowed combinations.)
In this case, the C function should accept a third ``PyObject *`` parameter
which will be a dictionary of keywords.
Use :c:func:`PyArg_ParseTupleAndKeywords` to parse the arguments to such a
function.
.. index:: single: PyArg_ParseTupleAndKeywords (C function)
The :c:func:`PyArg_ParseTupleAndKeywords` function is declared as follows::
@ -549,6 +833,19 @@ Philbrick (philbrick@hks.com)::
{NULL, NULL, 0, NULL} /* sentinel */
};
static struct PyModuleDef keywdarg_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "keywdarg",
.m_size = 0,
.m_methods = keywdarg_methods,
};
PyMODINIT_FUNC
PyInit_keywdarg(void)
{
return PyModuleDef_Init(&keywdarg_module);
}
.. _buildvalue:
@ -689,11 +986,11 @@ needed. Ownership of a reference can be transferred. There are three ways to
dispose of an owned reference: pass it on, store it, or call :c:func:`Py_DECREF`.
Forgetting to dispose of an owned reference creates a memory leak.
It is also possible to :dfn:`borrow` [#borrow]_ a reference to an object. The
It is also possible to :dfn:`borrow` [#]_ a reference to an object. The
borrower of a reference should not call :c:func:`Py_DECREF`. The borrower must
not hold on to the object longer than the owner from which it was borrowed.
Using a borrowed reference after the owner has disposed of it risks using freed
memory and should be avoided completely [#dont-check-refcount]_.
memory and should be avoided completely [#]_.
The advantage of borrowing over owning a reference is that you don't need to
take care of disposing of the reference on all possible paths through the code
@ -872,7 +1169,7 @@ checking.
The C function calling mechanism guarantees that the argument list passed to C
functions (``args`` in the examples) is never ``NULL`` --- in fact it guarantees
that it is always a tuple [#old-calling-convention]_.
that it is always a tuple [#]_.
It is a severe error to ever let a ``NULL`` pointer "escape" to the Python user.
@ -929,8 +1226,8 @@ the module whose functions one wishes to call might not have been loaded yet!
Portability therefore requires not to make any assumptions about symbol
visibility. This means that all symbols in extension modules should be declared
``static``, except for the module's initialization function, in order to
avoid name clashes with other extension modules. And it means that symbols
that *should* be accessible from
avoid name clashes with other extension modules (as discussed in section
:ref:`methodtable`). And it means that symbols that *should* be accessible from
other extension modules must be exported in a different way.
Python provides a special mechanism to pass C-level information (pointers) from
@ -972,9 +1269,8 @@ file corresponding to the module provides a macro that takes care of importing
the module and retrieving its C API pointers; client modules only have to call
this macro before accessing the C API.
The exporting module is a modification of the :mod:`!spam` module from the
:ref:`tutorial <first-extension-module>`.
The function :func:`!spam.system` does not call
The exporting module is a modification of the :mod:`!spam` module from section
:ref:`extending-simpleexample`. The function :func:`!spam.system` does not call
the C library function :c:func:`system` directly, but a function
:c:func:`!PySpam_System`, which would of course do something more complicated in
reality (such as adding "spam" to every command). This function
@ -1116,14 +1412,15 @@ code distribution).
.. rubric:: Footnotes
.. [#borrow] The metaphor of "borrowing" a reference is not completely correct:
the owner still has a copy of the reference.
.. [#] An interface for this function already exists in the standard module :mod:`os`
--- it was chosen as a simple and straightforward example.
.. [#dont-check-refcount] Checking that the reference count is at least 1
**does not work** --- the
.. [#] The metaphor of "borrowing" a reference is not completely correct: the owner
still has a copy of the reference.
.. [#] Checking that the reference count is at least 1 **does not work** --- the
reference count itself could be in freed memory and may thus be reused for
another object!
.. [#old-calling-convention] These guarantees don't hold when you use the
"old" style calling convention ---
.. [#] These guarantees don't hold when you use the "old" style calling convention ---
this is still found in much existing code.

View file

@ -1,667 +0,0 @@
.. highlight:: c
.. _extending-simpleexample:
.. _first-extension-module:
*********************************
Your first C API extension module
*********************************
This tutorial will take you through creating a simple
Python extension module written in C or C++.
We will use the low-level Python C API directly.
For easier ways to create extension modules, see
the :ref:`recommended third party tools <c-api-tools>`.
The tutorial assumes basic knowledge about Python: you should be able to
define functions in Python code before starting to write them in C.
See :ref:`tutorial-index` for an introduction to Python itself.
The tutorial should be approachable for anyone who can write a basic C library.
While we will mention several concepts that a C beginner would not be expected
to know, like ``static`` functions or linkage declarations, understanding these
is not necessary for success.
We will focus on giving you a "feel" of what Python's C API is like.
It will not teach you important concepts, like error handling
and reference counting, which are covered in later chapters.
We will assume that you use a Unix-like system (including macOS and
Linux), or Windows.
On other systems, you might need to adjust some details -- for example,
a system command name.
You need to have a suitable C compiler and Python development headers installed.
On Linux, headers are often in a package like ``python3-dev``
or ``python3-devel``.
You need to be able to install Python packages.
This tutorial uses `pip <https://pip.pypa.io/>`__ (``pip install``), but you
can substitute any tool that can build and install ``pyproject.toml``-based
projects, like `uv <https://docs.astral.sh/uv/>`_ (``uv pip install``).
Preferably, have a :ref:`virtual environment <venv-def>` activated.
.. note::
This tutorial uses APIs that were added in CPython 3.15.
To create an extension that's compatible with earlier versions of CPython,
please follow an earlier version of this documentation.
This tutorial uses C syntax added in C11 and C++20.
If your extension needs to be compatible with earlier standards,
please follow tutorials in documentation for Python 3.14 or below.
What we'll do
=============
Let's create an extension module called ``spam`` [#why-spam]_,
which will include a Python interface to the C
standard library function :c:func:`system`.
This function is defined in ``stdlib.h``.
It takes a C string as argument, runs the argument as a system
command, and returns a result value as an integer.
A manual page for :c:func:`system` might summarize it this way::
#include <stdlib.h>
int system(const char *command);
Note that like many functions in the C standard library,
this function is already exposed in Python.
In production, use :py:func:`os.system` or :py:func:`subprocess.run`
rather than the module you'll write here.
We want this function to be callable from Python as follows:
.. code-block:: pycon
>>> import spam
>>> status = spam.system("whoami")
User Name
>>> status
0
.. note::
The system command ``whoami`` prints out your username.
It's useful in tutorials like this one because it has the same name on
both Unix and Windows.
Start with the headers
======================
Begin by creating a directory for this tutorial, and switching to it
on the command line.
Then, create a file named :file:`spammodule.c` in your directory.
[#why-spammodule]_
In this file, we'll include two headers: :file:`Python.h` to pull in
all declarations of the Python C API, and :file:`stdlib.h` for the
:c:func:`system` function. [#stdlib-h]_
Add the following lines to :file:`spammodule.c`:
.. literalinclude:: ../includes/capi-extension/spammodule-01.c
:start-at: <Python.h>
:end-at: <stdlib.h>
Be sure to put :file:`stdlib.h`, and any other standard library includes,
*after* :file:`Python.h`.
On some systems, Python may define some pre-processor definitions
that affect the standard headers.
Running your build tool
=======================
With only the includes in place, your extension won't do anything.
Still, it's a good time to compile it and try to import it.
This will ensure that your build tool works, so that you can make
and test incremental changes as you follow the rest of the text.
CPython itself does not come with a tool to build extension modules;
it is recommended to use a third-party project for this.
In this tutorial, we'll use `meson-python`_.
(If you want to use another one, see :ref:`first-extension-other-tools`.)
.. at the time of writing, meson-python has the least overhead for a
simple extension using PyModExport.
Change this if another tool makes things easier.
``meson-python`` requires defining a "project" using two extra files.
First, add ``pyproject.toml`` with these contents:
.. code-block:: toml
[build-system]
build-backend = 'mesonpy'
requires = ['meson-python']
[project]
# Placeholder project information
# (change this before distributing the module)
name = 'sampleproject'
version = '0'
Then, create ``meson.build`` containing the following:
.. code-block:: meson
project('sampleproject', 'c')
py = import('python').find_installation(pure: false)
py.extension_module(
'spam', # name of the importable Python module
'spammodule.c', # the C source file
install: true,
)
.. note::
See `meson-python documentation <meson-python>`_ for details on
configuration.
Now, build install the *project in the current directory* (``.``) via ``pip``:
.. code-block:: sh
python -m pip install .
.. tip::
If you don't have ``pip`` installed, run ``python -m ensurepip``,
preferably in a :ref:`virtual environment <venv-def>`.
(Or, if you prefer another tool that can build and install
``pyproject.toml``-based projects, use that.)
.. _meson-python: https://mesonbuild.com/meson-python/
.. _virtual environment: https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#create-and-use-virtual-environments
Note that you will need to run this command again every time you change your
extension.
Unlike Python, C has an explicit compilation step.
When your extension is compiled and installed, start Python and try to
import it.
This should fail with the following exception:
.. code-block:: pycon
>>> import spam
Traceback (most recent call last):
...
ImportError: dynamic module does not define module export function (PyModExport_spam or PyInit_spam)
Module export hook
==================
The exception you got when you tried to import the module told you that Python
is looking for a "module export function", also known as a
:ref:`module export hook <extension-export-hook>`.
Let's define one.
First, add a prototype below the ``#include`` lines:
.. literalinclude:: ../includes/capi-extension/spammodule-01.c
:start-after: /// Export hook prototype
:end-before: ///
.. tip::
The prototype is not strictly necessary, but some modern compilers emit
warnings without it.
It's generally better to add the prototype than to disable the warning.
The :c:macro:`PyMODEXPORT_FUNC` macro declares the function's
return type, and adds any special linkage declarations needed
to make the function visible and usable when CPython loads it.
After the prototype, add the function itself.
For now, make it return ``NULL``:
.. code-block:: c
PyMODEXPORT_FUNC
PyModExport_spam(void)
{
return NULL;
}
Compile and load the module again.
You should get a different error this time.
.. code-block:: pycon
>>> import spam
Traceback (most recent call last):
...
SystemError: module export hook for module 'spam' failed without setting an exception
Simply returning ``NULL`` is *not* correct behavior for an export hook,
and CPython complains about it.
That's good -- it means that CPython found the function!
Let's now make it do something useful.
The slot table
==============
Rather than ``NULL``, the export hook should return the information needed to
create a module.
Let's start with the basics: the name and docstring.
The information should be defined in a ``static`` array of
:c:type:`PyModuleDef_Slot` entries, which are essentially key-value pairs.
Define this array just before your export hook:
.. code-block:: c
static PyModuleDef_Slot spam_slots[] = {
{Py_mod_name, "spam"},
{Py_mod_doc, "A wonderful module with an example function"},
{0, NULL}
};
For both :c:data:`Py_mod_name` and :c:data:`Py_mod_doc`, the values are C
strings -- that is, NUL-terminated, UTF-8 encoded byte arrays.
Note the zero-filled sentinel entry at the end.
If you forget it, you'll trigger undefined behavior.
The array is defined as ``static`` -- that is, not visible outside this ``.c`` file.
This will be a common theme.
CPython only needs to access the export hook; all global variables
and all other functions should generally be ``static``, so that they don't
clash with other extensions.
Return this array from your export hook instead of ``NULL``:
.. code-block:: c
:emphasize-lines: 4
PyMODEXPORT_FUNC
PyModExport_spam(void)
{
return spam_slots;
}
Now, recompile and try it out:
.. code-block:: pycon
>>> import spam
>>> print(spam)
<module 'spam' from '/home/encukou/dev/cpython/spam.so'>
You have an extension module!
Try ``help(spam)`` to see the docstring.
The next step will be adding a function.
.. _backtoexample:
Exposing a function
===================
To expose the :c:func:`system` C function directly to Python,
we'll need to write a layer of glue code to convert arguments from Python
objects to C values, and the C return value back to Python.
One of the simplest ways to write glue code is a ":c:data:`METH_O`" function,
which takes two Python objects and returns one.
All Python objects -- regardless of the Python type -- are represented in C
as pointers to the :c:type:`PyObject` structure.
Add such a function above the slots array::
static PyObject *
spam_system(PyObject *self, PyObject *arg)
{
Py_RETURN_NONE;
}
For now, we ignore the arguments, and use the :c:macro:`Py_RETURN_NONE`
macro, which expands to a ``return`` statement that properly returns
a Python :py:data:`None` object.
Recompile your extension to make sure you don't have syntax errors.
We haven't yet added ``spam_system`` to the module, so you might get a
warning that ``spam_system`` is unused.
.. _methodtable:
Method definitions
------------------
To expose the C function to Python, you will need to provide several pieces of
information in a structure called
:c:type:`PyMethodDef` [#why-pymethoddef]_:
* ``ml_name``: the name of the Python function;
* ``ml_doc``: a docstring;
* ``ml_meth``: the C function to be called; and
* ``ml_flags``: a set of flags describing details like how Python arguments are
passed to the C function.
We'll use :c:data:`METH_O` here -- the flag that matches our
``spam_system`` function's signature.
Because modules typically create several functions, these definitions
need to be collected in an array, with a zero-filled sentinel at the end.
Add this array just below the ``spam_system`` function:
.. literalinclude:: ../includes/capi-extension/spammodule-01.c
:start-after: /// Module method table
:end-before: ///
As with module slots, a zero-filled sentinel marks the end of the array.
Next, we'll add the method to the module.
Add a :c:data:`Py_mod_methods` slot to your :c:type:`PyMethodDef` array:
.. literalinclude:: ../includes/capi-extension/spammodule-01.c
:start-after: /// Module slot table
:end-before: ///
:emphasize-lines: 5
Recompile your extension again, and test it.
Be sure to restart the Python interpreter, so that ``import spam`` picks
up the new version of the module.
You should now be able to call the function:
.. code-block:: pycon
>>> import spam
>>> print(spam.system)
<built-in function system>
>>> print(spam.system('whoami'))
None
Note that our ``spam.system`` does not yet run the ``whoami`` command;
it only returns ``None``.
Check that the function accepts exactly one argument, as specified by
the :c:data:`METH_O` flag:
.. code-block:: pycon
>>> print(spam.system('too', 'many', 'arguments'))
Traceback (most recent call last):
...
TypeError: spam.system() takes exactly one argument (3 given)
Returning an integer
====================
Now, let's take a look at the return value.
Instead of ``None``, we'll want ``spam.system`` to return a number -- that is,
a Python :py:type:`int` object.
Eventually this will be the exit code of a system command,
but let's start with a fixed value, say, ``3``.
The Python C API provides a function to create a Python :py:type:`int` object
from a C ``int`` value: :c:func:`PyLong_FromLong`. [#why-pylongfromlong]_
To call it, replace the ``Py_RETURN_NONE`` with the following 3 lines:
.. this could be a one-liner, but we want to show the data types here
.. code-block:: c
:emphasize-lines: 4-6
static PyObject *
spam_system(PyObject *self, PyObject *arg)
{
int status = 3;
PyObject *result = PyLong_FromLong(status);
return result;
}
Recompile, restart the Python interpreter again,
and check that the function now returns 3:
.. code-block:: pycon
>>> import spam
>>> spam.system('whoami')
3
Accepting a string
==================
Finally, let's handle the function argument.
Our C function, :c:func:`!spam_system`, takes two arguments.
The first one, ``PyObject *self``, will be set to the ``spam`` module
object.
This isn't useful in our case, so we'll ignore it.
The other one, ``PyObject *arg``, will be set to the object that the user
passed from Python.
We expect that it should be a Python string.
In order to use the information in it, we will need
to convert it to a C value -- in this case, a C string (``const char *``).
There's a slight type mismatch here: Python's :py:class:`str` objects store
Unicode text, but C strings are arrays of bytes.
So, we'll need to *encode* the data, and we'll use the UTF-8 encoding for it.
(UTF-8 might not always be correct for system commands, but it's what
:py:meth:`str.encode` uses by default,
and the C API has special support for it.)
The function to encode a Python string into a UTF-8 buffer is named
:c:func:`PyUnicode_AsUTF8` [#why-pyunicodeasutf8]_.
Call it like this:
.. code-block:: c
:emphasize-lines: 4
static PyObject *
spam_system(PyObject *self, PyObject *arg)
{
const char *command = PyUnicode_AsUTF8(arg);
int status = 3;
PyObject *result = PyLong_FromLong(status);
return result;
}
If :c:func:`PyUnicode_AsUTF8` is successful, *command* will point to the
resulting array of bytes.
This buffer is managed by the *arg* object, which means we don't need to free
it, but we must follow some rules:
* We should only use the buffer inside the ``spam_system`` function.
When ``spam_system`` returns, *arg* and the buffer it manages might be
garbage-collected.
* We must not modify it. This is why we use ``const``.
If :c:func:`PyUnicode_AsUTF8` was *not* successful, it returns a ``NULL``
pointer.
When calling *any* Python C API, we always need to handle such error cases.
The way to do this in general is left for later chapters of this documentation.
For now, be assured that we are already handling errors from
:c:func:`PyLong_FromLong` correctly.
For the :c:func:`PyUnicode_AsUTF8` call, the correct way to handle errors is
returning ``NULL`` from ``spam_system``.
Add an ``if`` block for this:
.. code-block:: c
:emphasize-lines: 5-7
static PyObject *
spam_system(PyObject *self, PyObject *arg)
{
const char *command = PyUnicode_AsUTF8(arg);
if (command == NULL) {
return NULL;
}
int status = 3;
PyObject *result = PyLong_FromLong(status);
return result;
}
That's it for the setup.
Now, all that is left is calling the C library function :c:func:`system` with
the ``char *`` buffer, and using its result instead of the ``3``:
.. code-block:: c
:emphasize-lines: 8
static PyObject *
spam_system(PyObject *self, PyObject *arg)
{
const char *command = PyUnicode_AsUTF8(arg);
if (command == NULL) {
return NULL;
}
int status = system(command);
PyObject *result = PyLong_FromLong(status);
return result;
}
Compile your module, restart Python, and test.
This time, you should see your username -- the output of the ``whoami``
system command:
.. code-block:: pycon
>>> import spam
>>> result = spam.system('whoami')
User Name
>>> result
0
You might also want to test error cases:
.. code-block:: pycon
>>> import spam
>>> result = spam.system('nonexistent-command')
sh: line 1: nonexistent-command: command not found
>>> result
32512
>>> spam.system(3)
Traceback (most recent call last):
...
TypeError: bad argument type for built-in operation
The result
==========
Congratulations!
You have written a complete Python C API extension module,
and completed this tutorial!
Here is the entire source file, for your convenience:
.. _extending-spammodule-source:
.. literalinclude:: ../includes/capi-extension/spammodule-01.c
:start-at: ///
.. _first-extension-other-tools:
Appendix: Other build tools
===========================
You should be able to follow this tutorial -- except the
*Running your build tool* section itself -- with a build tool other
than ``meson-python``.
The Python Packaging User Guide has a `list of recommended tools <https://packaging.python.org/en/latest/guides/tool-recommendations/#build-backends-for-extension-modules>`_;
be sure to choose one for the C language.
Workaround for missing PyInit function
--------------------------------------
If your build tool output complains about missing ``PyInit_spam``,
add the following function to your module for now:
.. code-block:: c
// A workaround
void *PyInit_spam(void) { return NULL; }
This is a shim for an old-style :ref:`initialization function <extension-export-hook>`,
which was required in extension modules for CPython 3.14 and below.
Current CPython does not need it, but some build tools may still assume that
all extension modules need to define it.
If you use this workaround, you will get the exception
``SystemError: initialization of spam failed without raising an exception``
instead of
``ImportError: dynamic module does not define module export function``.
Compiling directly
------------------
Using a third-party build tool is heavily recommended,
as it will take care of various details of your platform and Python
installation, of naming the resulting extension, and, later, of distributing
your work.
If you are building an extension for as *specific* system, or for yourself
only, you might instead want to run your compiler directly.
The way to do this is system-specific; be prepared for issues you will need
to solve yourself.
Linux
^^^^^
On Linux, the Python development package may include a ``python3-config``
command that prints out the required compiler flags.
If you use it, check that it corresponds to the CPython interpreter you'll use
to load the module.
Then, start with the following command:
.. code-block:: sh
gcc --shared $(python3-config --cflags --ldflags) spammodule.c -o spam.so
This should generate a ``spam.so`` file that you need to put in a directory
on :py:attr:`sys.path`.
.. rubric:: Footnotes
.. [#why-spam] ``spam`` is the favorite food of Monty Python fans...
.. [#why-spammodule] The source file name is entirely up to you,
though some tools can be picky about the ``.c`` extension.
This tutorial uses the traditional ``*module.c`` suffix.
Some people would just use :file:`spam.c` to implement a module
named ``spam``,
projects where Python isn't the primary language might use ``py_spam.c``,
and so on.
.. [#stdlib-h] Including :file:`stdlib.h` is technically not necessary,
since :file:`Python.h` includes it and
:ref:`several other standard headers <capi-system-includes>` for its own use
or for backwards compatibility.
However, it is good practice to explicitly include what you need.
.. [#why-pymethoddef] The :c:type:`!PyMethodDef` structure is also used
to create methods of classes, so there's no separate
":c:type:`!PyFunctionDef`".
.. [#why-pylongfromlong] The name :c:func:`PyLong_FromLong`
might not seem obvious.
``PyLong`` refers to a the Python :py:class:`int`, which was originally
called ``long``; the ``FromLong`` refers to the C ``long`` (or ``long int``)
type.
.. [#why-pyunicodeasutf8] Here, ``PyUnicode`` refers to the original name of
the Python :py:class:`str` class: ``unicode``.

View file

@ -5,17 +5,15 @@
##################################################
This document describes how to write modules in C or C++ to extend the Python
interpreter with new modules. Those modules can do what Python code does --
define functions, object types and methods -- but also interact with native
libraries or achieve better performance by avoiding the overhead of an
interpreter. The document also describes how
interpreter with new modules. Those modules can not only define new functions
but also new object types and their methods. The document also describes how
to embed the Python interpreter in another application, for use as an extension
language. Finally, it shows how to compile and link extension modules so that
they can be loaded dynamically (at run time) into the interpreter, if the
underlying operating system supports this feature.
This document assumes basic knowledge about C and Python. For an informal
introduction to Python, see :ref:`tutorial-index`. :ref:`reference-index`
This document assumes basic knowledge about Python. For an informal
introduction to the language, see :ref:`tutorial-index`. :ref:`reference-index`
gives a more formal definition of the language. :ref:`library-index` documents
the existing object types, functions and modules (both built-in and written in
Python) that give the language its wide application range.
@ -23,75 +21,37 @@ Python) that give the language its wide application range.
For a detailed description of the whole Python/C API, see the separate
:ref:`c-api-index`.
To support extensions, Python's C API (Application Programmers Interface)
defines a set of functions, macros and variables that provide access to most
aspects of the Python run-time system. The Python API is incorporated in a C
source file by including the header ``"Python.h"``.
.. note::
The C extension interface is specific to CPython, and extension modules do
not work on other Python implementations. In many cases, it is possible to
avoid writing C extensions and preserve portability to other implementations.
For example, if your use case is calling C library functions or system calls,
you should consider using the :mod:`ctypes` module or the `cffi
<https://cffi.readthedocs.io/>`_ library rather than writing
custom C code.
These modules let you write Python code to interface with C code and are more
portable between implementations of Python than writing and compiling a C
extension module.
.. toctree::
:hidden:
first-extension-module.rst
extending.rst
newtypes_tutorial.rst
newtypes.rst
building.rst
windows.rst
embedding.rst
Recommended third party tools
=============================
This document only covers the basic tools for creating extensions provided
This guide only covers the basic tools for creating extensions provided
as part of this version of CPython. Some :ref:`third party tools
<c-api-tools>` offer both simpler and more sophisticated approaches to creating
C and C++ extensions for Python.
While this document is aimed at extension authors, it should also be helpful to
the authors of such tools.
For example, the tutorial module can serve as a simple test case for a build
tool or sample expected output of a code generator.
C API Tutorial
==============
This tutorial describes how to write a simple module in C or C++,
using the Python C API -- that is, using the basic tools provided
as part of this version of CPython.
#. :ref:`first-extension-module`
Guides for intermediate topics
==============================
Creating extensions without third party tools
=============================================
This section of the guide covers creating C and C++ extensions without
assistance from third party tools. It is intended primarily for creators
of those tools, rather than being a recommended way to create your own
C extensions.
* :ref:`extending-intro`
* :ref:`defining-new-types`
* :ref:`new-types-topics`
* :ref:`building`
* :ref:`building-on-windows`
.. seealso::
:pep:`489` -- Multi-phase extension module initialization
.. toctree::
:maxdepth: 2
:numbered:
extending.rst
newtypes_tutorial.rst
newtypes.rst
building.rst
windows.rst
Embedding the CPython runtime in a larger application
=====================================================
@ -101,4 +61,8 @@ interpreter as the main application, it is desirable to instead embed
the CPython runtime inside a larger application. This section covers
some of the details involved in doing that successfully.
* :ref:`embedding`
.. toctree::
:maxdepth: 2
:numbered:
embedding.rst

View file

@ -560,8 +560,6 @@ For an object to be weakly referenceable, the extension type must set the
field. The legacy :c:member:`~PyTypeObject.tp_weaklistoffset` field should
be left as zero.
If this flag is set, :c:macro:`Py_TPFLAGS_HAVE_GC` should also be set.
Concretely, here is how the statically declared type object would look::
static PyTypeObject TrivialType = {

View file

@ -186,7 +186,7 @@ How do I get documentation on Python?
-------------------------------------
The standard documentation for the current stable version of Python is available
at https://docs.python.org/3/. EPUB, plain text, and downloadable HTML versions are
at https://docs.python.org/3/. PDF, plain text, and downloadable HTML versions are
also available at https://docs.python.org/3/download.html.
The documentation is written in reStructuredText and processed by `the Sphinx

View file

@ -134,14 +134,6 @@ Glossary
iterator's :meth:`~object.__anext__` method until it raises a
:exc:`StopAsyncIteration` exception. Introduced by :pep:`492`.
atomic operation
An operation that appears to execute as a single, indivisible step: no
other thread can observe it half-done, and its effects become visible all
at once. Python does not guarantee that high-level statements are atomic
(for example, ``x += 1`` performs multiple bytecode operations and is not
atomic). Atomicity is only guaranteed where explicitly documented. See
also :term:`race condition` and :term:`data race`.
attached thread state
A :term:`thread state` that is active for the current OS thread.
@ -297,22 +289,6 @@ Glossary
advanced mathematical feature. If you're not aware of a need for them,
it's almost certain you can safely ignore them.
concurrency
The ability of a computer program to perform multiple tasks at the same
time. Python provides libraries for writing programs that make use of
different forms of concurrency. :mod:`asyncio` is a library for dealing
with asynchronous tasks and coroutines. :mod:`threading` provides
access to operating system threads and :mod:`multiprocessing` to
operating system processes. Multi-core processors can execute threads and
processes on different CPU cores at the same time (see
:term:`parallelism`).
concurrent modification
When multiple threads modify shared data at the same time. Concurrent
modification without proper synchronization can cause
:term:`race conditions <race condition>`, and might also trigger a
:term:`data race <data race>`, data corruption, or both.
context
This term has different meanings depending on where and how it is used.
Some common meanings:
@ -387,28 +363,6 @@ Glossary
the :term:`cyclic garbage collector <garbage collection>` is to identify these groups and break the reference
cycles so that the memory can be reclaimed.
data race
A situation where multiple threads access the same memory location
concurrently, at least one of the accesses is a write, and the threads
do not use any synchronization to control their access. Data races
lead to :term:`non-deterministic` behavior and can cause data corruption.
Proper use of :term:`locks <lock>` and other :term:`synchronization primitives
<synchronization primitive>` prevents data races. Note that data races
can only happen in native code, but that :term:`native code` might be
exposed in a Python API. See also :term:`race condition` and
:term:`thread-safe`.
deadlock
A situation in which two or more tasks (threads, processes, or coroutines)
wait indefinitely for each other to release resources or complete actions,
preventing any from making progress. For example, if thread A holds lock
1 and waits for lock 2, while thread B holds lock 2 and waits for lock 1,
both threads will wait indefinitely. In Python this often arises from
acquiring multiple locks in conflicting orders or from circular
join/await dependencies. Deadlocks can be avoided by always acquiring
multiple :term:`locks <lock>` in a consistent order. See also
:term:`lock` and :term:`reentrant`.
decorator
A function returning another function, usually applied as a function
transformation using the ``@wrapper`` syntax. Common examples for
@ -708,14 +662,6 @@ Glossary
requires the GIL to be held in order to use it. This refers to having an
:term:`attached thread state`.
global state
Data that is accessible throughout a program, such as module-level
variables, class variables, or C static variables in :term:`extension modules
<extension module>`. In multi-threaded programs, global state shared
between threads typically requires synchronization to avoid
:term:`race conditions <race condition>` and
:term:`data races <data race>`.
hash-based pyc
A bytecode cache file that uses the hash rather than the last-modified
time of the corresponding source file to determine its validity. See
@ -760,9 +706,7 @@ Glossary
tuples. Such an object cannot be altered. A new object has to
be created if a different value has to be stored. They play an important
role in places where a constant hash value is needed, for example as a key
in a dictionary. Immutable objects are inherently :term:`thread-safe`
because their state cannot be modified after creation, eliminating concerns
about improperly synchronized :term:`concurrent modification`.
in a dictionary.
import path
A list of locations (or :term:`path entries <path entry>`) that are
@ -852,9 +796,8 @@ Glossary
CPython does not consistently apply the requirement that an iterator
define :meth:`~iterator.__iter__`.
And also please note that :term:`free-threaded <free threading>`
CPython does not guarantee :term:`thread-safe` behavior of iterator
operations.
And also please note that the free-threading CPython does not guarantee
the thread-safety of iterator operations.
key function
@ -870,7 +813,7 @@ Glossary
:func:`itertools.groupby`.
There are several ways to create a key function. For example. the
:meth:`str.casefold` method can serve as a key function for case insensitive
:meth:`str.lower` method can serve as a key function for case insensitive
sorts. Alternatively, a key function can be built from a
:keyword:`lambda` expression such as ``lambda r: (r[0], r[2])``. Also,
:func:`operator.attrgetter`, :func:`operator.itemgetter`, and
@ -892,11 +835,10 @@ Glossary
:keyword:`if` statements.
In a multi-threaded environment, the LBYL approach can risk introducing a
:term:`race condition` between "the looking" and "the leaping". For example,
the code, ``if key in mapping: return mapping[key]`` can fail if another
race condition between "the looking" and "the leaping". For example, the
code, ``if key in mapping: return mapping[key]`` can fail if another
thread removes *key* from *mapping* after the test, but before the lookup.
This issue can be solved with :term:`locks <lock>` or by using the
:term:`EAFP` approach. See also :term:`thread-safe`.
This issue can be solved with locks or by using the EAFP approach.
lexical analyzer
@ -915,19 +857,6 @@ Glossary
clause is optional. If omitted, all elements in ``range(256)`` are
processed.
lock
A :term:`synchronization primitive` that allows only one thread at a
time to access a shared resource. A thread must acquire a lock before
accessing the protected resource and release it afterward. If a thread
attempts to acquire a lock that is already held by another thread, it
will block until the lock becomes available. Python's :mod:`threading`
module provides :class:`~threading.Lock` (a basic lock) and
:class:`~threading.RLock` (a :term:`reentrant` lock). Locks are used
to prevent :term:`race conditions <race condition>` and ensure
:term:`thread-safe` access to shared data. Alternative design patterns
to locks exist such as queues, producer/consumer patterns, and
thread-local state. See also :term:`deadlock`, and :term:`reentrant`.
loader
An object that loads a module.
It must define the :meth:`!exec_module` and :meth:`!create_module` methods
@ -1013,11 +942,8 @@ Glossary
See :term:`method resolution order`.
mutable
An :term:`object` with state that is allowed to change during the course
of the program. In multi-threaded programs, mutable objects that are
shared between threads require careful synchronization to avoid
:term:`race conditions <race condition>`. See also :term:`immutable`,
:term:`thread-safe`, and :term:`concurrent modification`.
Mutable objects can change their value but keep their :func:`id`. See
also :term:`immutable`.
named tuple
The term "named tuple" applies to any type or class that inherits from
@ -1069,13 +995,6 @@ Glossary
See also :term:`module`.
native code
Code that is compiled to machine instructions and runs directly on the
processor, as opposed to code that is interpreted or runs in a virtual
machine. In the context of Python, native code typically refers to
C, C++, Rust or Fortran code in :term:`extension modules <extension module>`
that can be called from Python. See also :term:`extension module`.
nested scope
The ability to refer to a variable in an enclosing definition. For
instance, a function defined inside another function can refer to
@ -1092,15 +1011,6 @@ Glossary
properties, :meth:`~object.__getattribute__`, class methods, and static
methods.
non-deterministic
Behavior where the outcome of a program can vary between executions with
the same inputs. In multi-threaded programs, non-deterministic behavior
often results from :term:`race conditions <race condition>` where the
relative timing or interleaving of threads affects the result.
Proper synchronization using :term:`locks <lock>` and other
:term:`synchronization primitives <synchronization primitive>` helps
ensure deterministic behavior.
object
Any data with state (attributes or value) and defined behavior
(methods). Also the ultimate base class of any :term:`new-style
@ -1115,15 +1025,6 @@ Glossary
applied to all scopes, only those relying on a known set of local
and nonlocal variable names are restricted to optimized scopes.
optional module
An :term:`extension module` that is part of the :term:`standard library`,
but may be absent in some builds of :term:`CPython`,
usually due to missing third-party libraries or because the module
is not available for a given platform.
See :ref:`optional-module-requirements` for a list of optional modules
that require third-party libraries.
package
A Python :term:`module` which can contain submodules or recursively,
subpackages. Technically, a package is a Python module with a
@ -1131,16 +1032,6 @@ Glossary
See also :term:`regular package` and :term:`namespace package`.
parallelism
Executing multiple operations at the same time (e.g. on multiple CPU
cores). In Python builds with the
:term:`global interpreter lock (GIL) <global interpreter lock>`, only one
thread runs Python bytecode at a time, so taking advantage of multiple
CPU cores typically involves multiple processes
(e.g. :mod:`multiprocessing`) or native extensions that release the GIL.
In :term:`free-threaded <free threading>` Python, multiple Python threads
can run Python code simultaneously on different cores.
parameter
A named entity in a :term:`function` (or method) definition that
specifies an :term:`argument` (or in some cases, arguments) that the
@ -1315,18 +1206,6 @@ Glossary
>>> email.mime.text.__name__
'email.mime.text'
race condition
A condition of a program where the its behavior
depends on the relative timing or ordering of events, particularly in
multi-threaded programs. Race conditions can lead to
:term:`non-deterministic` behavior and bugs that are difficult to
reproduce. A :term:`data race` is a specific type of race condition
involving unsynchronized access to shared memory. The :term:`LBYL`
coding style is particularly susceptible to race conditions in
multi-threaded code. Using :term:`locks <lock>` and other
:term:`synchronization primitives <synchronization primitive>`
helps prevent race conditions.
reference count
The number of references to an object. When the reference count of an
object drops to zero, it is deallocated. Some objects are
@ -1348,25 +1227,6 @@ Glossary
See also :term:`namespace package`.
reentrant
A property of a function or :term:`lock` that allows it to be called or
acquired multiple times by the same thread without causing errors or a
:term:`deadlock`.
For functions, reentrancy means the function can be safely called again
before a previous invocation has completed, which is important when
functions may be called recursively or from signal handlers. Thread-unsafe
functions may be :term:`non-deterministic` if they're called reentrantly in a
multithreaded program.
For locks, Python's :class:`threading.RLock` (reentrant lock) is
reentrant, meaning a thread that already holds the lock can acquire it
again without blocking. In contrast, :class:`threading.Lock` is not
reentrant - attempting to acquire it twice from the same thread will cause
a deadlock.
See also :term:`lock` and :term:`deadlock`.
REPL
An acronym for the "readevalprint loop", another name for the
:term:`interactive` interpreter shell.
@ -1471,18 +1331,6 @@ Glossary
See also :term:`borrowed reference`.
synchronization primitive
A basic building block for coordinating (synchronizing) the execution of
multiple threads to ensure :term:`thread-safe` access to shared resources.
Python's :mod:`threading` module provides several synchronization primitives
including :class:`~threading.Lock`, :class:`~threading.RLock`,
:class:`~threading.Semaphore`, :class:`~threading.Condition`,
:class:`~threading.Event`, and :class:`~threading.Barrier`. Additionally,
the :mod:`queue` module provides multi-producer, multi-consumer queues
that are especially useful in multithreaded programs. These
primitives help prevent :term:`race conditions <race condition>` and
coordinate thread execution. See also :term:`lock`.
t-string
t-strings
String literals prefixed with ``t`` or ``T`` are commonly called
@ -1535,19 +1383,6 @@ Glossary
See :ref:`Thread State and the Global Interpreter Lock <threads>` for more
information.
thread-safe
A module, function, or class that behaves correctly when used by multiple
threads concurrently. Thread-safe code uses appropriate
:term:`synchronization primitives <synchronization primitive>` like
:term:`locks <lock>` to protect shared mutable state, or is designed
to avoid shared mutable state entirely. In the
:term:`free-threaded <free threading>` build, built-in types like
:class:`dict`, :class:`list`, and :class:`set` use internal locking
to make many operations thread-safe, although thread safety is not
necessarily guaranteed. Code that is not thread-safe may experience
:term:`race conditions <race condition>` and :term:`data races <data race>`
when used in multi-threaded programs.
token
A small unit of source code, generated by the

View file

@ -1,7 +1,7 @@
.. _a-conceptual-overview-of-asyncio:
****************************************
A conceptual overview of :mod:`!asyncio`
A Conceptual Overview of :mod:`!asyncio`
****************************************
This :ref:`HOWTO <how-tos>` article seeks to help you build a sturdy mental
@ -37,15 +37,15 @@ In part 1, we'll cover the main, high-level building blocks of :mod:`!asyncio`:
the event loop, coroutine functions, coroutine objects, tasks, and ``await``.
==========
Event loop
Event Loop
==========
Everything in :mod:`!asyncio` happens relative to the event loop.
It's the star of the show, but prefers to work behind the scenes, managing
and coordinating resources.
It's the star of the show.
It's like an orchestra conductor.
It's behind the scenes managing resources.
Some power is explicitly granted to it, but a lot of its ability to get things
done comes from the respect and cooperation of its band members.
done comes from the respect and cooperation of its worker bees.
In more technical terms, the event loop contains a collection of jobs to be run.
Some jobs are added directly by you, and some indirectly by :mod:`!asyncio`.
@ -59,7 +59,7 @@ This process repeats indefinitely, with the event loop cycling endlessly
onwards.
If there are no more jobs pending execution, the event loop is smart enough to
rest and avoid needlessly wasting CPU cycles, and will come back when there's
more work to be done, such as when I/O operations complete or timers expire.
more work to be done.
Effective execution relies on jobs sharing well and cooperating; a greedy job
could hog control and leave the other jobs to starve, rendering the overall
@ -170,17 +170,14 @@ Roughly speaking, :ref:`tasks <asyncio-task-obj>` are coroutines (not coroutine
functions) tied to an event loop.
A task also maintains a list of callback functions whose importance will become
clear in a moment when we discuss :keyword:`await`.
The recommended way to create tasks is via :func:`asyncio.create_task`.
Creating a task automatically schedules it for execution (by adding a
callback to run it in the event loop's to-do list, that is, collection of jobs).
The recommended way to create tasks is via :func:`asyncio.create_task`.
:mod:`!asyncio` automatically associates tasks with the event loop for you.
This automatic association was purposely designed into :mod:`!asyncio` for
the sake of simplicity.
Without it, you'd have to keep track of the event loop object and pass it to
any coroutine function that wants to create tasks, adding redundant clutter
to your code.
Since there's only one event loop (in each thread), :mod:`!asyncio` takes care of
associating the task with the event loop for you. As such, there's no need
to specify the event loop.
::
@ -253,10 +250,6 @@ different ways::
In a crucial way, the behavior of ``await`` depends on the type of object
being awaited.
^^^^^^^^^^^^^^
Awaiting tasks
^^^^^^^^^^^^^^
Awaiting a task will cede control from the current task or coroutine to
the event loop.
In the process of relinquishing control, a few important things happen.
@ -288,10 +281,6 @@ This is a basic, yet reliable mental model.
In practice, the control handoffs are slightly more complex, but not by much.
In part 2, we'll walk through the details that make this possible.
^^^^^^^^^^^^^^^^^^^
Awaiting coroutines
^^^^^^^^^^^^^^^^^^^
**Unlike tasks, awaiting a coroutine does not hand control back to the event
loop!**
Wrapping a coroutine in a task first, then awaiting that would cede
@ -358,10 +347,8 @@ The design intentionally trades off some conceptual clarity around usage of
``await`` for improved performance.
Each time a task is awaited, control needs to be passed all the way up the
call stack to the event loop.
Then, the event loop needs to manage its internal state and work through
its processing logic to resume the next job.
That might sound minor, but in a large program with many ``await``\ s, that
overhead can add up to a non-negligible performance drag.
That might sound minor, but in a large program with many ``await`` statements and a deep
call stack, that overhead can add up to a meaningful performance drag.
------------------------------------------------
A conceptual overview part 2: the nuts and bolts
@ -377,8 +364,7 @@ and how to make your own asynchronous operators.
The inner workings of coroutines
================================
:mod:`!asyncio` leverages four components of Python to pass
around control.
:mod:`!asyncio` leverages four components to pass around control.
:meth:`coroutine.send(arg) <generator.send>` is the method used to start or
resume a coroutine.
@ -462,9 +448,9 @@ That might sound odd to you. You might be thinking:
That causes the error: ``SyntaxError: yield from not allowed in a coroutine.``
This was intentionally designed for the sake of simplicity -- mandating only
one way of using coroutines.
Despite that, ``yield from`` and ``await`` effectively do the same thing.
Initially ``yield`` was barred as well, but was re-accepted to allow for
async generators.
Despite that, ``yield from`` and ``await`` effectively do the same thing.
=======
Futures

View file

@ -45,12 +45,9 @@ single-phase initialization.
Multi-Phase Initialization
..........................
Extensions that use :ref:`multi-phase initialization <multi-phase-initialization>`
(functions like :c:func:`PyModuleDef_Init`,
:c:func:`PyModExport_* <PyModExport_modulename>` export hook,
:c:func:`PyModule_FromSlotsAndSpec`) should add a
:c:data:`Py_mod_gil` slot in the module definition.
If your extension supports older versions of CPython,
Extensions that use multi-phase initialization (i.e.,
:c:func:`PyModuleDef_Init`) should add a :c:data:`Py_mod_gil` slot in the
module definition. If your extension supports older versions of CPython,
you should guard the slot with a :c:data:`PY_VERSION_HEX` check.
::
@ -63,12 +60,18 @@ you should guard the slot with a :c:data:`PY_VERSION_HEX` check.
{0, NULL}
};
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
.m_slots = module_slots,
...
};
Single-Phase Initialization
...........................
Extensions that use legacy :ref:`single-phase initialization <single-phase-initialization>`
(that is, :c:func:`PyModule_Create`) should call :c:func:`PyUnstable_Module_SetGIL` to
Extensions that use single-phase initialization (i.e.,
:c:func:`PyModule_Create`) should call :c:func:`PyUnstable_Module_SetGIL` to
indicate that they support running with the GIL disabled. The function is
only defined in the free-threaded build, so you should guard the call with
``#ifdef Py_GIL_DISABLED`` to avoid compilation errors in the regular build.
@ -200,7 +203,7 @@ Memory Allocation APIs
Python's memory management C API provides functions in three different
:ref:`allocation domains <allocator-domains>`: "raw", "mem", and "object".
For thread-safety, the free-threaded build requires that only Python objects
are allocated using the object domain, and that all Python objects are
are allocated using the object domain, and that all Python object are
allocated using that domain. This differs from the prior Python versions,
where this was only a best practice and not a hard requirement.
@ -341,12 +344,12 @@ This means you cannot rely on nested critical sections to lock multiple objects
at once, as the inner critical section may suspend the outer ones. Instead, use
:c:macro:`Py_BEGIN_CRITICAL_SECTION2` to lock two objects simultaneously.
Note that the locks described above are only :c:type:`PyMutex` based locks.
Note that the locks described above are only :c:type:`!PyMutex` based locks.
The critical section implementation does not know about or affect other locking
mechanisms that might be in use, like POSIX mutexes. Also note that while
blocking on any :c:type:`PyMutex` causes the critical sections to be
blocking on any :c:type:`!PyMutex` causes the critical sections to be
suspended, only the mutexes that are part of the critical sections are
released. If :c:type:`PyMutex` is used without a critical section, it will
released. If :c:type:`!PyMutex` is used without a critical section, it will
not be released and therefore does not get the same deadlock avoidance.
Important Considerations
@ -394,8 +397,7 @@ The wheels, shared libraries, and binaries are indicated by a ``t`` suffix.
* `pypa/manylinux <https://github.com/pypa/manylinux>`_ supports the
free-threaded build, with the ``t`` suffix, such as ``python3.13t``.
* `pypa/cibuildwheel <https://github.com/pypa/cibuildwheel>`_ supports the
free-threaded build on Python 3.13 and 3.14. On Python 3.14, free-threaded
wheels will be built by default. On Python 3.13, you will need to set
free-threaded build if you set
`CIBW_ENABLE to cpython-freethreading <https://cibuildwheel.pypa.io/en/stable/options/#enable>`_.
Limited C API and Stable ABI

View file

@ -11,7 +11,9 @@ available processing power by running threads in parallel on available CPU cores
While not all software will benefit from this automatically, programs
designed with threading in mind will run faster on multi-core hardware.
Some third-party packages, in particular ones
The free-threaded mode is working and continues to be improved, but
there is some additional overhead in single-threaded workloads compared
to the regular build. Additionally, third-party packages, in particular ones
with an :term:`extension module`, may not be ready for use in a
free-threaded build, and will re-enable the :term:`GIL`.
@ -99,42 +101,60 @@ This section describes known limitations of the free-threaded CPython build.
Immortalization
---------------
In the free-threaded build, some objects are :term:`immortal`.
The free-threaded build of the 3.13 release makes some objects :term:`immortal`.
Immortal objects are not deallocated and have reference counts that are
never modified. This is done to avoid reference count contention that would
prevent efficient multi-threaded scaling.
As of the 3.14 release, immortalization is limited to:
An object will be made immortal when a new thread is started for the first time
after the main thread is running. The following objects are immortalized:
* Code constants: numeric literals, string literals, and tuple literals
composed of other constants.
* Strings interned by :func:`sys.intern`.
* :ref:`function <user-defined-funcs>` objects declared at the module level
* :ref:`method <instance-methods>` descriptors
* :ref:`code <code-objects>` objects
* :term:`module` objects and their dictionaries
* :ref:`classes <classes>` (type objects)
Because immortal objects are never deallocated, applications that create many
objects of these types may see increased memory usage. This is expected to be
addressed in the 3.14 release.
Additionally, numeric and string literals in the code as well as strings
returned by :func:`sys.intern` are also immortalized. This behavior is
expected to remain in the 3.14 free-threaded build.
Frame objects
-------------
It is not safe to access :attr:`frame.f_locals` from a :ref:`frame <frame-objects>`
object if that frame is currently executing in another thread, and doing so may
crash the interpreter.
It is not safe to access :ref:`frame <frame-objects>` objects from other
threads and doing so may cause your program to crash . This means that
:func:`sys._current_frames` is generally not safe to use in a free-threaded
build. Functions like :func:`inspect.currentframe` and :func:`sys._getframe`
are generally safe as long as the resulting frame object is not passed to
another thread.
Iterators
---------
It is generally not thread-safe to access the same iterator object from
multiple threads concurrently, and threads may see duplicate or missing
elements.
Sharing the same iterator object between multiple threads is generally not
safe and threads may see duplicate or missing elements when iterating or crash
the interpreter.
Single-threaded performance
---------------------------
The free-threaded build has additional overhead when executing Python code
compared to the default GIL-enabled build. The amount of overhead depends
on the workload and hardware. On the pyperformance benchmark suite, the
average overhead ranges from about 1% on macOS aarch64 to 8% on x86-64 Linux
systems.
compared to the default GIL-enabled build. In 3.13, this overhead is about
40% on the `pyperformance <https://pyperformance.readthedocs.io/>`_ suite.
Programs that spend most of their time in C extensions or I/O will see
less of an impact. The largest impact is because the specializing adaptive
interpreter (:pep:`659`) is disabled in the free-threaded build. We expect
to re-enable it in a thread-safe way in the 3.14 release. This overhead is
expected to be reduced in upcoming Python release. We are aiming for an
overhead of 10% or less on the pyperformance suite compared to the default
GIL-enabled build.
Behavioral changes

View file

@ -4,7 +4,7 @@
Functional Programming HOWTO
********************************
:Author: \A. M. Kuchling
:Author: A. M. Kuchling
:Release: 0.32
In this document, we'll take a tour of Python's features suitable for

View file

@ -136,7 +136,7 @@ enabled::
at Objects/unicodeobject.c:551
#7 0x0000000000440d94 in PyUnicodeUCS2_FromString (u=0x5c2b8d "__lltrace__") at Objects/unicodeobject.c:569
#8 0x0000000000584abd in PyDict_GetItemString (v=
{'Yuck': <type at remote 0xad4730>, '__builtins__': <module at remote 0x7ffff7fd5ee8>, '__file__': 'Lib/test/crashers/nasty_eq_vs_dict.py', '__package__': None, 'y': <Yuck(i=0) at remote 0xaacd80>, 'dict': {0: 0, 1: 1, 2: 2, 3: 3}, '__name__': '__main__', 'z': <Yuck(i=0) at remote 0xaace60>, '__doc__': None}, key=
{'Yuck': <type at remote 0xad4730>, '__builtins__': <module at remote 0x7ffff7fd5ee8>, '__file__': 'Lib/test/crashers/nasty_eq_vs_dict.py', '__package__': None, 'y': <Yuck(i=0) at remote 0xaacd80>, 'dict': {0: 0, 1: 1, 2: 2, 3: 3}, '__cached__': None, '__name__': '__main__', 'z': <Yuck(i=0) at remote 0xaace60>, '__doc__': None}, key=
0x5c2b8d "__lltrace__") at Objects/dictobject.c:2171
Notice how the dictionary argument to ``PyDict_GetItemString`` is displayed

Some files were not shown because too many files have changed in this diff Show more