mirror of
https://github.com/python/cpython.git
synced 2026-05-04 09:31:02 +00:00
Merge branch 'main' into issue-138750
This commit is contained in:
commit
9be4899b20
2895 changed files with 336519 additions and 103634 deletions
73
.devcontainer/wasi/devcontainer.json
Normal file
73
.devcontainer/wasi/devcontainer.json
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
.gitattributes
vendored
12
.gitattributes
vendored
|
|
@ -34,6 +34,9 @@ Lib/test/xmltestdata/* noeol
|
|||
Lib/venv/scripts/common/activate text eol=lf
|
||||
Lib/venv/scripts/posix/* text eol=lf
|
||||
|
||||
# Prevent GitHub's web conflict editor from converting LF to CRLF
|
||||
*.rst text eol=lf
|
||||
|
||||
# CRLF files
|
||||
[attr]dos text eol=crlf
|
||||
|
||||
|
|
@ -68,6 +71,7 @@ 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
|
||||
|
|
@ -82,13 +86,19 @@ 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
|
||||
Modules/_testinternalcapi/test_cases.c.h generated
|
||||
Modules/_testinternalcapi/test_targets.h generated
|
||||
Objects/typeslots.inc generated
|
||||
PC/python3dll.c generated
|
||||
Parser/parser.c generated
|
||||
|
|
@ -99,8 +109,10 @@ Python/executor_cases.c.h generated
|
|||
Python/generated_cases.c.h generated
|
||||
Python/optimizer_cases.c.h generated
|
||||
Python/opcode_targets.h generated
|
||||
Python/record_functions.c.h generated
|
||||
Python/stdlib_module_names.h generated
|
||||
Tools/peg_generator/pegen/grammar_parser.py generated
|
||||
aclocal.m4 generated
|
||||
configure generated
|
||||
*.min.js generated
|
||||
package-lock.json generated
|
||||
|
|
|
|||
147
.github/CODEOWNERS
vendored
147
.github/CODEOWNERS
vendored
|
|
@ -63,9 +63,10 @@
|
|||
.azure-pipelines/ @AA-Turner
|
||||
|
||||
# GitHub & related scripts
|
||||
.github/ @ezio-melotti @hugovk @AA-Turner
|
||||
Tools/build/compute-changes.py @AA-Turner
|
||||
Tools/build/verify_ensurepip_wheels.py @AA-Turner @pfmoore @pradyunsg
|
||||
.github/ @ezio-melotti @hugovk @AA-Turner @webknjaz
|
||||
Tools/build/compute-changes.py @AA-Turner @hugovk @webknjaz
|
||||
Lib/test/test_tools/test_compute_changes.py @AA-Turner @hugovk @webknjaz
|
||||
Tools/build/verify_ensurepip_wheels.py @AA-Turner @pfmoore @pradyunsg
|
||||
|
||||
# Pre-commit
|
||||
.pre-commit-config.yaml @hugovk
|
||||
|
|
@ -82,10 +83,14 @@ Tools/patchcheck/ @AA-Turner
|
|||
# Autotools
|
||||
configure* @erlend-aasland @corona10 @AA-Turner @emmatyping
|
||||
Makefile.pre.in @erlend-aasland @AA-Turner @emmatyping
|
||||
Modules/makesetup @erlend-aasland @AA-Turner @emmatyping
|
||||
Modules/Setup* @erlend-aasland @AA-Turner @emmatyping
|
||||
Modules/makesetup @emmatyping
|
||||
Tools/build/regen-configure.sh @AA-Turner
|
||||
|
||||
# generate-build-details
|
||||
Tools/build/generate-build-details.py @FFY00
|
||||
Lib/test/test_build_details.py @FFY00
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Documentation
|
||||
|
|
@ -95,17 +100,18 @@ Tools/build/regen-configure.sh @AA-Turner
|
|||
InternalDocs/ @AA-Turner
|
||||
|
||||
# Tools, Configuration, etc
|
||||
Doc/Makefile @AA-Turner @hugovk
|
||||
Doc/_static/ @AA-Turner @hugovk
|
||||
Doc/conf.py @AA-Turner @hugovk
|
||||
Doc/make.bat @AA-Turner @hugovk
|
||||
Doc/requirements.txt @AA-Turner @hugovk
|
||||
Doc/tools/ @AA-Turner @hugovk
|
||||
Doc/Makefile @AA-Turner @hugovk @StanFromIreland
|
||||
Doc/_static/ @AA-Turner @hugovk @StanFromIreland
|
||||
Doc/conf.py @AA-Turner @hugovk @StanFromIreland
|
||||
Doc/make.bat @AA-Turner @hugovk @StanFromIreland
|
||||
Doc/requirements.txt @AA-Turner @hugovk @StanFromIreland
|
||||
Doc/tools/ @AA-Turner @hugovk @StanFromIreland
|
||||
|
||||
# PR Previews
|
||||
.readthedocs.yml @AA-Turner
|
||||
|
||||
# Sections
|
||||
Doc/c-api/ @ZeroIntensity
|
||||
Doc/reference/ @willingc @AA-Turner
|
||||
Doc/whatsnew/ @AA-Turner
|
||||
|
||||
|
|
@ -122,8 +128,13 @@ 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
|
||||
Modules/_xxtestfuzz/ @python/fuzzers
|
||||
Lib/test/test_xxtestfuzz.py @python/fuzzers
|
||||
.github/workflows/reusable-cifuzz.yml @python/fuzzers
|
||||
|
||||
# Limited C API & Stable ABI
|
||||
Doc/c-api/stable.rst @encukou
|
||||
|
|
@ -136,6 +147,9 @@ Misc/externals.spdx.json @sethmlarson
|
|||
Misc/sbom.spdx.json @sethmlarson
|
||||
Tools/build/generate_sbom.py @sethmlarson
|
||||
|
||||
# ABI check
|
||||
Misc/libabigail.abignore @encukou
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Platform Support
|
||||
|
|
@ -150,6 +164,7 @@ Lib/test/test_android.py @mhsmith @freakboy3742
|
|||
# iOS
|
||||
Doc/using/ios.rst @freakboy3742
|
||||
Lib/_ios_support.py @freakboy3742
|
||||
Apple/ @freakboy3742
|
||||
iOS/ @freakboy3742
|
||||
|
||||
# macOS
|
||||
|
|
@ -165,9 +180,10 @@ Tools/wasm/config.site-wasm32-emscripten @freakboy3742 @emmatyping
|
|||
Tools/wasm/emscripten @freakboy3742 @emmatyping
|
||||
|
||||
# WebAssembly (WASI)
|
||||
Tools/wasm/wasi-env @brettcannon @emmatyping
|
||||
Tools/wasm/wasi.py @brettcannon @emmatyping
|
||||
Tools/wasm/wasi @brettcannon @emmatyping
|
||||
Platforms/WASI @brettcannon @emmatyping @savannahostrowski
|
||||
Tools/wasm/wasi-env @brettcannon @emmatyping @savannahostrowski
|
||||
Tools/wasm/wasi.py @brettcannon @emmatyping @savannahostrowski
|
||||
Tools/wasm/wasi @brettcannon @emmatyping @savannahostrowski
|
||||
|
||||
# Windows
|
||||
PC/ @python/windows-team
|
||||
|
|
@ -240,51 +256,57 @@ Lib/test/test_getpath.py @FFY00
|
|||
Modules/getpath* @FFY00
|
||||
|
||||
# Hashing / ``hash()`` and related
|
||||
Include/cpython/pyhash.h @gpshead @picnixz @tiran
|
||||
Include/internal/pycore_pyhash.h @gpshead @picnixz @tiran
|
||||
Include/pyhash.h @gpshead @picnixz @tiran
|
||||
Python/pyhash.c @gpshead @picnixz @tiran
|
||||
Include/cpython/pyhash.h @gpshead @picnixz
|
||||
Include/internal/pycore_pyhash.h @gpshead @picnixz
|
||||
Include/pyhash.h @gpshead @picnixz
|
||||
Python/pyhash.c @gpshead @picnixz
|
||||
|
||||
# The import system (including importlib)
|
||||
**/*import* @brettcannon @ericsnowcurrently @ncoghlan @warsaw
|
||||
Python/import.c @brettcannon @ericsnowcurrently @ncoghlan @warsaw @kumaraditya303
|
||||
**/*import* @brettcannon @ericsnowcurrently @ncoghlan @warsaw @FFY00
|
||||
Python/import.c @brettcannon @ericsnowcurrently @ncoghlan @warsaw @FFY00 @kumaraditya303
|
||||
**/*freeze* @ericsnowcurrently
|
||||
**/*frozen* @ericsnowcurrently
|
||||
**/*modsupport* @ericsnowcurrently
|
||||
**/*modulefinder* @ericsnowcurrently
|
||||
**/*modulefinder* @ericsnowcurrently @FFY00
|
||||
**/*moduleobject* @ericsnowcurrently
|
||||
**/*multiphase* @ericsnowcurrently
|
||||
**/*pkgutil* @ericsnowcurrently
|
||||
**/*pkgutil* @ericsnowcurrently @FFY00
|
||||
**/*pythonrun* @ericsnowcurrently
|
||||
**/*runpy* @ericsnowcurrently
|
||||
**/*runpy* @ericsnowcurrently @FFY00
|
||||
**/*singlephase* @ericsnowcurrently
|
||||
Doc/c-api/module.rst @ericsnowcurrently
|
||||
Lib/test/test_module/ @ericsnowcurrently
|
||||
Python/dynload_*.c @ericsnowcurrently
|
||||
Python/dynload_*.c @ericsnowcurrently @FFY00
|
||||
|
||||
# Initialisation
|
||||
**/*initconfig* @ericsnowcurrently
|
||||
**/*pathconfig* @ericsnowcurrently
|
||||
**/*preconfig* @ericsnowcurrently
|
||||
**/*initconfig* @ericsnowcurrently @FFY00
|
||||
**/*pathconfig* @ericsnowcurrently @FFY00
|
||||
**/*preconfig* @ericsnowcurrently @FFY00
|
||||
Doc/library/sys_path_init.rst @FFY00
|
||||
Doc/c-api/init_config.rst @FFY00
|
||||
|
||||
# Interpreter main program
|
||||
Modules/main.c @ericsnowcurrently
|
||||
Programs/_bootstrap_python.c @ericsnowcurrently
|
||||
Programs/python.c @ericsnowcurrently
|
||||
Modules/main.c @ericsnowcurrently @FFY00
|
||||
Programs/_bootstrap_python.c @ericsnowcurrently @FFY00
|
||||
Programs/python.c @ericsnowcurrently @FFY00
|
||||
|
||||
# JIT
|
||||
.github/workflows/jit.yml @savannahostrowski
|
||||
Include/internal/pycore_jit.h @brandtbucher @savannahostrowski @diegorusso
|
||||
Python/jit.c @brandtbucher @savannahostrowski @diegorusso
|
||||
Tools/jit/ @brandtbucher @savannahostrowski @diegorusso
|
||||
InternalDocs/jit.md @brandtbucher @savannahostrowski @diegorusso @AA-Turner
|
||||
|
||||
# Lazy imports (PEP 810)
|
||||
Objects/lazyimportobject.c @yhg1s @DinoV @pablogsal
|
||||
Include/internal/pycore_lazyimportobject.h @yhg1s @DinoV @pablogsal
|
||||
Lib/test/test_lazy_import @yhg1s @DinoV @pablogsal
|
||||
|
||||
# Micro-op / μop / Tier 2 Optimiser
|
||||
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
|
||||
Python/optimizer.c @markshannon @Fidget-Spinner
|
||||
Python/optimizer_analysis.c @markshannon @tomasr8 @Fidget-Spinner @savannahostrowski
|
||||
Python/optimizer_bytecodes.c @markshannon @tomasr8 @Fidget-Spinner @savannahostrowski
|
||||
Python/optimizer_symbols.c @markshannon @tomasr8 @Fidget-Spinner @savannahostrowski
|
||||
|
||||
# Parser, Lexer, and Grammar
|
||||
Grammar/python.gram @pablogsal @lysnikolaou
|
||||
|
|
@ -296,8 +318,8 @@ Tools/peg_generator/ @pablogsal @lysnikolaou
|
|||
|
||||
# Runtime state/lifecycle
|
||||
**/*gil* @ericsnowcurrently
|
||||
**/*pylifecycle* @ericsnowcurrently @ZeroIntensity
|
||||
**/*pystate* @ericsnowcurrently @ZeroIntensity
|
||||
**/*pylifecycle* @ericsnowcurrently @ZeroIntensity @FFY00
|
||||
**/*pystate* @ericsnowcurrently @ZeroIntensity @FFY00
|
||||
Include/internal/pycore_*_init.h @ericsnowcurrently
|
||||
Include/internal/pycore_*_state.h @ericsnowcurrently
|
||||
Include/internal/pycore_atexit.h @ericsnowcurrently
|
||||
|
|
@ -314,7 +336,7 @@ Tools/build/generate_global_objects.py @ericsnowcurrently
|
|||
# Remote Debugging
|
||||
Python/remote_debug.h @pablogsal
|
||||
Python/remote_debugging.c @pablogsal
|
||||
Modules/_remote_debugging_module.c @pablogsal @ambv @1st1
|
||||
Modules/_remote_debugging/ @pablogsal
|
||||
|
||||
# Sub-Interpreters
|
||||
**/*crossinterp* @ericsnowcurrently
|
||||
|
|
@ -370,14 +392,14 @@ Lib/calendar.py @AA-Turner
|
|||
Lib/test/test_calendar.py @AA-Turner
|
||||
|
||||
# Cryptographic Primitives and Applications
|
||||
**/*hashlib* @gpshead @picnixz @tiran
|
||||
**/*hashopenssl* @gpshead @picnixz @tiran
|
||||
**/*hashlib* @gpshead @picnixz
|
||||
**/*hashopenssl* @gpshead @picnixz
|
||||
**/*hmac* @gpshead @picnixz
|
||||
**/*ssl* @gpshead @picnixz
|
||||
Modules/_hacl/ @gpshead @picnixz
|
||||
Modules/*blake* @gpshead @picnixz @tiran
|
||||
Modules/*md5* @gpshead @picnixz @tiran
|
||||
Modules/*sha* @gpshead @picnixz @tiran
|
||||
Modules/*blake* @gpshead @picnixz
|
||||
Modules/*md5* @gpshead @picnixz
|
||||
Modules/*sha* @gpshead @picnixz
|
||||
|
||||
# Codecs
|
||||
Modules/cjkcodecs/ @corona10
|
||||
|
|
@ -405,14 +427,19 @@ Lib/dataclasses.py @ericvsmith
|
|||
Lib/test/test_dataclasses/ @ericvsmith
|
||||
|
||||
# Dates and times
|
||||
Doc/**/*time.rst @pganssle @abalkin
|
||||
Include/datetime.h @pganssle @abalkin
|
||||
Include/internal/pycore_time.h @pganssle @abalkin
|
||||
Lib/*time.py @pganssle @abalkin
|
||||
Lib/test/datetimetester.py @pganssle @abalkin
|
||||
Lib/test/test_*time.py @pganssle @abalkin
|
||||
Modules/*time* @pganssle @abalkin
|
||||
Python/pytime.c @pganssle @abalkin
|
||||
Doc/**/*time.rst @pganssle @StanFromIreland
|
||||
Doc/library/datetime-* @pganssle @StanFromIreland
|
||||
Doc/library/zoneinfo.rst @pganssle @StanFromIreland
|
||||
Include/datetime.h @pganssle @StanFromIreland
|
||||
Include/internal/pycore_time.h @pganssle @StanFromIreland
|
||||
Lib/test/test_zoneinfo/ @pganssle @StanFromIreland
|
||||
Lib/zoneinfo/ @pganssle @StanFromIreland
|
||||
Lib/*time.py @pganssle @StanFromIreland
|
||||
Lib/test/datetimetester.py @pganssle @StanFromIreland
|
||||
Lib/test/test_*time.py @pganssle @StanFromIreland
|
||||
Modules/*zoneinfo* @pganssle @StanFromIreland
|
||||
Modules/*time* @pganssle @StanFromIreland
|
||||
Python/pytime.c @pganssle @StanFromIreland
|
||||
|
||||
# Dbm
|
||||
Doc/library/dbm.rst @corona10 @erlend-aasland @serhiy-storchaka
|
||||
|
|
@ -451,8 +478,9 @@ Lib/test/test_functools.py @rhettinger
|
|||
Modules/_functoolsmodule.c @rhettinger
|
||||
|
||||
# Garbage collector
|
||||
Modules/gcmodule.c @pablogsal
|
||||
Doc/library/gc.rst @pablogsal
|
||||
Modules/gcmodule.c @pablogsal
|
||||
Doc/library/gc.rst @pablogsal
|
||||
InternalDocs/garbage_collector.md @pablogsal
|
||||
|
||||
# Gettext
|
||||
Doc/library/gettext.rst @tomasr8
|
||||
|
|
@ -479,13 +507,13 @@ Lib/idlelib/ @terryjreedy
|
|||
Lib/turtledemo/ @terryjreedy
|
||||
|
||||
# importlib.metadata
|
||||
Doc/library/importlib.metadata.rst @jaraco @warsaw
|
||||
Lib/importlib/metadata/ @jaraco @warsaw
|
||||
Lib/test/test_importlib/metadata/ @jaraco @warsaw
|
||||
Doc/library/importlib.metadata.rst @jaraco @warsaw @FFY00
|
||||
Lib/importlib/metadata/ @jaraco @warsaw @FFY00
|
||||
Lib/test/test_importlib/metadata/ @jaraco @warsaw @FFY00
|
||||
|
||||
# importlib.resources
|
||||
Doc/library/importlib.resources.abc.rst @jaraco @warsaw
|
||||
Doc/library/importlib.resources.rst @jaraco @warsaw
|
||||
Doc/library/importlib.resources.abc.rst @jaraco @warsaw @FFY00
|
||||
Doc/library/importlib.resources.rst @jaraco @warsaw @FFY00
|
||||
Lib/importlib/resources/ @jaraco @warsaw @FFY00
|
||||
Lib/test/test_importlib/resources/ @jaraco @warsaw @FFY00
|
||||
|
||||
|
|
@ -525,6 +553,11 @@ 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
|
||||
|
|
|
|||
20
.github/CONTRIBUTING.rst
vendored
20
.github/CONTRIBUTING.rst
vendored
|
|
@ -28,23 +28,23 @@ 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. The key points of
|
||||
our workflow that are not covered by a bot or status check are:
|
||||
comments they leave and their "Details" links, respectively.
|
||||
|
||||
- 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``
|
||||
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.
|
||||
|
||||
|
||||
Setting Expectations
|
||||
--------------------
|
||||
Due to the fact that this project is entirely volunteer-run (i.e. no one is paid
|
||||
to work on Python full-time), we unfortunately can make no guarantees as to if
|
||||
Due to the fact that this project is run by volunteers,
|
||||
unfortunately we cannot make any guarantees as to if
|
||||
or when a core developer will get around to reviewing your pull request.
|
||||
If no core developer has done a review or responded to changes made because of a
|
||||
"changes requested" review, please feel free to email python-dev to ask if
|
||||
someone could take a look at your pull request.
|
||||
"changes requested" review within a month, you can ask for someone to
|
||||
review your pull request via a post in the `Core Development Discourse
|
||||
category <https://discuss.python.org/c/core-dev/23>`__.
|
||||
|
||||
|
||||
Code of Conduct
|
||||
|
|
|
|||
3
.github/ISSUE_TEMPLATE/config.yml
vendored
3
.github/ISSUE_TEMPLATE/config.yml
vendored
|
|
@ -5,3 +5,6 @@ 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"
|
||||
|
|
|
|||
9
.github/ISSUE_TEMPLATE/documentation.md
vendored
9
.github/ISSUE_TEMPLATE/documentation.md
vendored
|
|
@ -1,9 +0,0 @@
|
|||
---
|
||||
name: Documentation
|
||||
about: Report a problem with the documentation
|
||||
labels: "docs"
|
||||
---
|
||||
|
||||
# Documentation
|
||||
|
||||
(A clear and concise description of the issue.)
|
||||
16
.github/ISSUE_TEMPLATE/documentation.yml
vendored
Normal file
16
.github/ISSUE_TEMPLATE/documentation.yml
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
name: Documentation
|
||||
description: Report a problem with the documentation
|
||||
labels: ["docs"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
> [!NOTE]
|
||||
> Trivial changes (for example typos) don’t require an issue before opening a PR.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: "Documentation"
|
||||
description: "A clear and concise description of the issue. Include a link to the page."
|
||||
validations:
|
||||
required: true
|
||||
4
.github/actionlint.yaml
vendored
4
.github/actionlint.yaml
vendored
|
|
@ -1,7 +1,3 @@
|
|||
self-hosted-runner:
|
||||
# Pending https://github.com/rhysd/actionlint/issues/533
|
||||
labels: ["windows-11-arm"]
|
||||
|
||||
config-variables: null
|
||||
|
||||
paths:
|
||||
|
|
|
|||
15
.github/dependabot.yml
vendored
15
.github/dependabot.yml
vendored
|
|
@ -3,7 +3,7 @@ updates:
|
|||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "quarterly"
|
||||
labels:
|
||||
- "skip issue"
|
||||
- "skip news"
|
||||
|
|
@ -12,10 +12,21 @@ updates:
|
|||
update-types:
|
||||
- "version-update:semver-minor"
|
||||
- "version-update:semver-patch"
|
||||
groups:
|
||||
actions:
|
||||
patterns:
|
||||
- "*"
|
||||
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:
|
||||
interval: "monthly"
|
||||
interval: "quarterly"
|
||||
labels:
|
||||
- "skip issue"
|
||||
- "skip news"
|
||||
cooldown:
|
||||
default-days: 14
|
||||
|
|
|
|||
4
.github/workflows/add-issue-header.yml
vendored
4
.github/workflows/add-issue-header.yml
vendored
|
|
@ -12,6 +12,8 @@ on:
|
|||
# Only ever run once
|
||||
- opened
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
add-header:
|
||||
|
|
@ -20,7 +22,7 @@ jobs:
|
|||
issues: write
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
- uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
# language=JavaScript
|
||||
script: |
|
||||
|
|
|
|||
433
.github/workflows/build.yml
vendored
433
.github/workflows/build.yml
vendored
|
|
@ -64,7 +64,7 @@ jobs:
|
|||
run: |
|
||||
apt update && apt install git -yq
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
|
@ -101,28 +101,16 @@ jobs:
|
|||
needs: build-context
|
||||
if: needs.build-context.outputs.run-tests == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
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
|
||||
|
|
@ -153,6 +141,14 @@ jobs:
|
|||
if: github.event_name == 'pull_request' # $GITHUB_EVENT_NAME
|
||||
run: make check-c-globals
|
||||
|
||||
check-c-api-docs:
|
||||
name: C API Docs
|
||||
needs: build-context
|
||||
if: >-
|
||||
needs.build-context.outputs.run-tests == 'true'
|
||||
|| needs.build-context.outputs.run-docs == 'true'
|
||||
uses: ./.github/workflows/reusable-check-c-api-docs.yml
|
||||
|
||||
build-windows:
|
||||
name: >-
|
||||
Windows
|
||||
|
|
@ -169,13 +165,21 @@ jobs:
|
|||
free-threading:
|
||||
- false
|
||||
- true
|
||||
interpreter:
|
||||
- switch-case
|
||||
exclude:
|
||||
# Skip Win32 on free-threaded builds
|
||||
- { arch: Win32, free-threading: true }
|
||||
include:
|
||||
# msvc::musttail is currently only supported on x64,
|
||||
# and only supported on 3.15+.
|
||||
- { arch: x64, free-threading: false, interpreter: tail-call }
|
||||
- { arch: x64, free-threading: true, interpreter: tail-call }
|
||||
uses: ./.github/workflows/reusable-windows.yml
|
||||
with:
|
||||
arch: ${{ matrix.arch }}
|
||||
free-threading: ${{ matrix.free-threading }}
|
||||
interpreter: ${{ matrix.interpreter }}
|
||||
|
||||
build-windows-msi:
|
||||
# ${{ '' } is a hack to nest jobs under the same sidebar category.
|
||||
|
|
@ -198,32 +202,23 @@ jobs:
|
|||
macOS
|
||||
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
|
||||
needs: build-context
|
||||
if: needs.build-context.outputs.run-tests == 'true'
|
||||
if: needs.build-context.outputs.run-macos == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Cirrus and macos-14 are M1, macos-13 is default GHA Intel.
|
||||
# macOS 13 only runs tests against the GIL-enabled CPython.
|
||||
# Cirrus used for upstream, macos-14 for forks.
|
||||
# macos-26 is Apple Silicon, macos-15-intel is Intel.
|
||||
# macos-15-intel only runs tests against the GIL-enabled CPython.
|
||||
os:
|
||||
- ghcr.io/cirruslabs/macos-runner:sonoma
|
||||
- macos-14
|
||||
- macos-13
|
||||
is-fork: # only used for the exclusion trick
|
||||
- ${{ github.repository_owner != 'python' }}
|
||||
- macos-26
|
||||
- macos-15-intel
|
||||
free-threading:
|
||||
- false
|
||||
- true
|
||||
exclude:
|
||||
- os: ghcr.io/cirruslabs/macos-runner:sonoma
|
||||
is-fork: true
|
||||
- os: macos-14
|
||||
is-fork: false
|
||||
- os: macos-13
|
||||
- os: macos-15-intel
|
||||
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 }}
|
||||
|
||||
|
|
@ -233,7 +228,7 @@ jobs:
|
|||
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
|
||||
${{ fromJSON(matrix.bolt) && '(bolt)' || '' }}
|
||||
needs: build-context
|
||||
if: needs.build-context.outputs.run-tests == 'true'
|
||||
if: needs.build-context.outputs.run-ubuntu == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -253,195 +248,160 @@ jobs:
|
|||
# BOLT currently crashes during instrumentation on aarch64
|
||||
- os: ubuntu-24.04-arm
|
||||
bolt: true
|
||||
include:
|
||||
# Enable CPU-intensive tests on ARM (default build only)
|
||||
- os: ubuntu-24.04-arm
|
||||
bolt: false
|
||||
free-threading: false
|
||||
test-opts: '-u cpu'
|
||||
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 }}
|
||||
test-opts: ${{ matrix.test-opts || '' }}
|
||||
|
||||
build-ubuntu-ssltests-openssl:
|
||||
name: 'Ubuntu SSL tests with OpenSSL'
|
||||
build-ubuntu-ssltests:
|
||||
name: 'Ubuntu SSL tests'
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
needs: build-context
|
||||
if: needs.build-context.outputs.run-tests == 'true'
|
||||
if: needs.build-context.outputs.run-ubuntu == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04]
|
||||
# Keep 1.1.1w in our list despite it being upstream EOL and otherwise
|
||||
# unsupported as it most resembles other 1.1.1-work-a-like ssl APIs
|
||||
# supported by important vendors such as AWS-LC.
|
||||
openssl_ver: [1.1.1w, 3.0.17, 3.2.5, 3.3.4, 3.4.2, 3.5.2]
|
||||
# See Tools/ssl/make_ssl_data.py for notes on adding a new version
|
||||
ssllib:
|
||||
# See Tools/ssl/make_ssl_data.py for notes on adding a new version
|
||||
## OpenSSL
|
||||
# Keep 1.1.1w in our list despite it being upstream EOL and otherwise
|
||||
# unsupported as it most resembles other 1.1.1-work-a-like ssl APIs
|
||||
# supported by important vendors such as AWS-LC.
|
||||
- { name: openssl, version: 1.1.1w }
|
||||
- { name: openssl, version: 3.0.19 }
|
||||
- { name: openssl, version: 3.3.6 }
|
||||
- { name: openssl, version: 3.4.4 }
|
||||
- { name: openssl, version: 3.5.5 }
|
||||
- { name: openssl, version: 3.6.1 }
|
||||
## AWS-LC
|
||||
- { name: aws-lc, version: 1.68.0 }
|
||||
env:
|
||||
OPENSSL_VER: ${{ matrix.openssl_ver }}
|
||||
SSLLIB_VER: ${{ matrix.ssllib.version }}
|
||||
MULTISSL_DIR: ${{ github.workspace }}/multissl
|
||||
OPENSSL_DIR: ${{ github.workspace }}/multissl/openssl/${{ matrix.openssl_ver }}
|
||||
LD_LIBRARY_PATH: ${{ github.workspace }}/multissl/openssl/${{ matrix.openssl_ver }}/lib
|
||||
SSLLIB_DIR: ${{ github.workspace }}/multissl/${{ matrix.ssllib.name }}/${{ matrix.ssllib.version }}
|
||||
LD_LIBRARY_PATH: ${{ github.workspace }}/multissl/${{ matrix.ssllib.name }}/${{ matrix.ssllib.version }}/lib
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
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: Install dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: Configure OpenSSL env vars
|
||||
run: |
|
||||
echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> "$GITHUB_ENV"
|
||||
echo "OPENSSL_DIR=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}" >> "$GITHUB_ENV"
|
||||
echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> "$GITHUB_ENV"
|
||||
- name: 'Restore OpenSSL build'
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v4
|
||||
- name: 'Restore SSL library build'
|
||||
id: cache-ssl-lib
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
|
||||
key: ${{ matrix.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
|
||||
- name: Install OpenSSL
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
run: python3 Tools/ssl/multissltests.py --steps=library --base-directory "$MULTISSL_DIR" --openssl "$OPENSSL_VER" --system Linux
|
||||
- name: Add ccache to PATH
|
||||
run: |
|
||||
echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: false
|
||||
- name: Configure CPython
|
||||
run: ./configure CFLAGS="-fdiagnostics-format=json" --config-cache --enable-slower-safety --with-pydebug --with-openssl="$OPENSSL_DIR"
|
||||
- name: Build CPython
|
||||
run: make -j4
|
||||
- name: Display build info
|
||||
run: make pythoninfo
|
||||
- name: SSL tests
|
||||
run: ./python Lib/test/ssltests.py
|
||||
|
||||
build-ubuntu-ssltests-awslc:
|
||||
name: 'Ubuntu SSL tests with AWS-LC'
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
needs: build-context
|
||||
if: needs.build-context.outputs.run-tests == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04]
|
||||
awslc_ver: [1.55.0]
|
||||
env:
|
||||
AWSLC_VER: ${{ matrix.awslc_ver}}
|
||||
MULTISSL_DIR: ${{ github.workspace }}/multissl
|
||||
OPENSSL_DIR: ${{ github.workspace }}/multissl/aws-lc/${{ matrix.awslc_ver }}
|
||||
LD_LIBRARY_PATH: ${{ github.workspace }}/multissl/aws-lc/${{ matrix.awslc_ver }}/lib
|
||||
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: Install dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: Configure SSL lib env vars
|
||||
run: |
|
||||
echo "MULTISSL_DIR=${GITHUB_WORKSPACE}/multissl" >> "$GITHUB_ENV"
|
||||
echo "OPENSSL_DIR=${GITHUB_WORKSPACE}/multissl/aws-lc/${AWSLC_VER}" >> "$GITHUB_ENV"
|
||||
echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/aws-lc/${AWSLC_VER}/lib" >> "$GITHUB_ENV"
|
||||
- name: 'Restore AWS-LC build'
|
||||
id: cache-aws-lc
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ./multissl/aws-lc/${{ matrix.awslc_ver }}
|
||||
key: ${{ matrix.os }}-multissl-aws-lc-${{ matrix.awslc_ver }}
|
||||
- name: Install AWS-LC
|
||||
if: steps.cache-aws-lc.outputs.cache-hit != 'true'
|
||||
path: ./multissl/${{ matrix.ssllib.name }}/${{ matrix.ssllib.version }}
|
||||
key: ${{ matrix.os }}-multissl-${{ matrix.ssllib.name }}-${{ matrix.ssllib.version }}
|
||||
- name: Install SSL Library
|
||||
if: steps.cache-ssl-lib.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
python3 Tools/ssl/multissltests.py \
|
||||
--steps=library \
|
||||
--base-directory "$MULTISSL_DIR" \
|
||||
--awslc ${{ matrix.awslc_ver }} \
|
||||
'--${{ matrix.ssllib.name }}' '${{ matrix.ssllib.version }}' \
|
||||
--system Linux
|
||||
- name: Add ccache to PATH
|
||||
run: |
|
||||
echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: false
|
||||
- name: Configure CPython
|
||||
run: |
|
||||
./configure CFLAGS="-fdiagnostics-format=json" \
|
||||
--config-cache \
|
||||
--enable-slower-safety \
|
||||
--with-pydebug \
|
||||
--with-openssl="$OPENSSL_DIR" \
|
||||
--with-openssl="$SSLLIB_DIR" \
|
||||
--with-builtin-hashlib-hashes=blake2 \
|
||||
--with-ssl-default-suites=openssl
|
||||
- name: Build CPython
|
||||
run: make -j
|
||||
run: make -j4
|
||||
- name: Display build info
|
||||
run: make pythoninfo
|
||||
- name: Verify python is linked to AWS-LC
|
||||
run: ./python -c 'import ssl; print(ssl.OPENSSL_VERSION)' | grep AWS-LC
|
||||
- name: Verify python is linked to the right lib
|
||||
run: |
|
||||
./python -c 'import ssl; print(ssl.OPENSSL_VERSION)' \
|
||||
| grep -iE '${{ matrix.ssllib.name }}.*${{ matrix.ssllib.version }}'
|
||||
- name: SSL tests
|
||||
run: ./python Lib/test/ssltests.py
|
||||
|
||||
build-android:
|
||||
name: Android (${{ matrix.arch }})
|
||||
needs: build-context
|
||||
if: needs.build-context.outputs.run-tests == 'true'
|
||||
if: needs.build-context.outputs.run-android == 'true'
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Use the same runs-on configuration as build-macos and build-ubuntu.
|
||||
- arch: aarch64
|
||||
runs-on: ${{ github.repository_owner == 'python' && 'ghcr.io/cirruslabs/macos-runner:sonoma' || 'macos-14' }}
|
||||
runs-on: macos-26
|
||||
- arch: x86_64
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Build and test
|
||||
run: ./Android/android.py ci ${{ matrix.arch }}-linux-android
|
||||
run: python3 Platforms/Android 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
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 Platforms/Apple ci iOS --fast-ci --simulator 'iPhone SE (3rd generation),OS=17.5'
|
||||
|
||||
build-emscripten:
|
||||
name: 'Emscripten'
|
||||
needs: build-context
|
||||
if: needs.build-context.outputs.run-emscripten == 'true'
|
||||
uses: ./.github/workflows/reusable-emscripten.yml
|
||||
|
||||
build-wasi:
|
||||
name: 'WASI'
|
||||
needs: build-context
|
||||
if: needs.build-context.outputs.run-tests == 'true'
|
||||
if: needs.build-context.outputs.run-wasi == '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-tests == 'true'
|
||||
if: needs.build-context.outputs.run-ubuntu == 'true'
|
||||
env:
|
||||
OPENSSL_VER: 3.0.16
|
||||
OPENSSL_VER: 3.5.5
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Register gcc problem matcher
|
||||
|
|
@ -455,20 +415,13 @@ jobs:
|
|||
echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> "$GITHUB_ENV"
|
||||
- name: 'Restore OpenSSL build'
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
|
||||
key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
|
||||
- name: Install OpenSSL
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
run: python3 Tools/ssl/multissltests.py --steps=library --base-directory "$MULTISSL_DIR" --openssl "$OPENSSL_VER" --system Linux
|
||||
- name: Add ccache to PATH
|
||||
run: |
|
||||
echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: false
|
||||
- name: Setup directory envs for out-of-tree builds
|
||||
run: |
|
||||
echo "CPYTHON_RO_SRCDIR=$(realpath -m "${GITHUB_WORKSPACE}"/../cpython-ro-srcdir)" >> "$GITHUB_ENV"
|
||||
|
|
@ -479,11 +432,6 @@ 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: |
|
||||
|
|
@ -514,7 +462,7 @@ jobs:
|
|||
./python -m venv "$VENV_LOC" && "$VENV_PYTHON" -m pip install -r "${GITHUB_WORKSPACE}/Tools/requirements-hypothesis.txt"
|
||||
- name: 'Restore Hypothesis database'
|
||||
id: cache-hypothesis-database
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ${{ env.CPYTHON_BUILDDIR }}/.hypothesis/
|
||||
key: hypothesis-database-${{ github.head_ref || github.run_id }}
|
||||
|
|
@ -541,7 +489,7 @@ jobs:
|
|||
-x test_subprocess \
|
||||
-x test_signal \
|
||||
-x test_sysconfig
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
if: always()
|
||||
with:
|
||||
name: hypothesis-example-db
|
||||
|
|
@ -552,32 +500,27 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
needs: build-context
|
||||
if: needs.build-context.outputs.run-tests == 'true'
|
||||
if: needs.build-context.outputs.run-ubuntu == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04]
|
||||
env:
|
||||
OPENSSL_VER: 3.0.16
|
||||
OPENSSL_VER: 3.5.5
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
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: Install dependencies
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh
|
||||
- name: Set up GCC-10 for ASAN
|
||||
uses: egor-tensin/setup-gcc@v1
|
||||
uses: egor-tensin/setup-gcc@a2861a8b8538f49cf2850980acccf6b05a1b2ae4 # v2.0
|
||||
with:
|
||||
version: 10
|
||||
- name: Configure OpenSSL env vars
|
||||
|
|
@ -587,23 +530,15 @@ jobs:
|
|||
echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> "$GITHUB_ENV"
|
||||
- name: 'Restore OpenSSL build'
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
|
||||
key: ${{ matrix.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
|
||||
- name: Install OpenSSL
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
run: python3 Tools/ssl/multissltests.py --steps=library --base-directory "$MULTISSL_DIR" --openssl "$OPENSSL_VER" --system Linux
|
||||
- name: Add ccache to PATH
|
||||
run: |
|
||||
echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: ${{ github.event_name == 'push' }}
|
||||
max-size: "200M"
|
||||
- name: Configure CPython
|
||||
run: ./configure --config-cache --with-address-sanitizer --without-pymalloc
|
||||
run: ./configure --config-cache --with-address-sanitizer --without-pymalloc --with-openssl="$OPENSSL_DIR"
|
||||
- name: Build CPython
|
||||
run: make -j4
|
||||
- name: Display build info
|
||||
|
|
@ -615,7 +550,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-tests == 'true'
|
||||
if: needs.build-context.outputs.run-ubuntu == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -633,7 +568,6 @@ 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:
|
||||
|
|
@ -641,18 +575,13 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
needs: build-context
|
||||
if: needs.build-context.outputs.run-tests == 'true'
|
||||
if: needs.build-context.outputs.run-ubuntu == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
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
|
||||
|
|
@ -676,45 +605,49 @@ jobs:
|
|||
run: |
|
||||
"$BUILD_DIR/cross-python/bin/python3" -m test test_sysconfig test_site test_embed
|
||||
|
||||
# CIFuzz job based on https://google.github.io/oss-fuzz/getting-started/continuous-integration/
|
||||
cifuzz:
|
||||
name: CIFuzz
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
# ${{ '' } is a hack to nest jobs under the same sidebar category.
|
||||
name: CIFuzz${{ '' }} # zizmor: ignore[obfuscation]
|
||||
needs: build-context
|
||||
if: needs.build-context.outputs.run-ci-fuzz == 'true'
|
||||
if: >-
|
||||
needs.build-context.outputs.run-ci-fuzz == 'true'
|
||||
|| needs.build-context.outputs.run-ci-fuzz-stdlib == 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
sanitizer: [address, undefined, memory]
|
||||
steps:
|
||||
- name: Build fuzzers (${{ matrix.sanitizer }})
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
sanitizer:
|
||||
- address
|
||||
oss-fuzz-project-name:
|
||||
- cpython3
|
||||
- python3-libraries
|
||||
include:
|
||||
- sanitizer: undefined
|
||||
oss-fuzz-project-name: cpython3
|
||||
sanitizer: ${{ matrix.sanitizer }}
|
||||
- name: Run fuzzers (${{ matrix.sanitizer }})
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
fuzz-seconds: 600
|
||||
- sanitizer: memory
|
||||
oss-fuzz-project-name: cpython3
|
||||
output-sarif: true
|
||||
sanitizer: ${{ matrix.sanitizer }}
|
||||
- name: Upload crash
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.sanitizer }}-artifacts
|
||||
path: ./out/artifacts
|
||||
- name: Upload SARIF
|
||||
if: always() && steps.build.outcome == 'success'
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: cifuzz-sarif/results.sarif
|
||||
checkout_path: cifuzz-sarif
|
||||
exclude:
|
||||
# Note that the 'no-exclude' sentinel below is to prevent
|
||||
# an empty string value from excluding all jobs and causing
|
||||
# GHA to create a 'default' matrix entry with all empty values.
|
||||
- oss-fuzz-project-name: >-
|
||||
${{
|
||||
needs.build-context.outputs.run-ci-fuzz == 'true'
|
||||
&& 'no-exclude'
|
||||
|| 'cpython3'
|
||||
}}
|
||||
- oss-fuzz-project-name: >-
|
||||
${{
|
||||
needs.build-context.outputs.run-ci-fuzz-stdlib == 'true'
|
||||
&& 'no-exclude'
|
||||
|| 'python3-libraries'
|
||||
}}
|
||||
uses: ./.github/workflows/reusable-cifuzz.yml
|
||||
with:
|
||||
oss-fuzz-project-name: ${{ matrix.oss-fuzz-project-name }}
|
||||
sanitizer: ${{ matrix.sanitizer }}
|
||||
|
||||
all-required-green: # This job does nothing and is only used for the branch protection
|
||||
name: All required checks pass
|
||||
|
|
@ -725,13 +658,14 @@ jobs:
|
|||
- check-docs
|
||||
- check-autoconf-regen
|
||||
- check-generated-files
|
||||
- check-c-api-docs
|
||||
- build-windows
|
||||
- build-windows-msi
|
||||
- build-macos
|
||||
- build-ubuntu
|
||||
- build-ubuntu-ssltests-awslc
|
||||
- build-ubuntu-ssltests-openssl
|
||||
- build-android
|
||||
- build-ubuntu-ssltests
|
||||
- build-ios
|
||||
- build-emscripten
|
||||
- build-wasi
|
||||
- test-hypothesis
|
||||
- build-asan
|
||||
|
|
@ -745,30 +679,41 @@ jobs:
|
|||
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe
|
||||
with:
|
||||
allowed-failures: >-
|
||||
build-android,
|
||||
build-emscripten,
|
||||
build-windows-msi,
|
||||
build-ubuntu-ssltests-awslc,
|
||||
build-ubuntu-ssltests-openssl,
|
||||
build-ubuntu-ssltests,
|
||||
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,
|
||||
build-macos,
|
||||
'
|
||||
|| ''
|
||||
}}
|
||||
${{
|
||||
!fromJSON(needs.build-context.outputs.run-tests)
|
||||
&& !fromJSON(needs.build-context.outputs.run-docs)
|
||||
&& 'check-c-api-docs,'
|
||||
|| ''
|
||||
}}
|
||||
${{ !fromJSON(needs.build-context.outputs.run-windows-tests) && 'build-windows,' || '' }}
|
||||
${{
|
||||
!fromJSON(needs.build-context.outputs.run-ci-fuzz)
|
||||
&& !fromJSON(needs.build-context.outputs.run-ci-fuzz-stdlib)
|
||||
&& 'cifuzz,' ||
|
||||
''
|
||||
}}
|
||||
${{ !fromJSON(needs.build-context.outputs.run-macos) && 'build-macos,' || '' }}
|
||||
${{
|
||||
!fromJSON(needs.build-context.outputs.run-ubuntu)
|
||||
&& '
|
||||
build-ubuntu,
|
||||
build-ubuntu-ssltests-awslc,
|
||||
build-ubuntu-ssltests-openssl,
|
||||
build-android,
|
||||
build-wasi,
|
||||
build-ubuntu-ssltests,
|
||||
test-hypothesis,
|
||||
build-asan,
|
||||
build-san,
|
||||
|
|
@ -776,18 +721,8 @@ jobs:
|
|||
'
|
||||
|| ''
|
||||
}}
|
||||
${{
|
||||
!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-android) && 'build-android,' || '' }}
|
||||
${{ !fromJSON(needs.build-context.outputs.run-ios) && 'build-ios,' || '' }}
|
||||
${{ !fromJSON(needs.build-context.outputs.run-emscripten) && 'build-emscripten,' || '' }}
|
||||
${{ !fromJSON(needs.build-context.outputs.run-wasi) && 'build-wasi,' || '' }}
|
||||
jobs: ${{ toJSON(needs) }}
|
||||
|
|
|
|||
28
.github/workflows/documentation-links.yml
vendored
28
.github/workflows/documentation-links.yml
vendored
|
|
@ -1,28 +0,0 @@
|
|||
name: Read the Docs PR preview
|
||||
# Automatically edits a pull request's descriptions with a link
|
||||
# to the documentation's preview on Read the Docs.
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
paths:
|
||||
- 'Doc/**'
|
||||
- '.github/workflows/doc.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
documentation-links:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
timeout-minutes: 5
|
||||
|
||||
steps:
|
||||
- uses: readthedocs/actions/preview@v1
|
||||
with:
|
||||
project-slug: "cpython-previews"
|
||||
single-version: "true"
|
||||
199
.github/workflows/jit.yml
vendored
199
.github/workflows/jit.yml
vendored
|
|
@ -1,25 +1,18 @@
|
|||
name: JIT
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
paths: &paths
|
||||
- '**jit**'
|
||||
- 'Python/bytecodes.c'
|
||||
- 'Python/optimizer*.c'
|
||||
- 'Python/executor_cases.c.h'
|
||||
- 'Python/optimizer_cases.c.h'
|
||||
- '**_testinternalcapi**'
|
||||
- '!Python/perf_jit_trampoline.c'
|
||||
- '!**/*.md'
|
||||
- '!**/*.ini'
|
||||
push:
|
||||
paths:
|
||||
- '**jit**'
|
||||
- 'Python/bytecodes.c'
|
||||
- 'Python/optimizer*.c'
|
||||
- 'Python/executor_cases.c.h'
|
||||
- 'Python/optimizer_cases.c.h'
|
||||
- '!Python/perf_jit_trampoline.c'
|
||||
- '!**/*.md'
|
||||
- '!**/*.ini'
|
||||
paths: *paths
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
|
|
@ -31,14 +24,15 @@ concurrency:
|
|||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
LLVM_VERSION: 21
|
||||
|
||||
jobs:
|
||||
interpreter:
|
||||
name: Interpreter (Debug)
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 90
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Build tier two interpreter
|
||||
|
|
@ -48,11 +42,12 @@ jobs:
|
|||
- name: Test tier two interpreter
|
||||
run: |
|
||||
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
jit:
|
||||
|
||||
windows:
|
||||
name: ${{ matrix.target }} (${{ matrix.debug && 'Debug' || 'Release' }})
|
||||
needs: interpreter
|
||||
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 90
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -60,62 +55,66 @@ jobs:
|
|||
- i686-pc-windows-msvc/msvc
|
||||
- x86_64-pc-windows-msvc/msvc
|
||||
- aarch64-pc-windows-msvc/msvc
|
||||
- x86_64-apple-darwin/clang
|
||||
- aarch64-apple-darwin/clang
|
||||
- x86_64-unknown-linux-gnu/gcc
|
||||
- aarch64-unknown-linux-gnu/gcc
|
||||
debug:
|
||||
- true
|
||||
- false
|
||||
llvm:
|
||||
- 19
|
||||
include:
|
||||
- target: i686-pc-windows-msvc/msvc
|
||||
architecture: Win32
|
||||
runner: windows-latest
|
||||
runner: windows-2025-vs2026
|
||||
- target: x86_64-pc-windows-msvc/msvc
|
||||
architecture: x64
|
||||
runner: windows-latest
|
||||
runner: windows-2025-vs2026
|
||||
- target: aarch64-pc-windows-msvc/msvc
|
||||
architecture: ARM64
|
||||
runner: windows-11-arm
|
||||
- target: x86_64-apple-darwin/clang
|
||||
architecture: x86_64
|
||||
runner: macos-13
|
||||
- target: aarch64-apple-darwin/clang
|
||||
architecture: aarch64
|
||||
runner: macos-14
|
||||
- target: x86_64-unknown-linux-gnu/gcc
|
||||
architecture: x86_64
|
||||
runner: ubuntu-24.04
|
||||
- target: aarch64-unknown-linux-gnu/gcc
|
||||
architecture: aarch64
|
||||
runner: ubuntu-24.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
# PCbuild downloads LLVM automatically:
|
||||
- name: Windows
|
||||
if: runner.os == 'Windows'
|
||||
- name: Build
|
||||
run: |
|
||||
./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }}
|
||||
- name: Test
|
||||
run: |
|
||||
./PCbuild/rt.bat ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
||||
# The `find` line is required as a result of https://github.com/actions/runner-images/issues/9966.
|
||||
# This is a bug in the macOS runner image where the pre-installed Python is installed in the same
|
||||
# directory as the Homebrew Python, which causes the build to fail for macos-13. This line removes
|
||||
# the symlink to the pre-installed Python so that the Homebrew Python is used instead.
|
||||
- name: macOS
|
||||
if: runner.os == 'macOS'
|
||||
macos:
|
||||
name: ${{ matrix.target }} (${{ matrix.debug && 'Debug' || 'Release' }})
|
||||
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
- x86_64-apple-darwin/clang
|
||||
- aarch64-apple-darwin/clang
|
||||
debug:
|
||||
- true
|
||||
- false
|
||||
include:
|
||||
- target: x86_64-apple-darwin/clang
|
||||
runner: macos-15-intel
|
||||
- target: aarch64-apple-darwin/clang
|
||||
runner: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Install LLVM
|
||||
run: |
|
||||
brew update
|
||||
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
|
||||
brew install llvm@${{ matrix.llvm }}
|
||||
brew install llvm@${{ env.LLVM_VERSION }}
|
||||
- name: Build
|
||||
run: |
|
||||
export SDKROOT="$(xcrun --show-sdk-path)"
|
||||
# Set MACOSX_DEPLOYMENT_TARGET and -Werror=unguarded-availability to
|
||||
# make sure we don't break downstream distributors (like uv):
|
||||
|
|
@ -123,41 +122,83 @@ jobs:
|
|||
export MACOSX_DEPLOYMENT_TARGET=10.15
|
||||
./configure --enable-experimental-jit --enable-universalsdk --with-universal-archs=universal2 ${{ matrix.debug && '--with-pydebug' || '' }}
|
||||
make all --jobs 4
|
||||
- name: Test
|
||||
run: |
|
||||
./python.exe -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
||||
- name: Linux
|
||||
if: runner.os == 'Linux'
|
||||
linux:
|
||||
name: ${{ matrix.target }} (${{ matrix.debug && 'Debug' || 'Release' }})
|
||||
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
- x86_64-unknown-linux-gnu/gcc
|
||||
- aarch64-unknown-linux-gnu/gcc
|
||||
debug:
|
||||
- true
|
||||
- false
|
||||
include:
|
||||
- target: x86_64-unknown-linux-gnu/gcc
|
||||
runner: ubuntu-24.04
|
||||
- target: aarch64-unknown-linux-gnu/gcc
|
||||
runner: ubuntu-24.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Build
|
||||
run: |
|
||||
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
|
||||
export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
|
||||
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ env.LLVM_VERSION }}
|
||||
export PATH="$(llvm-config-${{ env.LLVM_VERSION }} --bindir):$PATH"
|
||||
./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '' }}
|
||||
make all --jobs 4
|
||||
- name: Test
|
||||
run: |
|
||||
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
||||
# XXX: GH-133171
|
||||
# jit-with-disabled-gil:
|
||||
# name: Free-Threaded (Debug)
|
||||
# needs: interpreter
|
||||
# runs-on: ubuntu-24.04
|
||||
# timeout-minutes: 90
|
||||
# strategy:
|
||||
# fail-fast: false
|
||||
# matrix:
|
||||
# llvm:
|
||||
# - 19
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with:
|
||||
# persist-credentials: false
|
||||
# - uses: actions/setup-python@v5
|
||||
# with:
|
||||
# python-version: '3.11'
|
||||
# - name: Build with JIT enabled and GIL disabled
|
||||
# run: |
|
||||
# sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
|
||||
# export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
|
||||
# ./configure --enable-experimental-jit --with-pydebug --disable-gil
|
||||
# make all --jobs 4
|
||||
# - name: Run tests
|
||||
# run: |
|
||||
# ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
linux-extras:
|
||||
name: ${{ matrix.name }}
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: Free-Threaded (Debug)
|
||||
configure_flags: --enable-experimental-jit --with-pydebug --disable-gil
|
||||
continue_on_error: true
|
||||
- name: JIT without optimizations (Debug)
|
||||
configure_flags: --enable-experimental-jit --with-pydebug
|
||||
test_env: "PYTHON_UOPS_OPTIMIZE=0"
|
||||
- name: JIT with tail calling interpreter
|
||||
configure_flags: --enable-experimental-jit --with-tail-call-interp --with-pydebug
|
||||
use_clang: true
|
||||
run_tests: false
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Build
|
||||
run: |
|
||||
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ env.LLVM_VERSION }}
|
||||
export PATH="$(llvm-config-${{ env.LLVM_VERSION }} --bindir):$PATH"
|
||||
if [ "${{ matrix.use_clang }}" = "true" ]; then
|
||||
export CC=clang-${{ env.LLVM_VERSION }}
|
||||
fi
|
||||
./configure ${{ matrix.configure_flags }}
|
||||
make all --jobs 4
|
||||
- name: Test
|
||||
if: matrix.run_tests != false
|
||||
run: |
|
||||
${{ matrix.test_env }} ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
continue-on-error: ${{ matrix.continue_on_error }}
|
||||
|
|
|
|||
7
.github/workflows/lint.yml
vendored
7
.github/workflows/lint.yml
vendored
|
|
@ -19,10 +19,7 @@ jobs:
|
|||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- uses: pre-commit/action@v3.0.1
|
||||
- uses: j178/prek-action@0bb87d7f00b0c99306c8bcb8b8beba1eb581c037 # v1.1.1
|
||||
|
|
|
|||
8
.github/workflows/mypy.yml
vendored
8
.github/workflows/mypy.yml
vendored
|
|
@ -16,8 +16,10 @@ 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_levenshtein_examples.py"
|
||||
- "Tools/build/generate_sbom.py"
|
||||
- "Tools/build/generate_stdlib_module_names.py"
|
||||
- "Tools/build/mypy.ini"
|
||||
|
|
@ -25,6 +27,7 @@ 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/**"
|
||||
|
|
@ -57,15 +60,16 @@ jobs:
|
|||
"Lib/tomllib",
|
||||
"Tools/build",
|
||||
"Tools/cases_generator",
|
||||
"Tools/check-c-api-docs",
|
||||
"Tools/clinic",
|
||||
"Tools/jit",
|
||||
"Tools/peg_generator",
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: "3.13"
|
||||
cache: pip
|
||||
|
|
|
|||
10
.github/workflows/new-bugs-announce-notifier.yml
vendored
10
.github/workflows/new-bugs-announce-notifier.yml
vendored
|
|
@ -6,19 +6,21 @@ on:
|
|||
- opened
|
||||
|
||||
permissions:
|
||||
issues: read
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
notify-new-bugs-announce:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: read
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: 20
|
||||
- run: npm install mailgun.js form-data
|
||||
- name: Send notification
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
env:
|
||||
MAILGUN_API_KEY: ${{ secrets.MAILGUN_PYTHON_ORG_MAILGUN_KEY }}
|
||||
with:
|
||||
|
|
@ -44,7 +46,7 @@ jobs:
|
|||
// We need to truncate the body size, because the max size for
|
||||
// the whole payload is 16kb. We want to be safe and assume that
|
||||
// body can take up to ~8kb of space.
|
||||
body : issue.data.body.substring(0, 8000)
|
||||
body : (issue.data.body || "").substring(0, 8000)
|
||||
};
|
||||
|
||||
const data = {
|
||||
|
|
|
|||
22
.github/workflows/posix-deps-apt.sh
vendored
22
.github/workflows/posix-deps-apt.sh
vendored
|
|
@ -1,10 +1,9 @@
|
|||
#!/bin/sh
|
||||
apt-get update
|
||||
|
||||
apt-get -yq install \
|
||||
apt-get -yq --no-install-recommends install \
|
||||
build-essential \
|
||||
pkg-config \
|
||||
ccache \
|
||||
cmake \
|
||||
gdb \
|
||||
lcov \
|
||||
|
|
@ -27,9 +26,16 @@ apt-get -yq install \
|
|||
xvfb \
|
||||
zlib1g-dev
|
||||
|
||||
# Workaround missing libmpdec-dev on ubuntu 24.04:
|
||||
# https://launchpad.net/~ondrej/+archive/ubuntu/php
|
||||
# https://deb.sury.org/
|
||||
sudo add-apt-repository ppa:ondrej/php
|
||||
apt-get update
|
||||
apt-get -yq install libmpdec-dev
|
||||
# Workaround missing libmpdec-dev on ubuntu 24.04 by building mpdecimal
|
||||
# from source. ppa:ondrej/php (launchpad.net) are unreliable
|
||||
# (https://status.canonical.com) so fetch the tarball directly
|
||||
# from the upstream host.
|
||||
# https://www.bytereef.org/mpdecimal/
|
||||
MPDECIMAL_VERSION=4.0.1
|
||||
curl -fsSL "https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-${MPDECIMAL_VERSION}.tar.gz" \
|
||||
| tar -xz -C /tmp
|
||||
(cd "/tmp/mpdecimal-${MPDECIMAL_VERSION}" \
|
||||
&& ./configure --prefix=/usr/local \
|
||||
&& make -j"$(nproc)" \
|
||||
&& make install)
|
||||
ldconfig
|
||||
|
|
|
|||
31
.github/workflows/project-updater.yml
vendored
31
.github/workflows/project-updater.yml
vendored
|
|
@ -1,31 +0,0 @@
|
|||
name: Update GH projects
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
- labeled
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
add-to-project:
|
||||
name: Add issues to projects
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# if an issue has any of these labels, it will be added
|
||||
# to the corresponding project
|
||||
- { project: 2, label: "release-blocker, deferred-blocker" }
|
||||
- { project: 32, label: sprint }
|
||||
|
||||
steps:
|
||||
- uses: actions/add-to-project@v1.0.0
|
||||
with:
|
||||
project-url: https://github.com/orgs/python/projects/${{ matrix.project }}
|
||||
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
|
||||
labeled: ${{ matrix.label }}
|
||||
2
.github/workflows/regen-abidump.sh
vendored
2
.github/workflows/regen-abidump.sh
vendored
|
|
@ -2,7 +2,7 @@ set -ex
|
|||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
./.github/workflows/posix-deps-apt.sh
|
||||
apt-get install -yq abigail-tools python3
|
||||
apt-get install -yq --no-install-recommends abigail-tools python3
|
||||
export CFLAGS="-g3 -O0"
|
||||
./configure --enable-shared && make
|
||||
make regen-abidump
|
||||
|
|
|
|||
11
.github/workflows/require-pr-label.yml
vendored
11
.github/workflows/require-pr-label.yml
vendored
|
|
@ -4,6 +4,9 @@ on:
|
|||
pull_request:
|
||||
types: [opened, reopened, labeled, unlabeled, synchronize]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
label-dnm:
|
||||
name: DO-NOT-MERGE
|
||||
|
|
@ -15,7 +18,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Check there's no DO-NOT-MERGE
|
||||
uses: mheap/github-action-required-labels@v5
|
||||
uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2
|
||||
with:
|
||||
mode: exactly
|
||||
count: 0
|
||||
|
|
@ -33,7 +36,7 @@ jobs:
|
|||
steps:
|
||||
# Check that the PR is not awaiting changes from the author due to previous review.
|
||||
- name: Check there's no required changes
|
||||
uses: mheap/github-action-required-labels@v5
|
||||
uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2
|
||||
with:
|
||||
mode: exactly
|
||||
count: 0
|
||||
|
|
@ -42,7 +45,7 @@ jobs:
|
|||
awaiting change review
|
||||
- id: is-feature
|
||||
name: Check whether this PR is a feature (contains a "type-feature" label)
|
||||
uses: mheap/github-action-required-labels@v5
|
||||
uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2
|
||||
with:
|
||||
mode: exactly
|
||||
count: 1
|
||||
|
|
@ -53,7 +56,7 @@ jobs:
|
|||
- id: awaiting-merge
|
||||
if: steps.is-feature.outputs.status == 'success'
|
||||
name: Check for complete review
|
||||
uses: mheap/github-action-required-labels@v5
|
||||
uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2
|
||||
with:
|
||||
mode: exactly
|
||||
count: 1
|
||||
|
|
|
|||
25
.github/workflows/reusable-check-c-api-docs.yml
vendored
Normal file
25
.github/workflows/reusable-check-c-api-docs.yml
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
name: Reusable C API Docs Check
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
jobs:
|
||||
check-c-api-docs:
|
||||
name: 'Check if all C APIs are documented'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Check for undocumented C APIs
|
||||
run: python Tools/check-c-api-docs/main.py
|
||||
67
.github/workflows/reusable-check-html-ids.yml
vendored
Normal file
67
.github/workflows/reusable-check-html-ids.yml
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
name: Reusable check HTML IDs
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
jobs:
|
||||
check-html-ids:
|
||||
name: 'Check for removed HTML IDs'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: 'Check out PR head'
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: 'Find merge base'
|
||||
id: merge-base
|
||||
run: |
|
||||
BASE="${{ github.event.pull_request.base.sha }}"
|
||||
HEAD="${{ github.event.pull_request.head.sha }}"
|
||||
git fetch --depth=$((${{ github.event.pull_request.commits }} + 10)) --no-tags origin "$BASE" "$HEAD"
|
||||
|
||||
if ! MERGE_BASE=$(git merge-base "$BASE" "$HEAD" 2>/dev/null); then
|
||||
git fetch --deepen=1 --no-tags origin "$BASE" "$HEAD"
|
||||
|
||||
OLDEST=$(git rev-list --reflog --max-parents=0 --reverse "${BASE}^" "${HEAD}^" | head -1)
|
||||
TIMESTAMP=$(git show --format=%at --no-patch "$OLDEST")
|
||||
|
||||
git fetch --shallow-since="$TIMESTAMP" --no-tags origin "$BASE" "$HEAD"
|
||||
|
||||
MERGE_BASE=$(git merge-base "$BASE" "$HEAD")
|
||||
fi
|
||||
echo "sha=$MERGE_BASE" >> "$GITHUB_OUTPUT"
|
||||
- name: 'Create worktree at merge base'
|
||||
env:
|
||||
MERGE_BASE: ${{ steps.merge-base.outputs.sha }}
|
||||
run: git worktree add /tmp/merge-base "$MERGE_BASE" --detach
|
||||
- name: 'Set up Python'
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'Doc/requirements.txt'
|
||||
- name: 'Install build dependencies'
|
||||
run: make -C /tmp/merge-base/Doc/ venv
|
||||
- name: 'Build HTML documentation'
|
||||
run: make -C /tmp/merge-base/Doc/ SPHINXOPTS="--quiet" html
|
||||
- name: 'Collect HTML IDs'
|
||||
run: python Doc/tools/check-html-ids.py collect /tmp/merge-base/Doc/build/html -o /tmp/html-ids-base.json.gz
|
||||
- name: 'Download PR head HTML IDs'
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: html-ids-head.json.gz
|
||||
path: /tmp
|
||||
- name: 'Check for removed HTML IDs'
|
||||
run: |
|
||||
# shellcheck disable=SC2046
|
||||
python Doc/tools/check-html-ids.py -v check \
|
||||
/tmp/html-ids-base.json.gz /tmp/html-ids-head.json.gz \
|
||||
$([ -f Doc/tools/removed-ids.txt ] && echo "--exclude-file Doc/tools/removed-ids.txt")
|
||||
49
.github/workflows/reusable-cifuzz.yml
vendored
Normal file
49
.github/workflows/reusable-cifuzz.yml
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# CIFuzz job based on https://google.github.io/oss-fuzz/getting-started/continuous-integration/
|
||||
name: Reusable CIFuzz
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
oss-fuzz-project-name:
|
||||
description: OSS-Fuzz project name
|
||||
required: true
|
||||
type: string
|
||||
sanitizer:
|
||||
description: OSS-Fuzz sanitizer
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
cifuzz:
|
||||
name: ${{ inputs.oss-fuzz-project-name }} (${{ inputs.sanitizer }})
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Build fuzzers (${{ inputs.sanitizer }})
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@ed23f8af80ff82b25ca67cd9b101e690b8897b3f # master
|
||||
with:
|
||||
oss-fuzz-project-name: ${{ inputs.oss-fuzz-project-name }}
|
||||
sanitizer: ${{ inputs.sanitizer }}
|
||||
- name: Run fuzzers (${{ inputs.sanitizer }})
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@ed23f8af80ff82b25ca67cd9b101e690b8897b3f # master
|
||||
with:
|
||||
fuzz-seconds: 600
|
||||
oss-fuzz-project-name: ${{ inputs.oss-fuzz-project-name }}
|
||||
output-sarif: true
|
||||
sanitizer: ${{ inputs.sanitizer }}
|
||||
- name: Upload crash
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: ${{ inputs.sanitizer }}-artifacts
|
||||
path: ./out/artifacts
|
||||
- name: Upload SARIF
|
||||
if: always() && steps.build.outcome == 'success'
|
||||
uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
|
||||
with:
|
||||
sarif_file: cifuzz-sarif/results.sarif
|
||||
checkout_path: cifuzz-sarif
|
||||
56
.github/workflows/reusable-context.yml
vendored
56
.github/workflows/reusable-context.yml
vendored
|
|
@ -17,24 +17,45 @@ on: # yamllint disable-line rule:truthy
|
|||
# || 'falsy-branch'
|
||||
# }}
|
||||
#
|
||||
config-hash:
|
||||
description: Config hash value for use in cache keys
|
||||
value: ${{ jobs.compute-changes.outputs.config-hash }} # str
|
||||
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 for 'cpython' fuzzer
|
||||
value: ${{ jobs.compute-changes.outputs.run-ci-fuzz }} # bool
|
||||
run-ci-fuzz-stdlib:
|
||||
description: Whether to run the CIFuzz job for 'python3-libraries' fuzzer
|
||||
value: ${{ jobs.compute-changes.outputs.run-ci-fuzz-stdlib }} # bool
|
||||
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-windows-tests:
|
||||
description: Whether to run the Windows tests
|
||||
value: ${{ jobs.compute-changes.outputs.run-windows-tests }} # bool
|
||||
run-ubuntu:
|
||||
description: Whether to run the Ubuntu tests
|
||||
value: ${{ jobs.compute-changes.outputs.run-ubuntu }} # bool
|
||||
run-emscripten:
|
||||
description: Whether to run the Emscripten tests
|
||||
value: ${{ jobs.compute-changes.outputs.run-emscripten }} # 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-ci-fuzz:
|
||||
description: Whether to run the CIFuzz job
|
||||
value: ${{ jobs.compute-changes.outputs.run-ci-fuzz }} # bool
|
||||
run-windows-tests:
|
||||
description: Whether to run the Windows tests
|
||||
value: ${{ jobs.compute-changes.outputs.run-windows-tests }} # bool
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
compute-changes:
|
||||
|
|
@ -42,22 +63,28 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
config-hash: ${{ steps.config-hash.outputs.hash }}
|
||||
run-android: ${{ steps.changes.outputs.run-android }}
|
||||
run-ci-fuzz: ${{ steps.changes.outputs.run-ci-fuzz }}
|
||||
run-ci-fuzz-stdlib: ${{ steps.changes.outputs.run-ci-fuzz-stdlib }}
|
||||
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-emscripten: ${{ steps.changes.outputs.run-emscripten }}
|
||||
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:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: "3"
|
||||
|
||||
- run: >-
|
||||
echo '${{ github.event_name }}'
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: >-
|
||||
|
|
@ -100,8 +127,3 @@ 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"
|
||||
|
|
|
|||
32
.github/workflows/reusable-docs.yml
vendored
32
.github/workflows/reusable-docs.yml
vendored
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
refspec_pr: '+${{ github.event.pull_request.head.sha }}:remotes/origin/${{ github.event.pull_request.head.ref }}'
|
||||
steps:
|
||||
- name: 'Check out latest PR branch commit'
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: >-
|
||||
|
|
@ -52,11 +52,11 @@ jobs:
|
|||
git fetch origin "${refspec_base}" --shallow-since="${DATE}" \
|
||||
--no-tags --prune --no-recurse-submodules
|
||||
- name: 'Set up Python'
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'Doc/requirements.txt'
|
||||
cache-dependency-path: 'Doc/pylock.toml'
|
||||
- name: 'Install build dependencies'
|
||||
run: make -C Doc/ venv
|
||||
|
||||
|
|
@ -75,6 +75,22 @@ jobs:
|
|||
--fail-if-regression \
|
||||
--fail-if-improved \
|
||||
--fail-if-new-news-nit
|
||||
- name: 'Collect HTML IDs'
|
||||
if: github.event_name == 'pull_request'
|
||||
run: python Doc/tools/check-html-ids.py collect Doc/build/html -o Doc/build/html-ids-head.json.gz
|
||||
- name: 'Upload HTML IDs'
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: html-ids-head
|
||||
path: Doc/build/html-ids-head.json.gz
|
||||
archive: false
|
||||
|
||||
check-html-ids:
|
||||
name: 'Check for removed HTML IDs'
|
||||
needs: build-doc
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/reusable-check-html-ids.yml
|
||||
|
||||
# Run "doctest" on HEAD as new syntax doesn't exist in the latest stable release
|
||||
doctest:
|
||||
|
|
@ -82,17 +98,17 @@ jobs:
|
|||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ubuntu-doc-${{ hashFiles('Doc/requirements.txt') }}
|
||||
restore-keys: |
|
||||
ubuntu-doc-
|
||||
- name: 'Install Dependencies'
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh && sudo apt-get install wamerican
|
||||
run: sudo ./.github/workflows/posix-deps-apt.sh && sudo apt-get install --no-install-recommends wamerican
|
||||
- name: 'Configure CPython'
|
||||
run: ./configure --with-pydebug
|
||||
- name: 'Build CPython'
|
||||
|
|
@ -108,11 +124,11 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: 'Set up Python'
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3'
|
||||
cache: 'pip'
|
||||
|
|
|
|||
77
.github/workflows/reusable-emscripten.yml
vendored
Normal file
77
.github/workflows/reusable-emscripten.yml
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
name: Reusable Emscripten
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
jobs:
|
||||
build-emscripten-reusable:
|
||||
name: 'build and test'
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 40
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: "Read Emscripten config"
|
||||
id: emscripten-config
|
||||
shell: python
|
||||
run: |
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
config = tomllib.loads(Path("Platforms/emscripten/config.toml").read_text())
|
||||
h = hashlib.sha256()
|
||||
h.update(json.dumps(config["dependencies"], sort_keys=True).encode())
|
||||
h.update(Path("Platforms/emscripten/make_libffi.sh").read_bytes())
|
||||
h.update(b'1') # Update to explicitly bust cache
|
||||
emsdk_cache = Path(os.environ["RUNNER_TEMP"]) / "emsdk-cache"
|
||||
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
|
||||
f.write(f"emscripten-version={config['emscripten-version']}\n")
|
||||
f.write(f"node-version={config['node-version']}\n")
|
||||
f.write(f"deps-hash={h.hexdigest()}\n")
|
||||
with open(os.environ["GITHUB_ENV"], "a") as f:
|
||||
f.write(f"EMSDK_CACHE={emsdk_cache}\n")
|
||||
- name: "Install Node.js"
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: ${{ steps.emscripten-config.outputs.node-version }}
|
||||
- name: "Cache Emscripten SDK"
|
||||
id: emsdk-cache
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ${{ env.EMSDK_CACHE }}
|
||||
key: emsdk-${{ steps.emscripten-config.outputs.emscripten-version }}-${{ steps.emscripten-config.outputs.deps-hash }}
|
||||
restore-keys: emsdk-${{ steps.emscripten-config.outputs.emscripten-version }}
|
||||
- name: "Install Python"
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: "Runner image version"
|
||||
run: echo "IMAGE_OS_VERSION=${ImageOS}-${ImageVersion}" >> "$GITHUB_ENV"
|
||||
- name: "Install Emscripten"
|
||||
run: python3 Platforms/emscripten install-emscripten
|
||||
- name: "Configure build Python"
|
||||
run: python3 Platforms/emscripten configure-build-python -- --config-cache --with-pydebug
|
||||
- name: "Make build Python"
|
||||
run: python3 Platforms/emscripten make-build-python
|
||||
- name: "Make dependencies"
|
||||
run: >-
|
||||
python3 Platforms/emscripten make-dependencies
|
||||
${{ steps.emsdk-cache.outputs.cache-hit == 'true' && '--check-up-to-date' || '' }}
|
||||
- name: "Configure host Python"
|
||||
run: python3 Platforms/emscripten configure-host --host-runner node -- --config-cache
|
||||
- name: "Make host Python"
|
||||
run: python3 Platforms/emscripten make-host
|
||||
- name: "Display build info"
|
||||
run: python3 Platforms/emscripten run --pythoninfo
|
||||
- name: "Test"
|
||||
run: python3 Platforms/emscripten run --test
|
||||
25
.github/workflows/reusable-macos.yml
vendored
25
.github/workflows/reusable-macos.yml
vendored
|
|
@ -3,9 +3,6 @@ name: Reusable macOS
|
|||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
config_hash:
|
||||
required: true
|
||||
type: string
|
||||
free-threading:
|
||||
required: false
|
||||
type: boolean
|
||||
|
|
@ -15,6 +12,9 @@ on:
|
|||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
|
|
@ -31,21 +31,16 @@ jobs:
|
|||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
TERM: linux
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
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 }}-${{ inputs.config_hash }}
|
||||
- name: Install Homebrew dependencies
|
||||
run: |
|
||||
brew install pkg-config openssl@3.0 xz gdbm tcl-tk@8 make
|
||||
brew install pkg-config openssl@3.5 xz gdbm tcl-tk@9 make
|
||||
# Because alternate versions are not symlinked into place by default:
|
||||
brew link --overwrite tcl-tk@8
|
||||
brew link --overwrite tcl-tk@9
|
||||
- name: Configure CPython
|
||||
run: |
|
||||
MACOSX_DEPLOYMENT_TARGET=10.15 \
|
||||
|
|
@ -58,17 +53,17 @@ jobs:
|
|||
--enable-safety \
|
||||
${{ inputs.free-threading && '--disable-gil' || '' }} \
|
||||
--prefix=/opt/python-dev \
|
||||
--with-openssl="$(brew --prefix openssl@3.0)"
|
||||
--with-openssl="$(brew --prefix openssl@3.5)"
|
||||
- name: Build CPython
|
||||
if : ${{ inputs.free-threading || inputs.os != 'macos-13' }}
|
||||
if : ${{ inputs.free-threading || inputs.os != 'macos-15-intel' }}
|
||||
run: gmake -j8
|
||||
- name: Build CPython for compiler warning check
|
||||
if : ${{ !inputs.free-threading && inputs.os == 'macos-13' }}
|
||||
if : ${{ !inputs.free-threading && inputs.os == 'macos-15-intel' }}
|
||||
run: set -o pipefail; gmake -j8 --output-sync 2>&1 | tee compiler_output_macos.txt
|
||||
- name: Display build info
|
||||
run: make pythoninfo
|
||||
- name: Check compiler warnings
|
||||
if : ${{ !inputs.free-threading && inputs.os == 'macos-13' }}
|
||||
if : ${{ !inputs.free-threading && inputs.os == 'macos-15-intel' }}
|
||||
run: >-
|
||||
python3 Tools/build/check_warnings.py
|
||||
--compiler-output-file-path=compiler_output_macos.txt
|
||||
|
|
|
|||
42
.github/workflows/reusable-san.yml
vendored
42
.github/workflows/reusable-san.yml
vendored
|
|
@ -6,15 +6,15 @@ on:
|
|||
sanitizer:
|
||||
required: true
|
||||
type: string
|
||||
config_hash:
|
||||
required: true
|
||||
type: string
|
||||
free-threading:
|
||||
description: Whether to use free-threaded mode
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
|
|
@ -29,33 +29,26 @@ jobs:
|
|||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
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 }}-${{ inputs.sanitizer }}-${{ inputs.config_hash }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo ./.github/workflows/posix-deps-apt.sh
|
||||
# Install clang
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 20
|
||||
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-20 100
|
||||
sudo update-alternatives --set clang /usr/bin/clang-20
|
||||
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-20 100
|
||||
sudo update-alternatives --set clang++ /usr/bin/clang++-20
|
||||
|
||||
if [ "${SANITIZER}" = "TSan" ]; then
|
||||
sudo ./llvm.sh 17 # gh-121946: llvm-18 package is temporarily broken
|
||||
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-17 100
|
||||
sudo update-alternatives --set clang /usr/bin/clang-17
|
||||
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-17 100
|
||||
sudo update-alternatives --set clang++ /usr/bin/clang++-17
|
||||
# Reduce ASLR to avoid TSan crashing
|
||||
sudo sysctl -w vm.mmap_rnd_bits=28
|
||||
else
|
||||
sudo ./llvm.sh 20
|
||||
fi
|
||||
|
||||
- name: Sanitizer option setup
|
||||
|
|
@ -67,21 +60,13 @@ jobs:
|
|||
|| ''
|
||||
}}.txt handle_segv=0" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "UBSAN_OPTIONS=${SAN_LOG_OPTION}" >> "$GITHUB_ENV"
|
||||
echo "UBSAN_OPTIONS=${SAN_LOG_OPTION} halt_on_error=1 suppressions=${GITHUB_WORKSPACE}/Tools/ubsan/suppressions.txt" >> "$GITHUB_ENV"
|
||||
fi
|
||||
echo "CC=clang" >> "$GITHUB_ENV"
|
||||
echo "CXX=clang++" >> "$GITHUB_ENV"
|
||||
env:
|
||||
SANITIZER: ${{ inputs.sanitizer }}
|
||||
SAN_LOG_OPTION: log_path=${{ github.workspace }}/san_log
|
||||
- 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
|
||||
|
|
@ -89,7 +74,7 @@ jobs:
|
|||
${{
|
||||
inputs.sanitizer == 'TSan'
|
||||
&& '--with-thread-sanitizer'
|
||||
|| '--with-undefined-behavior-sanitizer'
|
||||
|| '--with-undefined-behavior-sanitizer --with-strict-overflow'
|
||||
}}
|
||||
--with-pydebug
|
||||
${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }}
|
||||
|
|
@ -97,10 +82,13 @@ jobs:
|
|||
run: make -j4
|
||||
- name: Display build info
|
||||
run: make pythoninfo
|
||||
# test_{capi,faulthandler} are skipped under UBSan because
|
||||
# they raise signals that UBSan with halt_on_error=1 intercepts.
|
||||
- name: Tests
|
||||
run: >-
|
||||
./python -m test
|
||||
${{ inputs.sanitizer == 'TSan' && '--tsan' || '' }}
|
||||
${{ inputs.sanitizer == 'UBSan' && '-x test_capi -x test_faulthandler' || '' }}
|
||||
-j4
|
||||
- name: Parallel tests
|
||||
if: >-
|
||||
|
|
@ -112,7 +100,7 @@ jobs:
|
|||
run: find "${GITHUB_WORKSPACE}" -name 'san_log.*' | xargs head -n 1000
|
||||
- name: Archive logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: >-
|
||||
${{ inputs.sanitizer }}-logs-${{
|
||||
|
|
|
|||
36
.github/workflows/reusable-ubuntu.yml
vendored
36
.github/workflows/reusable-ubuntu.yml
vendored
|
|
@ -3,9 +3,6 @@ name: Reusable Ubuntu
|
|||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
config_hash:
|
||||
required: true
|
||||
type: string
|
||||
bolt-optimizations:
|
||||
description: Whether to enable BOLT optimizations
|
||||
required: false
|
||||
|
|
@ -20,6 +17,14 @@ on:
|
|||
description: OS to run the job
|
||||
required: true
|
||||
type: string
|
||||
test-opts:
|
||||
description: Extra options to pass to the test runner via TESTOPTS
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
|
@ -30,11 +35,11 @@ jobs:
|
|||
runs-on: ${{ inputs.os }}
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
OPENSSL_VER: 3.0.15
|
||||
OPENSSL_VER: 3.5.5
|
||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||
TERM: linux
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Register gcc problem matcher
|
||||
|
|
@ -45,7 +50,7 @@ jobs:
|
|||
if: ${{ fromJSON(inputs.bolt-optimizations) }}
|
||||
run: |
|
||||
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh 19
|
||||
sudo apt-get install bolt-19
|
||||
sudo apt-get install --no-install-recommends bolt-19
|
||||
echo PATH="$(llvm-config-19 --bindir):$PATH" >> $GITHUB_ENV
|
||||
- name: Configure OpenSSL env vars
|
||||
run: |
|
||||
|
|
@ -54,21 +59,13 @@ jobs:
|
|||
echo "LD_LIBRARY_PATH=${GITHUB_WORKSPACE}/multissl/openssl/${OPENSSL_VER}/lib" >> "$GITHUB_ENV"
|
||||
- name: 'Restore OpenSSL build'
|
||||
id: cache-openssl
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
|
||||
key: ${{ inputs.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
|
||||
- name: Install OpenSSL
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
run: python3 Tools/ssl/multissltests.py --steps=library --base-directory "$MULTISSL_DIR" --openssl "$OPENSSL_VER" --system Linux
|
||||
- name: Add ccache to PATH
|
||||
run: |
|
||||
echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
|
||||
- name: Configure ccache action
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
save: ${{ github.event_name == 'push' }}
|
||||
max-size: "200M"
|
||||
- name: Setup directory envs for out-of-tree builds
|
||||
run: |
|
||||
echo "CPYTHON_RO_SRCDIR=$(realpath -m "${GITHUB_WORKSPACE}"/../cpython-ro-srcdir)" >> "$GITHUB_ENV"
|
||||
|
|
@ -79,11 +76,6 @@ 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
|
||||
|
|
@ -124,4 +116,6 @@ jobs:
|
|||
run: sudo mount "$CPYTHON_RO_SRCDIR" -oremount,rw
|
||||
- name: Tests
|
||||
working-directory: ${{ env.CPYTHON_BUILDDIR }}
|
||||
run: xvfb-run make ci
|
||||
run: xvfb-run make ci EXTRATESTOPTS="${TEST_OPTS}"
|
||||
env:
|
||||
TEST_OPTS: ${{ inputs.test-opts }}
|
||||
|
|
|
|||
75
.github/workflows/reusable-wasi.yml
vendored
75
.github/workflows/reusable-wasi.yml
vendored
|
|
@ -2,10 +2,9 @@ name: Reusable WASI
|
|||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
config_hash:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
|
@ -13,71 +12,55 @@ env:
|
|||
jobs:
|
||||
build-wasi-reusable:
|
||||
name: 'build and test'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-24.04-arm
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
WASMTIME_VERSION: 22.0.0
|
||||
WASI_SDK_VERSION: 24
|
||||
WASI_SDK_PATH: /opt/wasi-sdk
|
||||
WASMTIME_VERSION: 38.0.3
|
||||
CROSS_BUILD_PYTHON: cross-build/build
|
||||
CROSS_BUILD_WASI: cross-build/wasm32-wasip1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
# No problem resolver registered as one doesn't currently exist for Clang.
|
||||
- name: "Install wasmtime"
|
||||
uses: bytecodealliance/actions/wasmtime/setup@v1
|
||||
uses: bytecodealliance/actions/wasmtime/setup@9152e710e9f7182e4c29ad218e4f335a7b203613 # v1.1.3
|
||||
with:
|
||||
version: ${{ env.WASMTIME_VERSION }}
|
||||
- name: "Restore WASI SDK"
|
||||
id: cache-wasi-sdk
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.WASI_SDK_PATH }}
|
||||
key: ${{ runner.os }}-wasi-sdk-${{ env.WASI_SDK_VERSION }}
|
||||
- name: "Install WASI SDK" # Hard-coded to x64.
|
||||
if: steps.cache-wasi-sdk.outputs.cache-hit != 'true'
|
||||
- name: "Read WASI SDK version"
|
||||
id: wasi-sdk-version
|
||||
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-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
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
import os
|
||||
config = tomllib.loads(Path("Platforms/WASI/config.toml").read_text())
|
||||
version = config["targets"]["wasi-sdk"]
|
||||
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
|
||||
f.write(f"version={version}\n")
|
||||
shell: python
|
||||
- name: "Install WASI SDK"
|
||||
id: install-wasi-sdk
|
||||
uses: bytecodealliance/setup-wasi-sdk-action@b2de090b44eb70013ee96b393727d473b35e1728
|
||||
with:
|
||||
save: ${{ github.event_name == 'push' }}
|
||||
max-size: "200M"
|
||||
- name: "Add ccache to PATH"
|
||||
run: echo "PATH=/usr/lib/ccache:$PATH" >> "$GITHUB_ENV"
|
||||
version: ${{ steps.wasi-sdk-version.outputs.version }}
|
||||
add-to-path: false
|
||||
- name: "Install Python"
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
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.py configure-build-python -- --config-cache --with-pydebug
|
||||
run: python3 Platforms/WASI configure-build-python -- --config-cache --with-pydebug
|
||||
- name: "Make build Python"
|
||||
run: python3 Tools/wasm/wasi.py make-build-python
|
||||
- name: "Restore host config.cache"
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.CROSS_BUILD_WASI }}/config.cache
|
||||
# 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 }}
|
||||
run: python3 Platforms/WASI make-build-python
|
||||
- name: "Configure host"
|
||||
# `--with-pydebug` inferred from configure-build-python
|
||||
run: python3 Tools/wasm/wasi.py configure-host -- --config-cache
|
||||
run: python3 Platforms/WASI configure-host -- --config-cache
|
||||
env:
|
||||
WASI_SDK_PATH: ${{ steps.install-wasi-sdk.outputs.wasi-sdk-path }}
|
||||
- name: "Make host"
|
||||
run: python3 Tools/wasm/wasi.py make-host
|
||||
run: python3 Platforms/WASI make-host
|
||||
- name: "Display build info"
|
||||
run: make --directory "${CROSS_BUILD_WASI}" pythoninfo
|
||||
- name: "Test"
|
||||
|
|
|
|||
4
.github/workflows/reusable-windows-msi.yml
vendored
4
.github/workflows/reusable-windows-msi.yml
vendored
|
|
@ -17,13 +17,13 @@ env:
|
|||
jobs:
|
||||
build:
|
||||
name: installer for ${{ inputs.arch }}
|
||||
runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-latest' }}
|
||||
runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2025-vs2026' }}
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
ARCH: ${{ inputs.arch }}
|
||||
IncludeFreethreaded: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Build CPython installer
|
||||
|
|
|
|||
21
.github/workflows/reusable-windows.yml
vendored
21
.github/workflows/reusable-windows.yml
vendored
|
|
@ -12,6 +12,13 @@ on:
|
|||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
interpreter:
|
||||
description: Which interpreter to build (switch-case or tail-call)
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
|
@ -20,22 +27,25 @@ env:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
name: Build and test (${{ inputs.arch }})
|
||||
runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-latest' }}
|
||||
name: Build and test (${{ inputs.arch }}, ${{ inputs.interpreter }})
|
||||
runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2025-vs2026' }}
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
ARCH: ${{ inputs.arch }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Register MSVC problem matcher
|
||||
if: inputs.arch != 'Win32'
|
||||
run: echo "::add-matcher::.github/problem-matchers/msvc.json"
|
||||
- name: Build CPython
|
||||
# msvc::musttail is not supported for debug builds, so we have to
|
||||
# switch to release.
|
||||
run: >-
|
||||
.\\PCbuild\\build.bat
|
||||
-e -d -v
|
||||
-e -v
|
||||
${{ inputs.interpreter == 'switch-case' && '-d' || '--tail-call-interp -c Release' }}
|
||||
-p "${ARCH}"
|
||||
${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }}
|
||||
shell: bash
|
||||
|
|
@ -45,6 +55,7 @@ jobs:
|
|||
run: >-
|
||||
.\\PCbuild\\rt.bat
|
||||
-p "${ARCH}"
|
||||
-d -q --fast-ci
|
||||
-q --fast-ci
|
||||
${{ inputs.interpreter == 'switch-case' && '-d' || '' }}
|
||||
${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }}
|
||||
shell: bash
|
||||
|
|
|
|||
6
.github/workflows/stale.yml
vendored
6
.github/workflows/stale.yml
vendored
|
|
@ -4,17 +4,21 @@ on:
|
|||
schedule:
|
||||
- cron: "0 */6 * * *"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
if: github.repository_owner == 'python'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: write
|
||||
pull-requests: write
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: "Check PRs"
|
||||
uses: actions/stale@v9
|
||||
uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-pr-message: 'This PR is stale because it has been open for 30 days with no activity.'
|
||||
|
|
|
|||
141
.github/workflows/tail-call.yml
vendored
141
.github/workflows/tail-call.yml
vendored
|
|
@ -1,19 +1,14 @@
|
|||
name: Tail calling interpreter
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
paths: &paths
|
||||
- '.github/workflows/tail-call.yml'
|
||||
- 'Python/bytecodes.c'
|
||||
- 'Python/ceval.c'
|
||||
- 'Python/ceval_macros.h'
|
||||
- 'Python/generated_cases.c.h'
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/tail-call.yml'
|
||||
- 'Python/bytecodes.c'
|
||||
- 'Python/ceval.c'
|
||||
- 'Python/ceval_macros.h'
|
||||
- 'Python/generated_cases.c.h'
|
||||
paths: *paths
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
|
|
@ -25,115 +20,73 @@ concurrency:
|
|||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
LLVM_VERSION: 21
|
||||
|
||||
jobs:
|
||||
tail-call:
|
||||
macos:
|
||||
name: ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 90
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
# Un-comment as we add support for more platforms for tail-calling interpreters.
|
||||
# - i686-pc-windows-msvc/msvc
|
||||
- x86_64-pc-windows-msvc/msvc
|
||||
# - aarch64-pc-windows-msvc/msvc
|
||||
- x86_64-apple-darwin/clang
|
||||
- aarch64-apple-darwin/clang
|
||||
- x86_64-unknown-linux-gnu/gcc
|
||||
- aarch64-unknown-linux-gnu/gcc
|
||||
- free-threading
|
||||
llvm:
|
||||
- 20
|
||||
include:
|
||||
# - target: i686-pc-windows-msvc/msvc
|
||||
# architecture: Win32
|
||||
# runner: windows-latest
|
||||
- target: x86_64-pc-windows-msvc/msvc
|
||||
architecture: x64
|
||||
runner: windows-latest
|
||||
# - target: aarch64-pc-windows-msvc/msvc
|
||||
# architecture: ARM64
|
||||
# runner: windows-latest
|
||||
- target: x86_64-apple-darwin/clang
|
||||
architecture: x86_64
|
||||
runner: macos-13
|
||||
runner: macos-15-intel
|
||||
- target: aarch64-apple-darwin/clang
|
||||
architecture: aarch64
|
||||
runner: macos-14
|
||||
- target: x86_64-unknown-linux-gnu/gcc
|
||||
architecture: x86_64
|
||||
runner: ubuntu-24.04
|
||||
- target: aarch64-unknown-linux-gnu/gcc
|
||||
architecture: aarch64
|
||||
runner: ubuntu-24.04-arm
|
||||
- target: free-threading
|
||||
architecture: x86_64
|
||||
runner: ubuntu-24.04
|
||||
runner: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Native Windows (debug)
|
||||
if: runner.os == 'Windows' && matrix.architecture != 'ARM64'
|
||||
shell: cmd
|
||||
run: |
|
||||
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 (release)
|
||||
if: runner.os == 'Windows' && matrix.architecture == 'ARM64'
|
||||
shell: cmd
|
||||
run: |
|
||||
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
|
||||
./PCbuild/build.bat --tail-call-interp -p ${{ matrix.architecture }}
|
||||
|
||||
# The `find` line is required as a result of https://github.com/actions/runner-images/issues/9966.
|
||||
# This is a bug in the macOS runner image where the pre-installed Python is installed in the same
|
||||
# directory as the Homebrew Python, which causes the build to fail for macos-13. This line removes
|
||||
# the symlink to the pre-installed Python so that the Homebrew Python is used instead.
|
||||
# Note: when a new LLVM is released, the homebrew installation directory changes, so the builds will fail.
|
||||
# We either need to upgrade LLVM or change the directory being pointed to.
|
||||
- name: Native macOS (release)
|
||||
if: runner.os == 'macOS'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew update
|
||||
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
|
||||
brew install llvm@${{ matrix.llvm }}
|
||||
brew install llvm@${{ env.LLVM_VERSION }}
|
||||
- name: Build
|
||||
run: |
|
||||
export SDKROOT="$(xcrun --show-sdk-path)"
|
||||
export PATH="/usr/local/opt/llvm@${{ matrix.llvm }}/bin:$PATH"
|
||||
export PATH="/opt/homebrew/opt/llvm@${{ matrix.llvm }}/bin:$PATH"
|
||||
CC=clang-20 ./configure --with-tail-call-interp
|
||||
export PATH="/usr/local/opt/llvm@${{ env.LLVM_VERSION }}/bin:$PATH"
|
||||
export PATH="/opt/homebrew/opt/llvm@${{ env.LLVM_VERSION }}/bin:$PATH"
|
||||
CC=clang-${{ env.LLVM_VERSION }} ./configure --with-tail-call-interp
|
||||
make all --jobs 4
|
||||
- name: Test
|
||||
run: |
|
||||
./python.exe -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
||||
- name: Native Linux (debug)
|
||||
if: runner.os == 'Linux' && matrix.target != 'free-threading'
|
||||
linux:
|
||||
name: ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-gnu/gcc
|
||||
runner: ubuntu-24.04
|
||||
configure_flags: --with-pydebug
|
||||
- target: x86_64-unknown-linux-gnu/gcc-free-threading
|
||||
runner: ubuntu-24.04
|
||||
configure_flags: --disable-gil
|
||||
- target: aarch64-unknown-linux-gnu/gcc
|
||||
runner: ubuntu-24.04-arm
|
||||
configure_flags: --with-pydebug
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Build
|
||||
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-20 ./configure --with-tail-call-interp --with-pydebug
|
||||
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ env.LLVM_VERSION }}
|
||||
export PATH="$(llvm-config-${{ env.LLVM_VERSION }} --bindir):$PATH"
|
||||
CC=clang-${{ env.LLVM_VERSION }} ./configure --with-tail-call-interp ${{ matrix.configure_flags }}
|
||||
make all --jobs 4
|
||||
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
||||
- name: Native Linux with free-threading (release)
|
||||
if: matrix.target == 'free-threading'
|
||||
- name: Test
|
||||
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-20 ./configure --with-tail-call-interp --disable-gil
|
||||
make all --jobs 4
|
||||
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3'
|
||||
- name: Compare checksum of bundled wheels to the ones published on PyPI
|
||||
|
|
|
|||
32
.github/workflows/verify-expat.yml
vendored
Normal file
32
.github/workflows/verify-expat.yml
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
name: Verify bundled libexpat
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'Modules/expat/**'
|
||||
- '.github/workflows/verify-expat.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'Modules/expat/**'
|
||||
- '.github/workflows/verify-expat.yml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Download and verify bundled libexpat files
|
||||
run: |
|
||||
./Modules/expat/refresh.sh
|
||||
git diff --exit-code Modules/expat/
|
||||
8
.github/zizmor.yml
vendored
8
.github/zizmor.yml
vendored
|
|
@ -1,10 +1,6 @@
|
|||
# Configuration for the zizmor static analysis tool, run via pre-commit in CI
|
||||
# https://woodruffw.github.io/zizmor/configuration/
|
||||
# Configuration for the zizmor static analysis tool, run via prek in CI
|
||||
# https://docs.zizmor.sh/configuration/
|
||||
rules:
|
||||
dangerous-triggers:
|
||||
ignore:
|
||||
- documentation-links.yml
|
||||
unpinned-uses:
|
||||
config:
|
||||
policies:
|
||||
"*": ref-pin
|
||||
|
|
|
|||
23
.gitignore
vendored
23
.gitignore
vendored
|
|
@ -5,6 +5,7 @@
|
|||
*.cover
|
||||
*.iml
|
||||
*.o
|
||||
*.o.tmp
|
||||
*.lto
|
||||
*.a
|
||||
*.so
|
||||
|
|
@ -45,6 +46,7 @@ gmon.out
|
|||
.pytest_cache/
|
||||
.ruff_cache/
|
||||
.DS_Store
|
||||
.pixi/
|
||||
|
||||
*.exe
|
||||
|
||||
|
|
@ -71,15 +73,15 @@ Lib/test/data/*
|
|||
/Makefile
|
||||
/Makefile.pre
|
||||
/iOSTestbed.*
|
||||
iOS/Frameworks/
|
||||
iOS/Resources/Info.plist
|
||||
iOS/testbed/build
|
||||
iOS/testbed/Python.xcframework/ios-*/bin
|
||||
iOS/testbed/Python.xcframework/ios-*/include
|
||||
iOS/testbed/Python.xcframework/ios-*/lib
|
||||
iOS/testbed/Python.xcframework/ios-*/Python.framework
|
||||
iOS/testbed/iOSTestbed.xcodeproj/project.xcworkspace
|
||||
iOS/testbed/iOSTestbed.xcodeproj/xcuserdata
|
||||
Apple/iOS/Frameworks/
|
||||
Apple/iOS/Resources/Info.plist
|
||||
Apple/testbed/build
|
||||
Apple/testbed/Python.xcframework/*/bin
|
||||
Apple/testbed/Python.xcframework/*/include
|
||||
Apple/testbed/Python.xcframework/*/lib
|
||||
Apple/testbed/Python.xcframework/*/Python.framework
|
||||
Apple/testbed/*Testbed.xcodeproj/project.xcworkspace
|
||||
Apple/testbed/*Testbed.xcodeproj/xcuserdata
|
||||
Mac/Makefile
|
||||
Mac/PythonLauncher/Info.plist
|
||||
Mac/PythonLauncher/Makefile
|
||||
|
|
@ -135,9 +137,8 @@ Tools/unicode/data/
|
|||
/config.log
|
||||
/config.status
|
||||
/config.status.lineno
|
||||
# hendrikmuhs/ccache-action@v1
|
||||
/.ccache
|
||||
/cross-build/
|
||||
/cross-build*/
|
||||
/jit_stencils*.h
|
||||
/platform
|
||||
/profile-clean-stamp
|
||||
|
|
|
|||
|
|
@ -1,56 +1,79 @@
|
|||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.12.8
|
||||
rev: e05c5c0818279e5ac248ac9e954431ba58865e61 # frozen: v0.15.7
|
||||
hooks:
|
||||
- id: ruff
|
||||
- id: ruff-check
|
||||
name: Run Ruff (lint) on Platforms/Apple/
|
||||
args: [--exit-non-zero-on-fix, --config=Platforms/Apple/.ruff.toml]
|
||||
files: ^Platforms/Apple/
|
||||
- id: ruff-check
|
||||
name: Run Ruff (lint) on Doc/
|
||||
args: [--exit-non-zero-on-fix]
|
||||
files: ^Doc/
|
||||
- id: ruff
|
||||
- id: ruff-check
|
||||
name: Run Ruff (lint) on Lib/test/
|
||||
args: [--exit-non-zero-on-fix]
|
||||
files: ^Lib/test/
|
||||
- id: ruff
|
||||
- id: ruff-check
|
||||
name: Run Ruff (lint) on Platforms/WASI/
|
||||
args: [--exit-non-zero-on-fix, --config=Platforms/WASI/.ruff.toml]
|
||||
files: ^Platforms/WASI/
|
||||
- id: ruff-check
|
||||
name: Run Ruff (lint) on Tools/build/
|
||||
args: [--exit-non-zero-on-fix, --config=Tools/build/.ruff.toml]
|
||||
files: ^Tools/build/
|
||||
- id: ruff
|
||||
- id: ruff-check
|
||||
name: Run Ruff (lint) on Tools/i18n/
|
||||
args: [--exit-non-zero-on-fix, --config=Tools/i18n/.ruff.toml]
|
||||
files: ^Tools/i18n/
|
||||
- id: ruff
|
||||
- id: ruff-check
|
||||
name: Run Ruff (lint) on Argument Clinic
|
||||
args: [--exit-non-zero-on-fix, --config=Tools/clinic/.ruff.toml]
|
||||
files: ^Tools/clinic/|Lib/test/test_clinic.py
|
||||
- id: ruff
|
||||
- id: ruff-check
|
||||
name: Run Ruff (lint) on Tools/peg_generator/
|
||||
args: [--exit-non-zero-on-fix, --config=Tools/peg_generator/.ruff.toml]
|
||||
files: ^Tools/peg_generator/
|
||||
- id: ruff-check
|
||||
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 Platforms/Apple/
|
||||
args: [--exit-non-zero-on-fix, --config=Platforms/Apple/.ruff.toml]
|
||||
files: ^Platforms/Apple/
|
||||
- id: ruff-format
|
||||
name: Run Ruff (format) on Doc/
|
||||
args: [--check]
|
||||
args: [--exit-non-zero-on-fix]
|
||||
files: ^Doc/
|
||||
- id: ruff-format
|
||||
name: Run Ruff (format) on Platforms/WASI/
|
||||
args: [--exit-non-zero-on-fix, --config=Platforms/WASI/.ruff.toml]
|
||||
files: ^Platforms/WASI/
|
||||
- id: ruff-format
|
||||
name: Run Ruff (format) on Tools/build/check_warnings.py
|
||||
args: [--check, --config=Tools/build/.ruff.toml]
|
||||
args: [--exit-non-zero-on-fix, --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]
|
||||
files: ^Tools/wasm/
|
||||
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 25.1.0
|
||||
rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0
|
||||
hooks:
|
||||
- id: black
|
||||
name: Run Black on Tools/jit/
|
||||
files: ^Tools/jit/
|
||||
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: v1.5.5
|
||||
rev: ad1b27d73581aa16cca06fc4a0761fc563ffe8e8 # frozen: v1.5.6
|
||||
hooks:
|
||||
- id: remove-tabs
|
||||
types: [python]
|
||||
exclude: ^Tools/c-analyzer/cpython/_parser.py
|
||||
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v6.0.0
|
||||
rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
|
||||
hooks:
|
||||
- id: check-case-conflict
|
||||
- id: check-merge-conflict
|
||||
|
|
@ -62,30 +85,33 @@ repos:
|
|||
exclude: Lib/test/tokenizedata/coding20731.py
|
||||
- id: end-of-file-fixer
|
||||
files: '^\.github/CODEOWNERS$'
|
||||
- id: mixed-line-ending
|
||||
args: [--fix=auto]
|
||||
exclude: '^Lib/test/.*data/'
|
||||
- id: trailing-whitespace
|
||||
types_or: [c, inc, python, rst, yaml]
|
||||
- id: trailing-whitespace
|
||||
files: '^\.github/CODEOWNERS|\.(gram)$'
|
||||
|
||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||
rev: 0.33.2
|
||||
rev: 9f48a48aa91a6040d749ad68ec70907d907a5a7f # frozen: 0.37.0
|
||||
hooks:
|
||||
- id: check-dependabot
|
||||
- id: check-github-workflows
|
||||
- id: check-readthedocs
|
||||
|
||||
- repo: https://github.com/rhysd/actionlint
|
||||
rev: v1.7.7
|
||||
rev: 393031adb9afb225ee52ae2ccd7a5af5525e03e8 # frozen: v1.7.11
|
||||
hooks:
|
||||
- id: actionlint
|
||||
|
||||
- repo: https://github.com/woodruffw/zizmor-pre-commit
|
||||
rev: v1.11.0
|
||||
- repo: https://github.com/zizmorcore/zizmor-pre-commit
|
||||
rev: b546b77c44c466a54a42af5499dcc0dcc1a3193f # frozen: v1.22.0
|
||||
hooks:
|
||||
- id: zizmor
|
||||
|
||||
- repo: https://github.com/sphinx-contrib/sphinx-lint
|
||||
rev: v1.0.0
|
||||
rev: c883505f64b59c3c5c9375191e4ad9f98e727ccd # frozen: v1.0.2
|
||||
hooks:
|
||||
- id: sphinx-lint
|
||||
args: [--enable=default-role]
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
import os
|
||||
import runpy
|
||||
import shlex
|
||||
import signal
|
||||
import sys
|
||||
|
||||
# Some tests use SIGUSR1, but that's blocked by default in an Android app in
|
||||
# order to make it available to `sigwait` in the Signal Catcher thread.
|
||||
# (https://cs.android.com/android/platform/superproject/+/android14-qpr3-release:art/runtime/signal_catcher.cc).
|
||||
# That thread's functionality is only useful for debugging the JVM, so disabling
|
||||
# it should not weaken the tests.
|
||||
#
|
||||
# There's no safe way of stopping the thread completely (#123982), but simply
|
||||
# unblocking SIGUSR1 is enough to fix most tests.
|
||||
#
|
||||
# However, in tests that generate multiple different signals in quick
|
||||
# succession, it's possible for SIGUSR1 to arrive while the main thread is busy
|
||||
# running the C-level handler for a different signal. In that case, the SIGUSR1
|
||||
# may be sent to the Signal Catcher thread instead, which will generate a log
|
||||
# message containing the text "reacting to signal".
|
||||
#
|
||||
# Such tests may need to be changed in one of the following ways:
|
||||
# * Use a signal other than SIGUSR1 (e.g. test_stress_delivery_simultaneous in
|
||||
# test_signal.py).
|
||||
# * Send the signal to a specific thread rather than the whole process (e.g.
|
||||
# test_signals in test_threadsignals.py.
|
||||
signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGUSR1])
|
||||
|
||||
mode = os.environ["PYTHON_MODE"]
|
||||
module = os.environ["PYTHON_MODULE"]
|
||||
sys.argv[1:] = shlex.split(os.environ["PYTHON_ARGS"])
|
||||
|
||||
cwd = f"{sys.prefix}/cwd"
|
||||
if not os.path.exists(cwd):
|
||||
# Empty directories are lost in the asset packing/unpacking process.
|
||||
os.mkdir(cwd)
|
||||
os.chdir(cwd)
|
||||
|
||||
if mode == "-c":
|
||||
# In -c mode, sys.path starts with an empty string, which means whatever the current
|
||||
# working directory is at the moment of each import.
|
||||
sys.path.insert(0, "")
|
||||
exec(module, {})
|
||||
elif mode == "-m":
|
||||
sys.path.insert(0, os.getcwd())
|
||||
runpy.run_module(module, run_name="__main__", alter_sys=True)
|
||||
else:
|
||||
raise ValueError(f"unknown mode: {mode}")
|
||||
|
|
@ -32,6 +32,9 @@ ignore = [
|
|||
"E501", # Ignore line length errors (we use auto-formatting)
|
||||
]
|
||||
|
||||
[lint.per-file-ignores]
|
||||
"tools/check-html-ids.py" = ["I001"] # Unsorted imports
|
||||
|
||||
[format]
|
||||
preview = true
|
||||
quote-style = "preserve"
|
||||
|
|
|
|||
25
Doc/Makefile
25
Doc/Makefile
|
|
@ -13,7 +13,7 @@ JOBS = auto
|
|||
PAPER =
|
||||
SOURCES =
|
||||
DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py)
|
||||
REQUIREMENTS = requirements.txt
|
||||
REQUIREMENTS = pylock.toml
|
||||
SPHINXERRORHANDLING = --fail-on-warning
|
||||
|
||||
# Internal variables.
|
||||
|
|
@ -58,7 +58,7 @@ build:
|
|||
@if [ -f ../Misc/NEWS ] ; then \
|
||||
echo "Using existing Misc/NEWS file"; \
|
||||
cp ../Misc/NEWS build/NEWS; \
|
||||
elif $(BLURB) help >/dev/null 2>&1 && $(SPHINXBUILD) --version >/dev/null 2>&1; then \
|
||||
elif $(BLURB) --version && $(SPHINXBUILD) --version ; then \
|
||||
if [ -d ../Misc/NEWS.d ]; then \
|
||||
echo "Building NEWS from Misc/NEWS.d with blurb"; \
|
||||
$(BLURB) merge -f build/NEWS; \
|
||||
|
|
@ -88,6 +88,7 @@ htmlhelp: build
|
|||
"build/htmlhelp/pydoc.hhp project file."
|
||||
|
||||
.PHONY: latex
|
||||
latex: _ensure-sphinxcontrib-svg2pdfconverter
|
||||
latex: BUILDER = latex
|
||||
latex: build
|
||||
@echo "Build finished; the LaTeX files are in build/latex."
|
||||
|
|
@ -140,7 +141,8 @@ 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/topics.py ../Lib/pydoc_data/topics.py" \
|
||||
"&& cp build/pydoc-topics/module_docs.py ../Lib/pydoc_data/module_docs.py"
|
||||
|
||||
.PHONY: gettext
|
||||
gettext: BUILDER = gettext
|
||||
|
|
@ -184,7 +186,7 @@ venv:
|
|||
fi
|
||||
|
||||
.PHONY: dist-no-html
|
||||
dist-no-html: dist-text dist-pdf dist-epub dist-texinfo
|
||||
dist-no-html: dist-text dist-epub dist-texinfo
|
||||
|
||||
.PHONY: dist
|
||||
dist:
|
||||
|
|
@ -230,7 +232,7 @@ dist-text:
|
|||
@echo "Build finished and archived!"
|
||||
|
||||
.PHONY: dist-pdf
|
||||
dist-pdf:
|
||||
dist-pdf: _ensure-sphinxcontrib-svg2pdfconverter
|
||||
# archive the A4 latex
|
||||
@echo "Building LaTeX (A4 paper)..."
|
||||
mkdir -p dist
|
||||
|
|
@ -241,7 +243,8 @@ 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
|
||||
(cd build/latex; $(MAKE) clean && $(MAKE) --jobs=$$((`nproc`+1)) --output-sync LATEXMKOPTS='-quiet' all-pdf && $(MAKE) FMT=pdf zip bz2)
|
||||
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)
|
||||
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!"
|
||||
|
|
@ -290,6 +293,10 @@ _ensure-pre-commit:
|
|||
_ensure-sphinx-autobuild:
|
||||
$(MAKE) _ensure-package PACKAGE=sphinx-autobuild
|
||||
|
||||
.PHONY: _ensure-sphinxcontrib-svg2pdfconverter
|
||||
_ensure-sphinxcontrib-svg2pdfconverter:
|
||||
$(MAKE) _ensure-package PACKAGE=sphinxcontrib-svg2pdfconverter
|
||||
|
||||
.PHONY: check
|
||||
check: _ensure-pre-commit
|
||||
$(VENVDIR)/bin/python3 -m pre_commit run --all-files
|
||||
|
|
@ -334,3 +341,9 @@ autobuild-stable-html:
|
|||
exit 1;; \
|
||||
esac
|
||||
@$(MAKE) autobuild-dev-html
|
||||
|
||||
# Collect HTML IDs to a JSON document
|
||||
.PHONY: html-ids
|
||||
html-ids:
|
||||
$(PYTHON) tools/check-html-ids.py collect build/html \
|
||||
-o build/html/html-ids.json.gz
|
||||
|
|
|
|||
570
Doc/_static/profiling-sampling-visualization.css
Normal file
570
Doc/_static/profiling-sampling-visualization.css
Normal file
|
|
@ -0,0 +1,570 @@
|
|||
/**
|
||||
* Sampling Profiler Visualization - Scoped CSS
|
||||
*/
|
||||
|
||||
.sampling-profiler-viz {
|
||||
/* Match docs background colors */
|
||||
--bg-page: #ffffff;
|
||||
--bg-panel: #ffffff;
|
||||
--bg-subtle: #f8f8f8;
|
||||
--bg-code: #f8f8f8;
|
||||
|
||||
/* Match docs border style */
|
||||
--border-color: #e1e4e8;
|
||||
--border-accent: #3776ab;
|
||||
|
||||
/* Match docs text colors */
|
||||
--text-primary: #0d0d0d;
|
||||
--text-secondary: #505050;
|
||||
--text-muted: #6e6e6e;
|
||||
--text-code: #333333;
|
||||
|
||||
/* Accent colors */
|
||||
--color-python-blue: #306998;
|
||||
--color-green: #388e3c;
|
||||
--color-orange: #e65100;
|
||||
--color-purple: #7b1fa2;
|
||||
--color-red: #c62828;
|
||||
--color-teal: #00897b;
|
||||
--color-yellow: #d4a910;
|
||||
--color-highlight: #fff9e6;
|
||||
|
||||
--radius-lg: 8px;
|
||||
--radius-md: 6px;
|
||||
--radius-sm: 4px;
|
||||
|
||||
/* Lighter shadows to match docs style */
|
||||
--shadow-card: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
|
||||
|
||||
--container-height: 520px;
|
||||
--code-panel-width: 320px;
|
||||
|
||||
/* Reset for isolation */
|
||||
font-family: var(--font-ui);
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--bg-page);
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
/* Layout */
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 920px;
|
||||
height: var(--container-height);
|
||||
display: grid;
|
||||
grid-template-columns: var(--code-panel-width) 1fr;
|
||||
margin: 24px auto;
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-card);
|
||||
border: 1px solid var(--border-color);
|
||||
background: var(--bg-panel);
|
||||
/* Prevent any DOM changes inside from affecting page scroll */
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Code Panel - Left Column */
|
||||
.sampling-profiler-viz #code-panel {
|
||||
background: var(--bg-panel);
|
||||
border-right: 1px solid var(--border-color);
|
||||
overflow-y: auto;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
line-height: 1.6;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .code-panel-title {
|
||||
padding: 12px 16px;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
background: var(--bg-code);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .code-container {
|
||||
margin: 0;
|
||||
padding: 12px 0;
|
||||
overflow-x: auto;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .line {
|
||||
display: flex;
|
||||
padding: 1px 0;
|
||||
min-height: 20px;
|
||||
transition: background-color 0.1s ease;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .line-number {
|
||||
color: var(--text-muted);
|
||||
min-width: 40px;
|
||||
text-align: right;
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
user-select: none;
|
||||
flex-shrink: 0;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .line-content {
|
||||
flex: 1;
|
||||
color: var(--text-code);
|
||||
padding-right: 12px;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .line.highlighted {
|
||||
background: var(--color-highlight);
|
||||
border-left: 3px solid var(--color-yellow);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .line.highlighted .line-number {
|
||||
color: var(--color-yellow);
|
||||
padding-left: 9px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .line.highlighted .line-content {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Python Syntax Highlighting */
|
||||
.sampling-profiler-viz #code-panel .keyword {
|
||||
color: var(--color-red);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .function {
|
||||
color: var(--color-purple);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .number {
|
||||
color: var(--color-python-blue);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .string {
|
||||
color: #032f62;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .comment {
|
||||
color: #6a737d;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel .builtin {
|
||||
color: var(--color-python-blue);
|
||||
}
|
||||
|
||||
/* Visualization Column - Right Side */
|
||||
.sampling-profiler-viz .viz-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-subtle);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Stack Section */
|
||||
.sampling-profiler-viz .stack-section {
|
||||
padding: 12px 16px;
|
||||
flex: 1;
|
||||
min-height: 150px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .stack-section-title {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .stack-visualization {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-height: 80px;
|
||||
}
|
||||
|
||||
/* Stack Frames - Vertical Layout */
|
||||
.sampling-profiler-viz .stack-frame {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
cursor: pointer;
|
||||
contain: layout style paint;
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .stack-frame.visible {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
transition:
|
||||
opacity 0.3s ease,
|
||||
transform 0.3s ease;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .stack-frame-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: var(--radius-sm);
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .stack-frame-text {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font: 500 11px var(--font-mono);
|
||||
color: white;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .stack-frame-flash {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: white;
|
||||
border-radius: var(--radius-sm);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .stack-frame:hover .stack-frame-bg {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* Flying frames */
|
||||
.sampling-profiler-viz .stack-frame.flying {
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: auto;
|
||||
height: 32px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Flying stack clone */
|
||||
.stack-visualization.flying-clone {
|
||||
transform-origin: center center;
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
|
||||
/* Sampling Panel */
|
||||
.sampling-profiler-viz .sampling-panel {
|
||||
margin: 0 16px 12px 16px;
|
||||
background: var(--bg-panel);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-md);
|
||||
box-shadow: var(--shadow-sm);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 0 0 auto;
|
||||
height: 200px;
|
||||
/* Lock font size to prevent Sphinx responsive scaling */
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .sampling-header {
|
||||
padding: 8px 10px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .sampling-title {
|
||||
font: 600 10px var(--font-mono);
|
||||
color: var(--text-primary);
|
||||
margin: 0 0 3px 0;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .sampling-stats {
|
||||
font: 400 9px var(--font-mono);
|
||||
color: var(--text-secondary);
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .sampling-stats .missed {
|
||||
color: var(--color-red);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .sampling-bars {
|
||||
flex: 1;
|
||||
padding: 10px 12px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .sampling-bar-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .bar-label {
|
||||
font: 500 8px var(--font-mono);
|
||||
color: var(--text-primary);
|
||||
flex-shrink: 0;
|
||||
width: 60px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .bar-container {
|
||||
flex: 1;
|
||||
height: 12px;
|
||||
background: var(--border-color);
|
||||
border-radius: 3px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .bar-fill {
|
||||
height: 100%;
|
||||
border-radius: 3px;
|
||||
transition: width 0.2s ease;
|
||||
min-width: 2px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .bar-percent {
|
||||
font: 500 8px var(--font-mono);
|
||||
color: var(--text-secondary);
|
||||
width: 36px;
|
||||
text-align: right;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Impact effect circle */
|
||||
.impact-circle {
|
||||
position: fixed;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-teal);
|
||||
transform: translate(-50%, -50%);
|
||||
pointer-events: none;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
/* Control Panel - Integrated */
|
||||
.sampling-profiler-viz #control-panel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 12px 16px;
|
||||
background: var(--bg-panel);
|
||||
border-top: 1px solid var(--border-color);
|
||||
flex-shrink: 0;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .control-group {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .control-group label {
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .control-btn {
|
||||
background: var(--bg-panel);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 6px 10px;
|
||||
border-radius: var(--radius-sm);
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .control-btn:hover {
|
||||
background: var(--bg-subtle);
|
||||
border-color: var(--text-muted);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .control-btn:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .control-btn.active {
|
||||
background: var(--color-python-blue);
|
||||
color: white;
|
||||
border-color: var(--color-python-blue);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .control-btn.active:hover {
|
||||
background: #2f6493;
|
||||
}
|
||||
|
||||
/* Timeline Scrubber */
|
||||
.sampling-profiler-viz .timeline-scrubber {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-width: 160px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #timeline-scrubber {
|
||||
flex: 1;
|
||||
height: 5px;
|
||||
border-radius: 3px;
|
||||
background: var(--border-color);
|
||||
outline: none;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
cursor: pointer;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #timeline-scrubber::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-python-blue);
|
||||
cursor: pointer;
|
||||
transition: transform 0.15s;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #timeline-scrubber::-webkit-slider-thumb:hover {
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #timeline-scrubber::-moz-range-thumb {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-python-blue);
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #time-display {
|
||||
font: 500 10px var(--font-mono);
|
||||
color: var(--text-secondary);
|
||||
min-width: 90px;
|
||||
text-align: right;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
/* Sample Interval Slider */
|
||||
.sampling-profiler-viz #sample-interval {
|
||||
width: 80px;
|
||||
height: 4px;
|
||||
border-radius: 2px;
|
||||
background: var(--border-color);
|
||||
outline: none;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #sample-interval::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-teal);
|
||||
cursor: pointer;
|
||||
transition: transform 0.15s;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #sample-interval::-webkit-slider-thumb:hover {
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #sample-interval::-moz-range-thumb {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-teal);
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #interval-display {
|
||||
font: 500 9px var(--font-mono);
|
||||
color: var(--text-secondary);
|
||||
min-width: 40px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
/* Flash overlay */
|
||||
.sampling-profiler-viz .flash-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: white;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Performance optimizations */
|
||||
.sampling-profiler-viz .stack-frame,
|
||||
.sampling-profiler-viz .flying-frame,
|
||||
.sampling-profiler-viz .sampling-bar-row {
|
||||
will-change: transform, opacity;
|
||||
contain: layout style paint;
|
||||
}
|
||||
|
||||
/* Reduced motion support */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.sampling-profiler-viz .stack-frame,
|
||||
.sampling-profiler-viz .flying-frame,
|
||||
.sampling-profiler-viz .sampling-bar-row,
|
||||
.impact-circle {
|
||||
animation-duration: 0.01ms !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive adjustments for narrower viewports */
|
||||
@media (max-width: 800px) {
|
||||
.sampling-profiler-viz {
|
||||
grid-template-columns: 280px 1fr;
|
||||
--container-height: 550px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz #code-panel {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.sampling-profiler-viz .control-btn {
|
||||
padding: 5px 8px;
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
1163
Doc/_static/profiling-sampling-visualization.js
Normal file
1163
Doc/_static/profiling-sampling-visualization.js
Normal file
File diff suppressed because it is too large
Load diff
3260
Doc/_static/tachyon-example-flamegraph.html
generated
Normal file
3260
Doc/_static/tachyon-example-flamegraph.html
generated
Normal file
File diff suppressed because one or more lines are too long
3804
Doc/_static/tachyon-example-heatmap.html
generated
Normal file
3804
Doc/_static/tachyon-example-heatmap.html
generated
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -32,8 +32,9 @@ Contributors to the Python documentation
|
|||
----------------------------------------
|
||||
|
||||
Many people have contributed to the Python language, the Python standard
|
||||
library, and the Python documentation. See :source:`Misc/ACKS` in the Python
|
||||
source distribution for a partial list of contributors.
|
||||
library, and the Python documentation. See the `CPython
|
||||
GitHub repository <https://github.com/python/cpython/graphs/contributors>`__
|
||||
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!
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ stability. In order to maintain this reputation, the developers would like to
|
|||
know of any deficiencies you find in Python.
|
||||
|
||||
It can be sometimes faster to fix bugs yourself and contribute patches to
|
||||
Python as it streamlines the process and involves less people. Learn how to
|
||||
Python as it streamlines the process and involves fewer people. Learn how to
|
||||
:ref:`contribute <contributing-to-python>`.
|
||||
|
||||
Documentation bugs
|
||||
|
|
@ -19,6 +19,12 @@ 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
|
||||
`translation’s repository <TRANSLATION_REPO_>`_ instead.
|
||||
|
||||
You can also open a discussion item on our
|
||||
`Documentation Discourse forum <https://discuss.python.org/c/documentation/26>`_.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
.. _allocating-objects:
|
||||
|
||||
Allocating Objects on the Heap
|
||||
Allocating objects on the heap
|
||||
==============================
|
||||
|
||||
|
||||
|
|
@ -140,10 +140,6 @@ 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
|
||||
|
|
@ -156,3 +152,37 @@ Allocating Objects on the Heap
|
|||
:ref:`moduleobjects`
|
||||
To allocate and create extension modules.
|
||||
|
||||
|
||||
Soft-deprecated aliases
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
These are aliases to existing functions and macros.
|
||||
They exist solely for backwards compatibility.
|
||||
|
||||
|
||||
.. list-table::
|
||||
:widths: auto
|
||||
:header-rows: 1
|
||||
|
||||
* * Soft-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`
|
||||
|
|
|
|||
|
|
@ -34,6 +34,23 @@ See :ref:`stable` for a discussion of API and ABI stability across versions.
|
|||
This can be ``0xA`` for alpha, ``0xB`` for beta, ``0xC`` for release
|
||||
candidate or ``0xF`` for final.
|
||||
|
||||
|
||||
.. c:namespace:: NULL
|
||||
.. c:macro:: PY_RELEASE_LEVEL_ALPHA
|
||||
:no-typesetting:
|
||||
.. c:macro:: PY_RELEASE_LEVEL_BETA
|
||||
:no-typesetting:
|
||||
.. c:macro:: PY_RELEASE_LEVEL_GAMMA
|
||||
:no-typesetting:
|
||||
.. c:macro:: PY_RELEASE_LEVEL_FINAL
|
||||
:no-typesetting:
|
||||
|
||||
For completeness, the values are available as macros:
|
||||
:c:macro:`!PY_RELEASE_LEVEL_ALPHA` (``0xA``),
|
||||
:c:macro:`!PY_RELEASE_LEVEL_BETA` (``0xB``),
|
||||
:c:macro:`!PY_RELEASE_LEVEL_GAMMA` (``0xC``), and
|
||||
:c:macro:`!PY_RELEASE_LEVEL_FINAL` (``0xF``).
|
||||
|
||||
.. c:macro:: PY_RELEASE_SERIAL
|
||||
|
||||
The ``2`` in ``3.4.1a2``. Zero for final releases.
|
||||
|
|
@ -46,6 +63,12 @@ See :ref:`stable` for a discussion of API and ABI stability across versions.
|
|||
Use this for numeric comparisons, for example,
|
||||
``#if PY_VERSION_HEX >= ...``.
|
||||
|
||||
.. c:macro:: PY_VERSION
|
||||
|
||||
The Python version as a string, for example, ``"3.4.1a2"``.
|
||||
|
||||
These macros are defined in :source:`Include/patchlevel.h`.
|
||||
|
||||
|
||||
Run-time version
|
||||
----------------
|
||||
|
|
|
|||
|
|
@ -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 have to call
|
||||
The buffer may contain embedded null bytes. The caller has to call
|
||||
:c:func:`PyBuffer_Release` when it is done with the buffer.
|
||||
|
||||
``es`` (:class:`str`) [const char \*encoding, char \*\*buffer]
|
||||
|
|
@ -305,7 +305,7 @@ the minimal value for the corresponding signed integer type of the same size.
|
|||
``D`` (:class:`complex`) [Py_complex]
|
||||
Convert a Python complex number to a C :c:type:`Py_complex` structure.
|
||||
|
||||
.. deprecated:: next
|
||||
.. deprecated:: 3.15
|
||||
|
||||
For unsigned integer formats ``B``, ``H``, ``I``, ``k`` and ``K``,
|
||||
:exc:`DeprecationWarning` is emitted when the value is larger than
|
||||
|
|
@ -516,6 +516,28 @@ API Functions
|
|||
}
|
||||
|
||||
|
||||
.. c:function:: int PyArg_ParseArray(PyObject *const *args, Py_ssize_t nargs, const char *format, ...)
|
||||
|
||||
Parse the parameters of a function that takes only array parameters into
|
||||
local variables (that is, a function using the :c:macro:`METH_FASTCALL`
|
||||
calling convention).
|
||||
Returns true on success; on failure, it returns false and raises the
|
||||
appropriate exception.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
|
||||
.. c:function:: int PyArg_ParseArrayAndKeywords(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, const char *format, const char * const *kwlist, ...)
|
||||
|
||||
Parse the parameters of a function that takes both array and keyword
|
||||
parameters into local variables (that is, a function using the
|
||||
:c:macro:`METH_FASTCALL` ``|`` :c:macro:`METH_KEYWORDS` calling convention).
|
||||
Returns true on success; on failure, it returns false and raises the
|
||||
appropriate exception.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
|
||||
.. c:function:: int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)
|
||||
|
||||
A simpler form of parameter retrieval which does not use a format string to
|
||||
|
|
|
|||
|
|
@ -10,11 +10,6 @@
|
|||
Buffer Protocol
|
||||
---------------
|
||||
|
||||
.. sectionauthor:: Greg Stein <gstein@lyra.org>
|
||||
.. sectionauthor:: Benjamin Peterson
|
||||
.. sectionauthor:: Stefan Krah
|
||||
|
||||
|
||||
Certain objects available in Python wrap access to an underlying memory
|
||||
array or *buffer*. Such objects include the built-in :class:`bytes` and
|
||||
:class:`bytearray`, and some extension types like :class:`array.array`.
|
||||
|
|
@ -261,6 +256,12 @@ 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 an alias to :c:macro:`PyBUF_WRITABLE`.
|
||||
|
||||
.. soft-deprecated:: 3.13
|
||||
|
||||
.. c:macro:: PyBUF_FORMAT
|
||||
|
||||
Controls the :c:member:`~Py_buffer.format` field. If set, this field MUST
|
||||
|
|
@ -501,10 +502,11 @@ Buffer-related functions
|
|||
*indices* must point to an array of ``view->ndim`` indices.
|
||||
|
||||
|
||||
.. c:function:: int PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char fort)
|
||||
.. c:function:: int PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char order)
|
||||
|
||||
Copy contiguous *len* bytes from *buf* to *view*.
|
||||
*fort* can be ``'C'`` or ``'F'`` (for C-style or Fortran-style ordering).
|
||||
*order* can be ``'C'`` or ``'F'`` or ``'A'`` (for C-style or Fortran-style
|
||||
ordering or either one).
|
||||
``0`` is returned on success, ``-1`` on error.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ Direct API functions
|
|||
|
||||
On failure, return ``NULL`` with an exception set.
|
||||
|
||||
.. note::
|
||||
If the object implements the buffer protocol, then the buffer
|
||||
must not be mutated while the bytearray object is being created.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyByteArray_FromStringAndSize(const char *string, Py_ssize_t len)
|
||||
|
||||
|
|
@ -58,6 +62,10 @@ Direct API functions
|
|||
|
||||
On failure, return ``NULL`` with an exception set.
|
||||
|
||||
.. note::
|
||||
If the object implements the buffer protocol, then the buffer
|
||||
must not be mutated while the bytearray object is being created.
|
||||
|
||||
|
||||
.. c:function:: Py_ssize_t PyByteArray_Size(PyObject *bytearray)
|
||||
|
||||
|
|
@ -70,6 +78,9 @@ Direct API functions
|
|||
``NULL`` pointer. The returned array always has an extra
|
||||
null byte appended.
|
||||
|
||||
.. note::
|
||||
It is not thread-safe to mutate the bytearray object while using the returned char array.
|
||||
|
||||
|
||||
.. c:function:: int PyByteArray_Resize(PyObject *bytearray, Py_ssize_t len)
|
||||
|
||||
|
|
@ -89,6 +100,9 @@ These macros trade safety for speed and they don't check pointers.
|
|||
|
||||
Similar to :c:func:`PyByteArray_AsString`, but without error checking.
|
||||
|
||||
.. note::
|
||||
It is not thread-safe to mutate the bytearray object while using the returned char array.
|
||||
|
||||
|
||||
.. c:function:: Py_ssize_t PyByteArray_GET_SIZE(PyObject *bytearray)
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ called with a non-bytes parameter.
|
|||
*len* on success, and ``NULL`` on failure. If *v* is ``NULL``, the contents of
|
||||
the bytes object are uninitialized.
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
Use the :c:type:`PyBytesWriter` API instead of
|
||||
``PyBytes_FromStringAndSize(NULL, len)``.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyBytes_FromFormat(const char *format, ...)
|
||||
|
||||
|
|
@ -123,6 +127,10 @@ called with a non-bytes parameter.
|
|||
Return the bytes representation of object *o* that implements the buffer
|
||||
protocol.
|
||||
|
||||
.. note::
|
||||
If the object implements the buffer protocol, then the buffer
|
||||
must not be mutated while the bytes object is being created.
|
||||
|
||||
|
||||
.. c:function:: Py_ssize_t PyBytes_Size(PyObject *o)
|
||||
|
||||
|
|
@ -181,6 +189,9 @@ called with a non-bytes parameter.
|
|||
created, the old reference to *bytes* will still be discarded and the value
|
||||
of *\*bytes* will be set to ``NULL``; the appropriate exception will be set.
|
||||
|
||||
.. note::
|
||||
If *newpart* implements the buffer protocol, then the buffer
|
||||
must not be mutated while the new bytes object is being created.
|
||||
|
||||
.. c:function:: void PyBytes_ConcatAndDel(PyObject **bytes, PyObject *newpart)
|
||||
|
||||
|
|
@ -188,6 +199,10 @@ called with a non-bytes parameter.
|
|||
appended to *bytes*. This version releases the :term:`strong reference`
|
||||
to *newpart* (i.e. decrements its reference count).
|
||||
|
||||
.. note::
|
||||
If *newpart* implements the buffer protocol, then the buffer
|
||||
must not be mutated while the new bytes object is being created.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable)
|
||||
|
||||
|
|
@ -206,6 +221,9 @@ called with a non-bytes parameter.
|
|||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. note::
|
||||
If *iterable* objects implement the buffer protocol, then the buffers
|
||||
must not be mutated while the new bytes object is being created.
|
||||
|
||||
.. c:function:: int _PyBytes_Resize(PyObject **bytes, Py_ssize_t newsize)
|
||||
|
||||
|
|
@ -219,3 +237,212 @@ called with a non-bytes parameter.
|
|||
reallocation fails, the original bytes object at *\*bytes* is deallocated,
|
||||
*\*bytes* is set to ``NULL``, :exc:`MemoryError` is set, and ``-1`` is
|
||||
returned.
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
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
|
||||
-------------
|
||||
|
||||
The :c:type:`PyBytesWriter` API can be used to create a Python :class:`bytes`
|
||||
object.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
.. c:type:: PyBytesWriter
|
||||
|
||||
A bytes writer instance.
|
||||
|
||||
The API is **not thread safe**: a writer should only be used by a single
|
||||
thread at the same time.
|
||||
|
||||
The instance must be destroyed by :c:func:`PyBytesWriter_Finish` on
|
||||
success, or :c:func:`PyBytesWriter_Discard` on error.
|
||||
|
||||
|
||||
Create, Finish, Discard
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. c:function:: PyBytesWriter* PyBytesWriter_Create(Py_ssize_t size)
|
||||
|
||||
Create a :c:type:`PyBytesWriter` to write *size* bytes.
|
||||
|
||||
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``.
|
||||
|
||||
*size* must be positive or zero.
|
||||
|
||||
.. c:function:: PyObject* PyBytesWriter_Finish(PyBytesWriter *writer)
|
||||
|
||||
Finish a :c:type:`PyBytesWriter` created by
|
||||
:c:func:`PyBytesWriter_Create`.
|
||||
|
||||
On success, return a Python :class:`bytes` object.
|
||||
On error, set an exception and return ``NULL``.
|
||||
|
||||
The writer instance is invalid after the call in any case.
|
||||
No API can be called on the writer after :c:func:`PyBytesWriter_Finish`.
|
||||
|
||||
.. c:function:: PyObject* PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
|
||||
|
||||
Similar to :c:func:`PyBytesWriter_Finish`, but resize the writer
|
||||
to *size* bytes before creating the :class:`bytes` object.
|
||||
|
||||
.. c:function:: PyObject* PyBytesWriter_FinishWithPointer(PyBytesWriter *writer, void *buf)
|
||||
|
||||
Similar to :c:func:`PyBytesWriter_Finish`, but resize the writer
|
||||
using *buf* pointer before creating the :class:`bytes` object.
|
||||
|
||||
Set an exception and return ``NULL`` if *buf* pointer is outside the
|
||||
internal buffer bounds.
|
||||
|
||||
Function pseudo-code::
|
||||
|
||||
Py_ssize_t size = (char*)buf - (char*)PyBytesWriter_GetData(writer);
|
||||
return PyBytesWriter_FinishWithSize(writer, size);
|
||||
|
||||
.. c:function:: void PyBytesWriter_Discard(PyBytesWriter *writer)
|
||||
|
||||
Discard a :c:type:`PyBytesWriter` created by :c:func:`PyBytesWriter_Create`.
|
||||
|
||||
Do nothing if *writer* is ``NULL``.
|
||||
|
||||
The writer instance is invalid after the call.
|
||||
No API can be called on the writer after :c:func:`PyBytesWriter_Discard`.
|
||||
|
||||
High-level API
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:function:: int PyBytesWriter_WriteBytes(PyBytesWriter *writer, const void *bytes, Py_ssize_t size)
|
||||
|
||||
Grow the *writer* internal buffer by *size* bytes,
|
||||
write *size* bytes of *bytes* at the *writer* end,
|
||||
and add *size* to the *writer* size.
|
||||
|
||||
If *size* is equal to ``-1``, call ``strlen(bytes)`` to get the
|
||||
string length.
|
||||
|
||||
On success, return ``0``.
|
||||
On error, set an exception and return ``-1``.
|
||||
|
||||
.. c:function:: int PyBytesWriter_Format(PyBytesWriter *writer, const char *format, ...)
|
||||
|
||||
Similar to :c:func:`PyBytes_FromFormat`, but write the output directly at
|
||||
the writer end. Grow the writer internal buffer on demand. Then add the
|
||||
written size to the writer size.
|
||||
|
||||
On success, return ``0``.
|
||||
On error, set an exception and return ``-1``.
|
||||
|
||||
|
||||
Getters
|
||||
^^^^^^^
|
||||
|
||||
.. c:function:: Py_ssize_t PyBytesWriter_GetSize(PyBytesWriter *writer)
|
||||
|
||||
Get the writer size.
|
||||
|
||||
The function cannot fail.
|
||||
|
||||
.. c:function:: void* PyBytesWriter_GetData(PyBytesWriter *writer)
|
||||
|
||||
Get the writer data: start of the internal buffer.
|
||||
|
||||
The pointer is valid until :c:func:`PyBytesWriter_Finish` or
|
||||
:c:func:`PyBytesWriter_Discard` is called on *writer*.
|
||||
|
||||
The function cannot fail.
|
||||
|
||||
|
||||
Low-level API
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. c:function:: int PyBytesWriter_Resize(PyBytesWriter *writer, Py_ssize_t size)
|
||||
|
||||
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.
|
||||
|
||||
On success, return ``0``.
|
||||
On error, set an exception and return ``-1``.
|
||||
|
||||
*size* must be positive or zero.
|
||||
|
||||
.. 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.
|
||||
|
||||
On success, return ``0``.
|
||||
On error, set an exception and return ``-1``.
|
||||
|
||||
*size* can be negative to shrink the writer.
|
||||
|
||||
.. c:function:: void* PyBytesWriter_GrowAndUpdatePointer(PyBytesWriter *writer, Py_ssize_t size, void *buf)
|
||||
|
||||
Similar to :c:func:`PyBytesWriter_Grow`, but update also the *buf*
|
||||
pointer.
|
||||
|
||||
The *buf* pointer is moved if the internal buffer is moved in memory.
|
||||
The *buf* relative position within the internal buffer is left
|
||||
unchanged.
|
||||
|
||||
On error, set an exception and return ``NULL``.
|
||||
|
||||
*buf* must not be ``NULL``.
|
||||
|
||||
Function pseudo-code::
|
||||
|
||||
Py_ssize_t pos = (char*)buf - (char*)PyBytesWriter_GetData(writer);
|
||||
if (PyBytesWriter_Grow(writer, size) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return (char*)PyBytesWriter_GetData(writer) + pos;
|
||||
|
|
|
|||
|
|
@ -347,6 +347,8 @@ please see individual documentation for details.
|
|||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
.. c:function:: PyObject* _PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||
:no-typesetting:
|
||||
|
||||
.. c:function:: PyObject* PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||
|
||||
|
|
@ -358,7 +360,12 @@ please see individual documentation for details.
|
|||
Return the result of the call on success, or raise an exception and return
|
||||
*NULL* on failure.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
.. versionadded:: 3.8 as ``_PyObject_Vectorcall``
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
|
||||
Renamed to the current name, without the leading underscore.
|
||||
The old provisional name is :term:`soft deprecated`.
|
||||
|
||||
.. c:function:: PyObject* PyObject_VectorcallDict(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwdict)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,13 +15,19 @@ Refer to :ref:`using-capsules` for more information on using these objects.
|
|||
.. c:type:: PyCapsule
|
||||
|
||||
This subtype of :c:type:`PyObject` represents an opaque value, useful for C
|
||||
extension modules who need to pass an opaque value (as a :c:expr:`void*`
|
||||
extension modules which 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::
|
||||
|
|
|
|||
|
|
@ -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 contains a reference to
|
||||
variables of each stack frame that references the value contain 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
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
Code Objects
|
||||
------------
|
||||
|
||||
.. sectionauthor:: Jeffrey Yasskin <jyasskin@gmail.com>
|
||||
|
||||
Code objects are a low-level detail of the CPython implementation.
|
||||
Each one represents a chunk of executable code that hasn't yet been
|
||||
bound into a function.
|
||||
|
|
@ -69,13 +67,14 @@ bound into a function.
|
|||
The old name is deprecated, but will remain available until the
|
||||
signature changes again.
|
||||
|
||||
.. c:function:: PyCodeObject* PyCode_NewWithPosOnlyArgs(...)
|
||||
:no-typesetting:
|
||||
|
||||
.. c:function:: PyCodeObject* PyUnstable_Code_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, PyObject *qualname, int firstlineno, PyObject *linetable, PyObject *exceptiontable)
|
||||
|
||||
Similar to :c:func:`PyUnstable_Code_New`, but with an extra "posonlyargcount" for positional-only arguments.
|
||||
The same caveats that apply to ``PyUnstable_Code_New`` also apply to this function.
|
||||
|
||||
.. index:: single: PyCode_NewWithPosOnlyArgs (C function)
|
||||
|
||||
.. versionadded:: 3.8 as ``PyCode_NewWithPosOnlyArgs``
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
|
|
@ -211,6 +210,19 @@ bound into a function.
|
|||
.. versionadded:: 3.12
|
||||
|
||||
|
||||
.. c:function:: PyObject *PyCode_Optimize(PyObject *code, PyObject *consts, PyObject *names, PyObject *lnotab_obj)
|
||||
|
||||
This is a 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.
|
||||
|
||||
.. soft-deprecated:: 3.13
|
||||
|
||||
|
||||
.. _c_codeobject_flags:
|
||||
|
||||
Code Object Flags
|
||||
|
|
@ -287,9 +299,12 @@ These functions are part of the unstable C API tier:
|
|||
this functionality is a CPython implementation detail, and the API
|
||||
may change without deprecation warnings.
|
||||
|
||||
.. c:function:: Py_ssize_t _PyEval_RequestCodeExtraIndex(freefunc free)
|
||||
:no-typesetting:
|
||||
|
||||
.. c:function:: Py_ssize_t PyUnstable_Eval_RequestCodeExtraIndex(freefunc free)
|
||||
|
||||
Return a new an opaque index value used to adding data to code objects.
|
||||
Return a new 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
|
||||
|
|
@ -299,8 +314,6 @@ may change without deprecation warnings.
|
|||
*free* will be called on non-``NULL`` data stored under the new index.
|
||||
Use :c:func:`Py_DecRef` when storing :c:type:`PyObject`.
|
||||
|
||||
.. index:: single: _PyEval_RequestCodeExtraIndex (C function)
|
||||
|
||||
.. versionadded:: 3.6 as ``_PyEval_RequestCodeExtraIndex``
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
|
|
@ -309,6 +322,9 @@ may change without deprecation warnings.
|
|||
The old private name is deprecated, but will be available until the API
|
||||
changes.
|
||||
|
||||
.. c:function:: int _PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
|
||||
:no-typesetting:
|
||||
|
||||
.. c:function:: int PyUnstable_Code_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
|
||||
|
||||
Set *extra* to the extra data stored under the given index.
|
||||
|
|
@ -317,8 +333,6 @@ may change without deprecation warnings.
|
|||
If no data was set under the index, set *extra* to ``NULL`` and return
|
||||
0 without setting an exception.
|
||||
|
||||
.. index:: single: _PyCode_GetExtra (C function)
|
||||
|
||||
.. versionadded:: 3.6 as ``_PyCode_GetExtra``
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
|
|
@ -327,13 +341,14 @@ may change without deprecation warnings.
|
|||
The old private name is deprecated, but will be available until the API
|
||||
changes.
|
||||
|
||||
.. c:function:: int _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
|
||||
:no-typesetting:
|
||||
|
||||
.. c:function:: int PyUnstable_Code_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
|
||||
|
||||
Set the extra data stored under the given index to *extra*.
|
||||
Return 0 on success. Set an exception and return -1 on failure.
|
||||
|
||||
.. index:: single: _PyCode_SetExtra (C function)
|
||||
|
||||
.. versionadded:: 3.6 as ``_PyCode_SetExtra``
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ Codec registry and support functions
|
|||
|
||||
Register a new codec search function.
|
||||
|
||||
As side effect, this tries to load the :mod:`!encodings` package, if not yet
|
||||
As a 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 encoder can be found.
|
||||
:exc:`LookupError` if no decoder can be found.
|
||||
|
||||
|
||||
Codec lookup API
|
||||
|
|
@ -129,3 +129,13 @@ 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
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ Complex Number Objects
|
|||
|
||||
The complex number value, using the C :c:type:`Py_complex` representation.
|
||||
|
||||
.. deprecated-removed:: next 3.20
|
||||
.. deprecated-removed:: 3.15 3.20
|
||||
Use :c:func:`PyComplex_AsCComplex` and
|
||||
:c:func:`PyComplex_FromCComplex` to convert a
|
||||
Python complex number to/from the C :c:type:`Py_complex`
|
||||
|
|
@ -82,7 +82,7 @@ Complex Number Objects
|
|||
|
||||
.. c:type:: Py_complex
|
||||
|
||||
This C structure defines export format for a Python complex
|
||||
This C structure defines an export format for a Python complex
|
||||
number object.
|
||||
|
||||
.. c:member:: double real
|
||||
|
|
|
|||
|
|
@ -109,11 +109,21 @@ Other Objects
|
|||
descriptor.rst
|
||||
slice.rst
|
||||
memoryview.rst
|
||||
picklebuffer.rst
|
||||
weakref.rst
|
||||
capsule.rst
|
||||
sentinel.rst
|
||||
frame.rst
|
||||
gen.rst
|
||||
coro.rst
|
||||
contextvars.rst
|
||||
datetime.rst
|
||||
typehints.rst
|
||||
|
||||
|
||||
C API for extension modules
|
||||
===========================
|
||||
|
||||
.. toctree::
|
||||
|
||||
curses.rst
|
||||
datetime.rst
|
||||
|
|
|
|||
|
|
@ -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``, "something bad happened." ``str[size-1]`` is ``'\0'`` in
|
||||
* When ``rv < 0``, the output conversion failed and ``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 ``Py_INFINITY`` (with
|
||||
if ``overflow_exception`` is ``NULL`` return :c:macro:`!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,22 +128,46 @@ 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 values ``Py_DTSF_SIGN``,
|
||||
``Py_DTSF_ADD_DOT_0``, or ``Py_DTSF_ALT``, or-ed together:
|
||||
*flags* can be zero or more of the following values or-ed together:
|
||||
|
||||
* ``Py_DTSF_SIGN`` means to always precede the returned string with a sign
|
||||
character, even if *val* is non-negative.
|
||||
.. c:namespace:: NULL
|
||||
|
||||
* ``Py_DTSF_ADD_DOT_0`` means to ensure that the returned string will not look
|
||||
like an integer.
|
||||
.. c:macro:: Py_DTSF_SIGN
|
||||
|
||||
* ``Py_DTSF_ALT`` means to apply "alternate" formatting rules. See the
|
||||
documentation for the :c:func:`PyOS_snprintf` ``'#'`` specifier for
|
||||
details.
|
||||
Always precede the returned string with a sign
|
||||
character, even if *val* is non-negative.
|
||||
|
||||
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
|
||||
*val* is a finite number, an infinite number, or not a number, respectively.
|
||||
.. 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
|
||||
|
||||
If *ptype* is non-``NULL``, then the value it points to will be set to one
|
||||
of the following constants depending on the type of *val*:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:align: left
|
||||
|
||||
* - *\*ptype*
|
||||
- type of *val*
|
||||
* - .. c:macro:: Py_DTST_FINITE
|
||||
- finite number
|
||||
* - .. c:macro:: Py_DTST_INFINITE
|
||||
- infinite number
|
||||
* - .. c:macro:: Py_DTST_NAN
|
||||
- not a number
|
||||
|
||||
The return value is a pointer to *buffer* with the converted string or
|
||||
``NULL`` if the conversion failed. The caller is responsible for freeing the
|
||||
|
|
@ -152,13 +176,85 @@ The following functions provide locale-independent string to number conversions.
|
|||
.. versionadded:: 3.1
|
||||
|
||||
|
||||
.. c:function:: int PyOS_stricmp(const char *s1, const char *s2)
|
||||
.. c:function:: int PyOS_mystricmp(const char *str1, const char *str2)
|
||||
int PyOS_mystrnicmp(const char *str1, const char *str2, Py_ssize_t size)
|
||||
|
||||
Case insensitive comparison of strings. The function works almost
|
||||
identically to :c:func:`!strcmp` except that it ignores the case.
|
||||
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.
|
||||
|
||||
|
||||
.. c:function:: int PyOS_strnicmp(const char *s1, const char *s2, Py_ssize_t size)
|
||||
.. c:function:: int PyOS_stricmp(const char *str1, const char *str2)
|
||||
int PyOS_strnicmp(const char *str1, const char *str2, Py_ssize_t size)
|
||||
|
||||
Case insensitive comparison of strings. The function works almost
|
||||
identically to :c:func:`!strncmp` except that it ignores the case.
|
||||
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*.
|
||||
|
|
|
|||
138
Doc/c-api/curses.rst
Normal file
138
Doc/c-api/curses.rst
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
.. 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.
|
||||
|
||||
|
|
@ -8,11 +8,51 @@ 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.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
|
||||
This macro is now thread safe.
|
||||
|
||||
.. 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.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
|
||||
This variable should not be accessed directly as direct access is not thread-safe.
|
||||
Use :c:func:`PyDateTime_IMPORT` instead.
|
||||
|
||||
.. c:type:: PyDateTime_Date
|
||||
|
||||
This subtype of :c:type:`PyObject` represents a Python date object.
|
||||
|
|
@ -46,7 +86,7 @@ macros.
|
|||
|
||||
.. c:var:: PyTypeObject PyDateTime_DeltaType
|
||||
|
||||
This instance of :c:type:`PyTypeObject` represents Python type for
|
||||
This instance of :c:type:`PyTypeObject` represents the Python type for
|
||||
the difference between two datetime values;
|
||||
it is the same object as :class:`datetime.timedelta` in the Python layer.
|
||||
|
||||
|
|
@ -325,3 +365,16 @@ 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.
|
||||
|
|
|
|||
|
|
@ -8,33 +8,200 @@ Descriptor Objects
|
|||
"Descriptors" are objects that describe some attribute of an object. They are
|
||||
found in the dictionary of type objects.
|
||||
|
||||
.. XXX document these!
|
||||
|
||||
.. c:var:: PyTypeObject PyProperty_Type
|
||||
|
||||
The type object for the built-in descriptor types.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDescr_NewGetSet(PyTypeObject *type, struct PyGetSetDef *getset)
|
||||
|
||||
Create a new get-set descriptor for extension type *type* from the
|
||||
:c:type:`PyGetSetDef` structure *getset*.
|
||||
|
||||
.. c:function:: PyObject* PyDescr_NewMember(PyTypeObject *type, struct PyMemberDef *meth)
|
||||
Get-set descriptors expose attributes implemented by C getter and setter
|
||||
functions rather than stored directly in the instance. This is the same kind
|
||||
of descriptor created for entries in :c:member:`~PyTypeObject.tp_getset`, and
|
||||
it appears in Python as a :class:`types.GetSetDescriptorType` object.
|
||||
|
||||
On success, return a :term:`strong reference` to the descriptor. Return
|
||||
``NULL`` with an exception set on failure.
|
||||
|
||||
.. c:function:: PyObject* PyDescr_NewMember(PyTypeObject *type, struct PyMemberDef *member)
|
||||
|
||||
Create a new member descriptor for extension type *type* from the
|
||||
:c:type:`PyMemberDef` structure *member*.
|
||||
|
||||
Member descriptors expose fields in the type's C struct as Python
|
||||
attributes. This is the same kind of descriptor created for entries in
|
||||
:c:member:`~PyTypeObject.tp_members`, and it appears in Python as a
|
||||
:class:`types.MemberDescriptorType` object.
|
||||
|
||||
On success, return a :term:`strong reference` to the descriptor. Return
|
||||
``NULL`` with an exception set on failure.
|
||||
|
||||
.. 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. They correspond to
|
||||
:class:`types.GetSetDescriptorType` objects in Python.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDescr_NewMethod(PyTypeObject *type, struct PyMethodDef *meth)
|
||||
|
||||
Create a new method descriptor for extension type *type* from the
|
||||
:c:type:`PyMethodDef` structure *meth*.
|
||||
|
||||
.. c:function:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *wrapper, void *wrapped)
|
||||
Method descriptors expose C functions as methods on a type. This is the same
|
||||
kind of descriptor created for entries in
|
||||
:c:member:`~PyTypeObject.tp_methods`, and it appears in Python as a
|
||||
:class:`types.MethodDescriptorType` object.
|
||||
|
||||
On success, return a :term:`strong reference` to the descriptor. Return
|
||||
``NULL`` with an exception set on failure.
|
||||
|
||||
.. 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.MethodDescriptorType`
|
||||
objects in Python.
|
||||
|
||||
|
||||
.. c:struct:: wrapperbase
|
||||
|
||||
Describes a slot wrapper used by :c:func:`PyDescr_NewWrapper`.
|
||||
|
||||
Each ``wrapperbase`` record stores the Python-visible name and metadata for a
|
||||
special method implemented by a type slot, together with the wrapper
|
||||
function used to adapt that slot to Python's calling convention.
|
||||
|
||||
.. c:function:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
|
||||
|
||||
Create a new wrapper descriptor for extension type *type* from the
|
||||
:c:struct:`wrapperbase` structure *base* and the wrapped slot function
|
||||
pointer
|
||||
*wrapped*.
|
||||
|
||||
Wrapper descriptors expose special methods implemented by type slots. This
|
||||
is the same kind of descriptor that CPython creates for slot-based special
|
||||
methods such as ``__repr__`` or ``__add__``, and it appears in Python as a
|
||||
:class:`types.WrapperDescriptorType` object.
|
||||
|
||||
On success, return a :term:`strong reference` to the descriptor. Return
|
||||
``NULL`` with an exception set on failure.
|
||||
|
||||
.. 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)
|
||||
|
||||
Create a new class method descriptor for extension type *type* from the
|
||||
:c:type:`PyMethodDef` structure *method*.
|
||||
|
||||
Class method descriptors expose C methods that receive the class rather than
|
||||
an instance when accessed. This is the same kind of descriptor created for
|
||||
``METH_CLASS`` entries in :c:member:`~PyTypeObject.tp_methods`, and it
|
||||
appears in Python as a :class:`types.ClassMethodDescriptorType` object.
|
||||
|
||||
On success, return a :term:`strong reference` to the descriptor. Return
|
||||
``NULL`` with an exception set on failure.
|
||||
|
||||
.. c:function:: int PyDescr_IsData(PyObject *descr)
|
||||
|
||||
Return non-zero if the descriptor objects *descr* describes a data attribute, or
|
||||
Return non-zero if the descriptor object *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 *)
|
||||
.. c:function:: PyObject* PyWrapper_New(PyObject *d, PyObject *self)
|
||||
|
||||
Create a new bound wrapper object from the wrapper descriptor *d* and the
|
||||
instance *self*.
|
||||
|
||||
This is the bound form of a wrapper descriptor created by
|
||||
:c:func:`PyDescr_NewWrapper`. CPython creates these objects when a slot
|
||||
wrapper is accessed through an instance, and they appear in Python as
|
||||
:class:`types.MethodWrapperType` objects.
|
||||
|
||||
On success, return a :term:`strong reference` to the wrapper object. Return
|
||||
``NULL`` with an exception set on failure.
|
||||
|
||||
.. c:macro:: PyDescr_COMMON
|
||||
|
||||
This is a macro including the common fields for a
|
||||
descriptor object.
|
||||
|
||||
This was included in Python's C API by mistake; do not use it in extensions.
|
||||
For creating custom descriptor objects, create a class implementing the
|
||||
descriptor protocol (:c:member:`~PyTypeObject.tp_descr_get` and
|
||||
:c:member:`~PyTypeObject.tp_descr_set`).
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
|
||||
Built-in descriptors
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. c:var:: PyTypeObject PyProperty_Type
|
||||
|
||||
The type object for property objects. This is the same object as
|
||||
:class:`property` in the Python layer.
|
||||
|
||||
|
||||
.. 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 corresponds to
|
||||
:class:`types.ClassMethodDescriptorType` objects 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
.. _dictobjects:
|
||||
|
||||
Dictionary Objects
|
||||
Dictionary objects
|
||||
------------------
|
||||
|
||||
.. index:: pair: object; dictionary
|
||||
|
|
@ -42,18 +42,48 @@ Dictionary Objects
|
|||
enforces read-only behavior. This is normally used to create a view to
|
||||
prevent modification of the dictionary for non-dynamic class types.
|
||||
|
||||
The first argument can be a :class:`dict`, a :class:`frozendict`, or a
|
||||
mapping.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. 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.
|
||||
|
||||
Do nothing if the argument is not a :class:`dict` or a :class:`!dict`
|
||||
subclass.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_Contains(PyObject *p, PyObject *key)
|
||||
|
||||
Determine if dictionary *p* contains *key*. If an item in *p* is matches
|
||||
Determine if dictionary *p* contains *key*. If an item in *p* matches
|
||||
*key*, return ``1``, otherwise return ``0``. On error, return ``-1``.
|
||||
This is equivalent to the Python expression ``key in p``.
|
||||
|
||||
The first argument can be a :class:`dict` or a :class:`frozendict`.
|
||||
|
||||
.. note::
|
||||
|
||||
The operation is atomic on :term:`free threading <free-threaded build>`
|
||||
when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_ContainsString(PyObject *p, const char *key)
|
||||
|
||||
|
|
@ -61,14 +91,18 @@ Dictionary Objects
|
|||
:c:expr:`const char*` UTF-8 encoded bytes string, rather than a
|
||||
:c:expr:`PyObject*`.
|
||||
|
||||
The first argument can be a :class:`dict` or a :class:`frozendict`.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDict_Copy(PyObject *p)
|
||||
|
||||
Return a new dictionary that contains the same key-value pairs as *p*.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_SetItem(PyObject *p, PyObject *key, PyObject *val)
|
||||
|
||||
Insert *val* into the dictionary *p* with a key of *key*. *key* must be
|
||||
|
|
@ -76,6 +110,11 @@ Dictionary Objects
|
|||
``0`` on success or ``-1`` on failure. This function *does not* steal a
|
||||
reference to *val*.
|
||||
|
||||
.. note::
|
||||
|
||||
The operation is atomic on :term:`free threading <free-threaded build>`
|
||||
when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_SetItemString(PyObject *p, const char *key, PyObject *val)
|
||||
|
||||
|
|
@ -91,6 +130,11 @@ Dictionary Objects
|
|||
If *key* is not in the dictionary, :exc:`KeyError` is raised.
|
||||
Return ``0`` on success or ``-1`` on failure.
|
||||
|
||||
.. note::
|
||||
|
||||
The operation is atomic on :term:`free threading <free-threaded build>`
|
||||
when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_DelItemString(PyObject *p, const char *key)
|
||||
|
||||
|
|
@ -109,8 +153,18 @@ Dictionary Objects
|
|||
* If the key is missing, set *\*result* to ``NULL`` and return ``0``.
|
||||
* On error, raise an exception and return ``-1``.
|
||||
|
||||
The first argument can be a :class:`dict` or a :class:`frozendict`.
|
||||
|
||||
.. note::
|
||||
|
||||
The operation is atomic on :term:`free threading <free-threaded build>`
|
||||
when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
See also the :c:func:`PyObject_GetItem` function.
|
||||
|
||||
|
||||
|
|
@ -120,16 +174,28 @@ Dictionary Objects
|
|||
has a key *key*. Return ``NULL`` if the key *key* is missing *without*
|
||||
setting an exception.
|
||||
|
||||
The first argument can be a :class:`dict` or a :class:`frozendict`.
|
||||
|
||||
.. note::
|
||||
|
||||
Exceptions that occur while this calls :meth:`~object.__hash__` and
|
||||
:meth:`~object.__eq__` methods are silently ignored.
|
||||
Prefer the :c:func:`PyDict_GetItemWithError` function instead.
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, the returned
|
||||
:term:`borrowed reference` may become invalid if another thread modifies
|
||||
the dictionary concurrently. Prefer :c:func:`PyDict_GetItemRef`, which
|
||||
returns a :term:`strong reference`.
|
||||
|
||||
.. versionchanged:: 3.10
|
||||
Calling this API without an :term:`attached thread state` had been allowed for historical
|
||||
reason. It is no longer allowed.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDict_GetItemWithError(PyObject *p, PyObject *key)
|
||||
|
||||
|
|
@ -138,6 +204,16 @@ Dictionary Objects
|
|||
occurred. Return ``NULL`` **without** an exception set if the key
|
||||
wasn't present.
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, the returned
|
||||
:term:`borrowed reference` may become invalid if another thread modifies
|
||||
the dictionary concurrently. Prefer :c:func:`PyDict_GetItemRef`, which
|
||||
returns a :term:`strong reference`.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDict_GetItemString(PyObject *p, const char *key)
|
||||
|
||||
|
|
@ -153,6 +229,16 @@ Dictionary Objects
|
|||
Prefer using the :c:func:`PyDict_GetItemWithError` function with your own
|
||||
:c:func:`PyUnicode_FromString` *key* instead.
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, the returned
|
||||
:term:`borrowed reference` may become invalid if another thread modifies
|
||||
the dictionary concurrently. Prefer :c:func:`PyDict_GetItemStringRef`,
|
||||
which returns a :term:`strong reference`.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_GetItemStringRef(PyObject *p, const char *key, PyObject **result)
|
||||
|
||||
|
|
@ -162,6 +248,9 @@ Dictionary Objects
|
|||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDict_SetDefault(PyObject *p, PyObject *key, PyObject *defaultobj)
|
||||
|
||||
|
|
@ -173,6 +262,14 @@ Dictionary Objects
|
|||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, the returned
|
||||
:term:`borrowed reference` may become invalid if another thread modifies
|
||||
the dictionary concurrently. Prefer :c:func:`PyDict_SetDefaultRef`,
|
||||
which returns a :term:`strong reference`.
|
||||
|
||||
|
||||
|
||||
.. c:function:: int PyDict_SetDefaultRef(PyObject *p, PyObject *key, PyObject *default_value, PyObject **result)
|
||||
|
||||
|
|
@ -192,13 +289,18 @@ Dictionary Objects
|
|||
These may refer to the same object: in that case you hold two separate
|
||||
references to it.
|
||||
|
||||
.. note::
|
||||
|
||||
The operation is atomic on :term:`free threading <free-threaded build>`
|
||||
when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. c:function:: int PyDict_Pop(PyObject *p, PyObject *key, PyObject **result)
|
||||
|
||||
Remove *key* from dictionary *p* and optionally return the removed value.
|
||||
Do not raise :exc:`KeyError` if the key missing.
|
||||
Do not raise :exc:`KeyError` if the key is missing.
|
||||
|
||||
- If the key is present, set *\*result* to a new reference to the removed
|
||||
value if *result* is not ``NULL``, and return ``1``.
|
||||
|
|
@ -207,7 +309,12 @@ 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 missing.
|
||||
not raising :exc:`KeyError` if the key is missing.
|
||||
|
||||
.. note::
|
||||
|
||||
The operation is atomic on :term:`free threading <free-threaded build>`
|
||||
when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
|
@ -225,17 +332,32 @@ Dictionary Objects
|
|||
|
||||
Return a :c:type:`PyListObject` containing all the items from the dictionary.
|
||||
|
||||
The first argument can be a :class:`dict` or a :class:`frozendict`.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDict_Keys(PyObject *p)
|
||||
|
||||
Return a :c:type:`PyListObject` containing all the keys from the dictionary.
|
||||
|
||||
The first argument can be a :class:`dict` or a :class:`frozendict`.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyDict_Values(PyObject *p)
|
||||
|
||||
Return a :c:type:`PyListObject` containing all the values from the dictionary
|
||||
*p*.
|
||||
|
||||
The first argument can be a :class:`dict` or a :class:`frozendict`.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: Py_ssize_t PyDict_Size(PyObject *p)
|
||||
|
||||
|
|
@ -244,6 +366,19 @@ Dictionary Objects
|
|||
Return the number of items in the dictionary. This is equivalent to
|
||||
``len(p)`` on a dictionary.
|
||||
|
||||
The argument can be a :class:`dict` or a :class:`frozendict`.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: Py_ssize_t PyDict_GET_SIZE(PyObject *p)
|
||||
|
||||
Similar to :c:func:`PyDict_Size`, but without error checking.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_Next(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
|
||||
|
||||
|
|
@ -258,6 +393,8 @@ Dictionary Objects
|
|||
value represents offsets within the internal dictionary structure, and
|
||||
since the structure is sparse, the offsets are not consecutive.
|
||||
|
||||
The first argument can be a :class:`dict` or a :class:`frozendict`.
|
||||
|
||||
For example::
|
||||
|
||||
PyObject *key, *value;
|
||||
|
|
@ -291,7 +428,7 @@ Dictionary Objects
|
|||
}
|
||||
|
||||
The function is not thread-safe in the :term:`free-threaded <free threading>`
|
||||
build without external synchronization. You can use
|
||||
build without external synchronization for a mutable :class:`dict`. You can use
|
||||
:c:macro:`Py_BEGIN_CRITICAL_SECTION` to lock the dictionary while iterating
|
||||
over it::
|
||||
|
||||
|
|
@ -301,6 +438,8 @@ Dictionary Objects
|
|||
}
|
||||
Py_END_CRITICAL_SECTION();
|
||||
|
||||
The function is thread-safe on a :class:`frozendict`.
|
||||
|
||||
.. note::
|
||||
|
||||
On the free-threaded build, this function can be used safely inside a
|
||||
|
|
@ -311,6 +450,9 @@ Dictionary Objects
|
|||
:term:`strong reference <strong reference>` (for example, using
|
||||
:c:func:`Py_NewRef`).
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
Also accept :class:`frozendict`.
|
||||
|
||||
.. c:function:: int PyDict_Merge(PyObject *a, PyObject *b, int override)
|
||||
|
||||
Iterate over mapping object *b* adding key-value pairs to dictionary *a*.
|
||||
|
|
@ -320,6 +462,13 @@ Dictionary Objects
|
|||
only be added if there is not a matching key in *a*. Return ``0`` on
|
||||
success or ``-1`` if an exception was raised.
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, when *b* is a
|
||||
:class:`dict` (with the standard iterator), both *a* and *b* are locked
|
||||
for the duration of the operation. When *b* is a non-dict mapping, only
|
||||
*a* is locked; *b* may be concurrently modified by another thread.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_Update(PyObject *a, PyObject *b)
|
||||
|
||||
|
|
@ -329,6 +478,13 @@ Dictionary Objects
|
|||
argument has no "keys" attribute. Return ``0`` on success or ``-1`` if an
|
||||
exception was raised.
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, when *b* is a
|
||||
:class:`dict` (with the standard iterator), both *a* and *b* are locked
|
||||
for the duration of the operation. When *b* is a non-dict mapping, only
|
||||
*a* is locked; *b* may be concurrently modified by another thread.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_MergeFromSeq2(PyObject *a, PyObject *seq2, int override)
|
||||
|
||||
|
|
@ -344,6 +500,13 @@ Dictionary Objects
|
|||
if override or key not in a:
|
||||
a[key] = value
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded <free threading>` build, only *a* is locked.
|
||||
The iteration over *seq2* is not synchronized; *seq2* may be concurrently
|
||||
modified by another thread.
|
||||
|
||||
|
||||
.. c:function:: int PyDict_AddWatcher(PyDict_WatchCallback callback)
|
||||
|
||||
Register *callback* as a dictionary watcher. Return a non-negative integer
|
||||
|
|
@ -351,6 +514,13 @@ Dictionary Objects
|
|||
of error (e.g. no more watcher IDs available), return ``-1`` and set an
|
||||
exception.
|
||||
|
||||
.. note::
|
||||
|
||||
This function is not internally synchronized. In the
|
||||
:term:`free-threaded <free threading>` build, callers should ensure no
|
||||
concurrent calls to :c:func:`PyDict_AddWatcher` or
|
||||
:c:func:`PyDict_ClearWatcher` are in progress.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
.. c:function:: int PyDict_ClearWatcher(int watcher_id)
|
||||
|
|
@ -359,6 +529,13 @@ Dictionary Objects
|
|||
:c:func:`PyDict_AddWatcher`. Return ``0`` on success, ``-1`` on error (e.g.
|
||||
if the given *watcher_id* was never registered.)
|
||||
|
||||
.. note::
|
||||
|
||||
This function is not internally synchronized. In the
|
||||
:term:`free-threaded <free threading>` build, callers should ensure no
|
||||
concurrent calls to :c:func:`PyDict_AddWatcher` or
|
||||
:c:func:`PyDict_ClearWatcher` are in progress.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
.. c:function:: int PyDict_Watch(int watcher_id, PyObject *dict)
|
||||
|
|
@ -426,3 +603,189 @@ 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.
|
||||
|
||||
|
||||
Frozen dictionary objects
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
|
||||
.. c:var:: PyTypeObject PyFrozenDict_Type
|
||||
|
||||
This instance of :c:type:`PyTypeObject` represents the Python frozen
|
||||
dictionary type.
|
||||
This is the same object as :class:`frozendict` in the Python layer.
|
||||
|
||||
|
||||
.. c:function:: int PyAnyDict_Check(PyObject *p)
|
||||
|
||||
Return true if *p* is a :class:`dict` object, a :class:`frozendict` object,
|
||||
or an instance of a subtype of the :class:`!dict` or :class:`!frozendict`
|
||||
type.
|
||||
This function always succeeds.
|
||||
|
||||
|
||||
.. c:function:: int PyAnyDict_CheckExact(PyObject *p)
|
||||
|
||||
Return true if *p* is a :class:`dict` object or a :class:`frozendict` object,
|
||||
but not an instance of a subtype of the :class:`!dict` or
|
||||
:class:`!frozendict` type.
|
||||
This function always succeeds.
|
||||
|
||||
|
||||
.. c:function:: int PyFrozenDict_Check(PyObject *p)
|
||||
|
||||
Return true if *p* is a :class:`frozendict` object or an instance of a
|
||||
subtype of the :class:`!frozendict` type.
|
||||
This function always succeeds.
|
||||
|
||||
|
||||
.. c:function:: int PyFrozenDict_CheckExact(PyObject *p)
|
||||
|
||||
Return true if *p* is a :class:`frozendict` object, but not an instance of a
|
||||
subtype of the :class:`!frozendict` type.
|
||||
This function always succeeds.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyFrozenDict_New(PyObject *iterable)
|
||||
|
||||
Return a new :class:`frozendict` from an iterable, or ``NULL`` on failure
|
||||
with an exception set.
|
||||
|
||||
Create an empty dictionary if *iterable* is ``NULL``.
|
||||
|
||||
|
||||
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`
|
||||
|
|
|
|||
|
|
@ -309,6 +309,14 @@ 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
|
||||
|
|
@ -331,6 +339,23 @@ 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
|
||||
================
|
||||
|
||||
|
|
@ -394,6 +419,15 @@ 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
|
||||
|
|
@ -639,28 +673,51 @@ Signal Handling
|
|||
single: SIGINT (C macro)
|
||||
single: KeyboardInterrupt (built-in exception)
|
||||
|
||||
This function interacts with Python's signal handling.
|
||||
Handle external interruptions, such as signals or activating a debugger,
|
||||
whose processing has been delayed until it is safe
|
||||
to run Python code and/or raise exceptions.
|
||||
|
||||
If the function is called from the main thread and under the main Python
|
||||
interpreter, it checks whether a signal has been sent to the processes
|
||||
and if so, invokes the corresponding signal handler. If the :mod:`signal`
|
||||
module is supported, this can invoke a signal handler written in Python.
|
||||
For example, pressing :kbd:`Ctrl-C` causes a terminal to send the
|
||||
:py:data:`signal.SIGINT` signal.
|
||||
This function executes the corresponding Python signal handler, which,
|
||||
by default, raises the :exc:`KeyboardInterrupt` exception.
|
||||
|
||||
The function attempts to handle all pending signals, and then returns ``0``.
|
||||
However, if a Python signal handler raises an exception, the error
|
||||
indicator is set and the function returns ``-1`` immediately (such that
|
||||
other pending signals may not have been handled yet: they will be on the
|
||||
next :c:func:`PyErr_CheckSignals()` invocation).
|
||||
:c:func:`!PyErr_CheckSignals` should be called by long-running C code
|
||||
frequently enough so that the response appears immediate to humans.
|
||||
|
||||
If the function is called from a non-main thread, or under a non-main
|
||||
Python interpreter, it does nothing and returns ``0``.
|
||||
Handlers invoked by this function currently include:
|
||||
|
||||
This function can be called by long-running C code that wants to
|
||||
be interruptible by user requests (such as by pressing Ctrl-C).
|
||||
- Signal handlers, including Python functions registered using
|
||||
the :mod:`signal` module.
|
||||
|
||||
.. note::
|
||||
The default Python signal handler for :c:macro:`!SIGINT` raises the
|
||||
:exc:`KeyboardInterrupt` exception.
|
||||
Signal handlers are only run in the main thread of the main interpreter.
|
||||
|
||||
(This is where the function got the name: originally, signals
|
||||
were the only way to interrupt the interpreter.)
|
||||
|
||||
- Running the garbage collector, if necessary.
|
||||
|
||||
- Executing a pending :ref:`remote debugger <remote-debugging>` script.
|
||||
|
||||
- Raise the exception set by :c:func:`PyThreadState_SetAsyncExc`.
|
||||
|
||||
If any handler raises an exception, immediately return ``-1`` with that
|
||||
exception set.
|
||||
Any remaining interruptions are left to be processed on the next
|
||||
:c:func:`PyErr_CheckSignals()` invocation, if appropriate.
|
||||
|
||||
If all handlers finish successfully, or there are no handlers to run,
|
||||
return ``0``.
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
This function may now invoke the garbage collector.
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
This function may now execute a remote debugger script, if remote
|
||||
debugging is enabled.
|
||||
|
||||
.. versionchanged:: 3.15
|
||||
The exception set by :c:func:`PyThreadState_SetAsyncExc` is now raised.
|
||||
|
||||
|
||||
.. c:function:: void PyErr_SetInterrupt()
|
||||
|
|
@ -759,9 +816,33 @@ Exception Classes
|
|||
Return :c:member:`~PyTypeObject.tp_name` of the exception class *ob*.
|
||||
|
||||
|
||||
.. c:macro:: PyException_HEAD
|
||||
|
||||
This is a macro including the base fields for an
|
||||
exception object.
|
||||
|
||||
This was included in Python's C API by mistake and is not designed for use
|
||||
in extensions. For creating custom exception objects, use
|
||||
:c:func:`PyErr_NewException` or otherwise create a class inheriting from
|
||||
:c:data:`PyExc_BaseException`.
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
|
||||
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
|
||||
|
|
@ -939,6 +1020,9 @@ 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>`.
|
||||
|
||||
|
|
@ -979,6 +1063,27 @@ 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:
|
||||
|
||||
|
|
@ -1039,6 +1144,8 @@ Exception types
|
|||
* :exc:`FloatingPointError`
|
||||
* * .. c:var:: PyObject *PyExc_GeneratorExit
|
||||
* :exc:`GeneratorExit`
|
||||
* * .. c:var:: PyObject *PyExc_ImportCycleError
|
||||
* :exc:`ImportCycleError`
|
||||
* * .. c:var:: PyObject *PyExc_ImportError
|
||||
* :exc:`ImportError`
|
||||
* * .. c:var:: PyObject *PyExc_IndentationError
|
||||
|
|
@ -1207,3 +1314,37 @@ 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.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ 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 :ref:`initialization function <extension-export-hook>`.
|
||||
exports an :dfn:`export hook` function (or an
|
||||
old-style :ref:`initialization function <extension-pyinit>`).
|
||||
|
||||
To be importable by default (that is, by
|
||||
:py:class:`importlib.machinery.ExtensionFileLoader`),
|
||||
|
|
@ -23,25 +24,127 @@ 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.
|
||||
|
||||
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:
|
||||
|
||||
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.
|
||||
- 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.
|
||||
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.
|
||||
|
||||
This is called *multi-phase initialization* to distinguish it from the legacy
|
||||
(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.
|
||||
(but still supported) :ref:`single-phase initialization <single-phase-initialization>`,
|
||||
where an initialization function returns a fully constructed module.
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
|
||||
|
|
@ -53,7 +156,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.
|
||||
|
|
@ -83,36 +186,34 @@ A module may also be limited to the main interpreter using
|
|||
the :c:data:`Py_mod_multiple_interpreters` slot.
|
||||
|
||||
|
||||
.. _extension-export-hook:
|
||||
.. _extension-pyinit:
|
||||
|
||||
Initialization function
|
||||
.......................
|
||||
``PyInit`` function
|
||||
...................
|
||||
|
||||
The initialization function defined by an extension module has the
|
||||
following signature:
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
This functionality 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:
|
||||
|
||||
.. 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).
|
||||
|
||||
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:
|
||||
If a module exports both :samp:`PyInit_{<name>}` and
|
||||
:samp:`PyModExport_{<name>}`, the :samp:`PyInit_{<name>}` function
|
||||
is ignored.
|
||||
|
||||
.. 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:
|
||||
Like with :c:macro:`PyMODEXPORT_FUNC`, it is recommended to define the
|
||||
initialization function using a helper macro:
|
||||
|
||||
.. c:macro:: PyMODINIT_FUNC
|
||||
|
||||
|
|
@ -123,6 +224,34 @@ It is recommended to define the 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 = {
|
||||
|
|
@ -137,59 +266,22 @@ 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
|
||||
..................................
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
.. 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.
|
||||
|
||||
In single-phase initialization, the
|
||||
:ref:`initialization function <extension-export-hook>` (``PyInit_modulename``)
|
||||
However, there are no plans to remove support for it.
|
||||
|
||||
In single-phase initialization, the old-style
|
||||
:ref:`initialization function <extension-pyinit>` (``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`.
|
||||
|
|
@ -242,6 +334,8 @@ 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.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
.. _fileobjects:
|
||||
|
||||
File Objects
|
||||
File objects
|
||||
------------
|
||||
|
||||
.. index:: pair: object; file
|
||||
|
|
@ -93,6 +93,29 @@ 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)
|
||||
|
||||
|
|
@ -100,11 +123,34 @@ the :mod:`io` APIs instead.
|
|||
|
||||
Write object *obj* to file object *p*. The only supported flag for *flags* is
|
||||
:c:macro:`Py_PRINT_RAW`; if given, the :func:`str` of the object is written
|
||||
instead of the :func:`repr`. Return ``0`` on success or ``-1`` on failure; the
|
||||
appropriate exception will be set.
|
||||
instead of the :func:`repr`.
|
||||
|
||||
If *obj* is ``NULL``, write the string ``"<NULL>"``.
|
||||
|
||||
Return ``0`` on success or ``-1`` on failure; the
|
||||
appropriate exception will be set.
|
||||
|
||||
.. c:function:: int PyFile_WriteString(const char *s, PyObject *p)
|
||||
|
||||
Write string *s* to file object *p*. Return ``0`` on success or ``-1`` on
|
||||
failure; the appropriate exception will be set.
|
||||
|
||||
|
||||
Soft-deprecated API
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
These are APIs that were included in Python's C API
|
||||
by mistake. They are documented solely for completeness; use other
|
||||
``PyFile*`` APIs instead.
|
||||
|
||||
.. c:function:: PyObject *PyFile_NewStdPrinter(int fd)
|
||||
|
||||
Use :c:func:`PyFile_FromFd` with defaults (``fd, NULL, "w", -1, NULL, NULL, NULL, 0``) instead.
|
||||
|
||||
.. c:var:: PyTypeObject PyStdPrinter_Type
|
||||
|
||||
Type of file-like objects used internally at Python startup when :py:mod:`io` is
|
||||
not yet available.
|
||||
Use Python :py:func:`open` or :c:func:`PyFile_FromFd` to create file objects instead.
|
||||
|
|
|
|||
|
|
@ -78,6 +78,109 @@ Floating-Point Objects
|
|||
Return the minimum normalized positive float *DBL_MIN* as C :c:expr:`double`.
|
||||
|
||||
|
||||
.. c:macro:: Py_INFINITY
|
||||
|
||||
This macro expands to a 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.
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
|
||||
.. c:macro:: Py_NAN
|
||||
|
||||
This macro expands to a 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`.
|
||||
|
||||
.. soft-deprecated:: 3.14
|
||||
|
||||
|
||||
.. 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.
|
||||
|
||||
.. soft-deprecated:: 3.14
|
||||
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.
|
||||
|
||||
.. soft-deprecated:: 3.14
|
||||
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.
|
||||
|
||||
.. soft-deprecated:: 3.14
|
||||
Use :c:macro:`!isnan` instead.
|
||||
|
||||
|
||||
Pack and Unpack functions
|
||||
-------------------------
|
||||
|
||||
|
|
@ -85,24 +188,23 @@ The pack and unpack functions provide an efficient platform-independent way to
|
|||
store floating-point values as byte strings. The Pack routines produce a bytes
|
||||
string from a C :c:expr:`double`, and the Unpack routines produce a C
|
||||
:c:expr:`double` from such a bytes string. The suffix (2, 4 or 8) specifies the
|
||||
number of bytes in the bytes string.
|
||||
number of bytes in the bytes string:
|
||||
|
||||
On platforms that appear to use IEEE 754 formats these functions work by
|
||||
copying bits. On other platforms, the 2-byte format is identical to the IEEE
|
||||
754 binary16 half-precision format, the 4-byte format (32-bit) is identical to
|
||||
the IEEE 754 binary32 single precision format, and the 8-byte format to the
|
||||
IEEE 754 binary64 double precision format, although the packing of INFs and
|
||||
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.
|
||||
* The 2-byte format is the IEEE 754 binary16 half-precision format.
|
||||
* The 4-byte format is the IEEE 754 binary32 single-precision format.
|
||||
* The 8-byte format is the IEEE 754 binary64 double-precision format.
|
||||
|
||||
Note that NaNs type may not be preserved on IEEE platforms (silent NaN become
|
||||
quiet), for example on x86 systems in 32-bit mode.
|
||||
The NaN type may not be preserved on some platforms while unpacking (signaling
|
||||
NaNs become quiet NaNs), for example on x86 systems in 32-bit mode.
|
||||
|
||||
It's assumed that the :c:expr:`double` type has the IEEE 754 binary64 double
|
||||
precision format. What happens if it's not true is partly accidental (alas).
|
||||
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
|
||||
precision, or smaller dynamic range, not all values can be unpacked. What
|
||||
happens in such cases is partly accidental (alas).
|
||||
precision, or smaller dynamic range, not all values can be unpacked. The
|
||||
packing of special numbers like INFs and NaNs (if such things exist on the
|
||||
platform) may not be handled correctly, and attempting to unpack a bytes string
|
||||
containing an IEEE INF or NaN may raise an exception.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
|
@ -111,19 +213,14 @@ Pack functions
|
|||
|
||||
The pack routines write 2, 4 or 8 bytes, starting at *p*. *le* is an
|
||||
:c:expr:`int` argument, non-zero if you want the bytes string in little-endian
|
||||
format (exponent last, at ``p+1``, ``p+3``, or ``p+6`` ``p+7``), zero if you
|
||||
want big-endian format (exponent first, at *p*). The :c:macro:`PY_BIG_ENDIAN`
|
||||
constant can be used to use the native endian: it is equal to ``1`` on big
|
||||
endian processor, or ``0`` on little endian processor.
|
||||
format (exponent last, at ``p+1``, ``p+3``, or ``p+6`` and ``p+7``), zero if you
|
||||
want big-endian format (exponent first, at *p*). Use the :c:macro:`!PY_LITTLE_ENDIAN`
|
||||
constant to select the native endian: it is equal to ``0`` on big
|
||||
endian processor, or ``1`` on little endian processor.
|
||||
|
||||
Return value: ``0`` if all is OK, ``-1`` if error (and an exception is set,
|
||||
most likely :exc:`OverflowError`).
|
||||
|
||||
There are two problems on non-IEEE platforms:
|
||||
|
||||
* What this does is undefined if *x* is a NaN or infinity.
|
||||
* ``-0.0`` and ``+0.0`` produce the same bytes string.
|
||||
|
||||
.. c:function:: int PyFloat_Pack2(double x, char *p, int le)
|
||||
|
||||
Pack a C double as the IEEE 754 binary16 half-precision format.
|
||||
|
|
@ -136,6 +233,9 @@ There are two problems on non-IEEE platforms:
|
|||
|
||||
Pack a C double as the IEEE 754 binary64 double precision format.
|
||||
|
||||
.. impl-detail::
|
||||
This function always succeeds in CPython.
|
||||
|
||||
|
||||
Unpack functions
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
|
@ -143,16 +243,16 @@ Unpack functions
|
|||
The unpack routines read 2, 4 or 8 bytes, starting at *p*. *le* is an
|
||||
:c:expr:`int` argument, non-zero if the bytes string is in little-endian format
|
||||
(exponent last, at ``p+1``, ``p+3`` or ``p+6`` and ``p+7``), zero if big-endian
|
||||
(exponent first, at *p*). The :c:macro:`PY_BIG_ENDIAN` constant can be used to
|
||||
use the native endian: it is equal to ``1`` on big endian processor, or ``0``
|
||||
(exponent first, at *p*). Use the :c:macro:`!PY_LITTLE_ENDIAN` constant to
|
||||
select the native endian: it is equal to ``0`` on big endian processor, or ``1``
|
||||
on little endian processor.
|
||||
|
||||
Return value: The unpacked double. On error, this is ``-1.0`` and
|
||||
:c:func:`PyErr_Occurred` is true (and an exception is set, most likely
|
||||
:exc:`OverflowError`).
|
||||
|
||||
Note that on a non-IEEE platform this will refuse to unpack a bytes string that
|
||||
represents a NaN or infinity.
|
||||
.. impl-detail::
|
||||
These functions always succeed in CPython.
|
||||
|
||||
.. c:function:: double PyFloat_Unpack2(const char *p, int le)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
.. highlight:: c
|
||||
|
||||
Frame Objects
|
||||
Frame objects
|
||||
-------------
|
||||
|
||||
.. c:type:: PyFrameObject
|
||||
|
|
@ -29,6 +29,12 @@ 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.
|
||||
|
|
@ -44,6 +50,7 @@ See also :ref:`Reflection <reflection>`.
|
|||
|
||||
Return a :term:`strong reference`, or ``NULL`` if *frame* has no outer
|
||||
frame.
|
||||
This raises no exceptions.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
|
@ -140,7 +147,7 @@ See also :ref:`Reflection <reflection>`.
|
|||
Return the line number that *frame* is currently executing.
|
||||
|
||||
|
||||
Frame Locals Proxies
|
||||
Frame locals proxies
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
|
@ -161,7 +168,52 @@ See :pep:`667` for more information.
|
|||
|
||||
Return non-zero if *obj* is a frame :func:`locals` proxy.
|
||||
|
||||
Internal Frames
|
||||
|
||||
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)
|
||||
|
||||
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.
|
||||
|
||||
.. soft-deprecated:: 3.13
|
||||
This function now does nothing.
|
||||
|
||||
|
||||
.. c:function:: void PyFrame_FastToLocals(PyFrameObject *f)
|
||||
|
||||
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.
|
||||
|
||||
.. soft-deprecated:: 3.13
|
||||
This function now does nothing.
|
||||
|
||||
|
||||
.. c:function:: int PyFrame_FastToLocalsWithError(PyFrameObject *f)
|
||||
|
||||
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.
|
||||
|
||||
.. soft-deprecated:: 3.13
|
||||
This function now does nothing.
|
||||
|
||||
|
||||
.. seealso::
|
||||
:pep:`667`
|
||||
|
||||
|
||||
Internal frames
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Unless using :pep:`523`, you will not need this.
|
||||
|
|
@ -191,5 +243,3 @@ Unless using :pep:`523`, you will not need this.
|
|||
Return the currently executing line number, or -1 if there is no line number.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -102,6 +102,15 @@ 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``
|
||||
|
|
@ -175,6 +184,9 @@ There are a few functions specific to Python functions.
|
|||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
- ``PyFunction_PYFUNC_EVENT_MODIFY_QUALNAME``
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
.. c:type:: int (*PyFunction_WatchCallback)(PyFunction_WatchEvent event, PyFunctionObject *func, PyObject *new_value)
|
||||
|
||||
|
|
@ -197,7 +209,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.
|
||||
|
|
|
|||
|
|
@ -220,38 +220,6 @@ The :c:member:`~PyTypeObject.tp_traverse` handler accepts a function parameter o
|
|||
detection; it's not expected that users will need to write their own
|
||||
visitor functions.
|
||||
|
||||
The :c:member:`~PyTypeObject.tp_traverse` handler must have the following type:
|
||||
|
||||
|
||||
.. c:type:: int (*traverseproc)(PyObject *self, visitproc visit, void *arg)
|
||||
|
||||
Traversal function for a container object. Implementations must call the
|
||||
*visit* function for each object directly contained by *self*, with the
|
||||
parameters to *visit* being the contained object and the *arg* value passed
|
||||
to the handler. The *visit* function must not be called with a ``NULL``
|
||||
object argument. If *visit* returns a non-zero value that value should be
|
||||
returned immediately.
|
||||
|
||||
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*:
|
||||
|
||||
|
||||
.. c:macro:: Py_VISIT(o)
|
||||
|
||||
If the :c:expr:`PyObject *` *o* is not ``NULL``, call the *visit* callback, with arguments *o*
|
||||
and *arg*. If *visit* returns a non-zero value, then return it.
|
||||
Using this macro, :c:member:`~PyTypeObject.tp_traverse` handlers
|
||||
look like::
|
||||
|
||||
static int
|
||||
my_traverse(Noddy *self, visitproc visit, void *arg)
|
||||
{
|
||||
Py_VISIT(self->foo);
|
||||
Py_VISIT(self->bar);
|
||||
return 0;
|
||||
}
|
||||
|
||||
The :c:member:`~PyTypeObject.tp_clear` handler must be of the :c:type:`inquiry` type, or ``NULL``
|
||||
if the object is immutable.
|
||||
|
||||
|
|
@ -266,6 +234,225 @@ if the object is immutable.
|
|||
in a reference cycle.
|
||||
|
||||
|
||||
.. _gc-traversal:
|
||||
|
||||
Traversal
|
||||
---------
|
||||
|
||||
The :c:member:`~PyTypeObject.tp_traverse` handler must have the following type:
|
||||
|
||||
.. c:type:: int (*traverseproc)(PyObject *self, visitproc visit, void *arg)
|
||||
|
||||
Traversal function for a garbage-collected object, used by the garbage
|
||||
collector to detect reference cycles.
|
||||
Implementations must call the
|
||||
*visit* function for each object directly contained by *self*, with the
|
||||
parameters to *visit* being the contained object and the *arg* value passed
|
||||
to the handler. The *visit* function must not be called with a ``NULL``
|
||||
object argument. If *visit* returns a non-zero value, that value should be
|
||||
returned immediately.
|
||||
|
||||
A typical :c:member:`!tp_traverse` function calls the :c:func:`Py_VISIT`
|
||||
convenience macro on each of the instance's members that are Python
|
||||
objects that the instance owns.
|
||||
For example, this is a (slightly outdated) traversal function for
|
||||
the :py:class:`threading.local` class::
|
||||
|
||||
static int
|
||||
local_traverse(PyObject *op, visitproc visit, void *arg)
|
||||
{
|
||||
localobject *self = (localobject *) op;
|
||||
Py_VISIT(Py_TYPE(self));
|
||||
Py_VISIT(self->args);
|
||||
Py_VISIT(self->kw);
|
||||
Py_VISIT(self->dict);
|
||||
return 0;
|
||||
}
|
||||
|
||||
.. note::
|
||||
: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.
|
||||
|
||||
Instances of :ref:`heap-allocated types <heap-types>` hold a reference to
|
||||
their type. Their traversal function must therefore visit the type::
|
||||
|
||||
Py_VISIT(Py_TYPE(self));
|
||||
|
||||
Alternately, the type may delegate this responsibility by
|
||||
calling ``tp_traverse`` of a heap-allocated superclass (or another
|
||||
heap-allocated type, if applicable).
|
||||
If they do not, the type object may not be garbage-collected.
|
||||
|
||||
If the :c:macro:`Py_TPFLAGS_MANAGED_DICT` bit is set in the
|
||||
:c:member:`~PyTypeObject.tp_flags` field, the traverse function must call
|
||||
:c:func:`PyObject_VisitManagedDict` like this::
|
||||
|
||||
int err = PyObject_VisitManagedDict((PyObject*)self, visit, arg);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
Only the members that the instance *owns* (by having
|
||||
:term:`strong references <strong reference>` to them) must be
|
||||
visited. For instance, if an object supports weak references via the
|
||||
:c:member:`~PyTypeObject.tp_weaklist` slot, the pointer supporting
|
||||
the linked list (what *tp_weaklist* points to) must **not** be
|
||||
visited as the instance does not directly own the weak references to itself.
|
||||
|
||||
The traversal function has a limitation:
|
||||
|
||||
.. warning::
|
||||
|
||||
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, directly or indirectly.
|
||||
|
||||
This means that *most* Python C API functions may not be used, since
|
||||
they can raise a new exception, return a new reference to a result object,
|
||||
have internal logic that uses side effects.
|
||||
Also, unless documented otherwise, functions that happen to not have side
|
||||
effects may start having them in future versions, without warning.
|
||||
|
||||
For a list of safe functions, see a
|
||||
:ref:`separate section <duringgc-functions>` below.
|
||||
|
||||
.. note::
|
||||
|
||||
The :c:func:`Py_VISIT` call may be skipped for those members that provably
|
||||
cannot participate in reference cycles.
|
||||
In the ``local_traverse`` example above, there is also a ``self->key``
|
||||
member, but it can only be ``NULL`` or a Python string and therefore
|
||||
cannot be part of a reference cycle.
|
||||
|
||||
On the other hand, even if you know a member can never be part of a cycle,
|
||||
as a debugging aid you may want to visit it anyway just so the :mod:`gc`
|
||||
module's :func:`~gc.get_referents` function will include it.
|
||||
|
||||
.. note::
|
||||
|
||||
The :c:member:`~PyTypeObject.tp_traverse` function can be called from any
|
||||
thread.
|
||||
|
||||
.. impl-detail::
|
||||
|
||||
Garbage collection is a "stop-the-world" operation:
|
||||
even in :term:`free threading` builds, only one thread state is
|
||||
:term:`attached <attached thread state>` when :c:member:`!tp_traverse`
|
||||
handlers run.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
|
||||
Heap-allocated types are expected to visit ``Py_TYPE(self)`` in
|
||||
``tp_traverse``. In earlier versions of Python, due to
|
||||
`bug 40217 <https://bugs.python.org/issue40217>`_, doing this
|
||||
may lead to crashes in subclasses.
|
||||
|
||||
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*:
|
||||
|
||||
.. c:macro:: Py_VISIT(o)
|
||||
|
||||
If the :c:expr:`PyObject *` *o* is not ``NULL``, call the *visit*
|
||||
callback, with arguments *o* and *arg*.
|
||||
If *visit* returns a non-zero value, then return it.
|
||||
|
||||
This corresponds roughly to::
|
||||
|
||||
#define Py_VISIT(o) \
|
||||
if (op) { \
|
||||
int visit_result = visit(o, arg); \
|
||||
if (visit_result != 0) { \
|
||||
return visit_result; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
Traversal-safe functions
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The following functions and macros are safe to use in a
|
||||
:c:member:`~PyTypeObject.tp_traverse` handler:
|
||||
|
||||
* the *visit* function passed to ``tp_traverse``
|
||||
* :c:func:`Py_VISIT`
|
||||
* :c:func:`Py_SIZE`
|
||||
* :c:func:`Py_TYPE`: if called from a :c:member:`!tp_traverse` handler,
|
||||
:c:func:`!Py_TYPE`'s result will be valid for the duration of the handler call
|
||||
* :c:func:`PyObject_VisitManagedDict`
|
||||
* :c:func:`PyObject_TypeCheck`, :c:func:`PyType_IsSubtype`,
|
||||
:c:func:`PyType_HasFeature`
|
||||
* :samp:`Py{<type>}_Check` and :samp:`Py{<type>}_CheckExact` -- for example,
|
||||
:c:func:`PyTuple_Check`
|
||||
* :ref:`duringgc-functions`
|
||||
|
||||
.. _duringgc-functions:
|
||||
|
||||
"DuringGC" functions
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The following functions should *only* be used in a
|
||||
:c:member:`~PyTypeObject.tp_traverse` handler; calling them in other
|
||||
contexts may have unintended consequences.
|
||||
|
||||
These functions act like their counterparts without the ``_DuringGC`` suffix,
|
||||
but they are guaranteed to not have side effects, they do not set an exception
|
||||
on failure, and they return/set :term:`borrowed references <borrowed reference>`
|
||||
as detailed in the individual documentation.
|
||||
|
||||
Note that these functions may fail (return ``NULL`` or ``-1``),
|
||||
but as they do not set an exception, no error information is available.
|
||||
In some cases, failure is not distinguishable from a successful ``NULL`` result.
|
||||
|
||||
.. c:function:: void *PyObject_GetTypeData_DuringGC(PyObject *o, PyTypeObject *cls)
|
||||
void *PyObject_GetItemData_DuringGC(PyObject *o)
|
||||
void *PyType_GetModuleState_DuringGC(PyTypeObject *type)
|
||||
void *PyModule_GetState_DuringGC(PyObject *module)
|
||||
int PyModule_GetToken_DuringGC(PyObject *module, void** result)
|
||||
|
||||
See :ref:`duringgc-functions` for common information.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. seealso::
|
||||
|
||||
:c:func:`PyObject_GetTypeData`,
|
||||
:c:func:`PyObject_GetItemData`,
|
||||
:c:func:`PyType_GetModuleState`,
|
||||
:c:func:`PyModule_GetState`,
|
||||
:c:func:`PyModule_GetToken`,
|
||||
:c:func:`PyType_GetBaseByToken`
|
||||
|
||||
.. c:function:: int PyType_GetBaseByToken_DuringGC(PyTypeObject *type, void *tp_token, PyTypeObject **result)
|
||||
|
||||
See :ref:`duringgc-functions` for common information.
|
||||
|
||||
Sets *\*result* to a :term:`borrowed reference` rather than a strong one.
|
||||
The reference is valid for the duration
|
||||
of the :c:member:`!tp_traverse` handler call.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. seealso:: :c:func:`PyType_GetBaseByToken`
|
||||
|
||||
.. c:function:: PyObject* PyType_GetModule_DuringGC(PyTypeObject *type)
|
||||
PyObject* PyType_GetModuleByToken_DuringGC(PyTypeObject *type, const void *mod_token)
|
||||
|
||||
See :ref:`duringgc-functions` for common information.
|
||||
|
||||
These functions return a :term:`borrowed reference`, which is
|
||||
valid for the duration of the :c:member:`!tp_traverse` handler call.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. seealso::
|
||||
|
||||
:c:func:`PyType_GetModule`,
|
||||
:c:func:`PyType_GetModuleByToken`
|
||||
|
||||
|
||||
Controlling the Garbage Collector State
|
||||
---------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -44,3 +44,55 @@ 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
|
||||
|
||||
|
||||
Deprecated API
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:macro:: PyAsyncGenASend_CheckExact(op)
|
||||
|
||||
This is an API that was included in Python's C API
|
||||
by mistake.
|
||||
|
||||
It is solely here for completeness; do not use this API.
|
||||
|
||||
.. soft-deprecated:: 3.14
|
||||
|
|
|
|||
|
|
@ -11,42 +11,98 @@ 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.
|
||||
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.
|
||||
|
||||
.. 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`.
|
||||
|
|
@ -59,14 +115,20 @@ 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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -129,8 +129,7 @@ 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`. If applicable,
|
||||
:attr:`~module.__cached__` will also be set.
|
||||
object's :attr:`~codeobject.co_filename`.
|
||||
|
||||
This function will reload the module if it was already imported. See
|
||||
:c:func:`PyImport_ReloadModule` for the intended way to reload a module.
|
||||
|
|
@ -142,10 +141,13 @@ Importing Modules
|
|||
:c:func:`PyImport_ExecCodeModuleWithPathnames`.
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
The setting of :attr:`~module.__cached__` and :attr:`~module.__loader__`
|
||||
The setting of ``__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)
|
||||
|
||||
|
|
@ -157,16 +159,19 @@ Importing Modules
|
|||
|
||||
.. c:function:: PyObject* PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname, PyObject *cpathname)
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. versionchanged:: 3.12
|
||||
Setting :attr:`~module.__cached__` is deprecated. See
|
||||
Setting ``__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)
|
||||
|
||||
|
|
@ -314,6 +319,13 @@ 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*.
|
||||
|
|
@ -333,3 +345,78 @@ Importing Modules
|
|||
strings instead of Python :class:`str` objects.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. c:function:: PyImport_LazyImportsMode PyImport_GetLazyImportsMode()
|
||||
|
||||
Gets the current lazy imports mode.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
.. c:function:: PyObject* PyImport_GetLazyImportsFilter()
|
||||
|
||||
Return a :term:`strong reference` to the current lazy imports filter,
|
||||
or ``NULL`` if none exists. This function always succeeds.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
.. c:function:: int PyImport_SetLazyImportsMode(PyImport_LazyImportsMode mode)
|
||||
|
||||
Similar to :c:func:`PyImport_ImportModuleAttr`, but names are UTF-8 encoded
|
||||
strings instead of Python :class:`str` objects.
|
||||
|
||||
This function always returns ``0``.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
.. c:function:: int PyImport_SetLazyImportsFilter(PyObject *filter)
|
||||
|
||||
Sets the current lazy imports filter. The *filter* should be a callable that
|
||||
will receive ``(importing_module_name, imported_module_name, [fromlist])``
|
||||
when an import can potentially be lazy. The ``imported_module_name`` value
|
||||
is the resolved module name, so ``lazy from .spam import eggs`` passes
|
||||
``package.spam``. The callable must return ``True`` if the import should be
|
||||
lazy and ``False`` otherwise.
|
||||
|
||||
Return ``0`` on success and ``-1`` with an exception set otherwise.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
.. c:type:: PyImport_LazyImportsMode
|
||||
|
||||
Enumeration of possible lazy import modes.
|
||||
|
||||
.. c:enumerator:: PyImport_LAZY_NORMAL
|
||||
|
||||
Respect the ``lazy`` keyword in source code. This is the default mode.
|
||||
|
||||
.. c:enumerator:: PyImport_LAZY_ALL
|
||||
|
||||
Make all imports lazy by default.
|
||||
|
||||
.. c:enumerator:: PyImport_LAZY_NONE
|
||||
|
||||
Disable lazy imports entirely. Even explicit ``lazy`` statements become
|
||||
eager imports.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
.. 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.. _c-api-index:
|
||||
|
||||
##################################
|
||||
Python/C API Reference Manual
|
||||
Python/C API reference manual
|
||||
##################################
|
||||
|
||||
This manual documents the API used by C and C++ programmers who want to write
|
||||
|
|
@ -21,7 +21,12 @@ document the API functions in detail.
|
|||
utilities.rst
|
||||
abstract.rst
|
||||
concrete.rst
|
||||
init.rst
|
||||
interp-lifecycle.rst
|
||||
threads.rst
|
||||
synchronization.rst
|
||||
tls.rst
|
||||
subinterpreters.rst
|
||||
profiling.rst
|
||||
init_config.rst
|
||||
memory.rst
|
||||
objimpl.rst
|
||||
|
|
|
|||
2457
Doc/c-api/init.rst
2457
Doc/c-api/init.rst
File diff suppressed because it is too large
Load diff
|
|
@ -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 an UTF-8 encoded string.
|
||||
An error message is a UTF-8 encoded string.
|
||||
|
||||
If *config* has an exit code, format the exit code as an error
|
||||
message.
|
||||
|
|
@ -544,9 +544,9 @@ Configuration Options
|
|||
|
||||
Visibility:
|
||||
|
||||
* Public: Can by get by :c:func:`PyConfig_Get` and set by
|
||||
* Public: Can be retrieved by :c:func:`PyConfig_Get` and set by
|
||||
:c:func:`PyConfig_Set`.
|
||||
* Read-only: Can by get by :c:func:`PyConfig_Get`, but cannot be set by
|
||||
* Read-only: Can be retrieved by :c:func:`PyConfig_Get`, but cannot be set by
|
||||
:c:func:`PyConfig_Set`.
|
||||
|
||||
|
||||
|
|
@ -1153,7 +1153,7 @@ PyConfig
|
|||
|
||||
Most ``PyConfig`` methods :ref:`preinitialize Python <c-preinit>` if needed.
|
||||
In that case, the Python preinitialization configuration
|
||||
(:c:type:`PyPreConfig`) in based on the :c:type:`PyConfig`. If configuration
|
||||
(:c:type:`PyPreConfig`) is based on the :c:type:`PyConfig`. If configuration
|
||||
fields which are in common with :c:type:`PyPreConfig` are tuned, they must
|
||||
be set before calling a :c:type:`PyConfig` method:
|
||||
|
||||
|
|
@ -1278,6 +1278,11 @@ PyConfig
|
|||
|
||||
Default: ``0``.
|
||||
|
||||
.. deprecated-removed:: 3.15 3.17
|
||||
|
||||
The :option:`-b` and :option:`!-bb` options will become no-op in 3.17.
|
||||
:c:member:`~PyConfig.bytes_warning` member will be removed in 3.17.
|
||||
|
||||
.. c:member:: int warn_default_encoding
|
||||
|
||||
If non-zero, emit a :exc:`EncodingWarning` warning when :class:`io.TextIOWrapper`
|
||||
|
|
@ -1802,10 +1807,10 @@ PyConfig
|
|||
|
||||
.. c:member:: wchar_t* run_presite
|
||||
|
||||
``package.module`` path to module that should be imported before
|
||||
``site.py`` is run.
|
||||
``module`` or ``module:func`` entry point that should be executed before
|
||||
the :mod:`site` module is imported.
|
||||
|
||||
Set by the :option:`-X presite=package.module <-X>` command-line
|
||||
Set by the :option:`-X presite=module:func <-X>` command-line
|
||||
option and the :envvar:`PYTHON_PRESITE` environment variable.
|
||||
The command-line option takes precedence.
|
||||
|
||||
|
|
@ -2294,13 +2299,91 @@ Py_GetArgcArgv()
|
|||
|
||||
See also :c:member:`PyConfig.orig_argv` member.
|
||||
|
||||
Delaying main module execution
|
||||
==============================
|
||||
|
||||
In some embedding use cases, it may be desirable to separate interpreter initialization
|
||||
from the execution of the main module.
|
||||
Multi-Phase Initialization Private Provisional API
|
||||
==================================================
|
||||
|
||||
This separation can be achieved by setting ``PyConfig.run_command`` to the empty
|
||||
string during initialization (to prevent the interpreter from dropping into the
|
||||
interactive prompt), and then subsequently executing the desired main module
|
||||
code using ``__main__.__dict__`` as the global namespace.
|
||||
This section is a private provisional API introducing multi-phase
|
||||
initialization, the core feature of :pep:`432`:
|
||||
|
||||
* "Core" initialization phase, "bare minimum Python":
|
||||
|
||||
* Builtin types;
|
||||
* Builtin exceptions;
|
||||
* Builtin and frozen modules;
|
||||
* The :mod:`sys` module is only partially initialized
|
||||
(ex: :data:`sys.path` doesn't exist yet).
|
||||
|
||||
* "Main" initialization phase, Python is fully initialized:
|
||||
|
||||
* Install and configure :mod:`importlib`;
|
||||
* Apply the :ref:`Path Configuration <init-path-config>`;
|
||||
* Install signal handlers;
|
||||
* Finish :mod:`sys` module initialization (ex: create :data:`sys.stdout`
|
||||
and :data:`sys.path`);
|
||||
* Enable optional features like :mod:`faulthandler` and :mod:`tracemalloc`;
|
||||
* Import the :mod:`site` module;
|
||||
* etc.
|
||||
|
||||
Private provisional API:
|
||||
|
||||
.. c:member:: int PyConfig._init_main
|
||||
|
||||
If set to ``0``, :c:func:`Py_InitializeFromConfig` stops at the "Core"
|
||||
initialization phase.
|
||||
|
||||
.. c:function:: PyStatus _Py_InitializeMain(void)
|
||||
|
||||
Move to the "Main" initialization phase, finish the Python initialization.
|
||||
|
||||
No module is imported during the "Core" phase and the ``importlib`` module is
|
||||
not configured: the :ref:`Path Configuration <init-path-config>` is only
|
||||
applied during the "Main" phase. It may allow to customize Python in Python to
|
||||
override or tune the :ref:`Path Configuration <init-path-config>`, maybe
|
||||
install a custom :data:`sys.meta_path` importer or an import hook, etc.
|
||||
|
||||
It may become possible to calculate the :ref:`Path Configuration
|
||||
<init-path-config>` in Python, after the Core phase and before the Main phase,
|
||||
which is one of the :pep:`432` motivation.
|
||||
|
||||
The "Core" phase is not properly defined: what should be and what should
|
||||
not be available at this phase is not specified yet. The API is marked
|
||||
as private and provisional: the API can be modified or even be removed
|
||||
anytime until a proper public API is designed.
|
||||
|
||||
Example running Python code between "Core" and "Main" initialization
|
||||
phases::
|
||||
|
||||
void init_python(void)
|
||||
{
|
||||
PyStatus status;
|
||||
|
||||
PyConfig config;
|
||||
PyConfig_InitPythonConfig(&config);
|
||||
config._init_main = 0;
|
||||
|
||||
/* ... customize 'config' configuration ... */
|
||||
|
||||
status = Py_InitializeFromConfig(&config);
|
||||
PyConfig_Clear(&config);
|
||||
if (PyStatus_Exception(status)) {
|
||||
Py_ExitStatusException(status);
|
||||
}
|
||||
|
||||
/* Use sys.stderr because sys.stdout is only created
|
||||
by _Py_InitializeMain() */
|
||||
int res = PyRun_SimpleString(
|
||||
"import sys; "
|
||||
"print('Run Python code before _Py_InitializeMain', "
|
||||
"file=sys.stderr)");
|
||||
if (res < 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* ... put more configuration code here ... */
|
||||
|
||||
status = _Py_InitializeMain();
|
||||
if (PyStatus_Exception(status)) {
|
||||
Py_ExitStatusException(status);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
802
Doc/c-api/interp-lifecycle.rst
Normal file
802
Doc/c-api/interp-lifecycle.rst
Normal file
|
|
@ -0,0 +1,802 @@
|
|||
.. highlight:: c
|
||||
|
||||
.. _initialization:
|
||||
|
||||
Interpreter initialization and finalization
|
||||
===========================================
|
||||
|
||||
See :ref:`Python Initialization Configuration <init-config>` for details
|
||||
on how to configure the interpreter prior to initialization.
|
||||
|
||||
.. _pre-init-safe:
|
||||
|
||||
Before Python initialization
|
||||
----------------------------
|
||||
|
||||
In an application embedding Python, the :c:func:`Py_Initialize` function must
|
||||
be called before using any other Python/C API functions; with the exception of
|
||||
a few functions and the :ref:`global configuration variables
|
||||
<global-conf-vars>`.
|
||||
|
||||
The following functions can be safely called before Python is initialized:
|
||||
|
||||
* Functions that initialize the interpreter:
|
||||
|
||||
* :c:func:`Py_Initialize`
|
||||
* :c:func:`Py_InitializeEx`
|
||||
* :c:func:`Py_InitializeFromConfig`
|
||||
* :c:func:`Py_BytesMain`
|
||||
* :c:func:`Py_Main`
|
||||
* the runtime pre-initialization functions covered in :ref:`init-config`
|
||||
|
||||
* Configuration functions:
|
||||
|
||||
* :c:func:`PyImport_AppendInittab`
|
||||
* :c:func:`PyImport_ExtendInittab`
|
||||
* :c:func:`!PyInitFrozenExtensions`
|
||||
* :c:func:`PyMem_SetAllocator`
|
||||
* :c:func:`PyMem_SetupDebugHooks`
|
||||
* :c:func:`PyObject_SetArenaAllocator`
|
||||
* :c:func:`Py_SetProgramName`
|
||||
* :c:func:`Py_SetPythonHome`
|
||||
* the configuration functions covered in :ref:`init-config`
|
||||
|
||||
* Informative functions:
|
||||
|
||||
* :c:func:`Py_IsInitialized`
|
||||
* :c:func:`PyMem_GetAllocator`
|
||||
* :c:func:`PyObject_GetArenaAllocator`
|
||||
* :c:func:`Py_GetBuildInfo`
|
||||
* :c:func:`Py_GetCompiler`
|
||||
* :c:func:`Py_GetCopyright`
|
||||
* :c:func:`Py_GetPlatform`
|
||||
* :c:func:`Py_GetVersion`
|
||||
* :c:func:`Py_IsInitialized`
|
||||
|
||||
* Utilities:
|
||||
|
||||
* :c:func:`Py_DecodeLocale`
|
||||
* the status reporting and utility functions covered in :ref:`init-config`
|
||||
|
||||
* Memory allocators:
|
||||
|
||||
* :c:func:`PyMem_RawMalloc`
|
||||
* :c:func:`PyMem_RawRealloc`
|
||||
* :c:func:`PyMem_RawCalloc`
|
||||
* :c:func:`PyMem_RawFree`
|
||||
|
||||
* Synchronization:
|
||||
|
||||
* :c:func:`PyMutex_Lock`
|
||||
* :c:func:`PyMutex_Unlock`
|
||||
|
||||
.. note::
|
||||
|
||||
Despite their apparent similarity to some of the functions listed above,
|
||||
the following functions **should not be called** before the interpreter has
|
||||
been initialized: :c:func:`Py_EncodeLocale`, :c:func:`PyEval_InitThreads`, and
|
||||
:c:func:`Py_RunMain`.
|
||||
|
||||
|
||||
.. _global-conf-vars:
|
||||
|
||||
Global configuration variables
|
||||
------------------------------
|
||||
|
||||
Python has variables for the global configuration to control different features
|
||||
and options. By default, these flags are controlled by :ref:`command line
|
||||
options <using-on-interface-options>`.
|
||||
|
||||
When a flag is set by an option, the value of the flag is the number of times
|
||||
that the option was set. For example, ``-b`` sets :c:data:`Py_BytesWarningFlag`
|
||||
to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2.
|
||||
|
||||
|
||||
.. c:var:: int Py_BytesWarningFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.bytes_warning` should be used instead, see :ref:`Python
|
||||
Initialization Configuration <init-config>`.
|
||||
|
||||
Issue a warning when comparing :class:`bytes` or :class:`bytearray` with
|
||||
:class:`str` or :class:`bytes` with :class:`int`. Issue an error if greater
|
||||
or equal to ``2``.
|
||||
|
||||
Set by the :option:`-b` option.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_DebugFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.parser_debug` should be used instead, see :ref:`Python
|
||||
Initialization Configuration <init-config>`.
|
||||
|
||||
Turn on parser debugging output (for expert only, depending on compilation
|
||||
options).
|
||||
|
||||
Set by the :option:`-d` option and the :envvar:`PYTHONDEBUG` environment
|
||||
variable.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_DontWriteBytecodeFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.write_bytecode` should be used instead, see :ref:`Python
|
||||
Initialization Configuration <init-config>`.
|
||||
|
||||
If set to non-zero, Python won't try to write ``.pyc`` files on the
|
||||
import of source modules.
|
||||
|
||||
Set by the :option:`-B` option and the :envvar:`PYTHONDONTWRITEBYTECODE`
|
||||
environment variable.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_FrozenFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.pathconfig_warnings` should be used instead, see
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
Private flag used by ``_freeze_module`` and ``frozenmain`` programs.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_HashRandomizationFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.hash_seed` and :c:member:`PyConfig.use_hash_seed` should
|
||||
be used instead, see :ref:`Python Initialization Configuration
|
||||
<init-config>`.
|
||||
|
||||
Set to ``1`` if the :envvar:`PYTHONHASHSEED` environment variable is set to
|
||||
a non-empty string.
|
||||
|
||||
If the flag is non-zero, read the :envvar:`PYTHONHASHSEED` environment
|
||||
variable to initialize the secret hash seed.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_IgnoreEnvironmentFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.use_environment` should be used instead, see
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
Ignore all :envvar:`!PYTHON*` environment variables, e.g.
|
||||
:envvar:`PYTHONPATH` and :envvar:`PYTHONHOME`, that might be set.
|
||||
|
||||
Set by the :option:`-E` and :option:`-I` options.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_InspectFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.inspect` should be used instead, see
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
When a script is passed as first argument or the :option:`-c` option is used,
|
||||
enter interactive mode after executing the script or the command, even when
|
||||
:data:`sys.stdin` does not appear to be a terminal.
|
||||
|
||||
Set by the :option:`-i` option and the :envvar:`PYTHONINSPECT` environment
|
||||
variable.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_InteractiveFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.interactive` should be used instead, see
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
Set by the :option:`-i` option.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_IsolatedFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.isolated` should be used instead, see
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
Run Python in isolated mode. In isolated mode :data:`sys.path` contains
|
||||
neither the script's directory nor the user's site-packages directory.
|
||||
|
||||
Set by the :option:`-I` option.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_LegacyWindowsFSEncodingFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyPreConfig.legacy_windows_fs_encoding` should be used instead, see
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
If the flag is non-zero, use the ``mbcs`` encoding with ``replace`` error
|
||||
handler, instead of the UTF-8 encoding with ``surrogatepass`` error handler,
|
||||
for the :term:`filesystem encoding and error handler`.
|
||||
|
||||
Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment
|
||||
variable is set to a non-empty string.
|
||||
|
||||
See :pep:`529` for more details.
|
||||
|
||||
.. availability:: Windows.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_LegacyWindowsStdioFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.legacy_windows_stdio` should be used instead, see
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
If the flag is non-zero, use :class:`io.FileIO` instead of
|
||||
:class:`!io._WindowsConsoleIO` for :mod:`sys` standard streams.
|
||||
|
||||
Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSSTDIO` environment
|
||||
variable is set to a non-empty string.
|
||||
|
||||
See :pep:`528` for more details.
|
||||
|
||||
.. availability:: Windows.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_NoSiteFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.site_import` should be used instead, see
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
Disable the import of the module :mod:`site` and the site-dependent
|
||||
manipulations of :data:`sys.path` that it entails. Also disable these
|
||||
manipulations if :mod:`site` is explicitly imported later (call
|
||||
:func:`site.main` if you want them to be triggered).
|
||||
|
||||
Set by the :option:`-S` option.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_NoUserSiteDirectory
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.user_site_directory` should be used instead, see
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
Don't add the :data:`user site-packages directory <site.USER_SITE>` to
|
||||
:data:`sys.path`.
|
||||
|
||||
Set by the :option:`-s` and :option:`-I` options, and the
|
||||
:envvar:`PYTHONNOUSERSITE` environment variable.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_OptimizeFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.optimization_level` should be used instead, see
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
Set by the :option:`-O` option and the :envvar:`PYTHONOPTIMIZE` environment
|
||||
variable.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_QuietFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.quiet` should be used instead, see :ref:`Python
|
||||
Initialization Configuration <init-config>`.
|
||||
|
||||
Don't display the copyright and version messages even in interactive mode.
|
||||
|
||||
Set by the :option:`-q` option.
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_UnbufferedStdioFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.buffered_stdio` should be used instead, see :ref:`Python
|
||||
Initialization Configuration <init-config>`.
|
||||
|
||||
Force the stdout and stderr streams to be unbuffered.
|
||||
|
||||
Set by the :option:`-u` option and the :envvar:`PYTHONUNBUFFERED`
|
||||
environment variable.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
.. c:var:: int Py_VerboseFlag
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.verbose` should be used instead, see :ref:`Python
|
||||
Initialization Configuration <init-config>`.
|
||||
|
||||
Print a message each time a module is initialized, showing the place
|
||||
(filename or built-in module) from which it is loaded. If greater or equal
|
||||
to ``2``, print a message for each file that is checked for when
|
||||
searching for a module. Also provides information on module cleanup at exit.
|
||||
|
||||
Set by the :option:`-v` option and the :envvar:`PYTHONVERBOSE` environment
|
||||
variable.
|
||||
|
||||
.. deprecated-removed:: 3.12 3.15
|
||||
|
||||
|
||||
Initializing and finalizing the interpreter
|
||||
-------------------------------------------
|
||||
|
||||
.. c:function:: void Py_Initialize()
|
||||
|
||||
.. index::
|
||||
single: PyEval_InitThreads()
|
||||
single: modules (in module sys)
|
||||
single: path (in module sys)
|
||||
pair: module; builtins
|
||||
pair: module; __main__
|
||||
pair: module; sys
|
||||
triple: module; search; path
|
||||
single: Py_FinalizeEx (C function)
|
||||
|
||||
Initialize the Python interpreter. In an application embedding Python,
|
||||
this should be called before using any other Python/C API functions; see
|
||||
:ref:`Before Python Initialization <pre-init-safe>` for the few exceptions.
|
||||
|
||||
This initializes the table of loaded modules (``sys.modules``), and creates
|
||||
the fundamental modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`.
|
||||
It also initializes the module search path (``sys.path``). It does not set
|
||||
``sys.argv``; use the :ref:`Python Initialization Configuration <init-config>`
|
||||
API for that. This is a no-op when called for a second time (without calling
|
||||
:c:func:`Py_FinalizeEx` first). There is no return value; it is a fatal
|
||||
error if the initialization fails.
|
||||
|
||||
Use :c:func:`Py_InitializeFromConfig` to customize the
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
.. note::
|
||||
On Windows, changes the console mode from ``O_TEXT`` to ``O_BINARY``,
|
||||
which will also affect non-Python uses of the console using the C Runtime.
|
||||
|
||||
|
||||
.. c:function:: void Py_InitializeEx(int initsigs)
|
||||
|
||||
This function works like :c:func:`Py_Initialize` if *initsigs* is ``1``. If
|
||||
*initsigs* is ``0``, it skips initialization registration of signal handlers,
|
||||
which may be useful when CPython is embedded as part of a larger application.
|
||||
|
||||
Use :c:func:`Py_InitializeFromConfig` to customize the
|
||||
:ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
|
||||
.. c:function:: PyStatus Py_InitializeFromConfig(const PyConfig *config)
|
||||
|
||||
Initialize Python from *config* configuration, as described in
|
||||
:ref:`init-from-config`.
|
||||
|
||||
See the :ref:`init-config` section for details on pre-initializing the
|
||||
interpreter, populating the runtime configuration structure, and querying
|
||||
the returned status structure.
|
||||
|
||||
|
||||
.. c:function:: int Py_IsInitialized()
|
||||
|
||||
Return true (nonzero) when the Python interpreter has been initialized, false
|
||||
(zero) if not. After :c:func:`Py_FinalizeEx` is called, this returns false until
|
||||
:c:func:`Py_Initialize` is called again.
|
||||
|
||||
.. versionchanged:: next
|
||||
This function no longer returns true until initialization has fully
|
||||
completed, including import of the :mod:`site` module. Previously it
|
||||
could return true while :c:func:`Py_Initialize` was still running.
|
||||
|
||||
|
||||
.. c:function:: int Py_IsFinalizing()
|
||||
|
||||
Return true (non-zero) if the main Python interpreter is
|
||||
:term:`shutting down <interpreter shutdown>`. Return false (zero) otherwise.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. c:function:: int Py_FinalizeEx()
|
||||
|
||||
Undo all initializations made by :c:func:`Py_Initialize` and subsequent use of
|
||||
Python/C API functions, and destroy all sub-interpreters (see
|
||||
:c:func:`Py_NewInterpreter` below) that were created and not yet destroyed since
|
||||
the last call to :c:func:`Py_Initialize`. This is a no-op when called for a second
|
||||
time (without calling :c:func:`Py_Initialize` again first).
|
||||
|
||||
Since this is the reverse of :c:func:`Py_Initialize`, it should be called
|
||||
in the same thread with the same interpreter active. That means
|
||||
the main thread and the main interpreter.
|
||||
This should never be called while :c:func:`Py_RunMain` is running.
|
||||
|
||||
Normally the return value is ``0``.
|
||||
If there were errors during finalization (flushing buffered data),
|
||||
``-1`` is returned.
|
||||
|
||||
Note that Python will do a best effort at freeing all memory allocated by the Python
|
||||
interpreter. Therefore, any C-Extension should make sure to correctly clean up all
|
||||
of the previously allocated PyObjects before using them in subsequent calls to
|
||||
:c:func:`Py_Initialize`. Otherwise it could introduce vulnerabilities and incorrect
|
||||
behavior.
|
||||
|
||||
This function is provided for a number of reasons. An embedding application
|
||||
might want to restart Python without having to restart the application itself.
|
||||
An application that has loaded the Python interpreter from a dynamically
|
||||
loadable library (or DLL) might want to free all memory allocated by Python
|
||||
before unloading the DLL. During a hunt for memory leaks in an application a
|
||||
developer might want to free all memory allocated by Python before exiting from
|
||||
the application.
|
||||
|
||||
**Bugs and caveats:** The destruction of modules and objects in modules is done
|
||||
in random order; this may cause destructors (:meth:`~object.__del__` methods) to fail
|
||||
when they depend on other objects (even functions) or modules. Dynamically
|
||||
loaded extension modules loaded by Python are not unloaded. Small amounts of
|
||||
memory allocated by the Python interpreter may not be freed (if you find a leak,
|
||||
please report it). Memory tied up in circular references between objects is not
|
||||
freed. Interned strings will all be deallocated regardless of their reference count.
|
||||
Some memory allocated by extension modules may not be freed. Some extensions may not
|
||||
work properly if their initialization routine is called more than once; this can
|
||||
happen if an application calls :c:func:`Py_Initialize` and :c:func:`Py_FinalizeEx`
|
||||
more than once. :c:func:`Py_FinalizeEx` must not be called recursively from
|
||||
within itself. Therefore, it must not be called by any code that may be run
|
||||
as part of the interpreter shutdown process, such as :py:mod:`atexit`
|
||||
handlers, object finalizers, or any code that may be run while flushing the
|
||||
stdout and stderr files.
|
||||
|
||||
.. audit-event:: cpython._PySys_ClearAuditHooks "" c.Py_FinalizeEx
|
||||
|
||||
.. versionadded:: 3.6
|
||||
|
||||
|
||||
.. c:function:: void Py_Finalize()
|
||||
|
||||
This is a backwards-compatible version of :c:func:`Py_FinalizeEx` that
|
||||
disregards the return value.
|
||||
|
||||
|
||||
.. c:function:: int Py_BytesMain(int argc, char **argv)
|
||||
|
||||
Similar to :c:func:`Py_Main` but *argv* is an array of bytes strings,
|
||||
allowing the calling application to delegate the text decoding step to
|
||||
the CPython runtime.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
|
||||
.. c:function:: int Py_Main(int argc, wchar_t **argv)
|
||||
|
||||
The main program for the standard interpreter, encapsulating a full
|
||||
initialization/finalization cycle, as well as additional
|
||||
behaviour to implement reading configurations settings from the environment
|
||||
and command line, and then executing ``__main__`` in accordance with
|
||||
:ref:`using-on-cmdline`.
|
||||
|
||||
This is made available for programs which wish to support the full CPython
|
||||
command line interface, rather than just embedding a Python runtime in a
|
||||
larger application.
|
||||
|
||||
The *argc* and *argv* parameters are similar to those which are passed to a
|
||||
C program's :c:func:`main` function, except that the *argv* entries are first
|
||||
converted to ``wchar_t`` using :c:func:`Py_DecodeLocale`. It is also
|
||||
important to note that the argument list entries may be modified to point to
|
||||
strings other than those passed in (however, the contents of the strings
|
||||
pointed to by the argument list are not modified).
|
||||
|
||||
The return value is ``2`` if the argument list does not represent a valid
|
||||
Python command line, and otherwise the same as :c:func:`Py_RunMain`.
|
||||
|
||||
In terms of the CPython runtime configuration APIs documented in the
|
||||
:ref:`runtime configuration <init-config>` section (and without accounting
|
||||
for error handling), ``Py_Main`` is approximately equivalent to::
|
||||
|
||||
PyConfig config;
|
||||
PyConfig_InitPythonConfig(&config);
|
||||
PyConfig_SetArgv(&config, argc, argv);
|
||||
Py_InitializeFromConfig(&config);
|
||||
PyConfig_Clear(&config);
|
||||
|
||||
Py_RunMain();
|
||||
|
||||
In normal usage, an embedding application will call this function
|
||||
*instead* of calling :c:func:`Py_Initialize`, :c:func:`Py_InitializeEx` or
|
||||
:c:func:`Py_InitializeFromConfig` directly, and all settings will be applied
|
||||
as described elsewhere in this documentation. If this function is instead
|
||||
called *after* a preceding runtime initialization API call, then exactly
|
||||
which environmental and command line configuration settings will be updated
|
||||
is version dependent (as it depends on which settings correctly support
|
||||
being modified after they have already been set once when the runtime was
|
||||
first initialized).
|
||||
|
||||
|
||||
.. c:function:: int Py_RunMain(void)
|
||||
|
||||
Executes the main module in a fully configured CPython runtime.
|
||||
|
||||
Executes the command (:c:member:`PyConfig.run_command`), the script
|
||||
(:c:member:`PyConfig.run_filename`) or the module
|
||||
(:c:member:`PyConfig.run_module`) specified on the command line or in the
|
||||
configuration. If none of these values are set, runs the interactive Python
|
||||
prompt (REPL) using the ``__main__`` module's global namespace.
|
||||
|
||||
If :c:member:`PyConfig.inspect` is not set (the default), the return value
|
||||
will be ``0`` if the interpreter exits normally (that is, without raising
|
||||
an exception), the exit status of an unhandled :exc:`SystemExit`, or ``1``
|
||||
for any other unhandled exception.
|
||||
|
||||
If :c:member:`PyConfig.inspect` is set (such as when the :option:`-i` option
|
||||
is used), rather than returning when the interpreter exits, execution will
|
||||
instead resume in an interactive Python prompt (REPL) using the ``__main__``
|
||||
module's global namespace. If the interpreter exited with an exception, it
|
||||
is immediately raised in the REPL session. The function return value is
|
||||
then determined by the way the *REPL session* terminates: ``0``, ``1``, or
|
||||
the status of a :exc:`SystemExit`, as specified above.
|
||||
|
||||
This function always finalizes the Python interpreter before it returns.
|
||||
|
||||
See :ref:`Python Configuration <init-python-config>` for an example of a
|
||||
customized Python that always runs in isolated mode using
|
||||
:c:func:`Py_RunMain`.
|
||||
|
||||
.. c:function:: int PyUnstable_AtExit(PyInterpreterState *interp, void (*func)(void *), void *data)
|
||||
|
||||
Register an :mod:`atexit` callback for the target interpreter *interp*.
|
||||
This is similar to :c:func:`Py_AtExit`, but takes an explicit interpreter and
|
||||
data pointer for the callback.
|
||||
|
||||
There must be an :term:`attached thread state` for *interp*.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. _cautions-regarding-runtime-finalization:
|
||||
|
||||
Cautions regarding runtime finalization
|
||||
---------------------------------------
|
||||
|
||||
In the late stage of :term:`interpreter shutdown`, after attempting to wait for
|
||||
non-daemon threads to exit (though this can be interrupted by
|
||||
:class:`KeyboardInterrupt`) and running the :mod:`atexit` functions, the runtime
|
||||
is marked as *finalizing*: :c:func:`Py_IsFinalizing` and
|
||||
:func:`sys.is_finalizing` return true. At this point, only the *finalization
|
||||
thread* that initiated finalization (typically the main thread) is allowed to
|
||||
acquire the :term:`GIL`.
|
||||
|
||||
If any thread, other than the finalization thread, attempts to attach a :term:`thread state`
|
||||
during finalization, either explicitly or
|
||||
implicitly, the thread enters **a permanently blocked state**
|
||||
where it remains until the program exits. In most cases this is harmless, but this can result
|
||||
in deadlock if a later stage of finalization attempts to acquire a lock owned by the
|
||||
blocked thread, or otherwise waits on the blocked thread.
|
||||
|
||||
Gross? Yes. This prevents random crashes and/or unexpectedly skipped C++
|
||||
finalizations further up the call stack when such threads were forcibly exited
|
||||
here in CPython 3.13 and earlier. The CPython runtime :term:`thread state` C APIs
|
||||
have never had any error reporting or handling expectations at :term:`thread state`
|
||||
attachment time that would've allowed for graceful exit from this situation. Changing that
|
||||
would require new stable C APIs and rewriting the majority of C code in the
|
||||
CPython ecosystem to use those with error handling.
|
||||
|
||||
|
||||
Process-wide parameters
|
||||
-----------------------
|
||||
|
||||
.. c:function:: void Py_SetProgramName(const wchar_t *name)
|
||||
|
||||
.. index::
|
||||
single: Py_Initialize()
|
||||
single: main()
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.program_name` should be used instead, see :ref:`Python
|
||||
Initialization Configuration <init-config>`.
|
||||
|
||||
This function should be called before :c:func:`Py_Initialize` is called for
|
||||
the first time, if it is called at all. It tells the interpreter the value
|
||||
of the ``argv[0]`` argument to the :c:func:`main` function of the program
|
||||
(converted to wide characters).
|
||||
This is used by some other functions below to find
|
||||
the Python run-time libraries relative to the interpreter executable. The
|
||||
default value is ``'python'``. The argument should point to a
|
||||
zero-terminated wide character string in static storage whose contents will not
|
||||
change for the duration of the program's execution. No code in the Python
|
||||
interpreter will change the contents of this storage.
|
||||
|
||||
Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a
|
||||
:c:expr:`wchar_t*` string.
|
||||
|
||||
.. deprecated-removed:: 3.11 3.15
|
||||
|
||||
|
||||
.. c:function:: const char* Py_GetVersion()
|
||||
|
||||
Return the version of this Python interpreter. This is a string that looks
|
||||
something like ::
|
||||
|
||||
"3.0a5+ (py3k:63103M, May 12 2008, 00:53:55) \n[GCC 4.2.3]"
|
||||
|
||||
.. index:: single: version (in module sys)
|
||||
|
||||
The first word (up to the first space character) is the current Python version;
|
||||
the first characters are the major and minor version separated by a
|
||||
period. The returned string points into static storage; the caller should not
|
||||
modify its value. The value is available to Python code as :data:`sys.version`.
|
||||
|
||||
See also the :c:var:`Py_Version` constant.
|
||||
|
||||
|
||||
.. c:function:: const char* Py_GetPlatform()
|
||||
|
||||
.. index:: single: platform (in module sys)
|
||||
|
||||
Return the platform identifier for the current platform. On Unix, this is
|
||||
formed from the "official" name of the operating system, converted to lower
|
||||
case, followed by the major revision number; e.g., for Solaris 2.x, which is
|
||||
also known as SunOS 5.x, the value is ``'sunos5'``. On macOS, it is
|
||||
``'darwin'``. On Windows, it is ``'win'``. The returned string points into
|
||||
static storage; the caller should not modify its value. The value is available
|
||||
to Python code as ``sys.platform``.
|
||||
|
||||
|
||||
.. c:function:: const char* Py_GetCopyright()
|
||||
|
||||
Return the official copyright string for the current Python version, for example
|
||||
|
||||
``'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'``
|
||||
|
||||
.. index:: single: copyright (in module sys)
|
||||
|
||||
The returned string points into static storage; the caller should not modify its
|
||||
value. The value is available to Python code as ``sys.copyright``.
|
||||
|
||||
|
||||
.. c:function:: const char* Py_GetCompiler()
|
||||
|
||||
Return an indication of the compiler used to build the current Python version,
|
||||
in square brackets, for example::
|
||||
|
||||
"[GCC 2.7.2.2]"
|
||||
|
||||
.. index:: single: version (in module sys)
|
||||
|
||||
The returned string points into static storage; the caller should not modify its
|
||||
value. The value is available to Python code as part of the variable
|
||||
``sys.version``.
|
||||
|
||||
|
||||
.. c:function:: const char* Py_GetBuildInfo()
|
||||
|
||||
Return information about the sequence number and build date and time of the
|
||||
current Python interpreter instance, for example ::
|
||||
|
||||
"#67, Aug 1 1997, 22:34:28"
|
||||
|
||||
.. index:: single: version (in module sys)
|
||||
|
||||
The returned string points into static storage; the caller should not modify its
|
||||
value. The value is available to Python code as part of the variable
|
||||
``sys.version``.
|
||||
|
||||
|
||||
.. c:function:: void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
|
||||
|
||||
.. index::
|
||||
single: main()
|
||||
single: Py_FatalError()
|
||||
single: argv (in module sys)
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.argv`, :c:member:`PyConfig.parse_argv` and
|
||||
:c:member:`PyConfig.safe_path` should be used instead, see :ref:`Python
|
||||
Initialization Configuration <init-config>`.
|
||||
|
||||
Set :data:`sys.argv` based on *argc* and *argv*. These parameters are
|
||||
similar to those passed to the program's :c:func:`main` function with the
|
||||
difference that the first entry should refer to the script file to be
|
||||
executed rather than the executable hosting the Python interpreter. If there
|
||||
isn't a script that will be run, the first entry in *argv* can be an empty
|
||||
string. If this function fails to initialize :data:`sys.argv`, a fatal
|
||||
condition is signalled using :c:func:`Py_FatalError`.
|
||||
|
||||
If *updatepath* is zero, this is all the function does. If *updatepath*
|
||||
is non-zero, the function also modifies :data:`sys.path` according to the
|
||||
following algorithm:
|
||||
|
||||
- If the name of an existing script is passed in ``argv[0]``, the absolute
|
||||
path of the directory where the script is located is prepended to
|
||||
:data:`sys.path`.
|
||||
- Otherwise (that is, if *argc* is ``0`` or ``argv[0]`` doesn't point
|
||||
to an existing file name), an empty string is prepended to
|
||||
:data:`sys.path`, which is the same as prepending the current working
|
||||
directory (``"."``).
|
||||
|
||||
Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a
|
||||
:c:expr:`wchar_t*` string.
|
||||
|
||||
See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv`
|
||||
members of the :ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
.. note::
|
||||
It is recommended that applications embedding the Python interpreter
|
||||
for purposes other than executing a single script pass ``0`` as *updatepath*,
|
||||
and update :data:`sys.path` themselves if desired.
|
||||
See :cve:`2008-5983`.
|
||||
|
||||
On versions before 3.1.3, you can achieve the same effect by manually
|
||||
popping the first :data:`sys.path` element after having called
|
||||
:c:func:`PySys_SetArgv`, for example using::
|
||||
|
||||
PyRun_SimpleString("import sys; sys.path.pop(0)\n");
|
||||
|
||||
.. versionadded:: 3.1.3
|
||||
|
||||
.. deprecated-removed:: 3.11 3.15
|
||||
|
||||
|
||||
.. c:function:: void PySys_SetArgv(int argc, wchar_t **argv)
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.argv` and :c:member:`PyConfig.parse_argv` should be used
|
||||
instead, see :ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
This function works like :c:func:`PySys_SetArgvEx` with *updatepath* set
|
||||
to ``1`` unless the :program:`python` interpreter was started with the
|
||||
:option:`-I`.
|
||||
|
||||
Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a
|
||||
:c:expr:`wchar_t*` string.
|
||||
|
||||
See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv`
|
||||
members of the :ref:`Python Initialization Configuration <init-config>`.
|
||||
|
||||
.. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`.
|
||||
|
||||
.. deprecated-removed:: 3.11 3.15
|
||||
|
||||
|
||||
.. c:function:: void Py_SetPythonHome(const wchar_t *home)
|
||||
|
||||
This API is kept for backward compatibility: setting
|
||||
:c:member:`PyConfig.home` should be used instead, see :ref:`Python
|
||||
Initialization Configuration <init-config>`.
|
||||
|
||||
Set the default "home" directory, that is, the location of the standard
|
||||
Python libraries. See :envvar:`PYTHONHOME` for the meaning of the
|
||||
argument string.
|
||||
|
||||
The argument should point to a zero-terminated character string in static
|
||||
storage whose contents will not change for the duration of the program's
|
||||
execution. No code in the Python interpreter will change the contents of
|
||||
this storage.
|
||||
|
||||
Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a
|
||||
:c:expr:`wchar_t*` string.
|
||||
|
||||
.. deprecated-removed:: 3.11 3.15
|
||||
|
|
@ -107,6 +107,46 @@ 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>``
|
||||
* ``<string.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>``
|
||||
|
||||
.. 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
|
||||
=============
|
||||
|
||||
|
|
@ -116,18 +156,279 @@ defined closer to where they are useful (for example, :c:macro:`Py_RETURN_NONE`,
|
|||
Others of a more general utility are defined here. This is not necessarily a
|
||||
complete listing.
|
||||
|
||||
.. c:macro:: Py_CAN_START_THREADS
|
||||
|
||||
If this macro is defined, then the current system is able to start threads.
|
||||
|
||||
Currently, all systems supported by CPython (per :pep:`11`), with the
|
||||
exception of some WebAssembly platforms, support starting threads.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
.. c:macro:: Py_GETENV(s)
|
||||
|
||||
Like :samp:`getenv({s})`, but returns ``NULL`` if :option:`-E` was passed
|
||||
on the command line (see :c:member:`PyConfig.use_environment`).
|
||||
|
||||
|
||||
Docstring macros
|
||||
----------------
|
||||
|
||||
.. c:macro:: PyDoc_STRVAR(name, str)
|
||||
|
||||
Creates a variable with name *name* that can be used in docstrings.
|
||||
If Python is built without docstrings (:option:`--without-doc-strings`),
|
||||
the value will be an empty string.
|
||||
|
||||
Example::
|
||||
|
||||
PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element.");
|
||||
|
||||
static PyMethodDef deque_methods[] = {
|
||||
// ...
|
||||
{"pop", (PyCFunction)deque_pop, METH_NOARGS, pop_doc},
|
||||
// ...
|
||||
}
|
||||
|
||||
Expands to :samp:`PyDoc_VAR({name}) = PyDoc_STR({str})`.
|
||||
|
||||
.. c:macro:: PyDoc_STR(str)
|
||||
|
||||
Expands to the given input string, or an empty string
|
||||
if docstrings are disabled (:option:`--without-doc-strings`).
|
||||
|
||||
Example::
|
||||
|
||||
static PyMethodDef pysqlite_row_methods[] = {
|
||||
{"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS,
|
||||
PyDoc_STR("Returns the keys of the row.")},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
.. c:macro:: PyDoc_VAR(name)
|
||||
|
||||
Declares a static character array variable with the given *name*.
|
||||
Expands to :samp:`static const char {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.");
|
||||
|
||||
|
||||
General utility macros
|
||||
----------------------
|
||||
|
||||
The following macros are for common tasks not specific to Python.
|
||||
|
||||
.. c:macro:: Py_UNUSED(arg)
|
||||
|
||||
Use this for unused arguments in a function definition to silence compiler
|
||||
warnings. Example: ``int func(int a, int Py_UNUSED(b)) { return a; }``.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. c:macro:: Py_GCC_ATTRIBUTE(name)
|
||||
|
||||
Use a GCC attribute *name*, hiding it from compilers that don't support GCC
|
||||
attributes (such as MSVC).
|
||||
|
||||
This expands to :samp:`__attribute__(({name)})` on a GCC compiler,
|
||||
and expands to nothing on compilers that don't support GCC attributes.
|
||||
|
||||
|
||||
Numeric utilities
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. c:macro:: Py_ABS(x)
|
||||
|
||||
Return the absolute value of ``x``.
|
||||
|
||||
The argument may be evaluated more than once.
|
||||
Consequently, do not pass an expression with side-effects directly
|
||||
to this macro.
|
||||
|
||||
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.
|
||||
|
||||
Corresponds roughly to :samp:`(({x}) < 0 ? -({x}) : ({x}))`
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. c:macro:: Py_MAX(x, y)
|
||||
Py_MIN(x, y)
|
||||
|
||||
Return the larger or smaller of the arguments, respectively.
|
||||
|
||||
Any arguments may be evaluated more than once.
|
||||
Consequently, do not pass an expression with side-effects directly
|
||||
to this macro.
|
||||
|
||||
:c:macro:`!Py_MAX` corresponds roughly to
|
||||
:samp:`((({x}) > ({y})) ? ({x}) : ({y}))`.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. c:macro:: Py_ARITHMETIC_RIGHT_SHIFT(type, integer, positions)
|
||||
|
||||
Similar to :samp:`{integer} >> {positions}`, but forces sign extension,
|
||||
as the C standard does not define whether a right-shift of a signed
|
||||
integer will perform sign extension or a zero-fill.
|
||||
|
||||
*integer* should be any signed integer type.
|
||||
*positions* is the number of positions to shift to the right.
|
||||
|
||||
Both *integer* and *positions* can be evaluated more than once;
|
||||
consequently, avoid directly passing a function call or some other
|
||||
operation with side-effects to this macro. Instead, store the result as a
|
||||
variable and then pass it.
|
||||
|
||||
*type* is unused and only kept for backwards compatibility. Historically,
|
||||
*type* was used to cast *integer*.
|
||||
|
||||
.. versionchanged:: 3.1
|
||||
|
||||
This macro is now valid for all signed integer types, not just those for
|
||||
which ``unsigned type`` is legal. As a result, *type* is no longer
|
||||
used.
|
||||
|
||||
.. c:macro:: Py_CHARMASK(c)
|
||||
|
||||
Argument must be a character or an integer in the range [-128, 127] or [0,
|
||||
255]. This macro returns ``c`` cast to an ``unsigned char``.
|
||||
|
||||
|
||||
Assertion utilities
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. c:macro:: Py_UNREACHABLE()
|
||||
|
||||
Use this when you have a code path that cannot be reached by design.
|
||||
For example, in the ``default:`` clause in a ``switch`` statement for which
|
||||
all possible values are covered in ``case`` statements. Use this in places
|
||||
where you might be tempted to put an ``assert(0)`` or ``abort()`` call.
|
||||
|
||||
In release mode, the macro helps the compiler to optimize the code, and
|
||||
avoids a warning about unreachable code. For example, the macro is
|
||||
implemented with ``__builtin_unreachable()`` on GCC in release mode.
|
||||
|
||||
In debug mode, and on unsupported compilers, the macro expands to a call to
|
||||
:c:func:`Py_FatalError`.
|
||||
|
||||
A use for ``Py_UNREACHABLE()`` is following a call to a function that
|
||||
never returns but that is not declared ``_Noreturn``.
|
||||
|
||||
If a code path is very unlikely code but can be reached under exceptional
|
||||
case, this macro must not be used. For example, under low memory condition
|
||||
or if a system call returns a value out of the expected range. In this
|
||||
case, it's better to report the error to the caller. If the error cannot
|
||||
be reported to caller, :c:func:`Py_FatalError` can be used.
|
||||
|
||||
.. versionadded:: 3.7
|
||||
|
||||
.. c:macro:: Py_SAFE_DOWNCAST(value, larger, smaller)
|
||||
|
||||
Cast *value* to type *smaller* from type *larger*, validating that no
|
||||
information was lost.
|
||||
|
||||
On release builds of Python, this is roughly equivalent to
|
||||
:samp:`(({smaller}) {value})`
|
||||
(in C++, :samp:`static_cast<{smaller}>({value})` will be used instead).
|
||||
|
||||
On debug builds (implying that :c:macro:`Py_DEBUG` is defined), this asserts
|
||||
that no information was lost with the cast from *larger* to *smaller*.
|
||||
|
||||
*value*, *larger*, and *smaller* may all be evaluated more than once in the
|
||||
expression; consequently, do not pass an expression with side-effects
|
||||
directly to this macro.
|
||||
|
||||
.. 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.
|
||||
|
||||
Corresponds roughly to :samp:`static_assert({cond})` on C23 and above.
|
||||
|
||||
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
|
||||
|
||||
|
||||
Type size utilities
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. 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])
|
||||
|
||||
.. c:macro:: Py_MEMBER_SIZE(type, member)
|
||||
|
||||
Return the size of a structure (*type*) *member* in bytes.
|
||||
|
||||
Corresponds roughly to :samp:`sizeof((({type} *)NULL)->{member})`.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
|
||||
|
||||
Macro definition utilities
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. c:macro:: Py_FORCE_EXPANSION(X)
|
||||
|
||||
This is equivalent to :samp:`{X}`, which is useful for token-pasting in
|
||||
macros, as macro expansions in *X* are forcefully evaluated by the
|
||||
preprocessor.
|
||||
|
||||
.. c:macro:: Py_STRINGIFY(x)
|
||||
|
||||
Convert ``x`` to a C string. For example, ``Py_STRINGIFY(123)`` returns
|
||||
``"123"``.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
|
||||
Declaration utilities
|
||||
---------------------
|
||||
|
||||
The following macros can be used in declarations.
|
||||
They are most useful for defining the C API itself, and have limited use
|
||||
for extension authors.
|
||||
Most of them expand to compiler-specific spellings of common extensions
|
||||
to the C language.
|
||||
|
||||
.. c:macro:: Py_ALWAYS_INLINE
|
||||
|
||||
Ask the compiler to always inline a static inline function. The compiler can
|
||||
ignore it and decide to not inline the function.
|
||||
|
||||
Corresponds to ``always_inline`` attribute in GCC and ``__forceinline``
|
||||
in MSVC.
|
||||
|
||||
It can be used to inline performance critical static inline functions when
|
||||
building Python in debug mode with function inlining disabled. For example,
|
||||
MSC disables function inlining when building in debug mode.
|
||||
|
|
@ -145,15 +446,24 @@ complete listing.
|
|||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
.. c:macro:: Py_CHARMASK(c)
|
||||
.. c:macro:: Py_NO_INLINE
|
||||
|
||||
Argument must be a character or an integer in the range [-128, 127] or [0,
|
||||
255]. This macro returns ``c`` cast to an ``unsigned char``.
|
||||
Disable inlining on a function. For example, it reduces the C stack
|
||||
consumption: useful on LTO+PGO builds which heavily inline code (see
|
||||
:issue:`33720`).
|
||||
|
||||
Corresponds to the ``noinline`` attribute/specification on GCC and MSVC.
|
||||
|
||||
Usage::
|
||||
|
||||
Py_NO_INLINE static int random(void) { return 4; }
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
.. c:macro:: Py_DEPRECATED(version)
|
||||
|
||||
Use this for deprecated declarations. The macro must be placed before the
|
||||
symbol name.
|
||||
Use this to declare APIs that were deprecated in a specific CPython version.
|
||||
The macro must be placed before the symbol name.
|
||||
|
||||
Example::
|
||||
|
||||
|
|
@ -162,110 +472,153 @@ complete listing.
|
|||
.. versionchanged:: 3.8
|
||||
MSVC support was added.
|
||||
|
||||
.. c:macro:: Py_GETENV(s)
|
||||
.. c:macro:: Py_LOCAL(type)
|
||||
|
||||
Like ``getenv(s)``, but returns ``NULL`` if :option:`-E` was passed on the
|
||||
command line (see :c:member:`PyConfig.use_environment`).
|
||||
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 :samp:`static {type}`.
|
||||
|
||||
.. c:macro:: Py_MAX(x, y)
|
||||
.. c:macro:: Py_LOCAL_INLINE(type)
|
||||
|
||||
Return the maximum value between ``x`` and ``y``.
|
||||
Equivalent to :c:macro:`Py_LOCAL` but additionally requests the function
|
||||
be inlined.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
.. c:macro:: Py_LOCAL_SYMBOL
|
||||
|
||||
.. c:macro:: Py_MEMBER_SIZE(type, member)
|
||||
Macro used to declare a symbol as local to the shared library (hidden).
|
||||
On supported platforms, it ensures the symbol is not exported.
|
||||
|
||||
Return the size of a structure (``type``) ``member`` in bytes.
|
||||
On compatible versions of GCC/Clang, it
|
||||
expands to ``__attribute__((visibility("hidden")))``.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
.. c:macro:: Py_EXPORTED_SYMBOL
|
||||
|
||||
.. c:macro:: Py_MIN(x, y)
|
||||
Macro used to declare a symbol (function or data) as exported.
|
||||
On Windows, this expands to ``__declspec(dllexport)``.
|
||||
On compatible versions of GCC/Clang, it
|
||||
expands to ``__attribute__((visibility("default")))``.
|
||||
This macro is for defining the C API itself; extension modules should not use it.
|
||||
|
||||
Return the minimum value between ``x`` and ``y``.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
.. c:macro:: Py_IMPORTED_SYMBOL
|
||||
|
||||
.. c:macro:: Py_NO_INLINE
|
||||
Macro used to declare a symbol as imported.
|
||||
On Windows, this expands to ``__declspec(dllimport)``.
|
||||
This macro is for defining the C API itself; extension modules should not use it.
|
||||
|
||||
Disable inlining on a function. For example, it reduces the C stack
|
||||
consumption: useful on LTO+PGO builds which heavily inline code (see
|
||||
:issue:`33720`).
|
||||
|
||||
Usage::
|
||||
.. c:macro:: PyAPI_FUNC(type)
|
||||
|
||||
Py_NO_INLINE static int random(void) { return 4; }
|
||||
Macro used by CPython to declare a function as part of the C API.
|
||||
Its expansion depends on the platform and build configuration.
|
||||
This macro is intended for defining CPython's C API itself;
|
||||
extension modules should not use it for their own symbols.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
.. c:macro:: Py_STRINGIFY(x)
|
||||
.. c:macro:: PyAPI_DATA(type)
|
||||
|
||||
Convert ``x`` to a C string. E.g. ``Py_STRINGIFY(123)`` returns
|
||||
``"123"``.
|
||||
Macro used by CPython to declare a public global variable as part of the C API.
|
||||
Its expansion depends on the platform and build configuration.
|
||||
This macro is intended for defining CPython's C API itself;
|
||||
extension modules should not use it for their own symbols.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. c:macro:: Py_UNREACHABLE()
|
||||
Outdated macros
|
||||
---------------
|
||||
|
||||
Use this when you have a code path that cannot be reached by design.
|
||||
For example, in the ``default:`` clause in a ``switch`` statement for which
|
||||
all possible values are covered in ``case`` statements. Use this in places
|
||||
where you might be tempted to put an ``assert(0)`` or ``abort()`` call.
|
||||
The following :term:`soft deprecated` macros have been used to features that
|
||||
have been standardized in C11 (or previous standards).
|
||||
|
||||
In release mode, the macro helps the compiler to optimize the code, and
|
||||
avoids a warning about unreachable code. For example, the macro is
|
||||
implemented with ``__builtin_unreachable()`` on GCC in release mode.
|
||||
.. c:macro:: Py_ALIGNED(num)
|
||||
|
||||
A use for ``Py_UNREACHABLE()`` is following a call a function that
|
||||
never returns but that is not declared :c:macro:`_Py_NO_RETURN`.
|
||||
On some GCC-like compilers, specify alignment to *num* bytes.
|
||||
This does nothing on other compilers.
|
||||
|
||||
If a code path is very unlikely code but can be reached under exceptional
|
||||
case, this macro must not be used. For example, under low memory condition
|
||||
or if a system call returns a value out of the expected range. In this
|
||||
case, it's better to report the error to the caller. If the error cannot
|
||||
be reported to caller, :c:func:`Py_FatalError` can be used.
|
||||
Use the standard ``alignas`` specifier rather than this macro.
|
||||
|
||||
.. versionadded:: 3.7
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
.. c:macro:: Py_UNUSED(arg)
|
||||
.. c:macro:: PY_FORMAT_SIZE_T
|
||||
|
||||
Use this for unused arguments in a function definition to silence compiler
|
||||
warnings. Example: ``int func(int a, int Py_UNUSED(b)) { return a; }``.
|
||||
The :c:func:`printf` formatting modifier for :c:type:`size_t`.
|
||||
Use ``"z"`` directly instead.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
.. c:macro:: PyDoc_STRVAR(name, str)
|
||||
.. c:macro:: Py_LL(number)
|
||||
Py_ULL(number)
|
||||
|
||||
Creates a variable with name ``name`` that can be used in docstrings.
|
||||
If Python is built without docstrings, the value will be empty.
|
||||
Use *number* as a ``long long`` or ``unsigned long long`` integer literal,
|
||||
respectively.
|
||||
|
||||
Use :c:macro:`PyDoc_STRVAR` for docstrings to support building
|
||||
Python without docstrings, as specified in :pep:`7`.
|
||||
Expands to *number* followed by ``LL`` or ``LLU``, respectively, but will
|
||||
expand to some compiler-specific suffixes on some older compilers.
|
||||
|
||||
Example::
|
||||
Consider using the C99 standard suffixes ``LL`` and ``LLU`` directly.
|
||||
|
||||
PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element.");
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
static PyMethodDef deque_methods[] = {
|
||||
// ...
|
||||
{"pop", (PyCFunction)deque_pop, METH_NOARGS, pop_doc},
|
||||
// ...
|
||||
}
|
||||
.. c:macro:: PY_LONG_LONG
|
||||
PY_INT32_T
|
||||
PY_UINT32_T
|
||||
PY_INT64_T
|
||||
PY_UINT64_T
|
||||
|
||||
.. c:macro:: PyDoc_STR(str)
|
||||
Aliases for the types :c:type:`!long long`, :c:type:`!int32_t`,
|
||||
:c:type:`!uint32_t`. :c:type:`!int64_t` and :c:type:`!uint64_t`,
|
||||
respectively.
|
||||
Historically, these types needed compiler-specific extensions.
|
||||
|
||||
Creates a docstring for the given input string or an empty string
|
||||
if docstrings are disabled.
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
Use :c:macro:`PyDoc_STR` in specifying docstrings to support
|
||||
building Python without docstrings, as specified in :pep:`7`.
|
||||
.. c:macro:: PY_LLONG_MIN
|
||||
PY_LLONG_MAX
|
||||
PY_ULLONG_MAX
|
||||
PY_SIZE_MAX
|
||||
|
||||
Example::
|
||||
Aliases for the values :c:macro:`!LLONG_MIN`, :c:macro:`!LLONG_MAX`,
|
||||
:c:macro:`!ULLONG_MAX`, and :c:macro:`!SIZE_MAX`, respectively.
|
||||
Use these standard names instead.
|
||||
|
||||
static PyMethodDef pysqlite_row_methods[] = {
|
||||
{"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS,
|
||||
PyDoc_STR("Returns the keys of the row.")},
|
||||
{NULL, NULL}
|
||||
};
|
||||
The required header, ``<limits.h>``,
|
||||
:ref:`is included <capi-system-includes>` in ``Python.h``.
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
.. c:macro:: Py_MEMCPY(dest, src, n)
|
||||
|
||||
This is an alias to :c:func:`!memcpy`.
|
||||
|
||||
.. soft-deprecated:: 3.14
|
||||
Use :c:func:`!memcpy` directly instead.
|
||||
|
||||
.. c:macro:: Py_UNICODE_SIZE
|
||||
|
||||
Size of the :c:type:`!wchar_t` type.
|
||||
Use ``sizeof(wchar_t)`` or ``WCHAR_WIDTH/8`` instead.
|
||||
|
||||
The required header for the latter, ``<limits.h>``,
|
||||
:ref:`is included <capi-system-includes>` in ``Python.h``.
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
.. c:macro:: Py_UNICODE_WIDE
|
||||
|
||||
Defined if ``wchar_t`` can hold a Unicode character (UCS-4).
|
||||
Use ``sizeof(wchar_t) >= 4`` instead
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
.. c:macro:: Py_VA_COPY
|
||||
|
||||
This is an alias to the C99-standard ``va_copy`` function.
|
||||
|
||||
Historically, this would use a compiler-specific method to copy a ``va_list``.
|
||||
|
||||
.. versionchanged:: 3.6
|
||||
This is now an alias to ``va_copy``.
|
||||
|
||||
.. soft-deprecated:: 3.15
|
||||
|
||||
|
||||
.. _api-objects:
|
||||
|
|
|
|||
|
|
@ -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 and exception. *presult* is set to ``NULL``.
|
||||
- ``PYGEN_ERROR`` if iterator has raised an exception. *presult* is set to ``NULL``.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
|
|
|||
|
|
@ -50,3 +50,72 @@ 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.
|
||||
|
|
|
|||
|
|
@ -256,6 +256,8 @@ To allocate and free memory, see :ref:`allocating-objects`.
|
|||
collection (i.e., the :c:macro:`Py_TPFLAGS_HAVE_GC` flag is set); this may
|
||||
change in the future.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
|
||||
.. c:function:: int PyObject_CallFinalizerFromDealloc(PyObject *op)
|
||||
|
||||
|
|
@ -266,6 +268,8 @@ To allocate and free memory, see :ref:`allocating-objects`.
|
|||
should happen. Otherwise, this function returns 0 and destruction can
|
||||
continue normally.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. seealso::
|
||||
|
||||
:c:member:`~PyTypeObject.tp_dealloc` for example code.
|
||||
|
|
|
|||
|
|
@ -74,11 +74,25 @@ List Objects
|
|||
Like :c:func:`PyList_GetItemRef`, but returns a
|
||||
:term:`borrowed reference` instead of a :term:`strong reference`.
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, the returned
|
||||
:term:`borrowed reference` may become invalid if another thread modifies
|
||||
the list concurrently. Prefer :c:func:`PyList_GetItemRef`, which returns
|
||||
a :term:`strong reference`.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyList_GET_ITEM(PyObject *list, Py_ssize_t i)
|
||||
|
||||
Similar to :c:func:`PyList_GetItem`, but without error checking.
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, the returned
|
||||
:term:`borrowed reference` may become invalid if another thread modifies
|
||||
the list concurrently. Prefer :c:func:`PyList_GetItemRef`, which returns
|
||||
a :term:`strong reference`.
|
||||
|
||||
|
||||
.. c:function:: int PyList_SetItem(PyObject *list, Py_ssize_t index, PyObject *item)
|
||||
|
||||
|
|
@ -108,6 +122,14 @@ List Objects
|
|||
is being replaced; any reference in *list* at position *i* will be
|
||||
leaked.
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, this macro has no internal
|
||||
synchronization. It is normally only used to fill in new lists where no
|
||||
other thread has a reference to the list. If the list may be shared,
|
||||
use :c:func:`PyList_SetItem` instead, which uses a :term:`per-object
|
||||
lock`.
|
||||
|
||||
|
||||
.. c:function:: int PyList_Insert(PyObject *list, Py_ssize_t index, PyObject *item)
|
||||
|
||||
|
|
@ -138,6 +160,12 @@ List Objects
|
|||
Return ``0`` on success, ``-1`` on failure. Indexing from the end of the
|
||||
list is not supported.
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, when *itemlist* is a :class:`list`,
|
||||
both *list* and *itemlist* are locked for the duration of the operation.
|
||||
For other iterables (or ``NULL``), only *list* is locked.
|
||||
|
||||
|
||||
.. c:function:: int PyList_Extend(PyObject *list, PyObject *iterable)
|
||||
|
||||
|
|
@ -150,6 +178,14 @@ List Objects
|
|||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, when *iterable* is a :class:`list`,
|
||||
:class:`set`, :class:`dict`, or dict view, both *list* and *iterable*
|
||||
(or its underlying dict) are locked for the duration of the operation.
|
||||
For other iterables, only *list* is locked; *iterable* may be
|
||||
concurrently modified by another thread.
|
||||
|
||||
|
||||
.. c:function:: int PyList_Clear(PyObject *list)
|
||||
|
||||
|
|
@ -168,6 +204,14 @@ List Objects
|
|||
Sort the items of *list* in place. Return ``0`` on success, ``-1`` on
|
||||
failure. This is equivalent to ``list.sort()``.
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, element comparison via
|
||||
:meth:`~object.__lt__` can execute arbitrary Python code, during which
|
||||
the :term:`per-object lock` may be temporarily released. For built-in
|
||||
types (:class:`str`, :class:`int`, :class:`float`), the lock is not
|
||||
released during comparison.
|
||||
|
||||
|
||||
.. c:function:: int PyList_Reverse(PyObject *list)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ``256``. When you create an int in that range
|
||||
between ``-5`` and ``1024``. When you create an int in that range
|
||||
you actually just get back a reference to the existing object.
|
||||
|
||||
|
||||
|
|
@ -161,6 +161,17 @@ 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::
|
||||
|
|
@ -186,12 +197,10 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
|||
|
||||
.. c:function:: long PyLong_AS_LONG(PyObject *obj)
|
||||
|
||||
A :term:`soft deprecated` alias.
|
||||
Exactly equivalent to the preferred ``PyLong_AsLong``. In particular,
|
||||
it can fail with :exc:`OverflowError` or another exception.
|
||||
|
||||
.. deprecated:: 3.14
|
||||
The function is soft deprecated.
|
||||
.. soft-deprecated:: 3.14
|
||||
|
||||
.. c:function:: int PyLong_AsInt(PyObject *obj)
|
||||
|
||||
|
|
@ -442,8 +451,8 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
|
|||
|
||||
Otherwise, returns the number of bytes required to store the value.
|
||||
If this is equal to or less than *n_bytes*, the entire value was copied.
|
||||
All *n_bytes* of the buffer are written: large buffers are padded with
|
||||
zeroes.
|
||||
All *n_bytes* of the buffer are written: remaining bytes filled by
|
||||
copies of the sign bit.
|
||||
|
||||
If the returned value is greater than *n_bytes*, the value was
|
||||
truncated: as many of the lowest bits of the value as could fit are written,
|
||||
|
|
@ -575,6 +584,17 @@ 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*.
|
||||
|
|
@ -665,7 +685,7 @@ Export API
|
|||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. c:struct:: PyLongLayout
|
||||
.. c:type:: PyLongLayout
|
||||
|
||||
Layout of an array of "digits" ("limbs" in the GMP terminology), used to
|
||||
represent absolute value for arbitrary precision integers.
|
||||
|
|
@ -705,7 +725,7 @@ Export API
|
|||
|
||||
Get the native layout of Python :class:`int` objects.
|
||||
|
||||
See the :c:struct:`PyLongLayout` structure.
|
||||
See the :c:type:`PyLongLayout` structure.
|
||||
|
||||
The function must not be called before Python initialization nor after
|
||||
Python finalization. The returned layout is valid until Python is
|
||||
|
|
@ -713,7 +733,7 @@ Export API
|
|||
in a process, and so it can be cached.
|
||||
|
||||
|
||||
.. c:struct:: PyLongExport
|
||||
.. c:type:: PyLongExport
|
||||
|
||||
Export of a Python :class:`int` object.
|
||||
|
||||
|
|
@ -747,7 +767,7 @@ Export API
|
|||
|
||||
Export a Python :class:`int` object.
|
||||
|
||||
*export_long* must point to a :c:struct:`PyLongExport` structure allocated
|
||||
*export_long* must point to a :c:type:`PyLongExport` structure allocated
|
||||
by the caller. It must not be ``NULL``.
|
||||
|
||||
On success, fill in *\*export_long* and return ``0``.
|
||||
|
|
@ -777,7 +797,7 @@ The :c:type:`PyLongWriter` API can be used to import an integer.
|
|||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. c:struct:: PyLongWriter
|
||||
.. c:type:: PyLongWriter
|
||||
|
||||
A Python :class:`int` writer instance.
|
||||
|
||||
|
|
@ -805,7 +825,7 @@ The :c:type:`PyLongWriter` API can be used to import an integer.
|
|||
The layout of *digits* is described by :c:func:`PyLong_GetNativeLayout`.
|
||||
|
||||
Digits must be in the range [``0``; ``(1 << bits_per_digit) - 1``]
|
||||
(where the :c:struct:`~PyLongLayout.bits_per_digit` is the number of bits
|
||||
(where the :c:type:`~PyLongLayout.bits_per_digit` is the number of bits
|
||||
per digit).
|
||||
Any unused most significant digits must be set to ``0``.
|
||||
|
||||
|
|
@ -833,3 +853,31 @@ The :c:type:`PyLongWriter` API can be used to import an integer.
|
|||
If *writer* is ``NULL``, no operation is performed.
|
||||
|
||||
The writer instance and the *digits* array are invalid after the call.
|
||||
|
||||
|
||||
Deprecated API
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
These macros are :term:`soft deprecated`. They describe parameters
|
||||
of the internal representation of :c:type:`PyLongObject` instances.
|
||||
|
||||
Use :c:func:`PyLong_GetNativeLayout` instead, along with :c:func:`PyLong_Export`
|
||||
to read integer data or :c:type:`PyLongWriter` to write it.
|
||||
These currently use the same layout, but are designed to continue working correctly
|
||||
even if CPython's internal integer representation changes.
|
||||
|
||||
|
||||
.. c:macro:: PyLong_SHIFT
|
||||
|
||||
This is equivalent to :c:member:`~PyLongLayout.bits_per_digit` in
|
||||
the output of :c:func:`PyLong_GetNativeLayout`.
|
||||
|
||||
|
||||
.. c:macro:: PyLong_BASE
|
||||
|
||||
This is currently equivalent to :c:expr:`1 << PyLong_SHIFT`.
|
||||
|
||||
|
||||
.. c:macro:: PyLong_MASK
|
||||
|
||||
This is currently equivalent to :c:expr:`(1 << PyLong_SHIFT) - 1`
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and
|
|||
|
||||
.. note::
|
||||
|
||||
Exceptions which occur when this calls :meth:`~object.__getitem__`
|
||||
Exceptions which occur when this calls the :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 :meth:`~object.__getitem__`
|
||||
Exceptions that occur when this calls the :meth:`~object.__getitem__`
|
||||
method or while creating the temporary :class:`str`
|
||||
object are silently ignored.
|
||||
For proper error handling, use :c:func:`PyMapping_HasKeyStringWithError`,
|
||||
|
|
|
|||
|
|
@ -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 these variant if you are certain that you won't be reading
|
||||
file. Only use this 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`
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@
|
|||
Memory Management
|
||||
*****************
|
||||
|
||||
.. sectionauthor:: Vladimir Marangozov <Vladimir.Marangozov@inrialpes.fr>
|
||||
|
||||
|
||||
|
||||
.. _memoryoverview:
|
||||
|
||||
Overview
|
||||
|
|
@ -102,7 +98,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:`here <default-memory-allocators>`.
|
||||
table can be found at :ref:`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`.
|
||||
|
||||
|
|
@ -208,8 +204,11 @@ The following function sets, modeled after the ANSI C standard, but specifying
|
|||
behavior when requesting zero bytes, are available for allocating and releasing
|
||||
memory from the Python heap.
|
||||
|
||||
The :ref:`default memory allocator <default-memory-allocators>` uses the
|
||||
:ref:`pymalloc memory allocator <pymalloc>`.
|
||||
In the GIL-enabled build (default build) the
|
||||
:ref:`default memory allocator <default-memory-allocators>` uses the
|
||||
:ref:`pymalloc memory allocator <pymalloc>`, whereas in the
|
||||
:term:`free-threaded build`, the default is the
|
||||
:ref:`mimalloc memory allocator <mimalloc>` instead.
|
||||
|
||||
.. warning::
|
||||
|
||||
|
|
@ -219,6 +218,11 @@ The :ref:`default memory allocator <default-memory-allocators>` uses the
|
|||
|
||||
The default allocator is now pymalloc instead of system :c:func:`malloc`.
|
||||
|
||||
.. versionchanged:: 3.13
|
||||
|
||||
In the :term:`free-threaded <free threading>` build, the default allocator
|
||||
is now :ref:`mimalloc <mimalloc>`.
|
||||
|
||||
.. c:function:: void* PyMem_Malloc(size_t n)
|
||||
|
||||
Allocates *n* bytes and returns a pointer of type :c:expr:`void*` to the
|
||||
|
|
@ -293,17 +297,39 @@ The following type-oriented macros are provided for convenience. Note that
|
|||
|
||||
Same as :c:func:`PyMem_Free`.
|
||||
|
||||
In addition, the following macro sets are provided for calling the Python memory
|
||||
allocator directly, without involving the C API functions listed above. However,
|
||||
note that their use does not preserve binary compatibility across Python
|
||||
versions and is therefore deprecated in extension modules.
|
||||
|
||||
* ``PyMem_MALLOC(size)``
|
||||
* ``PyMem_NEW(type, size)``
|
||||
* ``PyMem_REALLOC(ptr, size)``
|
||||
* ``PyMem_RESIZE(ptr, type, size)``
|
||||
* ``PyMem_FREE(ptr)``
|
||||
* ``PyMem_DEL(ptr)``
|
||||
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
|
||||
* Corresponding function or macro
|
||||
* * .. c:macro:: PyMem_MALLOC(size)
|
||||
* :c:func:`PyMem_Malloc`
|
||||
* * .. c:macro:: PyMem_NEW(type, size)
|
||||
* :c:macro:`PyMem_New`
|
||||
* * .. c:macro:: PyMem_REALLOC(ptr, size)
|
||||
* :c:func:`PyMem_Realloc`
|
||||
* * .. c:macro:: PyMem_RESIZE(ptr, type, size)
|
||||
* :c:macro:`PyMem_Resize`
|
||||
* * .. c:macro:: PyMem_FREE(ptr)
|
||||
* :c:func:`PyMem_Free`
|
||||
* * .. c:macro:: PyMem_DEL(ptr)
|
||||
* :c:func:`PyMem_Free`
|
||||
|
||||
.. versionchanged:: 3.4
|
||||
|
||||
The macros are now aliases of the corresponding functions and macros.
|
||||
Previously, their behavior was the same, but their use did not necessarily
|
||||
preserve binary compatibility across Python versions.
|
||||
|
||||
.. deprecated:: 2.0
|
||||
|
||||
|
||||
.. _objectinterface:
|
||||
|
|
@ -322,7 +348,9 @@ memory from the Python heap.
|
|||
the :ref:`Customize Memory Allocators <customize-memory-allocators>` section.
|
||||
|
||||
The :ref:`default object allocator <default-memory-allocators>` uses the
|
||||
:ref:`pymalloc memory allocator <pymalloc>`.
|
||||
:ref:`pymalloc memory allocator <pymalloc>`. In the
|
||||
:term:`free-threaded <free threading>` build, the default is the
|
||||
:ref:`mimalloc memory allocator <mimalloc>` instead.
|
||||
|
||||
.. warning::
|
||||
|
||||
|
|
@ -402,14 +430,16 @@ Default Memory Allocators
|
|||
|
||||
Default memory allocators:
|
||||
|
||||
=============================== ==================== ================== ===================== ====================
|
||||
Configuration Name PyMem_RawMalloc PyMem_Malloc PyObject_Malloc
|
||||
=============================== ==================== ================== ===================== ====================
|
||||
Release build ``"pymalloc"`` ``malloc`` ``pymalloc`` ``pymalloc``
|
||||
Debug build ``"pymalloc_debug"`` ``malloc`` + debug ``pymalloc`` + debug ``pymalloc`` + debug
|
||||
Release build, without pymalloc ``"malloc"`` ``malloc`` ``malloc`` ``malloc``
|
||||
Debug build, without pymalloc ``"malloc_debug"`` ``malloc`` + debug ``malloc`` + debug ``malloc`` + debug
|
||||
=============================== ==================== ================== ===================== ====================
|
||||
=================================== ======================= ==================== ====================== ======================
|
||||
Configuration Name PyMem_RawMalloc PyMem_Malloc PyObject_Malloc
|
||||
=================================== ======================= ==================== ====================== ======================
|
||||
Release build ``"pymalloc"`` ``malloc`` ``pymalloc`` ``pymalloc``
|
||||
Debug build ``"pymalloc_debug"`` ``malloc`` + debug ``pymalloc`` + debug ``pymalloc`` + debug
|
||||
Release build, without pymalloc ``"malloc"`` ``malloc`` ``malloc`` ``malloc``
|
||||
Debug build, without pymalloc ``"malloc_debug"`` ``malloc`` + debug ``malloc`` + debug ``malloc`` + debug
|
||||
Free-threaded build ``"mimalloc"`` ``mimalloc`` ``mimalloc`` ``mimalloc``
|
||||
Free-threaded debug build ``"mimalloc_debug"`` ``mimalloc`` + debug ``mimalloc`` + debug ``mimalloc`` + debug
|
||||
=================================== ======================= ==================== ====================== ======================
|
||||
|
||||
Legend:
|
||||
|
||||
|
|
@ -417,8 +447,7 @@ Legend:
|
|||
* ``malloc``: system allocators from the standard C library, C functions:
|
||||
:c:func:`malloc`, :c:func:`calloc`, :c:func:`realloc` and :c:func:`free`.
|
||||
* ``pymalloc``: :ref:`pymalloc memory allocator <pymalloc>`.
|
||||
* ``mimalloc``: :ref:`mimalloc memory allocator <mimalloc>`. The pymalloc
|
||||
allocator will be used if mimalloc support isn't available.
|
||||
* ``mimalloc``: :ref:`mimalloc memory allocator <mimalloc>`.
|
||||
* "+ debug": with :ref:`debug hooks on the Python memory allocators
|
||||
<pymem-debug-hooks>`.
|
||||
* "Debug build": :ref:`Python build in debug mode <debug-build>`.
|
||||
|
|
@ -655,7 +684,11 @@ The pymalloc allocator
|
|||
Python has a *pymalloc* allocator optimized for small objects (smaller or equal
|
||||
to 512 bytes) with a short lifetime. It uses memory mappings called "arenas"
|
||||
with a fixed size of either 256 KiB on 32-bit platforms or 1 MiB on 64-bit
|
||||
platforms. It falls back to :c:func:`PyMem_RawMalloc` and
|
||||
platforms. When Python is configured with :option:`--with-pymalloc-hugepages`,
|
||||
the arena size on 64-bit platforms is increased to 2 MiB to match the huge page
|
||||
size, and arena allocation will attempt to use huge pages (``MAP_HUGETLB`` on
|
||||
Linux, ``MEM_LARGE_PAGES`` on Windows) with automatic fallback to regular pages.
|
||||
It falls back to :c:func:`PyMem_RawMalloc` and
|
||||
:c:func:`PyMem_RawRealloc` for allocations larger than 512 bytes.
|
||||
|
||||
*pymalloc* is the :ref:`default allocator <default-memory-allocators>` of the
|
||||
|
|
@ -711,9 +744,27 @@ The mimalloc allocator
|
|||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
Python supports the mimalloc allocator when the underlying platform support is available.
|
||||
mimalloc "is a general purpose allocator with excellent performance characteristics.
|
||||
Initially developed by Daan Leijen for the runtime systems of the Koka and Lean languages."
|
||||
Python supports the `mimalloc <https://github.com/microsoft/mimalloc/>`__
|
||||
allocator when the underlying platform support is available.
|
||||
mimalloc is a general purpose allocator with excellent performance
|
||||
characteristics, initially developed by Daan Leijen for the runtime systems
|
||||
of the Koka and Lean languages.
|
||||
|
||||
Unlike :ref:`pymalloc <pymalloc>`, which is optimized for small objects (512
|
||||
bytes or fewer), mimalloc handles allocations of any size.
|
||||
|
||||
In the :term:`free-threaded <free threading>` build, mimalloc is the default
|
||||
and **required** allocator for the :c:macro:`PYMEM_DOMAIN_MEM` and
|
||||
:c:macro:`PYMEM_DOMAIN_OBJ` domains. It cannot be disabled in free-threaded
|
||||
builds. The free-threaded build uses per-thread mimalloc heaps, which allows
|
||||
allocation and deallocation to proceed without locking in most cases.
|
||||
|
||||
In the default (non-free-threaded) build, mimalloc is available but not the
|
||||
default allocator. It can be selected at runtime using
|
||||
:envvar:`PYTHONMALLOC`\ ``=mimalloc`` (or ``mimalloc_debug`` to include
|
||||
:ref:`debug hooks <pymem-debug-hooks>`). It can be disabled at build time
|
||||
using the :option:`--without-mimalloc` configure option, but this option
|
||||
cannot be combined with :option:`--disable-gil`.
|
||||
|
||||
tracemalloc C API
|
||||
=================
|
||||
|
|
|
|||
|
|
@ -13,6 +13,12 @@ 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.
|
||||
|
|
|
|||
|
|
@ -3,17 +3,16 @@
|
|||
.. _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 ``types.ModuleType``.
|
||||
is exposed to Python programs as :py:class:`types.ModuleType`.
|
||||
|
||||
|
||||
.. c:function:: int PyModule_Check(PyObject *p)
|
||||
|
|
@ -71,6 +70,9 @@ 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)
|
||||
|
||||
|
|
@ -90,18 +92,19 @@ Module Objects
|
|||
Similar to :c:func:`PyModule_GetNameObject` but return the name encoded to
|
||||
``'utf-8'``.
|
||||
|
||||
.. 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`.
|
||||
|
||||
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:: 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)
|
||||
|
||||
|
|
@ -122,215 +125,119 @@ 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:
|
||||
.. _pymoduledef_slot:
|
||||
|
||||
Module definitions
|
||||
------------------
|
||||
Module definition
|
||||
-----------------
|
||||
|
||||
The functions in the previous section work on any module object, including
|
||||
modules imported from Python code.
|
||||
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.
|
||||
|
||||
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.
|
||||
.. versionchanged:: 3.15
|
||||
|
||||
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>`.
|
||||
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.
|
||||
|
||||
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.
|
||||
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>`.
|
||||
|
||||
.. c:type:: PyModuleDef
|
||||
Unless specified otherwise, the same slot ID may not be repeated
|
||||
in an array of slots.
|
||||
|
||||
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 values explained below.
|
||||
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.
|
||||
|
||||
.. 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:
|
||||
|
||||
.. c:macro:: Py_mod_create
|
||||
Metadata slots
|
||||
..............
|
||||
|
||||
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:macro:: Py_mod_name
|
||||
|
||||
.. c:function:: PyObject* create_module(PyObject *spec, PyModuleDef *def)
|
||||
:no-index-entry:
|
||||
:no-contents-entry:
|
||||
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for the name of the new module,
|
||||
as a NUL-terminated UTF8-encoded ``const char *``.
|
||||
|
||||
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``.
|
||||
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.
|
||||
|
||||
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.
|
||||
.. versionadded:: 3.15
|
||||
|
||||
Multiple ``Py_mod_create`` slots may not be specified in one module
|
||||
definition.
|
||||
Use :c:member:`PyModuleDef.m_name` instead to support previous versions.
|
||||
|
||||
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:macro:: Py_mod_doc
|
||||
|
||||
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``.
|
||||
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for the docstring of the new
|
||||
module, as a NUL-terminated UTF8-encoded ``const char *``.
|
||||
|
||||
.. c:macro:: Py_mod_exec
|
||||
Usually it is set to a variable created with :c:macro:`PyDoc_STRVAR`.
|
||||
|
||||
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:
|
||||
.. versionadded:: 3.15
|
||||
|
||||
.. c:function:: int exec_module(PyObject* module)
|
||||
:no-index-entry:
|
||||
:no-contents-entry:
|
||||
Use :c:member:`PyModuleDef.m_doc` instead to support previous versions.
|
||||
|
||||
If multiple ``Py_mod_exec`` slots are specified, they are processed in the
|
||||
order they appear in the *m_slots* array.
|
||||
|
||||
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`.
|
||||
|
||||
This slot is required, except for modules created from
|
||||
:c:struct:`PyModuleDef`.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
||||
.. c:macro:: Py_mod_multiple_interpreters
|
||||
|
||||
Specifies one of the following values:
|
||||
:c:type:`Slot ID <PyModuleDef_Slot.slot>` whose value is one of:
|
||||
|
||||
.. c:namespace:: NULL
|
||||
|
||||
|
|
@ -353,9 +260,6 @@ The available slot types are:
|
|||
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``.
|
||||
|
||||
|
|
@ -363,7 +267,7 @@ The available slot types are:
|
|||
|
||||
.. c:macro:: Py_mod_gil
|
||||
|
||||
Specifies one of the following values:
|
||||
:c:type:`Slot ID <PyModuleDef_Slot.slot>` whose value is one of:
|
||||
|
||||
.. c:namespace:: NULL
|
||||
|
||||
|
|
@ -381,45 +285,499 @@ The available slot types are:
|
|||
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
|
||||
|
||||
A pointer to a :c:struct:`PyABIInfo` structure that describes the ABI that
|
||||
the extension is using.
|
||||
Creation and initialization slots
|
||||
.................................
|
||||
|
||||
When the module is loaded, the :c:struct:`!PyABIInfo` in this slot is checked
|
||||
using :c:func:`PyABIInfo_Check`.
|
||||
.. c:macro:: Py_mod_create
|
||||
|
||||
A suitable :c:struct:`!PyABIInfo` variable can be defined using the
|
||||
:c:macro:`PyABIInfo_VAR` macro, as in:
|
||||
:c:type:`Slot ID <PyModuleDef_Slot.slot>` for a function that creates
|
||||
the module object itself.
|
||||
The function must have the signature:
|
||||
|
||||
.. code-block:: c
|
||||
.. c:function:: PyObject* create_module(PyObject *spec, PyModuleDef *def)
|
||||
:no-index-entry:
|
||||
:no-contents-entry:
|
||||
|
||||
PyABIInfo_VAR(abi_info);
|
||||
The function will be called with:
|
||||
|
||||
static PyModuleDef_Slot mymodule_slots[] = {
|
||||
{Py_mod_abi, &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).
|
||||
|
||||
.. 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 *module, Py_ssize_t *result)
|
||||
|
||||
Set *\*result* to the size of *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
|
||||
|
||||
|
||||
.. _moduledef-dynamic:
|
||||
|
||||
.. _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 overridden 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 token for *module* 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 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>`.
|
||||
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 with slot ID of 0
|
||||
(typically written as ``{0}`` or ``{0, NULL}`` in C).
|
||||
The array must include a :c:data:`Py_mod_abi` entry.
|
||||
|
||||
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 *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.
|
||||
|
||||
The struct, including all members, is part of the
|
||||
:ref:`Stable ABI <stable-abi>` for non-free-threaded builds (``abi3``).
|
||||
In the Stable ABI for free-threaded builds (``abi3t``),
|
||||
this struct is opaque, and unusable in practice; see :ref:`pymoduledef_slot`
|
||||
for a replacement.
|
||||
|
||||
.. 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`.
|
||||
|
||||
The struct is part of the :ref:`Stable ABI <stable-abi>` for
|
||||
non-free-threaded builds (``abi3``).
|
||||
In the Stable ABI for Free-Threaded Builds
|
||||
(``abi3t``), this struct is opaque, and unusable in practice.
|
||||
|
||||
.. 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.
|
||||
|
||||
If the array contains slots corresponding to :c:type:`PyModuleDef`
|
||||
members, the values must match.
|
||||
For example, if you use :c:macro:`Py_mod_name` in :c:member:`!m_slots`,
|
||||
:c:member:`PyModuleDef.m_name` must be set to the same pointer
|
||||
(not just an equal string).
|
||||
|
||||
.. 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 no longer called before the module state is allocated.
|
||||
|
||||
|
||||
.. c:var:: PyTypeObject PyModuleDef_Type
|
||||
|
||||
The type of ``PyModuleDef`` objects.
|
||||
|
||||
|
||||
.. _moduledef-dynamic:
|
||||
|
||||
The following API can be used to create modules from a :c:type:`!PyModuleDef`
|
||||
struct:
|
||||
|
||||
.. c:function:: PyObject* PyModule_Create(PyModuleDef *def)
|
||||
|
||||
|
|
@ -482,26 +840,30 @@ They are also used in
|
|||
.. versionadded:: 3.5
|
||||
|
||||
.. c:macro:: PYTHON_API_VERSION
|
||||
PYTHON_API_STRING
|
||||
|
||||
The C API version. Defined for backwards compatibility.
|
||||
The C API version, as an integer (``1013``) and string (``"1013"``), respectively.
|
||||
Defined for backwards compatibility.
|
||||
|
||||
Currently, this constant is not updated in new Python versions, and is not
|
||||
useful for versioning. This may change in the future.
|
||||
|
||||
.. c:macro:: PYTHON_ABI_VERSION
|
||||
PYTHON_ABI_STRING
|
||||
|
||||
Defined as ``3`` for backwards compatibility.
|
||||
Defined as ``3`` and ``"3"``, respectively, for backwards compatibility.
|
||||
|
||||
Currently, this constant is not updated in new Python versions, and is not
|
||||
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
|
||||
state.
|
||||
They are intended for a module's execution slots (:c:data:`Py_mod_exec`),
|
||||
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 initialization function for legacy :ref:`single-phase initialization <single-phase-initialization>`,
|
||||
or code that creates modules dynamically.
|
||||
|
||||
|
|
@ -603,9 +965,7 @@ or code that creates modules dynamically.
|
|||
// PyModule_AddObject() stole a reference to obj:
|
||||
// Py_XDECREF(obj) is not needed here.
|
||||
|
||||
.. deprecated:: 3.13
|
||||
|
||||
:c:func:`PyModule_AddObject` is :term:`soft deprecated`.
|
||||
.. soft-deprecated:: 3.13
|
||||
|
||||
|
||||
.. c:function:: int PyModule_AddIntConstant(PyObject *module, const char *name, long value)
|
||||
|
|
@ -667,6 +1027,9 @@ 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)
|
||||
|
|
@ -676,6 +1039,9 @@ or code that creates modules dynamically.
|
|||
``PyModuleDef`` (such as when using :ref:`multi-phase-initialization`,
|
||||
``PyModule_Create``, or ``PyModule_FromDefAndSpec``).
|
||||
|
||||
Return ``0`` on success.
|
||||
Return ``-1`` with an exception set on error.
|
||||
|
||||
.. versionadded:: 3.5
|
||||
|
||||
.. c:function:: int PyUnstable_Module_SetGIL(PyObject *module, void *gil)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
@ -205,6 +205,4 @@ would typically correspond to a python function.
|
|||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
.. deprecated:: 3.14
|
||||
|
||||
This function is :term:`soft deprecated`.
|
||||
.. soft-deprecated:: 3.14
|
||||
|
|
|
|||
|
|
@ -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 function would use the :func:`str` of the object
|
||||
If passed, these functions use the :func:`str` of the object
|
||||
instead of the :func:`repr`.
|
||||
|
||||
|
||||
|
|
@ -85,6 +85,35 @@ Object Protocol
|
|||
instead of the :func:`repr`.
|
||||
|
||||
|
||||
.. c:function:: void PyObject_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.
|
||||
|
|
@ -201,7 +230,7 @@ Object Protocol
|
|||
This case can arise from forgetting ``NULL`` checks and would delete the
|
||||
attribute.
|
||||
|
||||
.. versionchanged:: next
|
||||
.. versionchanged:: 3.15
|
||||
Must not be called with NULL value if an exception is set.
|
||||
|
||||
|
||||
|
|
@ -226,7 +255,7 @@ Object Protocol
|
|||
For more details, see :c:func:`PyUnicode_InternFromString`, which may be
|
||||
used internally to create a key object.
|
||||
|
||||
.. versionchanged:: next
|
||||
.. versionchanged:: 3.15
|
||||
Must not be called with NULL value if an exception is set.
|
||||
|
||||
|
||||
|
|
@ -334,6 +363,8 @@ Object Protocol
|
|||
representation on success, ``NULL`` on failure. This is the equivalent of the
|
||||
Python expression ``repr(o)``. Called by the :func:`repr` built-in function.
|
||||
|
||||
If argument is ``NULL``, return the string ``'<NULL>'``.
|
||||
|
||||
.. versionchanged:: 3.4
|
||||
This function now includes a debug assertion to help ensure that it
|
||||
does not silently discard an active exception.
|
||||
|
|
@ -348,6 +379,8 @@ Object Protocol
|
|||
a string similar to that returned by :c:func:`PyObject_Repr` in Python 2.
|
||||
Called by the :func:`ascii` built-in function.
|
||||
|
||||
If argument is ``NULL``, return the string ``'<NULL>'``.
|
||||
|
||||
.. index:: string; PyObject_Str (C function)
|
||||
|
||||
|
||||
|
|
@ -358,6 +391,8 @@ Object Protocol
|
|||
Python expression ``str(o)``. Called by the :func:`str` built-in function
|
||||
and, therefore, by the :func:`print` function.
|
||||
|
||||
If argument is ``NULL``, return the string ``'<NULL>'``.
|
||||
|
||||
.. versionchanged:: 3.4
|
||||
This function now includes a debug assertion to help ensure that it
|
||||
does not silently discard an active exception.
|
||||
|
|
@ -373,6 +408,8 @@ Object Protocol
|
|||
a TypeError is raised when *o* is an integer instead of a zero-initialized
|
||||
bytes object.
|
||||
|
||||
If argument is ``NULL``, return the :class:`bytes` object ``b'<NULL>'``.
|
||||
|
||||
|
||||
.. c:function:: int PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
||||
|
||||
|
|
@ -600,7 +637,7 @@ Object Protocol
|
|||
|
||||
Clear the managed dictionary of *obj*.
|
||||
|
||||
This function must only be called in a traverse function of the type which
|
||||
This function must only be called in a clear function of the type which
|
||||
has the :c:macro:`Py_TPFLAGS_MANAGED_DICT` flag set.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
|
@ -682,10 +719,10 @@ Object Protocol
|
|||
|
||||
:c:func:`PyUnstable_EnableTryIncRef` must have been called
|
||||
earlier on *obj* or this function may spuriously return ``0`` in the
|
||||
:term:`free threading` build.
|
||||
:term:`free-threaded build`.
|
||||
|
||||
This function is logically equivalent to the following C code, except that
|
||||
it behaves atomically in the :term:`free threading` build::
|
||||
it behaves atomically in the :term:`free-threaded build`::
|
||||
|
||||
if (Py_REFCNT(op) > 0) {
|
||||
Py_INCREF(op);
|
||||
|
|
@ -762,13 +799,30 @@ Object Protocol
|
|||
On GIL-enabled builds, this function is equivalent to
|
||||
:c:expr:`Py_REFCNT(op) == 1`.
|
||||
|
||||
On a :term:`free threaded <free threading>` build, this checks if *op*'s
|
||||
On a :term:`free-threaded build`, this checks if *op*'s
|
||||
:term:`reference count` is equal to one and additionally checks if *op*
|
||||
is only used by this thread. :c:expr:`Py_REFCNT(op) == 1` is **not**
|
||||
thread-safe on free threaded builds; prefer this function.
|
||||
thread-safe on free-threaded builds; prefer this function.
|
||||
|
||||
The caller must hold an :term:`attached thread state`, despite the fact
|
||||
that this function doesn't call into the Python interpreter. This function
|
||||
cannot fail.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
.. c:function:: int PyUnstable_SetImmortal(PyObject *op)
|
||||
|
||||
Marks the object *op* :term:`immortal`. The argument should be uniquely referenced by
|
||||
the calling thread. This is intended to be used for reducing reference counting contention
|
||||
in the :term:`free-threaded build` for objects which are shared across threads.
|
||||
|
||||
This is a one-way process: objects can only be made immortal; they cannot be
|
||||
made mortal once again. Immortal objects do not participate in reference counting
|
||||
and will never be garbage collected. If the object is GC-tracked, it is untracked.
|
||||
|
||||
This function is intended to be used soon after *op* is created, by the code that
|
||||
creates it, such as in the object's :c:member:`~PyTypeObject.tp_new` slot.
|
||||
Returns 1 if the object was made immortal and returns 0 if it was not.
|
||||
This function cannot fail.
|
||||
|
||||
.. versionadded:: 3.15
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ Note that holding an :term:`attached thread state` is not required for these API
|
|||
or ``-2`` on failure to create a lock. Check ``errno`` for more information
|
||||
about the cause of a failure.
|
||||
|
||||
.. c:function:: int PyUnstable_WritePerfMapEntry(const void *code_addr, unsigned int code_size, const char *entry_name)
|
||||
.. c:function:: int PyUnstable_WritePerfMapEntry(const void *code_addr, size_t code_size, const char *entry_name)
|
||||
|
||||
Write one single entry to the ``/tmp/perf-$pid.map`` file. This function is
|
||||
thread safe. Here is what an example entry looks like::
|
||||
|
|
|
|||
59
Doc/c-api/picklebuffer.rst
Normal file
59
Doc/c-api/picklebuffer.rst
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
.. 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.
|
||||
239
Doc/c-api/profiling.rst
Normal file
239
Doc/c-api/profiling.rst
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
.. highlight:: c
|
||||
|
||||
.. _profiling:
|
||||
|
||||
Profiling and tracing
|
||||
=====================
|
||||
|
||||
The Python interpreter provides some low-level support for attaching profiling
|
||||
and execution tracing facilities. These are used for profiling, debugging, and
|
||||
coverage analysis tools.
|
||||
|
||||
This C interface allows the profiling or tracing code to avoid the overhead of
|
||||
calling through Python-level callable objects, making a direct C function call
|
||||
instead. The essential attributes of the facility have not changed; the
|
||||
interface allows trace functions to be installed per-thread, and the basic
|
||||
events reported to the trace function are the same as had been reported to the
|
||||
Python-level trace functions in previous versions.
|
||||
|
||||
|
||||
.. c:type:: int (*Py_tracefunc)(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg)
|
||||
|
||||
The type of the trace function registered using :c:func:`PyEval_SetProfile` and
|
||||
:c:func:`PyEval_SetTrace`. The first parameter is the object passed to the
|
||||
registration function as *obj*, *frame* is the frame object to which the event
|
||||
pertains, *what* is one of the constants :c:data:`PyTrace_CALL`,
|
||||
:c:data:`PyTrace_EXCEPTION`, :c:data:`PyTrace_LINE`, :c:data:`PyTrace_RETURN`,
|
||||
:c:data:`PyTrace_C_CALL`, :c:data:`PyTrace_C_EXCEPTION`, :c:data:`PyTrace_C_RETURN`,
|
||||
or :c:data:`PyTrace_OPCODE`, and *arg* depends on the value of *what*:
|
||||
|
||||
+-------------------------------+----------------------------------------+
|
||||
| Value of *what* | Meaning of *arg* |
|
||||
+===============================+========================================+
|
||||
| :c:data:`PyTrace_CALL` | Always :c:data:`Py_None`. |
|
||||
+-------------------------------+----------------------------------------+
|
||||
| :c:data:`PyTrace_EXCEPTION` | Exception information as returned by |
|
||||
| | :func:`sys.exc_info`. |
|
||||
+-------------------------------+----------------------------------------+
|
||||
| :c:data:`PyTrace_LINE` | Always :c:data:`Py_None`. |
|
||||
+-------------------------------+----------------------------------------+
|
||||
| :c:data:`PyTrace_RETURN` | Value being returned to the caller, |
|
||||
| | or ``NULL`` if caused by an exception. |
|
||||
+-------------------------------+----------------------------------------+
|
||||
| :c:data:`PyTrace_C_CALL` | Function object being called. |
|
||||
+-------------------------------+----------------------------------------+
|
||||
| :c:data:`PyTrace_C_EXCEPTION` | Function object being called. |
|
||||
+-------------------------------+----------------------------------------+
|
||||
| :c:data:`PyTrace_C_RETURN` | Function object being called. |
|
||||
+-------------------------------+----------------------------------------+
|
||||
| :c:data:`PyTrace_OPCODE` | Always :c:data:`Py_None`. |
|
||||
+-------------------------------+----------------------------------------+
|
||||
|
||||
.. c:var:: int PyTrace_CALL
|
||||
|
||||
The value of the *what* parameter to a :c:type:`Py_tracefunc` function when a new
|
||||
call to a function or method is being reported, or a new entry into a generator.
|
||||
Note that the creation of the iterator for a generator function is not reported
|
||||
as there is no control transfer to the Python bytecode in the corresponding
|
||||
frame.
|
||||
|
||||
|
||||
.. c:var:: int PyTrace_EXCEPTION
|
||||
|
||||
The value of the *what* parameter to a :c:type:`Py_tracefunc` function when an
|
||||
exception has been raised. The callback function is called with this value for
|
||||
*what* when after any bytecode is processed after which the exception becomes
|
||||
set within the frame being executed. The effect of this is that as exception
|
||||
propagation causes the Python stack to unwind, the callback is called upon
|
||||
return to each frame as the exception propagates. Only trace functions receive
|
||||
these events; they are not needed by the profiler.
|
||||
|
||||
|
||||
.. c:var:: int PyTrace_LINE
|
||||
|
||||
The value passed as the *what* parameter to a :c:type:`Py_tracefunc` function
|
||||
(but not a profiling function) when a line-number event is being reported.
|
||||
It may be disabled for a frame by setting :attr:`~frame.f_trace_lines` to
|
||||
*0* on that frame.
|
||||
|
||||
|
||||
.. c:var:: int PyTrace_RETURN
|
||||
|
||||
The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a
|
||||
call is about to return.
|
||||
|
||||
|
||||
.. c:var:: int PyTrace_C_CALL
|
||||
|
||||
The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a C
|
||||
function is about to be called.
|
||||
|
||||
|
||||
.. c:var:: int PyTrace_C_EXCEPTION
|
||||
|
||||
The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a C
|
||||
function has raised an exception.
|
||||
|
||||
|
||||
.. c:var:: int PyTrace_C_RETURN
|
||||
|
||||
The value for the *what* parameter to :c:type:`Py_tracefunc` functions when a C
|
||||
function has returned.
|
||||
|
||||
|
||||
.. c:var:: int PyTrace_OPCODE
|
||||
|
||||
The value for the *what* parameter to :c:type:`Py_tracefunc` functions (but not
|
||||
profiling functions) when a new opcode is about to be executed. This event is
|
||||
not emitted by default: it must be explicitly requested by setting
|
||||
:attr:`~frame.f_trace_opcodes` to *1* on the frame.
|
||||
|
||||
|
||||
.. c:function:: void PyEval_SetProfile(Py_tracefunc func, PyObject *obj)
|
||||
|
||||
Set the profiler function to *func*. The *obj* parameter is passed to the
|
||||
function as its first parameter, and may be any Python object, or ``NULL``. If
|
||||
the profile function needs to maintain state, using a different value for *obj*
|
||||
for each thread provides a convenient and thread-safe place to store it. The
|
||||
profile function is called for all monitored events except :c:data:`PyTrace_LINE`
|
||||
:c:data:`PyTrace_OPCODE` and :c:data:`PyTrace_EXCEPTION`.
|
||||
|
||||
See also the :func:`sys.setprofile` function.
|
||||
|
||||
The caller must have an :term:`attached thread state`.
|
||||
|
||||
|
||||
.. c:function:: void PyEval_SetProfileAllThreads(Py_tracefunc func, PyObject *obj)
|
||||
|
||||
Like :c:func:`PyEval_SetProfile` but sets the profile function in all running threads
|
||||
belonging to the current interpreter instead of the setting it only on the current thread.
|
||||
|
||||
The caller must have an :term:`attached thread state`.
|
||||
|
||||
As :c:func:`PyEval_SetProfile`, this function ignores any exceptions raised while
|
||||
setting the profile functions in all threads.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
|
||||
.. c:function:: void PyEval_SetTrace(Py_tracefunc func, PyObject *obj)
|
||||
|
||||
Set the tracing function to *func*. This is similar to
|
||||
:c:func:`PyEval_SetProfile`, except the tracing function does receive line-number
|
||||
events and per-opcode events, but does not receive any event related to C function
|
||||
objects being called. Any trace function registered using :c:func:`PyEval_SetTrace`
|
||||
will not receive :c:data:`PyTrace_C_CALL`, :c:data:`PyTrace_C_EXCEPTION` or
|
||||
:c:data:`PyTrace_C_RETURN` as a value for the *what* parameter.
|
||||
|
||||
See also the :func:`sys.settrace` function.
|
||||
|
||||
The caller must have an :term:`attached thread state`.
|
||||
|
||||
|
||||
.. c:function:: void PyEval_SetTraceAllThreads(Py_tracefunc func, PyObject *obj)
|
||||
|
||||
Like :c:func:`PyEval_SetTrace` but sets the tracing function in all running threads
|
||||
belonging to the current interpreter instead of the setting it only on the current thread.
|
||||
|
||||
The caller must have an :term:`attached thread state`.
|
||||
|
||||
As :c:func:`PyEval_SetTrace`, this function ignores any exceptions raised while
|
||||
setting the trace functions in all threads.
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
|
||||
Reference tracing
|
||||
=================
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. c:type:: int (*PyRefTracer)(PyObject *, int event, void* data)
|
||||
|
||||
The type of the trace function registered using :c:func:`PyRefTracer_SetTracer`.
|
||||
The first parameter is a Python object that has been just created (when **event**
|
||||
is set to :c:data:`PyRefTracer_CREATE`) or about to be destroyed (when **event**
|
||||
is set to :c:data:`PyRefTracer_DESTROY`). The **data** argument is the opaque pointer
|
||||
that was provided when :c:func:`PyRefTracer_SetTracer` was called.
|
||||
|
||||
If a new tracing function is registered replacing the current one, a call to the
|
||||
trace function will be made with the object set to **NULL** and **event** set to
|
||||
:c:data:`PyRefTracer_TRACKER_REMOVED`. This will happen just before the new
|
||||
function is registered.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. c:var:: int PyRefTracer_CREATE
|
||||
|
||||
The value for the *event* parameter to :c:type:`PyRefTracer` functions when a Python
|
||||
object has been created.
|
||||
|
||||
|
||||
.. c:var:: int PyRefTracer_DESTROY
|
||||
|
||||
The value for the *event* parameter to :c:type:`PyRefTracer` functions when a Python
|
||||
object has been destroyed.
|
||||
|
||||
|
||||
.. c:var:: int PyRefTracer_TRACKER_REMOVED
|
||||
|
||||
The value for the *event* parameter to :c:type:`PyRefTracer` functions when the
|
||||
current tracer is about to be replaced by a new one.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
|
||||
.. c:function:: int PyRefTracer_SetTracer(PyRefTracer tracer, void *data)
|
||||
|
||||
Register a reference tracer function. The function will be called when a new
|
||||
Python object has been created or when an object is going to be destroyed. If
|
||||
**data** is provided it must be an opaque pointer that will be provided when
|
||||
the tracer function is called. Return ``0`` on success. Set an exception and
|
||||
return ``-1`` on error.
|
||||
|
||||
Note that tracer functions **must not** create Python objects inside or
|
||||
otherwise the call will be re-entrant. The tracer also **must not** clear
|
||||
any existing exception or set an exception. A :term:`thread state` will be active
|
||||
every time the tracer function is called.
|
||||
|
||||
There must be an :term:`attached thread state` when calling this function.
|
||||
|
||||
If another tracer function was already registered, the old function will be
|
||||
called with **event** set to :c:data:`PyRefTracer_TRACKER_REMOVED` just before
|
||||
the new function is registered.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. c:function:: PyRefTracer PyRefTracer_GetTracer(void** data)
|
||||
|
||||
Get the registered reference tracer function and the value of the opaque data
|
||||
pointer that was registered when :c:func:`PyRefTracer_SetTracer` was called.
|
||||
If no tracer was registered this function will return NULL and will set the
|
||||
**data** pointer to NULL.
|
||||
|
||||
There must be an :term:`attached thread state` when calling this function.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
|
@ -25,7 +25,7 @@ of Python objects.
|
|||
|
||||
.. note::
|
||||
|
||||
On :term:`free threaded <free threading>` builds of Python, returning 1
|
||||
On :term:`free-threaded builds <free-threaded build>` of Python, returning 1
|
||||
isn't sufficient to determine if it's safe to treat *o* as having no
|
||||
access by other threads. Use :c:func:`PyUnstable_Object_IsUniquelyReferenced`
|
||||
for that instead.
|
||||
|
|
|
|||
35
Doc/c-api/sentinel.rst
Normal file
35
Doc/c-api/sentinel.rst
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
.. highlight:: c
|
||||
|
||||
.. _sentinelobjects:
|
||||
|
||||
Sentinel objects
|
||||
----------------
|
||||
|
||||
.. c:var:: PyTypeObject PySentinel_Type
|
||||
|
||||
This instance of :c:type:`PyTypeObject` represents the Python
|
||||
:class:`sentinel` type. This is the same object as :class:`sentinel`.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. c:function:: int PySentinel_Check(PyObject *o)
|
||||
|
||||
Return true if *o* is a :class:`sentinel` object. The :class:`sentinel` type
|
||||
does not allow subclasses, so this check is exact.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. c:function:: PyObject* PySentinel_New(const char *name, const char *module_name)
|
||||
|
||||
Return a new :class:`sentinel` object with :attr:`~sentinel.__name__` set to
|
||||
*name* and :attr:`~sentinel.__module__` set to *module_name*.
|
||||
*name* must not be ``NULL``. If *module_name* is ``NULL``, :attr:`~sentinel.__module__`
|
||||
is set to ``None``.
|
||||
Return ``NULL`` with an exception set on failure.
|
||||
|
||||
For pickling to work, *module_name* must be the name of an importable
|
||||
module, and the sentinel must be accessible from that module under a
|
||||
path matching *name*. Pickle treats *name* as a global variable name
|
||||
in *module_name* (see :meth:`object.__reduce__`).
|
||||
|
||||
.. versionadded:: next
|
||||
|
|
@ -109,9 +109,8 @@ Sequence Protocol
|
|||
|
||||
Alias for :c:func:`PySequence_Contains`.
|
||||
|
||||
.. deprecated:: 3.14
|
||||
The function is :term:`soft deprecated` and should no longer be used to
|
||||
write new code.
|
||||
.. soft-deprecated:: 3.14
|
||||
The function should no longer be used to write new code.
|
||||
|
||||
|
||||
.. c:function:: Py_ssize_t PySequence_Index(PyObject *o, PyObject *value)
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@
|
|||
Set Objects
|
||||
-----------
|
||||
|
||||
.. sectionauthor:: Raymond D. Hettinger <python@rcn.com>
|
||||
|
||||
|
||||
.. index::
|
||||
pair: object; set
|
||||
pair: object; frozenset
|
||||
|
|
@ -92,6 +89,11 @@ the constructor functions work with any iterable Python object.
|
|||
actually iterable. The constructor is also useful for copying a set
|
||||
(``c=set(s)``).
|
||||
|
||||
.. note::
|
||||
|
||||
The operation is atomic on :term:`free threading <free-threaded build>`
|
||||
when *iterable* is a :class:`set`, :class:`frozenset`, :class:`dict` or :class:`frozendict`.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyFrozenSet_New(PyObject *iterable)
|
||||
|
||||
|
|
@ -100,6 +102,11 @@ the constructor functions work with any iterable Python object.
|
|||
set on success or ``NULL`` on failure. Raise :exc:`TypeError` if *iterable* is
|
||||
not actually iterable.
|
||||
|
||||
.. note::
|
||||
|
||||
The operation is atomic on :term:`free threading <free-threaded build>`
|
||||
when *iterable* is a :class:`set`, :class:`frozenset`, :class:`dict` or :class:`frozendict`.
|
||||
|
||||
|
||||
The following functions and macros are available for instances of :class:`set`
|
||||
or :class:`frozenset` or instances of their subtypes.
|
||||
|
|
@ -127,6 +134,10 @@ or :class:`frozenset` or instances of their subtypes.
|
|||
the *key* is unhashable. Raise :exc:`SystemError` if *anyset* is not a
|
||||
:class:`set`, :class:`frozenset`, or an instance of a subtype.
|
||||
|
||||
.. note::
|
||||
|
||||
The operation is atomic on :term:`free threading <free-threaded build>`
|
||||
when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`.
|
||||
|
||||
.. c:function:: int PySet_Add(PyObject *set, PyObject *key)
|
||||
|
||||
|
|
@ -138,6 +149,12 @@ or :class:`frozenset` or instances of their subtypes.
|
|||
:exc:`SystemError` if *set* is not an instance of :class:`set` or its
|
||||
subtype.
|
||||
|
||||
.. note::
|
||||
|
||||
The operation is atomic on :term:`free threading <free-threaded build>`
|
||||
when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`.
|
||||
|
||||
|
||||
|
||||
The following functions are available for instances of :class:`set` or its
|
||||
subtypes but not for instances of :class:`frozenset` or its subtypes.
|
||||
|
|
@ -147,11 +164,16 @@ 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:`~frozenset.discard`
|
||||
:exc:`TypeError` if the *key* is unhashable. Unlike the Python :meth:`~set.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.
|
||||
|
||||
.. note::
|
||||
|
||||
The operation is atomic on :term:`free threading <free-threaded build>`
|
||||
when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`.
|
||||
|
||||
|
||||
.. c:function:: PyObject* PySet_Pop(PyObject *set)
|
||||
|
||||
|
|
@ -166,3 +188,28 @@ subtypes but not for instances of :class:`frozenset` or its subtypes.
|
|||
Empty an existing set of all elements. Return ``0`` on
|
||||
success. Return ``-1`` and raise :exc:`SystemError` if *set* is not an instance of
|
||||
:class:`set` or its subtype.
|
||||
|
||||
.. note::
|
||||
|
||||
In the :term:`free-threaded build`, the set is emptied before its entries
|
||||
are cleared, so other threads will observe an empty set rather than
|
||||
intermediate states.
|
||||
|
||||
|
||||
Deprecated API
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:macro:: PySet_MINSIZE
|
||||
|
||||
A constant representing the size of an internal
|
||||
preallocated table inside :c:type:`PySetObject` instances.
|
||||
|
||||
This is documented solely for completeness, as there are no guarantees
|
||||
that a given version of CPython uses preallocated tables with a fixed
|
||||
size.
|
||||
In code that does not deal with unstable set internals,
|
||||
:c:macro:`!PySet_MINSIZE` can be replaced with a small constant like ``8``.
|
||||
|
||||
If looking for the size of a set, use :c:func:`PySet_Size` instead.
|
||||
|
||||
.. soft-deprecated:: 3.14
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue