Merge branch 'main' into fix-issue-42550

This commit is contained in:
IngridMorstrad 2025-05-30 02:58:08 -07:00 committed by GitHub
commit 7146d5b226
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
1201 changed files with 50215 additions and 17956 deletions

View file

@ -1,5 +1,5 @@
{
"image": "ghcr.io/python/devcontainer:2024.09.25.11038928730",
"image": "ghcr.io/python/devcontainer:2025.05.25.15232270922",
"onCreateCommand": [
// Install common tooling.
"dnf",

2
.gitattributes vendored
View file

@ -10,6 +10,7 @@
*.ico binary
*.jpg binary
*.pck binary
*.pdf binary
*.png binary
*.psd binary
*.tar binary
@ -67,6 +68,7 @@ PCbuild/readme.txt dos
**/clinic/*.cpp.h generated
**/clinic/*.h.h generated
*_db.h generated
Doc/c-api/lifecycle.dot.svg generated
Doc/data/stable_abi.dat generated
Doc/library/token-list.inc generated
Include/internal/pycore_ast.h generated

14
.github/CODEOWNERS vendored
View file

@ -188,7 +188,7 @@ Include/internal/pycore_time.h @pganssle @abalkin
# AST
Python/ast.c @isidentical @JelleZijlstra @eclips4
Python/ast_opt.c @isidentical @eclips4
Python/ast_preprocess.c @isidentical @eclips4
Parser/asdl.py @isidentical @JelleZijlstra @eclips4
Parser/asdl_c.py @isidentical @JelleZijlstra @eclips4
Lib/ast.py @isidentical @JelleZijlstra @eclips4
@ -298,7 +298,12 @@ Lib/test/test_interpreters/ @ericsnowcurrently
**/*-ios* @freakboy3742
# WebAssembly
/Tools/wasm/ @brettcannon @freakboy3742
Tools/wasm/config.site-wasm32-emscripten @freakboy3742
/Tools/wasm/README.md @brettcannon @freakboy3742
/Tools/wasm/wasi-env @brettcannon
/Tools/wasm/wasi.py @brettcannon
/Tools/wasm/emscripten @freakboy3742
/Tools/wasm/wasi @brettcannon
# SBOM
/Misc/externals.spdx.json @sethmlarson
@ -326,3 +331,8 @@ Modules/_xxtestfuzz/ @ammaraskar
**/*templateobject* @lysnikolaou
**/*templatelib* @lysnikolaou
**/*tstring* @lysnikolaou
# Remote debugging
Python/remote_debug.h @pablogsal
Python/remote_debugging.c @pablogsal
Modules/_remote_debugging_module.c @pablogsal @ambv @1st1

View file

@ -40,6 +40,7 @@ body:
- "3.12"
- "3.13"
- "3.14"
- "3.15"
- "CPython main branch"
validations:
required: true

View file

@ -33,6 +33,7 @@ body:
- "3.12"
- "3.13"
- "3.14"
- "3.15"
- "CPython main branch"
validations:
required: true

View file

@ -15,7 +15,13 @@ permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}-reusable
# https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#concurrency
# 'group' must be a key uniquely representing a PR or push event.
# github.workflow is the workflow name
# github.actor is the user invoking the workflow
# github.head_ref is the source branch of the PR or otherwise blank
# github.run_id is a unique number for the current run
group: ${{ github.workflow }}-${{ github.actor }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
env:

View file

@ -95,10 +95,10 @@ jobs:
with:
python-version: '3.11'
# PCbuild downloads LLVM automatically:
- name: Windows
if: runner.os == 'Windows'
run: |
choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}.1.0
./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }}
./PCbuild/rt.bat ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
@ -126,29 +126,30 @@ jobs:
make all --jobs 4
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
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
# 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

View file

@ -13,13 +13,18 @@ on:
- "Lib/test/libregrtest/**"
- "Lib/tomllib/**"
- "Misc/mypy/**"
- "Tools/build/compute-changes.py"
- "Tools/build/deepfreeze.py"
- "Tools/build/generate_sbom.py"
- "Tools/build/generate-build-details.py"
- "Tools/build/verify_ensurepip_wheels.py"
- "Tools/build/update_file.py"
- "Tools/build/umarshal.py"
- "Tools/cases_generator/**"
- "Tools/clinic/**"
- "Tools/jit/**"
- "Tools/peg_generator/**"
- "Tools/requirements-dev.txt"
- "Tools/wasm/**"
workflow_dispatch:
permissions:
@ -51,7 +56,6 @@ jobs:
"Tools/clinic",
"Tools/jit",
"Tools/peg_generator",
"Tools/wasm",
]
steps:
- uses: actions/checkout@v4

View file

@ -97,6 +97,9 @@ jobs:
run: python Tools/build/compute-changes.py
env:
GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
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

View file

@ -137,4 +137,3 @@ jobs:
CC=clang-20 ./configure --with-tail-call-interp --disable-gil
make all --jobs 4
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3

View file

@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.6
rev: v0.11.8
hooks:
- id: ruff
name: Run Ruff (lint) on Doc/
@ -22,14 +22,14 @@ repos:
name: Run Ruff (format) on Doc/
args: [--check]
files: ^Doc/
- id: ruff-format
name: Run Ruff (format) on Tools/build/check_warnings.py
args: [--check, --config=Tools/build/.ruff.toml]
files: ^Tools/build/check_warnings.py
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 25.1.0
hooks:
- id: black
name: Run Black on Tools/build/check_warnings.py
files: ^Tools/build/check_warnings.py
args: [--line-length=79]
- id: black
name: Run Black on Tools/jit/
files: ^Tools/jit/
@ -43,10 +43,14 @@ repos:
exclude: ^Lib/test/test_tomllib/
- id: check-yaml
- id: end-of-file-fixer
types: [python]
types_or: [python, yaml]
exclude: Lib/test/tokenizedata/coding20731.py
- id: end-of-file-fixer
files: '^\.github/CODEOWNERS$'
- id: trailing-whitespace
types_or: [c, inc, python, rst]
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.0

View file

@ -32,4 +32,3 @@ build:
- make -C Doc venv html
- mkdir _readthedocs
- mv Doc/build/html _readthedocs/html

View file

@ -16,7 +16,20 @@ Allocating Objects on the Heap
Initialize a newly allocated object *op* with its type and initial
reference. Returns the initialized object. Other fields of the object are
not affected.
not initialized. Despite its name, this function is unrelated to the
object's :meth:`~object.__init__` method (:c:member:`~PyTypeObject.tp_init`
slot). Specifically, this function does **not** call the object's
:meth:`!__init__` method.
In general, consider this function to be a low-level routine. Use
:c:member:`~PyTypeObject.tp_alloc` where possible.
For implementing :c:member:`!tp_alloc` for your type, prefer
:c:func:`PyType_GenericAlloc` or :c:func:`PyObject_New`.
.. note::
This function only initializes the object's memory corresponding to the
initial :c:type:`PyObject` structure. It does not zero the rest.
.. c:function:: PyVarObject* PyObject_InitVar(PyVarObject *op, PyTypeObject *type, Py_ssize_t size)
@ -24,38 +37,107 @@ Allocating Objects on the Heap
This does everything :c:func:`PyObject_Init` does, and also initializes the
length information for a variable-size object.
.. note::
This function only initializes some of the object's memory. It does not
zero the rest.
.. c:macro:: PyObject_New(TYPE, typeobj)
Allocate a new Python object using the C structure type *TYPE*
and the Python type object *typeobj* (``PyTypeObject*``).
Fields not defined by the Python object header are not initialized.
The caller will own the only reference to the object
(i.e. its reference count will be one).
The size of the memory allocation is determined from the
:c:member:`~PyTypeObject.tp_basicsize` field of the type object.
Allocates a new Python object using the C structure type *TYPE* and the
Python type object *typeobj* (``PyTypeObject*``) by calling
:c:func:`PyObject_Malloc` to allocate memory and initializing it like
:c:func:`PyObject_Init`. The caller will own the only reference to the
object (i.e. its reference count will be one).
Note that this function is unsuitable if *typeobj* has
:c:macro:`Py_TPFLAGS_HAVE_GC` set. For such objects,
use :c:func:`PyObject_GC_New` instead.
Avoid calling this directly to allocate memory for an object; call the type's
:c:member:`~PyTypeObject.tp_alloc` slot instead.
When populating a type's :c:member:`~PyTypeObject.tp_alloc` slot,
:c:func:`PyType_GenericAlloc` is preferred over a custom function that
simply calls this macro.
This macro does not call :c:member:`~PyTypeObject.tp_alloc`,
:c:member:`~PyTypeObject.tp_new` (:meth:`~object.__new__`), or
:c:member:`~PyTypeObject.tp_init` (:meth:`~object.__init__`).
This cannot be used for objects with :c:macro:`Py_TPFLAGS_HAVE_GC` set in
:c:member:`~PyTypeObject.tp_flags`; use :c:macro:`PyObject_GC_New` instead.
Memory allocated by this macro must be freed with :c:func:`PyObject_Free`
(usually called via the object's :c:member:`~PyTypeObject.tp_free` slot).
.. note::
The returned memory is not guaranteed to have been completely zeroed
before it was initialized.
.. note::
This macro does not construct a fully initialized object of the given
type; it merely allocates memory and prepares it for further
initialization by :c:member:`~PyTypeObject.tp_init`. To construct a
fully initialized object, call *typeobj* instead. For example::
PyObject *foo = PyObject_CallNoArgs((PyObject *)&PyFoo_Type);
.. seealso::
* :c:func:`PyObject_Free`
* :c:macro:`PyObject_GC_New`
* :c:func:`PyType_GenericAlloc`
* :c:member:`~PyTypeObject.tp_alloc`
.. c:macro:: PyObject_NewVar(TYPE, typeobj, size)
Allocate a new Python object using the C structure type *TYPE* and the
Python type object *typeobj* (``PyTypeObject*``).
Fields not defined by the Python object header
are not initialized. The allocated memory allows for the *TYPE* structure
plus *size* (``Py_ssize_t``) fields of the size
given by the :c:member:`~PyTypeObject.tp_itemsize` field of
*typeobj*. This is useful for implementing objects like tuples, which are
able to determine their size at construction time. Embedding the array of
fields into the same allocation decreases the number of allocations,
improving the memory management efficiency.
Like :c:macro:`PyObject_New` except:
Note that this function is unsuitable if *typeobj* has
:c:macro:`Py_TPFLAGS_HAVE_GC` set. For such objects,
use :c:func:`PyObject_GC_NewVar` instead.
* It allocates enough memory for the *TYPE* structure plus *size*
(``Py_ssize_t``) fields of the size given by the
:c:member:`~PyTypeObject.tp_itemsize` field of *typeobj*.
* The memory is initialized like :c:func:`PyObject_InitVar`.
This is useful for implementing objects like tuples, which are able to
determine their size at construction time. Embedding the array of fields
into the same allocation decreases the number of allocations, improving the
memory management efficiency.
Avoid calling this directly to allocate memory for an object; call the type's
:c:member:`~PyTypeObject.tp_alloc` slot instead.
When populating a type's :c:member:`~PyTypeObject.tp_alloc` slot,
:c:func:`PyType_GenericAlloc` is preferred over a custom function that
simply calls this macro.
This cannot be used for objects with :c:macro:`Py_TPFLAGS_HAVE_GC` set in
:c:member:`~PyTypeObject.tp_flags`; use :c:macro:`PyObject_GC_NewVar`
instead.
Memory allocated by this function must be freed with :c:func:`PyObject_Free`
(usually called via the object's :c:member:`~PyTypeObject.tp_free` slot).
.. note::
The returned memory is not guaranteed to have been completely zeroed
before it was initialized.
.. note::
This macro does not construct a fully initialized object of the given
type; it merely allocates memory and prepares it for further
initialization by :c:member:`~PyTypeObject.tp_init`. To construct a
fully initialized object, call *typeobj* instead. For example::
PyObject *list_instance = PyObject_CallNoArgs((PyObject *)&PyList_Type);
.. seealso::
* :c:func:`PyObject_Free`
* :c:macro:`PyObject_GC_NewVar`
* :c:func:`PyType_GenericAlloc`
* :c:member:`~PyTypeObject.tp_alloc`
.. c:function:: void PyObject_Del(void *op)
@ -71,6 +153,6 @@ Allocating Objects on the Heap
.. seealso::
:c:func:`PyModule_Create`
:ref:`moduleobjects`
To allocate and create extension modules.

View file

@ -274,7 +274,7 @@ small to receive the value.
Convert a Python integer to a C :c:expr:`unsigned long` without
overflow checking.
.. versionchanged:: next
.. versionchanged:: 3.14
Use :meth:`~object.__index__` if available.
``L`` (:class:`int`) [long long]
@ -284,7 +284,7 @@ small to receive the value.
Convert a Python integer to a C :c:expr:`unsigned long long`
without overflow checking.
.. versionchanged:: next
.. versionchanged:: 3.14
Use :meth:`~object.__index__` if available.
``n`` (:class:`int`) [:c:type:`Py_ssize_t`]
@ -380,10 +380,10 @@ Other objects
The *converter* for the ``O&`` format unit in *items* must not store
a borrowed buffer or a borrowed reference.
.. versionchanged:: next
.. versionchanged:: 3.14
:class:`str` and :class:`bytearray` objects no longer accepted as a sequence.
.. deprecated:: next
.. deprecated:: 3.14
Non-tuple sequences are deprecated if *items* contains format units
which store a borrowed buffer or a borrowed reference.
@ -396,7 +396,7 @@ Other objects
If the argument is not ``None``, it is parsed according to the specified
format unit.
.. versionadded:: next
.. versionadded:: 3.14
A few other characters have a meaning in a format string. These may not occur
inside nested parentheses. They are:

View file

@ -182,7 +182,7 @@ bound into a function.
Type of a code object watcher callback function.
If *event* is ``PY_CODE_EVENT_CREATE``, then the callback is invoked
after `co` has been fully initialized. Otherwise, the callback is invoked
after *co* has been fully initialized. Otherwise, the callback is invoked
before the destruction of *co* takes place, so the prior state of *co*
can be inspected.

View file

@ -169,7 +169,7 @@ There are a few functions specific to Python functions.
unpredictable effects, including infinite recursion.
If *event* is ``PyFunction_EVENT_CREATE``, then the callback is invoked
after `func` has been fully initialized. Otherwise, the callback is invoked
after *func* has been fully initialized. Otherwise, the callback is invoked
before the modification to *func* takes place, so the prior state of *func*
can be inspected. The runtime is permitted to optimize away the creation of
function objects when possible. In such cases no event will be emitted.

View file

@ -57,11 +57,49 @@ rules:
Analogous to :c:macro:`PyObject_New` but for container objects with the
:c:macro:`Py_TPFLAGS_HAVE_GC` flag set.
Do not call this directly to allocate memory for an object; call the type's
:c:member:`~PyTypeObject.tp_alloc` slot instead.
When populating a type's :c:member:`~PyTypeObject.tp_alloc` slot,
:c:func:`PyType_GenericAlloc` is preferred over a custom function that
simply calls this macro.
Memory allocated by this macro must be freed with
:c:func:`PyObject_GC_Del` (usually called via the object's
:c:member:`~PyTypeObject.tp_free` slot).
.. seealso::
* :c:func:`PyObject_GC_Del`
* :c:macro:`PyObject_New`
* :c:func:`PyType_GenericAlloc`
* :c:member:`~PyTypeObject.tp_alloc`
.. c:macro:: PyObject_GC_NewVar(TYPE, typeobj, size)
Analogous to :c:macro:`PyObject_NewVar` but for container objects with the
:c:macro:`Py_TPFLAGS_HAVE_GC` flag set.
Do not call this directly to allocate memory for an object; call the type's
:c:member:`~PyTypeObject.tp_alloc` slot instead.
When populating a type's :c:member:`~PyTypeObject.tp_alloc` slot,
:c:func:`PyType_GenericAlloc` is preferred over a custom function that
simply calls this macro.
Memory allocated by this macro must be freed with
:c:func:`PyObject_GC_Del` (usually called via the object's
:c:member:`~PyTypeObject.tp_free` slot).
.. seealso::
* :c:func:`PyObject_GC_Del`
* :c:macro:`PyObject_NewVar`
* :c:func:`PyType_GenericAlloc`
* :c:member:`~PyTypeObject.tp_alloc`
.. c:function:: PyObject* PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size)
Analogous to :c:macro:`PyObject_GC_New` but allocates *extra_size*
@ -73,6 +111,10 @@ rules:
The extra data will be deallocated with the object, but otherwise it is
not managed by Python.
Memory allocated by this function must be freed with
:c:func:`PyObject_GC_Del` (usually called via the object's
:c:member:`~PyTypeObject.tp_free` slot).
.. warning::
The function is marked as unstable because the final mechanism
for reserving extra data after an instance is not yet decided.
@ -136,6 +178,21 @@ rules:
Releases memory allocated to an object using :c:macro:`PyObject_GC_New` or
:c:macro:`PyObject_GC_NewVar`.
Do not call this directly to free an object's memory; call the type's
:c:member:`~PyTypeObject.tp_free` slot instead.
Do not use this for memory allocated by :c:macro:`PyObject_New`,
:c:macro:`PyObject_NewVar`, or related allocation functions; use
:c:func:`PyObject_Free` instead.
.. seealso::
* :c:func:`PyObject_Free` is the non-GC equivalent of this function.
* :c:macro:`PyObject_GC_New`
* :c:macro:`PyObject_GC_NewVar`
* :c:func:`PyType_GenericAlloc`
* :c:member:`~PyTypeObject.tp_free`
.. c:function:: void PyObject_GC_UnTrack(void *op)
@ -180,9 +237,9 @@ provided. In order to use this macro, the :c:member:`~PyTypeObject.tp_traverse`
must name its arguments exactly *visit* and *arg*:
.. c:function:: void Py_VISIT(PyObject *o)
.. c:macro:: Py_VISIT(o)
If *o* is not ``NULL``, call the *visit* callback, with arguments *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::

View file

@ -16,19 +16,6 @@ Importing Modules
This is a wrapper around :c:func:`PyImport_Import()` which takes a
:c:expr:`const char *` as an argument instead of a :c:expr:`PyObject *`.
.. c:function:: PyObject* PyImport_ImportModuleNoBlock(const char *name)
This function is a deprecated alias of :c:func:`PyImport_ImportModule`.
.. versionchanged:: 3.3
This function used to fail immediately when the import lock was held
by another thread. In Python 3.3 though, the locking scheme switched
to per-module locks for most purposes, so this function's special
behaviour isn't needed anymore.
.. deprecated-removed:: 3.13 3.15
Use :c:func:`PyImport_ImportModule` instead.
.. c:function:: PyObject* PyImport_ImportModuleEx(const char *name, PyObject *globals, PyObject *locals, PyObject *fromlist)

View file

@ -77,10 +77,7 @@ The following functions can be safely called before Python is initialized:
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:`Py_GetPath`,
:c:func:`Py_GetPrefix`, :c:func:`Py_GetExecPrefix`,
:c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome`,
:c:func:`Py_GetProgramName`, :c:func:`PyEval_InitThreads`, and
been initialized: :c:func:`Py_EncodeLocale`, :c:func:`PyEval_InitThreads`, and
:c:func:`Py_RunMain`.
@ -145,9 +142,6 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2.
:c:member:`PyConfig.pathconfig_warnings` should be used instead, see
:ref:`Python Initialization Configuration <init-config>`.
Suppress error messages when calculating the module search path in
:c:func:`Py_GetPath`.
Private flag used by ``_freeze_module`` and ``frozenmain`` programs.
.. deprecated-removed:: 3.12 3.15
@ -203,7 +197,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2.
Set by the :option:`-i` option.
.. deprecated:: 3.12
.. deprecated-removed:: 3.12 3.15
.. c:var:: int Py_IsolatedFlag
@ -586,7 +580,6 @@ Process-wide parameters
.. index::
single: Py_Initialize()
single: main()
single: Py_GetPath()
This API is kept for backward compatibility: setting
:c:member:`PyConfig.program_name` should be used instead, see :ref:`Python
@ -596,7 +589,7 @@ Process-wide parameters
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 :c:func:`Py_GetPath` and some other functions below to find
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
@ -609,146 +602,6 @@ Process-wide parameters
.. deprecated-removed:: 3.11 3.15
.. c:function:: wchar_t* Py_GetProgramName()
Return the program name set with :c:member:`PyConfig.program_name`, or the default.
The returned string points into static storage; the caller should not modify its
value.
This function should not be called before :c:func:`Py_Initialize`, otherwise
it returns ``NULL``.
.. versionchanged:: 3.10
It now returns ``NULL`` if called before :c:func:`Py_Initialize`.
.. deprecated-removed:: 3.13 3.15
Use :c:func:`PyConfig_Get("executable") <PyConfig_Get>`
(:data:`sys.executable`) instead.
.. c:function:: wchar_t* Py_GetPrefix()
Return the *prefix* for installed platform-independent files. This is derived
through a number of complicated rules from the program name set with
:c:member:`PyConfig.program_name` and some environment variables; for example, if the
program name is ``'/usr/local/bin/python'``, the prefix is ``'/usr/local'``. The
returned string points into static storage; the caller should not modify its
value. This corresponds to the :makevar:`prefix` variable in the top-level
:file:`Makefile` and the :option:`--prefix` argument to the :program:`configure`
script at build time. The value is available to Python code as ``sys.base_prefix``.
It is only useful on Unix. See also the next function.
This function should not be called before :c:func:`Py_Initialize`, otherwise
it returns ``NULL``.
.. versionchanged:: 3.10
It now returns ``NULL`` if called before :c:func:`Py_Initialize`.
.. deprecated-removed:: 3.13 3.15
Use :c:func:`PyConfig_Get("base_prefix") <PyConfig_Get>`
(:data:`sys.base_prefix`) instead. Use :c:func:`PyConfig_Get("prefix")
<PyConfig_Get>` (:data:`sys.prefix`) if :ref:`virtual environments
<venv-def>` need to be handled.
.. c:function:: wchar_t* Py_GetExecPrefix()
Return the *exec-prefix* for installed platform-*dependent* files. This is
derived through a number of complicated rules from the program name set with
:c:member:`PyConfig.program_name` and some environment variables; for example, if the
program name is ``'/usr/local/bin/python'``, the exec-prefix is
``'/usr/local'``. The returned string points into static storage; the caller
should not modify its value. This corresponds to the :makevar:`exec_prefix`
variable in the top-level :file:`Makefile` and the ``--exec-prefix``
argument to the :program:`configure` script at build time. The value is
available to Python code as ``sys.base_exec_prefix``. It is only useful on
Unix.
Background: The exec-prefix differs from the prefix when platform dependent
files (such as executables and shared libraries) are installed in a different
directory tree. In a typical installation, platform dependent files may be
installed in the :file:`/usr/local/plat` subtree while platform independent may
be installed in :file:`/usr/local`.
Generally speaking, a platform is a combination of hardware and software
families, e.g. Sparc machines running the Solaris 2.x operating system are
considered the same platform, but Intel machines running Solaris 2.x are another
platform, and Intel machines running Linux are yet another platform. Different
major revisions of the same operating system generally also form different
platforms. Non-Unix operating systems are a different story; the installation
strategies on those systems are so different that the prefix and exec-prefix are
meaningless, and set to the empty string. Note that compiled Python bytecode
files are platform independent (but not independent from the Python version by
which they were compiled!).
System administrators will know how to configure the :program:`mount` or
:program:`automount` programs to share :file:`/usr/local` between platforms
while having :file:`/usr/local/plat` be a different filesystem for each
platform.
This function should not be called before :c:func:`Py_Initialize`, otherwise
it returns ``NULL``.
.. versionchanged:: 3.10
It now returns ``NULL`` if called before :c:func:`Py_Initialize`.
.. deprecated-removed:: 3.13 3.15
Use :c:func:`PyConfig_Get("base_exec_prefix") <PyConfig_Get>`
(:data:`sys.base_exec_prefix`) instead. Use
:c:func:`PyConfig_Get("exec_prefix") <PyConfig_Get>`
(:data:`sys.exec_prefix`) if :ref:`virtual environments <venv-def>` need
to be handled.
.. c:function:: wchar_t* Py_GetProgramFullPath()
.. index::
single: executable (in module sys)
Return the full program name of the Python executable; this is computed as a
side-effect of deriving the default module search path from the program name
(set by :c:member:`PyConfig.program_name`). The returned string points into
static storage; the caller should not modify its value. The value is available
to Python code as ``sys.executable``.
This function should not be called before :c:func:`Py_Initialize`, otherwise
it returns ``NULL``.
.. versionchanged:: 3.10
It now returns ``NULL`` if called before :c:func:`Py_Initialize`.
.. deprecated-removed:: 3.13 3.15
Use :c:func:`PyConfig_Get("executable") <PyConfig_Get>`
(:data:`sys.executable`) instead.
.. c:function:: wchar_t* Py_GetPath()
.. index::
triple: module; search; path
single: path (in module sys)
Return the default module search path; this is computed from the program name
(set by :c:member:`PyConfig.program_name`) and some environment variables.
The returned string consists of a series of directory names separated by a
platform dependent delimiter character. The delimiter character is ``':'``
on Unix and macOS, ``';'`` on Windows. The returned string points into
static storage; the caller should not modify its value. The list
:data:`sys.path` is initialized with this value on interpreter startup; it
can be (and usually is) modified later to change the search path for loading
modules.
This function should not be called before :c:func:`Py_Initialize`, otherwise
it returns ``NULL``.
.. XXX should give the exact rules
.. versionchanged:: 3.10
It now returns ``NULL`` if called before :c:func:`Py_Initialize`.
.. deprecated-removed:: 3.13 3.15
Use :c:func:`PyConfig_Get("module_search_paths") <PyConfig_Get>`
(:data:`sys.path`) instead.
.. c:function:: const char* Py_GetVersion()
Return the version of this Python interpreter. This is a string that looks
@ -919,23 +772,6 @@ Process-wide parameters
.. deprecated-removed:: 3.11 3.15
.. c:function:: wchar_t* Py_GetPythonHome()
Return the default "home", that is, the value set by
:c:member:`PyConfig.home`, or the value of the :envvar:`PYTHONHOME`
environment variable if it is set.
This function should not be called before :c:func:`Py_Initialize`, otherwise
it returns ``NULL``.
.. versionchanged:: 3.10
It now returns ``NULL`` if called before :c:func:`Py_Initialize`.
.. deprecated-removed:: 3.13 3.15
Use :c:func:`PyConfig_Get("home") <PyConfig_Get>` or the
:envvar:`PYTHONHOME` environment variable instead.
.. _threads:
Thread State and the Global Interpreter Lock
@ -1083,8 +919,36 @@ Note that the ``PyGILState_*`` functions assume there is only one global
interpreter (created automatically by :c:func:`Py_Initialize`). Python
supports the creation of additional interpreters (using
:c:func:`Py_NewInterpreter`), but mixing multiple interpreters and the
``PyGILState_*`` API is unsupported.
``PyGILState_*`` API is unsupported. This is because :c:func:`PyGILState_Ensure`
and similar functions default to :term:`attaching <attached thread state>` a
:term:`thread state` for the main interpreter, meaning that the thread can't safely
interact with the calling subinterpreter.
Supporting subinterpreters in non-Python threads
------------------------------------------------
If you would like to support subinterpreters with non-Python created threads, you
must use the ``PyThreadState_*`` API instead of the traditional ``PyGILState_*``
API.
In particular, you must store the interpreter state from the calling
function and pass it to :c:func:`PyThreadState_New`, which will ensure that
the :term:`thread state` is targeting the correct interpreter::
/* The return value of PyInterpreterState_Get() from the
function that created this thread. */
PyInterpreterState *interp = ThreadData->interp;
PyThreadState *tstate = PyThreadState_New(interp);
PyThreadState_Swap(tstate);
/* GIL of the subinterpreter is now held.
Perform Python actions here. */
result = CallSomeFunction();
/* evaluate result or handle exception */
/* Destroy the thread state. No Python API allowed beyond this point. */
PyThreadState_Clear(tstate);
PyThreadState_DeleteCurrent();
.. _fork-and-threads:
@ -1261,6 +1125,10 @@ code, or when embedding the Python interpreter:
.. seealso:
:c:func:`PyEval_ReleaseThread`
.. note::
Similar to :c:func:`PyGILState_Ensure`, this function will hang the
thread if the runtime is finalizing.
The following functions use thread-local storage, and are not compatible
with sub-interpreters:
@ -1287,10 +1155,10 @@ with sub-interpreters:
When the function returns, there will be an :term:`attached thread state`
and the thread will be able to call arbitrary Python code. Failure is a fatal error.
.. note::
Calling this function from a thread when the runtime is finalizing will
hang the thread until the program exits, even if the thread was not
created by Python. Refer to
.. warning::
Calling this function when the runtime is finalizing is unsafe. Doing
so will either hang the thread until the program ends, or fully crash
the interpreter in rare cases. Refer to
:ref:`cautions-regarding-runtime-finalization` for more details.
.. versionchanged:: 3.14
@ -1307,7 +1175,6 @@ with sub-interpreters:
Every call to :c:func:`PyGILState_Ensure` must be matched by a call to
:c:func:`PyGILState_Release` on the same thread.
.. c:function:: PyThreadState* PyGILState_GetThisThreadState()
Get the :term:`attached thread state` for this thread. May return ``NULL`` if no
@ -1315,20 +1182,30 @@ with sub-interpreters:
always has such a thread-state, even if no auto-thread-state call has been
made on the main thread. This is mainly a helper/diagnostic function.
.. seealso: :c:func:`PyThreadState_Get``
.. note::
This function does not account for :term:`thread states <thread state>` created
by something other than :c:func:`PyGILState_Ensure` (such as :c:func:`PyThreadState_New`).
Prefer :c:func:`PyThreadState_Get` or :c:func:`PyThreadState_GetUnchecked`
for most cases.
.. seealso: :c:func:`PyThreadState_Get``
.. c:function:: int PyGILState_Check()
Return ``1`` if the current thread is holding the :term:`GIL` and ``0`` otherwise.
This function can be called from any thread at any time.
Only if it has had its Python thread state initialized and currently is
holding the :term:`GIL` will it return ``1``.
Only if it has had its :term:`thread state <attached thread state>` initialized
via :c:func:`PyGILState_Ensure` will it return ``1``.
This is mainly a helper/diagnostic function. It can be useful
for example in callback contexts or memory allocation functions when
knowing that the :term:`GIL` is locked can allow the caller to perform sensitive
actions or otherwise behave differently.
.. note::
If the current Python process has ever created a subinterpreter, this
function will *always* return ``1``. Prefer :c:func:`PyThreadState_GetUnchecked`
for most cases.
.. versionadded:: 3.4

View file

@ -363,7 +363,7 @@ Configuration Options
- Read-only
* - ``"import_time"``
- :c:member:`import_time <PyConfig.import_time>`
- ``bool``
- ``int``
- Read-only
* - ``"inspect"``
- :c:member:`inspect <PyConfig.inspect>`
@ -1477,13 +1477,19 @@ PyConfig
.. c:member:: int import_time
If non-zero, profile import time.
If ``1``, profile import time.
If ``2``, include additional output that indicates
when an imported module has already been loaded.
Set the ``1`` by the :option:`-X importtime <-X>` option and the
Set by the :option:`-X importtime <-X>` option and the
:envvar:`PYTHONPROFILEIMPORTTIME` environment variable.
Default: ``0``.
.. versionchanged:: 3.14
Added support for ``import_time = 2``
.. c:member:: int inspect
Enter interactive mode after executing a script or a command.
@ -2105,7 +2111,7 @@ initialization::
/* Specify sys.path explicitly */
/* If you want to modify the default set of paths, finish
initialization first and then use PySys_GetObject("path") */
initialization first and then use PySys_GetAttrString("path") */
config.module_search_paths_set = 1;
status = PyWideStringList_Append(&config.module_search_paths,
L"/path/to/stdlib");

View file

@ -127,7 +127,7 @@ complete listing.
item defined in the module file. Example::
static struct PyModuleDef spam_module = {
PyModuleDef_HEAD_INIT,
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "spam",
...
};
@ -135,7 +135,7 @@ complete listing.
PyMODINIT_FUNC
PyInit_spam(void)
{
return PyModule_Create(&spam_module);
return PyModuleDef_Init(&spam_module);
}
@ -779,20 +779,11 @@ found along :envvar:`PATH`.) The user can override this behavior by setting the
environment variable :envvar:`PYTHONHOME`, or insert additional directories in
front of the standard path by setting :envvar:`PYTHONPATH`.
.. index::
single: Py_GetPath (C function)
single: Py_GetPrefix (C function)
single: Py_GetExecPrefix (C function)
single: Py_GetProgramFullPath (C function)
The embedding application can steer the search by setting
:c:member:`PyConfig.program_name` *before* calling
:c:func:`Py_InitializeFromConfig`. Note that
:envvar:`PYTHONHOME` still overrides this and :envvar:`PYTHONPATH` is still
inserted in front of the standard path. An application that requires total
control has to provide its own implementation of :c:func:`Py_GetPath`,
:c:func:`Py_GetPrefix`, :c:func:`Py_GetExecPrefix`, and
:c:func:`Py_GetProgramFullPath` (all defined in :file:`Modules/getpath.c`).
inserted in front of the standard path.
.. index:: single: Py_IsInitialized (C function)
@ -826,14 +817,17 @@ frequently used builds will be described in the remainder of this section.
Compiling the interpreter with the :c:macro:`!Py_DEBUG` macro defined produces
what is generally meant by :ref:`a debug build of Python <debug-build>`.
:c:macro:`!Py_DEBUG` is enabled in the Unix build by adding
:option:`--with-pydebug` to the :file:`./configure` command.
It is also implied by the presence of the
not-Python-specific :c:macro:`!_DEBUG` macro. When :c:macro:`!Py_DEBUG` is enabled
in the Unix build, compiler optimization is disabled.
On Unix, :c:macro:`!Py_DEBUG` can be enabled by adding :option:`--with-pydebug`
to the :file:`./configure` command. This will also disable compiler optimization.
On Windows, selecting a debug build (e.g., by passing the :option:`-d` option to
:file:`PCbuild/build.bat`) automatically enables :c:macro:`!Py_DEBUG`.
Additionally, the presence of the not-Python-specific :c:macro:`!_DEBUG` macro,
when defined by the compiler, will also implicitly enable :c:macro:`!Py_DEBUG`.
In addition to the reference count debugging described below, extra checks are
performed, see :ref:`Python Debug Build <debug-build>`.
performed. See :ref:`Python Debug Build <debug-build>` for more details.
Defining :c:macro:`Py_TRACE_REFS` enables reference tracing
(see the :option:`configure --with-trace-refs option <--with-trace-refs>`).
@ -844,3 +838,41 @@ after every statement run by the interpreter.)
Please refer to :file:`Misc/SpecialBuilds.txt` in the Python source distribution
for more detailed information.
.. _c-api-tools:
Recommended third party tools
=============================
The following third party tools offer both simpler and more sophisticated
approaches to creating C, C++ and Rust extensions for Python:
* `Cython <https://cython.org/>`_
* `cffi <https://cffi.readthedocs.io>`_
* `HPy <https://hpyproject.org/>`_
* `nanobind <https://github.com/wjakob/nanobind>`_ (C++)
* `Numba <https://numba.pydata.org/>`_
* `pybind11 <https://pybind11.readthedocs.io/>`_ (C++)
* `PyO3 <https://pyo3.rs/>`_ (Rust)
* `SWIG <https://www.swig.org>`_
Using tools such as these can help avoid writing code that is tightly bound to
a particular version of CPython, avoid reference counting errors, and focus
more on your own code than on using the CPython API. In general, new versions
of Python can be supported by updating the tool, and your code will often use
newer and more efficient APIs automatically. Some tools also support compiling
for other implementations of Python from a single set of sources.
These projects are not supported by the same people who maintain Python, and
issues need to be raised with the projects directly. Remember to check that the
project is still maintained and supported, as the list above may become
outdated.
.. seealso::
`Python Packaging User Guide: Binary Extensions <https://packaging.python.org/guides/packaging-binary-extensions/>`_
The Python Packaging User Guide not only covers several available
tools that simplify the creation of binary extensions, but also
discusses the various reasons why creating an extension module may be
desirable in the first place.

156
Doc/c-api/lifecycle.dot Normal file
View file

@ -0,0 +1,156 @@
digraph "Life Events" {
graph [
fontnames="svg"
fontsize=12.0
id="life_events_graph"
layout="dot"
margin="0,0"
ranksep=0.25
stylesheet="lifecycle.dot.css"
]
node [
fontname="Courier"
fontsize=12.0
]
edge [
fontname="Times-Italic"
fontsize=12.0
]
"start" [fontname="Times-Italic" shape=plain label=< start > style=invis]
{
rank="same"
"tp_new" [href="typeobj.html#c.PyTypeObject.tp_new" target="_top"]
"tp_alloc" [href="typeobj.html#c.PyTypeObject.tp_alloc" target="_top"]
}
"tp_init" [href="typeobj.html#c.PyTypeObject.tp_init" target="_top"]
"reachable" [fontname="Times-Italic" shape=box]
"tp_traverse" [
href="typeobj.html#c.PyTypeObject.tp_traverse"
ordering="in"
target="_top"
]
"finalized?" [
fontname="Times-Italic"
label=<marked as<br/>finalized?>
ordering="in"
shape=diamond
tooltip="marked as finalized?"
]
"tp_finalize" [
href="typeobj.html#c.PyTypeObject.tp_finalize"
ordering="in"
target="_top"
]
"tp_clear" [href="typeobj.html#c.PyTypeObject.tp_clear" target="_top"]
"uncollectable" [
fontname="Times-Italic"
label=<uncollectable<br/>(leaked)>
shape=box
tooltip="uncollectable (leaked)"
]
"tp_dealloc" [
href="typeobj.html#c.PyTypeObject.tp_dealloc"
ordering="in"
target="_top"
]
"tp_free" [href="typeobj.html#c.PyTypeObject.tp_free" target="_top"]
"start" -> "tp_new" [
label=< type call >
]
"tp_new" -> "tp_alloc" [
label=< direct call > arrowhead=empty
labeltooltip="tp_new to tp_alloc: direct call"
tooltip="tp_new to tp_alloc: direct call"
]
"tp_new" -> "tp_init" [tooltip="tp_new to tp_init"]
"tp_init" -> "reachable" [tooltip="tp_init to reachable"]
"reachable" -> "tp_traverse" [
dir="back"
label=< not in a <br/> cyclic <br/> isolate >
labeltooltip="tp_traverse to reachable: not in a cyclic isolate"
tooltip="tp_traverse to reachable: not in a cyclic isolate"
]
"reachable" -> "tp_traverse" [
label=< periodic <br/> cyclic isolate <br/> detection >
labeltooltip="reachable to tp_traverse: periodic cyclic isolate detection"
tooltip="reachable to tp_traverse: periodic cyclic isolate detection"
]
"reachable" -> "tp_init" [tooltip="reachable to tp_init"]
"reachable" -> "tp_finalize" [
dir="back"
label=< resurrected <br/> (maybe remove <br/> finalized mark) >
labeltooltip="tp_finalize to reachable: resurrected (maybe remove finalized mark)"
tooltip="tp_finalize to reachable: resurrected (maybe remove finalized mark)"
]
"tp_traverse" -> "finalized?" [
label=< cyclic <br/> isolate >
labeltooltip="tp_traverse to finalized?: cyclic isolate"
tooltip="tp_traverse to finalized?: cyclic isolate"
]
"reachable" -> "finalized?" [
label=< no refs >
labeltooltip="reachable to finalized?: no refs"
tooltip="reachable to finalized?: no refs"
]
"finalized?" -> "tp_finalize" [
label=< no (mark <br/> as finalized) >
labeltooltip="finalized? to tp_finalize: no (mark as finalized)"
tooltip="finalized? to tp_finalize: no (mark as finalized)"
]
"finalized?" -> "tp_clear" [
label=< yes >
labeltooltip="finalized? to tp_clear: yes"
tooltip="finalized? to tp_clear: yes"
]
"tp_finalize" -> "tp_clear" [
label=< no refs or <br/> cyclic isolate >
labeltooltip="tp_finalize to tp_clear: no refs or cyclic isolate"
tooltip="tp_finalize to tp_clear: no refs or cyclic isolate"
]
"tp_finalize" -> "tp_dealloc" [
arrowtail=empty
dir="back"
href="lifecycle.html#c.PyObject_CallFinalizerFromDealloc"
style=dashed
label=< recommended<br/> call (see<br/> explanation)>
labeltooltip="tp_dealloc to tp_finalize: recommended call (see explanation)"
target="_top"
tooltip="tp_dealloc to tp_finalize: recommended call (see explanation)"
]
"tp_finalize" -> "tp_dealloc" [
label=< no refs >
labeltooltip="tp_finalize to tp_dealloc: no refs"
tooltip="tp_finalize to tp_dealloc: no refs"
]
"tp_clear" -> "tp_dealloc" [
label=< no refs >
labeltooltip="tp_clear to tp_dealloc: no refs"
tooltip="tp_clear to tp_dealloc: no refs"
]
"tp_clear" -> "uncollectable" [
label=< cyclic <br/> isolate >
labeltooltip="tp_clear to uncollectable: cyclic isolate"
tooltip="tp_clear to uncollectable: cyclic isolate"
]
"uncollectable" -> "tp_dealloc" [
style=invis
tooltip="uncollectable to tp_dealloc"
]
"reachable" -> "uncollectable" [
label=< cyclic <br/> isolate <br/> (no GC <br/> support) >
labeltooltip="reachable to uncollectable: cyclic isolate (no GC support)"
tooltip="reachable to uncollectable: cyclic isolate (no GC support)"
]
"reachable" -> "tp_dealloc" [
label=< no refs>
labeltooltip="reachable to tp_dealloc: no refs"
]
"tp_dealloc" -> "tp_free" [
arrowhead=empty
label=< direct call >
labeltooltip="tp_dealloc to tp_free: direct call"
tooltip="tp_dealloc to tp_free: direct call"
]
}

View file

@ -0,0 +1,21 @@
#life_events_graph {
--svg-fgcolor: currentcolor;
--svg-bgcolor: transparent;
}
#life_events_graph a {
color: inherit;
}
#life_events_graph [stroke="black"] {
stroke: var(--svg-fgcolor);
}
#life_events_graph text,
#life_events_graph [fill="black"] {
fill: var(--svg-fgcolor);
}
#life_events_graph [fill="white"] {
fill: var(--svg-bgcolor);
}
#life_events_graph [fill="none"] {
/* On links, setting fill will make the entire shape clickable */
fill: var(--svg-bgcolor);
}

BIN
Doc/c-api/lifecycle.dot.pdf Normal file

Binary file not shown.

374
Doc/c-api/lifecycle.dot.svg generated Normal file
View file

@ -0,0 +1,374 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet href="lifecycle.dot.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.0 (0)
-->
<!-- Title: Life Events Pages: 1 -->
<svg width="465pt" height="845pt"
viewBox="0.00 0.00 465.30 845.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="life_events_graph" class="graph" transform="scale(1 1) rotate(0) translate(4 841)">
<title>Life Events</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-841 461.3,-841 461.3,4 -4,4"/>
<!-- start -->
<!-- tp_new -->
<g id="life_events_graph_node2" class="node">
<title>tp_new</title>
<g id="a_life_events_graph_node2"><a xlink:href="typeobj.html#c.PyTypeObject.tp_new" xlink:title="tp_new" target="_top">
<ellipse fill="none" stroke="black" cx="192.8" cy="-772.5" rx="38.8" ry="18"/>
<text text-anchor="middle" x="192.8" y="-768.23" font-family="monospace,monospace" font-size="12.00">tp_new</text>
</a>
</g>
</g>
<!-- start&#45;&gt;tp_new -->
<g id="life_events_graph_edge1" class="edge">
<title>start&#45;&gt;tp_new</title>
<g id="a_life_events_graph_edge1"><a xlink:title="start to tp_new: type call">
<path fill="none" stroke="black" d="M192.8,-822.95C192.8,-817.85 192.8,-810.09 192.8,-802.22"/>
<polygon fill="black" stroke="black" points="196.3,-802.42 192.8,-792.42 189.3,-802.42 196.3,-802.42"/>
</a>
</g>
<g id="a_life_events_graph_edge1&#45;label"><a xlink:title="start to tp_new: type call">
<text text-anchor="start" x="192.8" y="-802.35" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;&#160;&#160;type call &#160;</text>
</a>
</g>
</g>
<!-- tp_alloc -->
<g id="life_events_graph_node3" class="node">
<title>tp_alloc</title>
<g id="a_life_events_graph_node3"><a xlink:href="typeobj.html#c.PyTypeObject.tp_alloc" xlink:title="tp_alloc" target="_top">
<ellipse fill="none" stroke="black" cx="373.8" cy="-772.5" rx="48.34" ry="18"/>
<text text-anchor="middle" x="373.8" y="-768.23" font-family="monospace,monospace" font-size="12.00">tp_alloc</text>
</a>
</g>
</g>
<!-- tp_new&#45;&gt;tp_alloc -->
<g id="life_events_graph_edge2" class="edge">
<title>tp_new&#45;&gt;tp_alloc</title>
<g id="a_life_events_graph_edge2"><a xlink:title="tp_new to tp_alloc: direct call">
<path fill="none" stroke="black" d="M232.07,-772.5C256,-772.5 287.05,-772.5 313.98,-772.5"/>
<polygon fill="none" stroke="black" points="313.73,-776 323.73,-772.5 313.73,-769 313.73,-776"/>
</a>
</g>
<g id="a_life_events_graph_edge2&#45;label"><a xlink:title="tp_new to tp_alloc: direct call">
<text text-anchor="start" x="240.65" y="-778.35" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;direct call &#160;</text>
</a>
</g>
</g>
<!-- tp_init -->
<g id="life_events_graph_node4" class="node">
<title>tp_init</title>
<g id="a_life_events_graph_node4"><a xlink:href="typeobj.html#c.PyTypeObject.tp_init" xlink:title="tp_init" target="_top">
<ellipse fill="none" stroke="black" cx="192.8" cy="-717.5" rx="43.57" ry="18"/>
<text text-anchor="middle" x="192.8" y="-713.23" font-family="monospace,monospace" font-size="12.00">tp_init</text>
</a>
</g>
</g>
<!-- tp_new&#45;&gt;tp_init -->
<g id="life_events_graph_edge3" class="edge">
<title>tp_new&#45;&gt;tp_init</title>
<g id="a_life_events_graph_edge3"><a xlink:title="tp_new to tp_init">
<path fill="none" stroke="black" d="M192.8,-754.15C192.8,-751.83 192.8,-749.42 192.8,-746.98"/>
<polygon fill="black" stroke="black" points="196.3,-747.23 192.8,-737.23 189.3,-747.23 196.3,-747.23"/>
</a>
</g>
</g>
<!-- reachable -->
<g id="life_events_graph_node5" class="node">
<title>reachable</title>
<polygon fill="none" stroke="black" points="230.8,-680.5 154.8,-680.5 154.8,-644.5 230.8,-644.5 230.8,-680.5"/>
<text text-anchor="middle" x="192.8" y="-658.23" font-family="serif,serif" font-style="italic" font-size="12.00">reachable</text>
</g>
<!-- tp_init&#45;&gt;reachable -->
<g id="life_events_graph_edge4" class="edge">
<title>tp_init&#45;&gt;reachable</title>
<g id="a_life_events_graph_edge4"><a xlink:title="tp_init to reachable">
<path fill="none" stroke="black" d="M186.44,-699.44C186.24,-697.12 186.11,-694.69 186.07,-692.24"/>
<polygon fill="black" stroke="black" points="189.56,-692.51 186.37,-682.41 182.56,-692.29 189.56,-692.51"/>
</a>
</g>
</g>
<!-- reachable&#45;&gt;tp_init -->
<g id="life_events_graph_edge7" class="edge">
<title>reachable&#45;&gt;tp_init</title>
<g id="a_life_events_graph_edge7"><a xlink:title="reachable to tp_init">
<path fill="none" stroke="black" d="M199.18,-680.89C199.37,-683.22 199.49,-685.65 199.53,-688.11"/>
<polygon fill="black" stroke="black" points="196.04,-687.81 199.2,-697.93 203.04,-688.05 196.04,-687.81"/>
</a>
</g>
</g>
<!-- tp_traverse -->
<g id="life_events_graph_node6" class="node">
<title>tp_traverse</title>
<g id="a_life_events_graph_node6"><a xlink:href="typeobj.html#c.PyTypeObject.tp_traverse" xlink:title="tp_traverse" target="_top">
<ellipse fill="none" stroke="black" cx="136.8" cy="-565.75" rx="62.65" ry="18"/>
<text text-anchor="middle" x="136.8" y="-561.48" font-family="monospace,monospace" font-size="12.00">tp_traverse</text>
</a>
</g>
</g>
<!-- reachable&#45;&gt;tp_traverse -->
<g id="life_events_graph_edge5" class="edge">
<title>reachable&#45;&gt;tp_traverse</title>
<g id="a_life_events_graph_edge5"><a xlink:title="tp_traverse to reachable: not in a cyclic isolate">
<path fill="none" stroke="black" d="M143.43,-658.77C108.3,-655.68 65.38,-649.16 54.05,-635.5 41.91,-620.88 42.8,-608.07 54.05,-592.75 60.55,-583.89 70.07,-577.97 80.37,-574.03"/>
<polygon fill="black" stroke="black" points="142.76,-662.23 153.01,-659.54 143.32,-655.25 142.76,-662.23"/>
</a>
</g>
<g id="a_life_events_graph_edge5&#45;label"><a xlink:title="tp_traverse to reachable: not in a cyclic isolate">
<text text-anchor="start" x="54.05" y="-624.1" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;not in a &#160;</text>
<text text-anchor="start" x="59.67" y="-609.85" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;cyclic &#160;</text>
<text text-anchor="start" x="57.05" y="-595.6" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;isolate &#160;</text>
</a>
</g>
</g>
<!-- reachable&#45;&gt;tp_traverse -->
<g id="life_events_graph_edge6" class="edge">
<title>reachable&#45;&gt;tp_traverse</title>
<g id="a_life_events_graph_edge6"><a xlink:title="reachable to tp_traverse: periodic cyclic isolate detection">
<path fill="none" stroke="black" d="M154.41,-650.07C147.94,-646.44 142.04,-641.69 138.05,-635.5 130.52,-623.82 129.57,-608.56 130.79,-595.38"/>
<polygon fill="black" stroke="black" points="134.25,-595.91 132.17,-585.52 127.31,-594.94 134.25,-595.91"/>
</a>
</g>
<g id="a_life_events_graph_edge6&#45;label"><a xlink:title="reachable to tp_traverse: periodic cyclic isolate detection">
<text text-anchor="start" x="154.17" y="-624.1" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;periodic &#160;</text>
<text text-anchor="start" x="138.05" y="-609.85" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;cyclic isolate &#160;&#160;</text>
<text text-anchor="start" x="151.17" y="-595.6" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;detection &#160;</text>
</a>
</g>
</g>
<!-- finalized? -->
<g id="life_events_graph_node7" class="node">
<title>finalized?</title>
<g id="a_life_events_graph_node7"><a xlink:title="marked as finalized?">
<polygon fill="none" stroke="black" points="191.8,-487 112.05,-450.5 191.8,-414 271.55,-450.5 191.8,-487"/>
<text text-anchor="start" x="159.92" y="-453.35" font-family="serif,serif" font-style="italic" font-size="12.00">marked as</text>
<text text-anchor="start" x="162.92" y="-439.1" font-family="serif,serif" font-style="italic" font-size="12.00">finalized?</text>
</a>
</g>
</g>
<!-- reachable&#45;&gt;finalized? -->
<g id="life_events_graph_edge10" class="edge">
<title>reachable&#45;&gt;finalized?</title>
<g id="a_life_events_graph_edge10"><a xlink:title="reachable to finalized?: no refs">
<path fill="none" stroke="black" d="M227.72,-644.32C230.51,-641.73 232.96,-638.8 234.8,-635.5 244.04,-618.9 235.48,-611.74 234.8,-592.75 233.24,-549.67 243.64,-536.1 227.8,-496 226.37,-492.38 224.53,-488.82 222.45,-485.4"/>
<polygon fill="black" stroke="black" points="225.47,-483.62 216.91,-477.39 219.72,-487.61 225.47,-483.62"/>
</a>
</g>
<g id="a_life_events_graph_edge10&#45;label"><a xlink:title="reachable to finalized?: no refs">
<text text-anchor="start" x="236.45" y="-561.48" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;no refs &#160;</text>
</a>
</g>
</g>
<!-- tp_finalize -->
<g id="life_events_graph_node8" class="node">
<title>tp_finalize</title>
<g id="a_life_events_graph_node8"><a xlink:href="typeobj.html#c.PyTypeObject.tp_finalize" xlink:title="tp_finalize" target="_top">
<ellipse fill="none" stroke="black" cx="122.8" cy="-321" rx="62.65" ry="18"/>
<text text-anchor="middle" x="122.8" y="-316.73" font-family="monospace,monospace" font-size="12.00">tp_finalize</text>
</a>
</g>
</g>
<!-- reachable&#45;&gt;tp_finalize -->
<g id="life_events_graph_edge8" class="edge">
<title>reachable&#45;&gt;tp_finalize</title>
<g id="a_life_events_graph_edge8"><a xlink:title="tp_finalize to reachable: resurrected (maybe remove finalized mark)">
<path fill="none" stroke="black" d="M142.86,-659.6C103.8,-656.96 53.97,-650.63 40.8,-635.5 -37.32,-545.75 69.61,-390.31 109.14,-338.99"/>
<polygon fill="black" stroke="black" points="142.62,-663.09 152.82,-660.2 143.05,-656.11 142.62,-663.09"/>
</a>
</g>
<g id="a_life_events_graph_edge8&#45;label"><a xlink:title="tp_finalize to reachable: resurrected (maybe remove finalized mark)">
<text text-anchor="start" x="33.68" y="-527.35" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;resurrected &#160;</text>
<text text-anchor="start" x="22.43" y="-513.1" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;(maybe remove &#160;</text>
<text text-anchor="start" x="23.18" y="-498.85" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;finalized mark) &#160;</text>
</a>
</g>
</g>
<!-- uncollectable -->
<g id="life_events_graph_node10" class="node">
<title>uncollectable</title>
<g id="a_life_events_graph_node10"><a xlink:title="uncollectable (leaked)">
<polygon fill="none" stroke="black" points="371.92,-159.75 275.67,-159.75 275.67,-123.25 371.92,-123.25 371.92,-159.75"/>
<text text-anchor="start" x="283.67" y="-144.35" font-family="serif,serif" font-style="italic" font-size="12.00">uncollectable</text>
<text text-anchor="start" x="299.42" y="-130.1" font-family="serif,serif" font-style="italic" font-size="12.00">(leaked)</text>
</a>
</g>
</g>
<!-- reachable&#45;&gt;uncollectable -->
<g id="life_events_graph_edge19" class="edge">
<title>reachable&#45;&gt;uncollectable</title>
<g id="a_life_events_graph_edge19"><a xlink:title="reachable to uncollectable: cyclic isolate (no GC support)">
<path fill="none" stroke="black" d="M231.2,-652.03C270.79,-639.69 326.8,-613.9 326.8,-566.75 326.8,-566.75 326.8,-566.75 326.8,-237.5 326.8,-215.3 325.97,-190.2 325.18,-171.37"/>
<polygon fill="black" stroke="black" points="328.68,-171.35 324.75,-161.52 321.69,-171.66 328.68,-171.35"/>
</a>
</g>
<g id="a_life_events_graph_edge19&#45;label"><a xlink:title="reachable to uncollectable: cyclic isolate (no GC support)">
<text text-anchor="start" x="335.05" y="-393.6" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;cyclic &#160;</text>
<text text-anchor="start" x="332.42" y="-379.35" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;isolate &#160;</text>
<text text-anchor="start" x="331.3" y="-365.1" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;(no GC &#160;</text>
<text text-anchor="start" x="326.8" y="-350.85" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;support) &#160;</text>
</a>
</g>
</g>
<!-- tp_dealloc -->
<g id="life_events_graph_node11" class="node">
<title>tp_dealloc</title>
<g id="a_life_events_graph_node11"><a xlink:href="typeobj.html#c.PyTypeObject.tp_dealloc" xlink:title="tp_dealloc" target="_top">
<ellipse fill="none" stroke="black" cx="200.8" cy="-86.25" rx="57.88" ry="18"/>
<text text-anchor="middle" x="200.8" y="-81.97" font-family="monospace,monospace" font-size="12.00">tp_dealloc</text>
</a>
</g>
</g>
<!-- reachable&#45;&gt;tp_dealloc -->
<g id="life_events_graph_edge20" class="edge">
<title>reachable&#45;&gt;tp_dealloc</title>
<path fill="none" stroke="black" d="M231.23,-661.18C293.08,-658.43 407.8,-643.03 407.8,-566.75 407.8,-566.75 407.8,-566.75 407.8,-140.5 407.8,-111.22 329.12,-97.8 268.77,-91.82"/>
<polygon fill="black" stroke="black" points="269.15,-88.34 258.87,-90.89 268.5,-95.31 269.15,-88.34"/>
<g id="a_life_events_graph_edge20&#45;label"><a xlink:title="reachable to tp_dealloc: no refs">
<text text-anchor="start" x="407.8" y="-316.73" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;no refs</text>
</a>
</g>
</g>
<!-- tp_traverse&#45;&gt;finalized? -->
<g id="life_events_graph_edge9" class="edge">
<title>tp_traverse&#45;&gt;finalized?</title>
<g id="a_life_events_graph_edge9"><a xlink:title="tp_traverse to finalized?: cyclic isolate">
<path fill="none" stroke="black" d="M145.15,-547.55C152.4,-532.62 163.18,-510.43 172.55,-491.13"/>
<polygon fill="black" stroke="black" points="175.7,-492.66 176.92,-482.14 169.4,-489.61 175.7,-492.66"/>
</a>
</g>
<g id="a_life_events_graph_edge9&#45;label"><a xlink:title="tp_traverse to finalized?: cyclic isolate">
<text text-anchor="start" x="171.85" y="-520.23" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;cyclic &#160;</text>
<text text-anchor="start" x="169.22" y="-505.98" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;isolate &#160;</text>
</a>
</g>
</g>
<!-- finalized?&#45;&gt;tp_finalize -->
<g id="life_events_graph_edge11" class="edge">
<title>finalized?&#45;&gt;tp_finalize</title>
<g id="a_life_events_graph_edge11"><a xlink:title="finalized? to tp_finalize: no (mark as finalized)">
<path fill="none" stroke="black" d="M172.89,-422.6C169.14,-416.89 165.34,-410.82 162.05,-405 151.89,-387.08 141.99,-366.11 134.68,-349.73"/>
<polygon fill="black" stroke="black" points="137.89,-348.35 130.66,-340.61 131.48,-351.17 137.89,-348.35"/>
</a>
</g>
<g id="a_life_events_graph_edge11&#45;label"><a xlink:title="finalized? to tp_finalize: no (mark as finalized)">
<text text-anchor="start" x="170.67" y="-379.35" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;no (mark &#160;</text>
<text text-anchor="start" x="162.05" y="-365.1" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;as finalized) &#160;</text>
</a>
</g>
</g>
<!-- tp_clear -->
<g id="life_events_graph_node9" class="node">
<title>tp_clear</title>
<g id="a_life_events_graph_node9"><a xlink:href="typeobj.html#c.PyTypeObject.tp_clear" xlink:title="tp_clear" target="_top">
<ellipse fill="none" stroke="black" cx="222.8" cy="-238.5" rx="48.34" ry="18"/>
<text text-anchor="middle" x="222.8" y="-234.22" font-family="monospace,monospace" font-size="12.00">tp_clear</text>
</a>
</g>
</g>
<!-- finalized?&#45;&gt;tp_clear -->
<g id="life_events_graph_edge12" class="edge">
<title>finalized?&#45;&gt;tp_clear</title>
<g id="a_life_events_graph_edge12"><a xlink:title="finalized? to tp_clear: yes">
<path fill="none" stroke="black" d="M227.56,-430.1C236.46,-423.41 244.86,-415.02 249.8,-405 277.22,-349.39 274.06,-322.55 249.8,-265.5 249.7,-265.27 249.6,-265.04 249.49,-264.81"/>
<polygon fill="black" stroke="black" points="252.41,-262.88 243.93,-256.52 246.6,-266.78 252.41,-262.88"/>
</a>
</g>
<g id="a_life_events_graph_edge12&#45;label"><a xlink:title="finalized? to tp_clear: yes">
<text text-anchor="start" x="269.2" y="-316.73" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;yes &#160;</text>
</a>
</g>
</g>
<!-- tp_finalize&#45;&gt;tp_clear -->
<g id="life_events_graph_edge13" class="edge">
<title>tp_finalize&#45;&gt;tp_clear</title>
<g id="a_life_events_graph_edge13"><a xlink:title="tp_finalize to tp_clear: no refs or cyclic isolate">
<path fill="none" stroke="black" d="M130.02,-302.72C135.75,-290.85 144.8,-275.49 156.8,-265.5 161.95,-261.21 167.9,-257.57 174.07,-254.49"/>
<polygon fill="black" stroke="black" points="175.46,-257.71 183.18,-250.45 172.62,-251.31 175.46,-257.71"/>
</a>
</g>
<g id="a_life_events_graph_edge13&#45;label"><a xlink:title="tp_finalize to tp_clear: no refs or cyclic isolate">
<text text-anchor="start" x="164.3" y="-282.6" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;no refs or &#160;&#160;</text>
<text text-anchor="start" x="156.8" y="-268.35" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;cyclic isolate &#160;</text>
</a>
</g>
</g>
<!-- tp_finalize&#45;&gt;tp_dealloc -->
<g id="life_events_graph_edge14" class="edge">
<title>tp_finalize&#45;&gt;tp_dealloc</title>
<g id="a_life_events_graph_edge14"><a xlink:href="lifecycle.html#c.PyObject_CallFinalizerFromDealloc" xlink:title="tp_dealloc to tp_finalize: recommended call (see explanation)" target="_top">
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M85.85,-298.52C42.09,-270.18 -21.4,-218.11 7.8,-168.75 36.22,-120.7 99.95,-100.97 146.42,-92.87"/>
<polygon fill="none" stroke="black" points="83.78,-301.35 94.11,-303.72 87.52,-295.43 83.78,-301.35"/>
</a>
</g>
<g id="a_life_events_graph_edge14&#45;label"><a xlink:href="lifecycle.html#c.PyObject_CallFinalizerFromDealloc" xlink:title="tp_dealloc to tp_finalize: recommended call (see explanation)" target="_top">
<text text-anchor="start" x="7.8" y="-200.1" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;recommended</text>
<text text-anchor="start" x="25.8" y="-185.85" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;call (see</text>
<text text-anchor="start" x="13.05" y="-171.6" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;explanation)</text>
</a>
</g>
</g>
<!-- tp_finalize&#45;&gt;tp_dealloc -->
<g id="life_events_graph_edge15" class="edge">
<title>tp_finalize&#45;&gt;tp_dealloc</title>
<g id="a_life_events_graph_edge15"><a xlink:title="tp_finalize to tp_dealloc: no refs">
<path fill="none" stroke="black" d="M123.03,-302.58C123.95,-273.77 128.08,-214.78 146.05,-168.75 153.95,-148.5 167.56,-128.2 179.24,-112.92"/>
<polygon fill="black" stroke="black" points="181.81,-115.32 185.25,-105.3 176.31,-110.98 181.81,-115.32"/>
</a>
</g>
<g id="a_life_events_graph_edge15&#45;label"><a xlink:title="tp_finalize to tp_dealloc: no refs">
<text text-anchor="start" x="146.05" y="-185.85" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;&#160;no refs &#160;</text>
</a>
</g>
</g>
<!-- tp_clear&#45;&gt;uncollectable -->
<g id="life_events_graph_edge17" class="edge">
<title>tp_clear&#45;&gt;uncollectable</title>
<g id="a_life_events_graph_edge17"><a xlink:title="tp_clear to uncollectable: cyclic isolate">
<path fill="none" stroke="black" d="M227.75,-220.38C232.99,-205 242.67,-182.74 258.05,-168.75 260.43,-166.58 263.02,-164.58 265.74,-162.73"/>
<polygon fill="black" stroke="black" points="267.27,-165.89 274.12,-157.81 263.73,-159.86 267.27,-165.89"/>
</a>
</g>
<g id="a_life_events_graph_edge17&#45;label"><a xlink:title="tp_clear to uncollectable: cyclic isolate">
<text text-anchor="start" x="260.67" y="-192.97" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;cyclic &#160;</text>
<text text-anchor="start" x="258.05" y="-178.72" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;isolate &#160;</text>
</a>
</g>
</g>
<!-- tp_clear&#45;&gt;tp_dealloc -->
<g id="life_events_graph_edge16" class="edge">
<title>tp_clear&#45;&gt;tp_dealloc</title>
<g id="a_life_events_graph_edge16"><a xlink:title="tp_clear to tp_dealloc: no refs">
<path fill="none" stroke="black" d="M219.7,-220.24C216.92,-204.51 212.83,-180.61 209.8,-159.75 207.7,-145.34 205.67,-129.26 204.07,-115.92"/>
<polygon fill="black" stroke="black" points="207.56,-115.59 202.91,-106.07 200.61,-116.41 207.56,-115.59"/>
</a>
</g>
<g id="a_life_events_graph_edge16&#45;label"><a xlink:title="tp_clear to tp_dealloc: no refs">
<text text-anchor="start" x="209.8" y="-137.22" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;no refs &#160;</text>
</a>
</g>
</g>
<!-- uncollectable&#45;&gt;tp_dealloc -->
<!-- tp_free -->
<g id="life_events_graph_node12" class="node">
<title>tp_free</title>
<g id="a_life_events_graph_node12"><a xlink:href="typeobj.html#c.PyTypeObject.tp_free" xlink:title="tp_free" target="_top">
<ellipse fill="none" stroke="black" cx="200.8" cy="-18" rx="43.57" ry="18"/>
<text text-anchor="middle" x="200.8" y="-13.72" font-family="monospace,monospace" font-size="12.00">tp_free</text>
</a>
</g>
</g>
<!-- tp_dealloc&#45;&gt;tp_free -->
<g id="life_events_graph_edge21" class="edge">
<title>tp_dealloc&#45;&gt;tp_free</title>
<g id="a_life_events_graph_edge21"><a xlink:title="tp_dealloc to tp_free: direct call">
<path fill="none" stroke="black" d="M200.8,-67.84C200.8,-61.63 200.8,-54.46 200.8,-47.56"/>
<polygon fill="none" stroke="black" points="204.3,-47.57 200.8,-37.57 197.3,-47.57 204.3,-47.57"/>
</a>
</g>
<g id="a_life_events_graph_edge21&#45;label"><a xlink:title="tp_dealloc to tp_free: direct call">
<text text-anchor="start" x="200.8" y="-47.85" font-family="serif,serif" font-style="italic" font-size="12.00"> &#160;&#160;&#160;direct call &#160;</text>
</a>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

273
Doc/c-api/lifecycle.rst Normal file
View file

@ -0,0 +1,273 @@
.. highlight:: c
.. _life-cycle:
Object Life Cycle
=================
This section explains how a type's slots relate to each other throughout the
life of an object. It is not intended to be a complete canonical reference for
the slots; instead, refer to the slot-specific documentation in
:ref:`type-structs` for details about a particular slot.
Life Events
-----------
The figure below illustrates the order of events that can occur throughout an
object's life. An arrow from *A* to *B* indicates that event *B* can occur
after event *A* has occurred, with the arrow's label indicating the condition
that must be true for *B* to occur after *A*.
.. only:: html and not epub
.. raw:: html
<style type="text/css">
.. raw:: html
:file: lifecycle.dot.css
.. raw:: html
</style>
.. raw:: html
:file: lifecycle.dot.svg
.. raw:: html
<script>
(() => {
const g = document.getElementById('life_events_graph');
const title = g.querySelector(':scope > title');
title.id = 'life-events-graph-title';
const svg = g.closest('svg');
svg.role = 'img';
svg.setAttribute('aria-describedby',
'life-events-graph-description');
svg.setAttribute('aria-labelledby', 'life-events-graph-title');
})();
</script>
.. only:: epub or not (html or latex)
.. image:: lifecycle.dot.svg
:align: center
:class: invert-in-dark-mode
:alt: Diagram showing events in an object's life. Explained in detail
below.
.. only:: latex
.. image:: lifecycle.dot.pdf
:align: center
:class: invert-in-dark-mode
:alt: Diagram showing events in an object's life. Explained in detail
below.
.. container::
:name: life-events-graph-description
Explanation:
* When a new object is constructed by calling its type:
#. :c:member:`~PyTypeObject.tp_new` is called to create a new object.
#. :c:member:`~PyTypeObject.tp_alloc` is directly called by
:c:member:`~PyTypeObject.tp_new` to allocate the memory for the new
object.
#. :c:member:`~PyTypeObject.tp_init` initializes the newly created object.
:c:member:`!tp_init` can be called again to re-initialize an object, if
desired. The :c:member:`!tp_init` call can also be skipped entirely,
for example by Python code calling :py:meth:`~object.__new__`.
* After :c:member:`!tp_init` completes, the object is ready to use.
* Some time after the last reference to an object is removed:
#. If an object is not marked as *finalized*, it might be finalized by
marking it as *finalized* and calling its
:c:member:`~PyTypeObject.tp_finalize` function. Python does
*not* finalize an object when the last reference to it is deleted; use
:c:func:`PyObject_CallFinalizerFromDealloc` to ensure that
:c:member:`~PyTypeObject.tp_finalize` is always called.
#. If the object is marked as finalized,
:c:member:`~PyTypeObject.tp_clear` might be called by the garbage collector
to clear references held by the object. It is *not* called when the
object's reference count reaches zero.
#. :c:member:`~PyTypeObject.tp_dealloc` is called to destroy the object.
To avoid code duplication, :c:member:`~PyTypeObject.tp_dealloc` typically
calls into :c:member:`~PyTypeObject.tp_clear` to free up the object's
references.
#. When :c:member:`~PyTypeObject.tp_dealloc` finishes object destruction,
it directly calls :c:member:`~PyTypeObject.tp_free` (usually set to
:c:func:`PyObject_Free` or :c:func:`PyObject_GC_Del` automatically as
appropriate for the type) to deallocate the memory.
* The :c:member:`~PyTypeObject.tp_finalize` function is permitted to add a
reference to the object if desired. If it does, the object is
*resurrected*, preventing its pending destruction. (Only
:c:member:`!tp_finalize` is allowed to resurrect an object;
:c:member:`~PyTypeObject.tp_clear` and
:c:member:`~PyTypeObject.tp_dealloc` cannot without calling into
:c:member:`!tp_finalize`.) Resurrecting an object may
or may not cause the object's *finalized* mark to be removed. Currently,
Python does not remove the *finalized* mark from a resurrected object if
it supports garbage collection (i.e., the :c:macro:`Py_TPFLAGS_HAVE_GC`
flag is set) but does remove the mark if the object does not support
garbage collection; either or both of these behaviors may change in the
future.
* :c:member:`~PyTypeObject.tp_dealloc` can optionally call
:c:member:`~PyTypeObject.tp_finalize` via
:c:func:`PyObject_CallFinalizerFromDealloc` if it wishes to reuse that
code to help with object destruction. This is recommended because it
guarantees that :c:member:`!tp_finalize` is always called before
destruction. See the :c:member:`~PyTypeObject.tp_dealloc` documentation
for example code.
* If the object is a member of a :term:`cyclic isolate` and either
:c:member:`~PyTypeObject.tp_clear` fails to break the reference cycle or
the cyclic isolate is not detected (perhaps :func:`gc.disable` was called,
or the :c:macro:`Py_TPFLAGS_HAVE_GC` flag was erroneously omitted in one
of the involved types), the objects remain indefinitely uncollectable
(they "leak"). See :data:`gc.garbage`.
If the object is marked as supporting garbage collection (the
:c:macro:`Py_TPFLAGS_HAVE_GC` flag is set in
:c:member:`~PyTypeObject.tp_flags`), the following events are also possible:
* The garbage collector occasionally calls
:c:member:`~PyTypeObject.tp_traverse` to identify :term:`cyclic isolates
<cyclic isolate>`.
* When the garbage collector discovers a :term:`cyclic isolate`, it
finalizes one of the objects in the group by marking it as *finalized* and
calling its :c:member:`~PyTypeObject.tp_finalize` function, if it has one.
This repeats until the cyclic isolate doesn't exist or all of the objects
have been finalized.
* :c:member:`~PyTypeObject.tp_finalize` is permitted to resurrect the object
by adding a reference from outside the :term:`cyclic isolate`. The new
reference causes the group of objects to no longer form a cyclic isolate
(the reference cycle may still exist, but if it does the objects are no
longer isolated).
* When the garbage collector discovers a :term:`cyclic isolate` and all of
the objects in the group have already been marked as *finalized*, the
garbage collector clears one or more of the uncleared objects in the group
(possibly concurrently) by calling each's
:c:member:`~PyTypeObject.tp_clear` function. This repeats as long as the
cyclic isolate still exists and not all of the objects have been cleared.
Cyclic Isolate Destruction
--------------------------
Listed below are the stages of life of a hypothetical :term:`cyclic isolate`
that continues to exist after each member object is finalized or cleared. It
is a memory leak if a cyclic isolate progresses through all of these stages; it should
vanish once all objects are cleared, if not sooner. A cyclic isolate can
vanish either because the reference cycle is broken or because the objects are
no longer isolated due to finalizer resurrection (see
:c:member:`~PyTypeObject.tp_finalize`).
0. **Reachable** (not yet a cyclic isolate): All objects are in their normal,
reachable state. A reference cycle could exist, but an external reference
means the objects are not yet isolated.
#. **Unreachable but consistent:** The final reference from outside the cyclic
group of objects has been removed, causing the objects to become isolated
(thus a cyclic isolate is born). None of the group's objects have been
finalized or cleared yet. The cyclic isolate remains at this stage until
some future run of the garbage collector (not necessarily the next run
because the next run might not scan every object).
#. **Mix of finalized and not finalized:** Objects in a cyclic isolate are
finalized one at a time, which means that there is a period of time when the
cyclic isolate is composed of a mix of finalized and non-finalized objects.
Finalization order is unspecified, so it can appear random. A finalized
object must behave in a sane manner when non-finalized objects interact with
it, and a non-finalized object must be able to tolerate the finalization of
an arbitrary subset of its referents.
#. **All finalized:** All objects in a cyclic isolate are finalized before any
of them are cleared.
#. **Mix of finalized and cleared:** The objects can be cleared serially or
concurrently (but with the :term:`GIL` held); either way, some will finish
before others. A finalized object must be able to tolerate the clearing of
a subset of its referents. :pep:`442` calls this stage "cyclic trash".
#. **Leaked:** If a cyclic isolate still exists after all objects in the group
have been finalized and cleared, then the objects remain indefinitely
uncollectable (see :data:`gc.garbage`). It is a bug if a cyclic isolate
reaches this stage---it means the :c:member:`~PyTypeObject.tp_clear` methods
of the participating objects have failed to break the reference cycle as
required.
If :c:member:`~PyTypeObject.tp_clear` did not exist, then Python would have no
way to safely break a reference cycle. Simply destroying an object in a cyclic
isolate would result in a dangling pointer, triggering undefined behavior when
an object referencing the destroyed object is itself destroyed. The clearing
step makes object destruction a two-phase process: first
:c:member:`~PyTypeObject.tp_clear` is called to partially destroy the objects
enough to detangle them from each other, then
:c:member:`~PyTypeObject.tp_dealloc` is called to complete the destruction.
Unlike clearing, finalization is not a phase of destruction. A finalized
object must still behave properly by continuing to fulfill its design
contracts. An object's finalizer is allowed to execute arbitrary Python code,
and is even allowed to prevent the impending destruction by adding a reference.
The finalizer is only related to destruction by call order---if it runs, it runs
before destruction, which starts with :c:member:`~PyTypeObject.tp_clear` (if
called) and concludes with :c:member:`~PyTypeObject.tp_dealloc`.
The finalization step is not necessary to safely reclaim the objects in a
cyclic isolate, but its existence makes it easier to design types that behave
in a sane manner when objects are cleared. Clearing an object might
necessarily leave it in a broken, partially destroyed state---it might be
unsafe to call any of the cleared object's methods or access any of its
attributes. With finalization, only finalized objects can possibly interact
with cleared objects; non-finalized objects are guaranteed to interact with
only non-cleared (but potentially finalized) objects.
To summarize the possible interactions:
* A non-finalized object might have references to or from non-finalized and
finalized objects, but not to or from cleared objects.
* A finalized object might have references to or from non-finalized, finalized,
and cleared objects.
* A cleared object might have references to or from finalized and cleared
objects, but not to or from non-finalized objects.
Without any reference cycles, an object can be simply destroyed once its last
reference is deleted; the finalization and clearing steps are not necessary to
safely reclaim unused objects. However, it can be useful to automatically call
:c:member:`~PyTypeObject.tp_finalize` and :c:member:`~PyTypeObject.tp_clear`
before destruction anyway because type design is simplified when all objects
always experience the same series of events regardless of whether they
participated in a cyclic isolate. Python currently only calls
:c:member:`~PyTypeObject.tp_finalize` and :c:member:`~PyTypeObject.tp_clear` as
needed to destroy a cyclic isolate; this may change in a future version.
Functions
---------
To allocate and free memory, see :ref:`allocating-objects`.
.. c:function:: void PyObject_CallFinalizer(PyObject *op)
Finalizes the object as described in :c:member:`~PyTypeObject.tp_finalize`.
Call this function (or :c:func:`PyObject_CallFinalizerFromDealloc`) instead
of calling :c:member:`~PyTypeObject.tp_finalize` directly because this
function may deduplicate multiple calls to :c:member:`!tp_finalize`.
Currently, calls are only deduplicated if the type supports garbage
collection (i.e., the :c:macro:`Py_TPFLAGS_HAVE_GC` flag is set); this may
change in the future.
.. c:function:: int PyObject_CallFinalizerFromDealloc(PyObject *op)
Same as :c:func:`PyObject_CallFinalizer` but meant to be called at the
beginning of the object's destructor (:c:member:`~PyTypeObject.tp_dealloc`).
There must not be any references to the object. If the object's finalizer
resurrects the object, this function returns -1; no further destruction
should happen. Otherwise, this function returns 0 and destruction can
continue normally.
.. seealso::
:c:member:`~PyTypeObject.tp_dealloc` for example code.

View file

@ -376,6 +376,24 @@ The :ref:`default object allocator <default-memory-allocators>` uses the
If *p* is ``NULL``, no operation is performed.
Do not call this directly to free an object's memory; call the type's
:c:member:`~PyTypeObject.tp_free` slot instead.
Do not use this for memory allocated by :c:macro:`PyObject_GC_New` or
:c:macro:`PyObject_GC_NewVar`; use :c:func:`PyObject_GC_Del` instead.
.. seealso::
* :c:func:`PyObject_GC_Del` is the equivalent of this function for memory
allocated by types that support garbage collection.
* :c:func:`PyObject_Malloc`
* :c:func:`PyObject_Realloc`
* :c:func:`PyObject_Calloc`
* :c:macro:`PyObject_New`
* :c:macro:`PyObject_NewVar`
* :c:func:`PyType_GenericAlloc`
* :c:member:`~PyTypeObject.tp_free`
.. _default-memory-allocators:

View file

@ -613,6 +613,38 @@ Object Protocol
.. versionadded:: 3.14
.. c:function:: int PyUnstable_Object_IsUniqueReferencedTemporary(PyObject *obj)
Check if *obj* is a unique temporary object.
Returns ``1`` if *obj* is known to be a unique temporary object,
and ``0`` otherwise. This function cannot fail, but the check is
conservative, and may return ``0`` in some cases even if *obj* is a unique
temporary object.
If an object is a unique temporary, it is guaranteed that the current code
has the only reference to the object. For arguments to C functions, this
should be used instead of checking if the reference count is ``1``. Starting
with Python 3.14, the interpreter internally avoids some reference count
modifications when loading objects onto the operands stack by
:term:`borrowing <borrowed reference>` references when possible, which means
that a reference count of ``1`` by itself does not guarantee that a function
argument uniquely referenced.
In the example below, ``my_func`` is called with a unique temporary object
as its argument::
my_func([1, 2, 3])
In the example below, ``my_func`` is **not** called with a unique temporary
object as its argument, even if its refcount is ``1``::
my_list = [1, 2, 3]
my_func(my_list)
See also the function :c:func:`Py_REFCNT`.
.. versionadded:: 3.14
.. c:function:: int PyUnstable_IsImmortal(PyObject *obj)
This function returns non-zero if *obj* is :term:`immortal`, and zero
@ -705,3 +737,21 @@ Object Protocol
caller must hold a :term:`strong reference` to *obj* when calling this.
.. versionadded:: 3.14
.. c:function:: int PyUnstable_Object_IsUniquelyReferenced(PyObject *op)
Determine if *op* only has one reference.
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
: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.
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

View file

@ -12,6 +12,7 @@ object types.
.. toctree::
allocation.rst
lifecycle.rst
structures.rst
typeobj.rst
gcsupport.rst

View file

@ -23,6 +23,15 @@ of Python objects.
Use the :c:func:`Py_SET_REFCNT()` function to set an object reference count.
.. note::
On :term:`free threaded <free threading>` builds 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.
See also the function :c:func:`PyUnstable_Object_IsUniqueReferencedTemporary()`.
.. versionchanged:: 3.10
:c:func:`Py_REFCNT()` is changed to the inline static function.

View file

@ -258,10 +258,57 @@ These are utility functions that make functionality from the :mod:`sys` module
accessible to C code. They all work with the current interpreter thread's
:mod:`sys` module's dict, which is contained in the internal thread state structure.
.. c:function:: PyObject *PySys_GetAttr(PyObject *name)
Get the attribute *name* of the :mod:`sys` module.
Return a :term:`strong reference`.
Raise :exc:`RuntimeError` and return ``NULL`` if it does not exist or
if the :mod:`sys` module cannot be found.
If the non-existing object should not be treated as a failure, you can use
:c:func:`PySys_GetOptionalAttr` instead.
.. versionadded:: next
.. c:function:: PyObject *PySys_GetAttrString(const char *name)
This is the same as :c:func:`PySys_GetAttr`, but *name* is
specified as a :c:expr:`const char*` UTF-8 encoded bytes string,
rather than a :c:expr:`PyObject*`.
If the non-existing object should not be treated as a failure, you can use
:c:func:`PySys_GetOptionalAttrString` instead.
.. versionadded:: next
.. c:function:: int PySys_GetOptionalAttr(PyObject *name, PyObject **result)
Variant of :c:func:`PySys_GetAttr` which doesn't raise
exception if the object does not exist.
* Set *\*result* to a new :term:`strong reference` to the object and
return ``1`` if the object exists.
* Set *\*result* to ``NULL`` and return ``0`` without setting an exception
if the object does not exist.
* Set an exception, set *\*result* to ``NULL``, and return ``-1``,
if an error occurred.
.. versionadded:: next
.. c:function:: int PySys_GetOptionalAttrString(const char *name, PyObject **result)
This is the same as :c:func:`PySys_GetOptionalAttr`, but *name* is
specified as a :c:expr:`const char*` UTF-8 encoded bytes string,
rather than a :c:expr:`PyObject*`.
.. versionadded:: next
.. c:function:: PyObject *PySys_GetObject(const char *name)
Return the object *name* from the :mod:`sys` module or ``NULL`` if it does
not exist, without setting an exception.
Similar to :c:func:`PySys_GetAttrString`, but return a :term:`borrowed
reference` and return ``NULL`` *without* setting exception on failure.
Preserves exception that was set before the call.
.. c:function:: int PySys_SetObject(const char *name, PyObject *v)

View file

@ -151,14 +151,29 @@ Type Objects
.. c:function:: PyObject* PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
Generic handler for the :c:member:`~PyTypeObject.tp_alloc` slot of a type object. Use
Python's default memory allocation mechanism to allocate a new instance and
initialize all its contents to ``NULL``.
Generic handler for the :c:member:`~PyTypeObject.tp_alloc` slot of a type
object. Uses Python's default memory allocation mechanism to allocate memory
for a new instance, zeros the memory, then initializes the memory as if by
calling :c:func:`PyObject_Init` or :c:func:`PyObject_InitVar`.
Do not call this directly to allocate memory for an object; call the type's
:c:member:`~PyTypeObject.tp_alloc` slot instead.
For types that support garbage collection (i.e., the
:c:macro:`Py_TPFLAGS_HAVE_GC` flag is set), this function behaves like
:c:macro:`PyObject_GC_New` or :c:macro:`PyObject_GC_NewVar` (except the
memory is guaranteed to be zeroed before initialization), and should be
paired with :c:func:`PyObject_GC_Del` in :c:member:`~PyTypeObject.tp_free`.
Otherwise, it behaves like :c:macro:`PyObject_New` or
:c:macro:`PyObject_NewVar` (except the memory is guaranteed to be zeroed
before initialization) and should be paired with :c:func:`PyObject_Free` in
:c:member:`~PyTypeObject.tp_free`.
.. c:function:: PyObject* PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
Generic handler for the :c:member:`~PyTypeObject.tp_new` slot of a type object. Create a
new instance using the type's :c:member:`~PyTypeObject.tp_alloc` slot.
Generic handler for the :c:member:`~PyTypeObject.tp_new` slot of a type
object. Creates a new instance using the type's
:c:member:`~PyTypeObject.tp_alloc` slot and returns the resulting object.
.. c:function:: int PyType_Ready(PyTypeObject *type)

View file

@ -79,7 +79,7 @@ Quick Reference
| :c:member:`~PyTypeObject.tp_setattro` | :c:type:`setattrofunc` | __setattr__, | X | X | | G |
| | | __delattr__ | | | | |
+------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
| :c:member:`~PyTypeObject.tp_as_buffer` | :c:type:`PyBufferProcs` * | | | | | % |
| :c:member:`~PyTypeObject.tp_as_buffer` | :c:type:`PyBufferProcs` * | :ref:`sub-slots` | | | | % |
+------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
| :c:member:`~PyTypeObject.tp_flags` | unsigned long | | X | X | | ? |
+------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
@ -325,9 +325,10 @@ sub-slots
+---------------------------------------------------------+-----------------------------------+---------------+
| |
+---------------------------------------------------------+-----------------------------------+---------------+
| :c:member:`~PyBufferProcs.bf_getbuffer` | :c:func:`getbufferproc` | |
| :c:member:`~PyBufferProcs.bf_getbuffer` | :c:func:`getbufferproc` | __buffer__ |
+---------------------------------------------------------+-----------------------------------+---------------+
| :c:member:`~PyBufferProcs.bf_releasebuffer` | :c:func:`releasebufferproc` | |
| :c:member:`~PyBufferProcs.bf_releasebuffer` | :c:func:`releasebufferproc` | __release_\ |
| | | buffer\__ |
+---------------------------------------------------------+-----------------------------------+---------------+
.. _slot-typedefs-table:
@ -676,77 +677,122 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: destructor PyTypeObject.tp_dealloc
A pointer to the instance destructor function. This function must be defined
unless the type guarantees that its instances will never be deallocated (as is
the case for the singletons ``None`` and ``Ellipsis``). The function signature is::
A pointer to the instance destructor function. The function signature is::
void tp_dealloc(PyObject *self);
The destructor function is called by the :c:func:`Py_DECREF` and
:c:func:`Py_XDECREF` macros when the new reference count is zero. At this point,
the instance is still in existence, but there are no references to it. The
destructor function should free all references which the instance owns, free all
memory buffers owned by the instance (using the freeing function corresponding
to the allocation function used to allocate the buffer), and call the type's
:c:member:`~PyTypeObject.tp_free` function. If the type is not subtypable
(doesn't have the :c:macro:`Py_TPFLAGS_BASETYPE` flag bit set), it is
permissible to call the object deallocator directly instead of via
:c:member:`~PyTypeObject.tp_free`. The object deallocator should be the one used to allocate the
instance; this is normally :c:func:`PyObject_Free` if the instance was allocated
using :c:macro:`PyObject_New` or :c:macro:`PyObject_NewVar`, or
:c:func:`PyObject_GC_Del` if the instance was allocated using
:c:macro:`PyObject_GC_New` or :c:macro:`PyObject_GC_NewVar`.
The destructor function should remove all references which the instance owns
(e.g., call :c:func:`Py_CLEAR`), free all memory buffers owned by the
instance, and call the type's :c:member:`~PyTypeObject.tp_free` function to
free the object itself.
If the type supports garbage collection (has the :c:macro:`Py_TPFLAGS_HAVE_GC`
flag bit set), the destructor should call :c:func:`PyObject_GC_UnTrack`
No guarantees are made about when an object is destroyed, except:
* Python will destroy an object immediately or some time after the final
reference to the object is deleted, unless its finalizer
(:c:member:`~PyTypeObject.tp_finalize`) subsequently resurrects the
object.
* An object will not be destroyed while it is being automatically finalized
(:c:member:`~PyTypeObject.tp_finalize`) or automatically cleared
(:c:member:`~PyTypeObject.tp_clear`).
CPython currently destroys an object immediately from :c:func:`Py_DECREF`
when the new reference count is zero, but this may change in a future
version.
It is recommended to call :c:func:`PyObject_CallFinalizerFromDealloc` at the
beginning of :c:member:`!tp_dealloc` to guarantee that the object is always
finalized before destruction.
If the type supports garbage collection (the :c:macro:`Py_TPFLAGS_HAVE_GC`
flag is set), the destructor should call :c:func:`PyObject_GC_UnTrack`
before clearing any member fields.
.. code-block:: c
It is permissible to call :c:member:`~PyTypeObject.tp_clear` from
:c:member:`!tp_dealloc` to reduce code duplication and to guarantee that the
object is always cleared before destruction. Beware that
:c:member:`!tp_clear` might have already been called.
static void
foo_dealloc(PyObject *op)
{
If the type is heap allocated (:c:macro:`Py_TPFLAGS_HEAPTYPE`), the
deallocator should release the owned reference to its type object (via
:c:func:`Py_DECREF`) after calling the type deallocator. See the example
code below.::
static void
foo_dealloc(PyObject *op)
{
foo_object *self = (foo_object *) op;
PyObject_GC_UnTrack(self);
Py_CLEAR(self->ref);
Py_TYPE(self)->tp_free(self);
}
}
Finally, if the type is heap allocated (:c:macro:`Py_TPFLAGS_HEAPTYPE`), the
deallocator should release the owned reference to its type object
(via :c:func:`Py_DECREF`) after
calling the type deallocator. In order to avoid dangling pointers, the
recommended way to achieve this is:
:c:member:`!tp_dealloc` must leave the exception status unchanged. If it
needs to call something that might raise an exception, the exception state
must be backed up first and restored later (after logging any exceptions
with :c:func:`PyErr_WriteUnraisable`).
.. code-block:: c
Example::
static void
foo_dealloc(PyObject *op)
{
PyTypeObject *tp = Py_TYPE(op);
// free references and buffers here
tp->tp_free(op);
Py_DECREF(tp);
}
static void
foo_dealloc(PyObject *self)
{
PyObject *exc = PyErr_GetRaisedException();
.. warning::
if (PyObject_CallFinalizerFromDealloc(self) < 0) {
// self was resurrected.
goto done;
}
In a garbage collected Python, :c:member:`!tp_dealloc` may be called from
any Python thread, not just the thread which created the object (if the
object becomes part of a refcount cycle, that cycle might be collected by
a garbage collection on any thread). This is not a problem for Python
API calls, since the thread on which :c:member:`!tp_dealloc` is called
with an :term:`attached thread state`. However, if the object being
destroyed in turn destroys objects from some other C or C++ library, care
should be taken to ensure that destroying those objects on the thread
which called :c:member:`!tp_dealloc` will not violate any assumptions of
the library.
PyTypeObject *tp = Py_TYPE(self);
if (tp->tp_flags & Py_TPFLAGS_HAVE_GC) {
PyObject_GC_UnTrack(self);
}
// Optional, but convenient to avoid code duplication.
if (tp->tp_clear && tp->tp_clear(self) < 0) {
PyErr_WriteUnraisable(self);
}
// Any additional destruction goes here.
tp->tp_free(self);
self = NULL; // In case PyErr_WriteUnraisable() is called below.
if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) {
Py_CLEAR(tp);
}
done:
// Optional, if something was called that might have raised an
// exception.
if (PyErr_Occurred()) {
PyErr_WriteUnraisable(self);
}
PyErr_SetRaisedException(exc);
}
:c:member:`!tp_dealloc` may be called from
any Python thread, not just the thread which created the object (if the
object becomes part of a refcount cycle, that cycle might be collected by
a garbage collection on any thread). This is not a problem for Python
API calls, since the thread on which :c:member:`!tp_dealloc` is called
with an :term:`attached thread state`. However, if the object being
destroyed in turn destroys objects from some other C library, care
should be taken to ensure that destroying those objects on the thread
which called :c:member:`!tp_dealloc` will not violate any assumptions of
the library.
**Inheritance:**
This field is inherited by subtypes.
.. seealso::
:ref:`life-cycle` for details about how this slot relates to other slots.
.. c:member:: Py_ssize_t PyTypeObject.tp_vectorcall_offset
@ -1137,11 +1183,11 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:macro:: Py_TPFLAGS_HAVE_GC
This bit is set when the object supports garbage collection. If this bit
is set, instances must be created using :c:macro:`PyObject_GC_New` and
destroyed using :c:func:`PyObject_GC_Del`. More information in section
:ref:`supporting-cycle-detection`. This bit also implies that the
GC-related fields :c:member:`~PyTypeObject.tp_traverse` and :c:member:`~PyTypeObject.tp_clear` are present in
the type object.
is set, memory for new instances (see :c:member:`~PyTypeObject.tp_alloc`)
must be allocated using :c:macro:`PyObject_GC_New` or
:c:func:`PyType_GenericAlloc` and deallocated (see
:c:member:`~PyTypeObject.tp_free`) using :c:func:`PyObject_GC_Del`. More
information in section :ref:`supporting-cycle-detection`.
**Inheritance:**
@ -1192,7 +1238,7 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:macro:: Py_TPFLAGS_MANAGED_DICT
This bit indicates that instances of the class have a `~object.__dict__`
This bit indicates that instances of the class have a :attr:`~object.__dict__`
attribute, and that the space for the dictionary is managed by the VM.
If this flag is set, :c:macro:`Py_TPFLAGS_HAVE_GC` should also be set.
@ -1478,6 +1524,11 @@ and :c:data:`PyType_Type` effectively act as defaults.)
heap-allocated superclass).
If they do not, the type object may not be garbage-collected.
.. note::
The :c:member:`~PyTypeObject.tp_traverse` function can be called from any
thread.
.. versionchanged:: 3.9
Heap-allocated types are expected to visit ``Py_TYPE(self)`` in
@ -1497,20 +1548,101 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: inquiry PyTypeObject.tp_clear
An optional pointer to a clear function for the garbage collector. This is only
used if the :c:macro:`Py_TPFLAGS_HAVE_GC` flag bit is set. The signature is::
An optional pointer to a clear function. The signature is::
int tp_clear(PyObject *);
The :c:member:`~PyTypeObject.tp_clear` member function is used to break reference cycles in cyclic
garbage detected by the garbage collector. Taken together, all :c:member:`~PyTypeObject.tp_clear`
functions in the system must combine to break all reference cycles. This is
subtle, and if in any doubt supply a :c:member:`~PyTypeObject.tp_clear` function. For example,
the tuple type does not implement a :c:member:`~PyTypeObject.tp_clear` function, because it's
possible to prove that no reference cycle can be composed entirely of tuples.
Therefore the :c:member:`~PyTypeObject.tp_clear` functions of other types must be sufficient to
break any cycle containing a tuple. This isn't immediately obvious, and there's
rarely a good reason to avoid implementing :c:member:`~PyTypeObject.tp_clear`.
The purpose of this function is to break reference cycles that are causing a
:term:`cyclic isolate` so that the objects can be safely destroyed. A
cleared object is a partially destroyed object; the object is not obligated
to satisfy design invariants held during normal use.
:c:member:`!tp_clear` does not need to delete references to objects that
can't participate in reference cycles, such as Python strings or Python
integers. However, it may be convenient to clear all references, and write
the type's :c:member:`~PyTypeObject.tp_dealloc` function to invoke
:c:member:`!tp_clear` to avoid code duplication. (Beware that
:c:member:`!tp_clear` might have already been called. Prefer calling
idempotent functions like :c:func:`Py_CLEAR`.)
Any non-trivial cleanup should be performed in
:c:member:`~PyTypeObject.tp_finalize` instead of :c:member:`!tp_clear`.
.. note::
If :c:member:`!tp_clear` fails to break a reference cycle then the
objects in the :term:`cyclic isolate` may remain indefinitely
uncollectable ("leak"). See :data:`gc.garbage`.
.. note::
Referents (direct and indirect) might have already been cleared; they are
not guaranteed to be in a consistent state.
.. note::
The :c:member:`~PyTypeObject.tp_clear` function can be called from any
thread.
.. note::
An object is not guaranteed to be automatically cleared before its
destructor (:c:member:`~PyTypeObject.tp_dealloc`) is called.
This function differs from the destructor
(:c:member:`~PyTypeObject.tp_dealloc`) in the following ways:
* The purpose of clearing an object is to remove references to other objects
that might participate in a reference cycle. The purpose of the
destructor, on the other hand, is a superset: it must release *all*
resources it owns, including references to objects that cannot participate
in a reference cycle (e.g., integers) as well as the object's own memory
(by calling :c:member:`~PyTypeObject.tp_free`).
* When :c:member:`!tp_clear` is called, other objects might still hold
references to the object being cleared. Because of this,
:c:member:`!tp_clear` must not deallocate the object's own memory
(:c:member:`~PyTypeObject.tp_free`). The destructor, on the other hand,
is only called when no (strong) references exist, and as such, must
safely destroy the object itself by deallocating it.
* :c:member:`!tp_clear` might never be automatically called. An object's
destructor, on the other hand, will be automatically called some time
after the object becomes unreachable (i.e., either there are no references
to the object or the object is a member of a :term:`cyclic isolate`).
No guarantees are made about when, if, or how often Python automatically
clears an object, except:
* Python will not automatically clear an object if it is reachable, i.e.,
there is a reference to it and it is not a member of a :term:`cyclic
isolate`.
* Python will not automatically clear an object if it has not been
automatically finalized (see :c:member:`~PyTypeObject.tp_finalize`). (If
the finalizer resurrected the object, the object may or may not be
automatically finalized again before it is cleared.)
* If an object is a member of a :term:`cyclic isolate`, Python will not
automatically clear it if any member of the cyclic isolate has not yet
been automatically finalized (:c:member:`~PyTypeObject.tp_finalize`).
* Python will not destroy an object until after any automatic calls to its
:c:member:`!tp_clear` function have returned. This ensures that the act
of breaking a reference cycle does not invalidate the ``self`` pointer
while :c:member:`!tp_clear` is still executing.
* Python will not automatically call :c:member:`!tp_clear` multiple times
concurrently.
CPython currently only automatically clears objects as needed to break
reference cycles in a :term:`cyclic isolate`, but future versions might
clear objects regularly before their destruction.
Taken together, all :c:member:`~PyTypeObject.tp_clear` functions in the
system must combine to break all reference cycles. This is subtle, and if
in any doubt supply a :c:member:`~PyTypeObject.tp_clear` function. For
example, the tuple type does not implement a
:c:member:`~PyTypeObject.tp_clear` function, because it's possible to prove
that no reference cycle can be composed entirely of tuples. Therefore the
:c:member:`~PyTypeObject.tp_clear` functions of other types are responsible
for breaking any cycle containing a tuple. This isn't immediately obvious,
and there's rarely a good reason to avoid implementing
:c:member:`~PyTypeObject.tp_clear`.
Implementations of :c:member:`~PyTypeObject.tp_clear` should drop the instance's references to
those of its members that may be Python objects, and set its pointers to those
@ -1545,18 +1677,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
PyObject_ClearManagedDict((PyObject*)self);
Note that :c:member:`~PyTypeObject.tp_clear` is not *always* called
before an instance 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:`~PyTypeObject.tp_dealloc` is
called directly.
Because the goal of :c:member:`~PyTypeObject.tp_clear` functions is to break reference cycles,
it's not necessary to clear contained objects like Python strings or Python
integers, which can't participate in reference cycles. On the other hand, it may
be convenient to clear all contained Python objects, and write the type's
:c:member:`~PyTypeObject.tp_dealloc` function to invoke :c:member:`~PyTypeObject.tp_clear`.
More information about Python's garbage collection scheme can be found in
section :ref:`supporting-cycle-detection`.
@ -1569,6 +1689,10 @@ and :c:data:`PyType_Type` effectively act as defaults.)
:c:member:`~PyTypeObject.tp_clear` are all inherited from the base type if they are all zero in
the subtype.
.. seealso::
:ref:`life-cycle` for details about how this slot relates to other slots.
.. c:member:: richcmpfunc PyTypeObject.tp_richcompare
@ -1945,18 +2069,17 @@ and :c:data:`PyType_Type` effectively act as defaults.)
**Inheritance:**
This field is inherited by static subtypes, but not by dynamic
subtypes (subtypes created by a class statement).
Static subtypes inherit this slot, which will be
:c:func:`PyType_GenericAlloc` if inherited from :class:`object`.
:ref:`Heap subtypes <heap-types>` do not inherit this slot.
**Default:**
For dynamic subtypes, this field is always set to
:c:func:`PyType_GenericAlloc`, to force a standard heap
allocation strategy.
For heap subtypes, this field is always set to
:c:func:`PyType_GenericAlloc`.
For static subtypes, :c:data:`PyBaseObject_Type` uses
:c:func:`PyType_GenericAlloc`. That is the recommended value
for all statically defined types.
For static subtypes, this slot is inherited (see above).
.. c:member:: newfunc PyTypeObject.tp_new
@ -2004,20 +2127,27 @@ and :c:data:`PyType_Type` effectively act as defaults.)
void tp_free(void *self);
An initializer that is compatible with this signature is :c:func:`PyObject_Free`.
This function must free the memory allocated by
:c:member:`~PyTypeObject.tp_alloc`.
**Inheritance:**
This field is inherited by static subtypes, but not by dynamic
subtypes (subtypes created by a class statement)
Static subtypes inherit this slot, which will be :c:func:`PyObject_Free` if
inherited from :class:`object`. Exception: If the type supports garbage
collection (i.e., the :c:macro:`Py_TPFLAGS_HAVE_GC` flag is set in
:c:member:`~PyTypeObject.tp_flags`) and it would inherit
:c:func:`PyObject_Free`, then this slot is not inherited but instead defaults
to :c:func:`PyObject_GC_Del`.
:ref:`Heap subtypes <heap-types>` do not inherit this slot.
**Default:**
In dynamic subtypes, this field is set to a deallocator suitable to
match :c:func:`PyType_GenericAlloc` and the value of the
:c:macro:`Py_TPFLAGS_HAVE_GC` flag bit.
For :ref:`heap subtypes <heap-types>`, this slot defaults to a deallocator suitable to match
:c:func:`PyType_GenericAlloc` and the value of the
:c:macro:`Py_TPFLAGS_HAVE_GC` flag.
For static subtypes, :c:data:`PyBaseObject_Type` uses :c:func:`PyObject_Free`.
For static subtypes, this slot is inherited (see above).
.. c:member:: inquiry PyTypeObject.tp_is_gc
@ -2144,29 +2274,138 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: destructor PyTypeObject.tp_finalize
An optional pointer to an instance finalization function. Its signature is::
An optional pointer to an instance finalization function. This is the C
implementation of the :meth:`~object.__del__` special method. Its signature
is::
void tp_finalize(PyObject *self);
If :c:member:`~PyTypeObject.tp_finalize` is set, the interpreter calls it once when
finalizing an instance. It is called either from the garbage
collector (if the instance is part of an isolated reference cycle) or
just before the object is deallocated. Either way, it is guaranteed
to be called before attempting to break reference cycles, ensuring
that it finds the object in a sane state.
The primary purpose of finalization is to perform any non-trivial cleanup
that must be performed before the object is destroyed, while the object and
any other objects it directly or indirectly references are still in a
consistent state. The finalizer is allowed to execute
arbitrary Python code.
:c:member:`~PyTypeObject.tp_finalize` should not mutate the current exception status;
therefore, a recommended way to write a non-trivial finalizer is::
Before Python automatically finalizes an object, some of the object's direct
or indirect referents might have themselves been automatically finalized.
However, none of the referents will have been automatically cleared
(:c:member:`~PyTypeObject.tp_clear`) yet.
Other non-finalized objects might still be using a finalized object, so the
finalizer must leave the object in a sane state (e.g., invariants are still
met).
.. note::
After Python automatically finalizes an object, Python might start
automatically clearing (:c:member:`~PyTypeObject.tp_clear`) the object
and its referents (direct and indirect). Cleared objects are not
guaranteed to be in a consistent state; a finalized object must be able
to tolerate cleared referents.
.. note::
An object is not guaranteed to be automatically finalized before its
destructor (:c:member:`~PyTypeObject.tp_dealloc`) is called. It is
recommended to call :c:func:`PyObject_CallFinalizerFromDealloc` at the
beginning of :c:member:`!tp_dealloc` to guarantee that the object is
always finalized before destruction.
.. note::
The :c:member:`~PyTypeObject.tp_finalize` function can be called from any
thread, although the :term:`GIL` will be held.
.. note::
The :c:member:`!tp_finalize` function can be called during shutdown,
after some global variables have been deleted. See the documentation of
the :meth:`~object.__del__` method for details.
When Python finalizes an object, it behaves like the following algorithm:
#. Python might mark the object as *finalized*. Currently, Python always
marks objects whose type supports garbage collection (i.e., the
:c:macro:`Py_TPFLAGS_HAVE_GC` flag is set in
:c:member:`~PyTypeObject.tp_flags`) and never marks other types of
objects; this might change in a future version.
#. If the object is not marked as *finalized* and its
:c:member:`!tp_finalize` finalizer function is non-``NULL``, the
finalizer function is called.
#. If the finalizer function was called and the finalizer made the object
reachable (i.e., there is a reference to the object and it is not a
member of a :term:`cyclic isolate`), then the finalizer is said to have
*resurrected* the object. It is unspecified whether the finalizer can
also resurrect the object by adding a new reference to the object that
does not make it reachable, i.e., the object is (still) a member of a
cyclic isolate.
#. If the finalizer resurrected the object, the object's pending destruction
is canceled and the object's *finalized* mark might be removed if
present. Currently, Python never removes the *finalized* mark; this
might change in a future version.
*Automatic finalization* refers to any finalization performed by Python
except via calls to :c:func:`PyObject_CallFinalizer` or
:c:func:`PyObject_CallFinalizerFromDealloc`. No guarantees are made about
when, if, or how often an object is automatically finalized, except:
* Python will not automatically finalize an object if it is reachable, i.e.,
there is a reference to it and it is not a member of a :term:`cyclic
isolate`.
* Python will not automatically finalize an object if finalizing it would
not mark the object as *finalized*. Currently, this applies to objects
whose type does not support garbage collection, i.e., the
:c:macro:`Py_TPFLAGS_HAVE_GC` flag is not set. Such objects can still be
manually finalized by calling :c:func:`PyObject_CallFinalizer` or
:c:func:`PyObject_CallFinalizerFromDealloc`.
* Python will not automatically finalize any two members of a :term:`cyclic
isolate` concurrently.
* Python will not automatically finalize an object after it has
automatically cleared (:c:member:`~PyTypeObject.tp_clear`) the object.
* If an object is a member of a :term:`cyclic isolate`, Python will not
automatically finalize it after automatically clearing (see
:c:member:`~PyTypeObject.tp_clear`) any other member.
* Python will automatically finalize every member of a :term:`cyclic
isolate` before it automatically clears (see
:c:member:`~PyTypeObject.tp_clear`) any of them.
* If Python is going to automatically clear an object
(:c:member:`~PyTypeObject.tp_clear`), it will automatically finalize the
object first.
Python currently only automatically finalizes objects that are members of a
:term:`cyclic isolate`, but future versions might finalize objects regularly
before their destruction.
To manually finalize an object, do not call this function directly; call
:c:func:`PyObject_CallFinalizer` or
:c:func:`PyObject_CallFinalizerFromDealloc` instead.
:c:member:`~PyTypeObject.tp_finalize` should leave the current exception
status unchanged. The recommended way to write a non-trivial finalizer is
to back up the exception at the beginning by calling
:c:func:`PyErr_GetRaisedException` and restore the exception at the end by
calling :c:func:`PyErr_SetRaisedException`. If an exception is encountered
in the middle of the finalizer, log and clear it with
:c:func:`PyErr_WriteUnraisable` or :c:func:`PyErr_FormatUnraisable`. For
example::
static void
local_finalize(PyObject *self)
foo_finalize(PyObject *self)
{
/* Save the current exception, if any. */
// Save the current exception, if any.
PyObject *exc = PyErr_GetRaisedException();
/* ... */
// ...
/* Restore the saved exception. */
if (do_something_that_might_raise() != success_indicator) {
PyErr_WriteUnraisable(self);
goto done;
}
done:
// Restore the saved exception. This silently discards any exception
// raised above, so be sure to call PyErr_WriteUnraisable first if
// necessary.
PyErr_SetRaisedException(exc);
}
@ -2182,7 +2421,13 @@ and :c:data:`PyType_Type` effectively act as defaults.)
:c:macro:`Py_TPFLAGS_HAVE_FINALIZE` flags bit in order for this field to be
used. This is no longer required.
.. seealso:: "Safe object finalization" (:pep:`442`)
.. seealso::
* :pep:`442`: "Safe object finalization"
* :ref:`life-cycle` for details about how this slot relates to other
slots.
* :c:func:`PyObject_CallFinalizer`
* :c:func:`PyObject_CallFinalizerFromDealloc`
.. c:member:: vectorcallfunc PyTypeObject.tp_vectorcall

View file

@ -645,6 +645,17 @@ APIs:
difference being that it decrements the reference count of *right* by one.
.. c:function:: PyObject* PyUnicode_BuildEncodingMap(PyObject* string)
Return a mapping suitable for decoding a custom single-byte encoding.
Given a Unicode string *string* of up to 256 characters representing an encoding
table, returns either a compact internal mapping object or a dictionary
mapping character ordinals to byte values. Raises a :exc:`TypeError` and
return ``NULL`` on invalid input.
.. versionadded:: 3.2
.. c:function:: const char* PyUnicode_GetDefaultEncoding(void)
Return the name of the default string encoding, ``"utf-8"``.
@ -1450,10 +1461,6 @@ the user settings on the machine running the codec.
.. versionadded:: 3.3
Methods & Slots
"""""""""""""""
.. _unicodemethodsandslots:
Methods and Slot Functions
@ -1715,10 +1722,6 @@ They all return ``NULL`` or ``-1`` if an exception occurs.
from user input, prefer calling :c:func:`PyUnicode_FromString` and
:c:func:`PyUnicode_InternInPlace` directly.
.. impl-detail::
Strings interned this way are made :term:`immortal`.
.. c:function:: unsigned int PyUnicode_CHECK_INTERNED(PyObject *str)
@ -1795,9 +1798,24 @@ object.
See also :c:func:`PyUnicodeWriter_DecodeUTF8Stateful`.
.. c:function:: int PyUnicodeWriter_WriteASCII(PyUnicodeWriter *writer, const char *str, Py_ssize_t size)
Write the ASCII string *str* into *writer*.
*size* is the string length in bytes. If *size* is equal to ``-1``, call
``strlen(str)`` to get the string length.
*str* must only contain ASCII characters. The behavior is undefined if
*str* contains non-ASCII characters.
On success, return ``0``.
On error, set an exception, leave the writer unchanged, and return ``-1``.
.. versionadded:: next
.. c:function:: int PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer, const wchar_t *str, Py_ssize_t size)
Writer the wide string *str* into *writer*.
Write the wide string *str* into *writer*.
*size* is a number of wide characters. If *size* is equal to ``-1``, call
``wcslen(str)`` to get the string length.

View file

@ -308,7 +308,6 @@ nitpick_ignore += [
('py:attr', '__annotations__'),
('py:meth', '__missing__'),
('py:attr', '__wrapped__'),
('py:attr', 'decimal.Context.clamp'),
('py:meth', 'index'), # list.index, tuple.index, etc.
]

View file

@ -1093,9 +1093,6 @@ PyImport_ImportModuleLevelObject:PyObject*:locals:0:???
PyImport_ImportModuleLevelObject:PyObject*:fromlist:0:???
PyImport_ImportModuleLevelObject:int:level::
PyImport_ImportModuleNoBlock:PyObject*::+1:
PyImport_ImportModuleNoBlock:const char*:name::
PyImport_ReloadModule:PyObject*::+1:
PyImport_ReloadModule:PyObject*:m:0:
@ -2781,6 +2778,9 @@ PyUnicode_AppendAndDel:void:::
PyUnicode_AppendAndDel:PyObject**:p_left:0:
PyUnicode_AppendAndDel:PyObject*:right:-1:
PyUnicode_BuildEncodingMap:PyObject*::+1:
PyUnicode_BuildEncodingMap:PyObject*:string:::
PyUnicode_GetDefaultEncoding:const char*:::
PyUnicode_GetDefaultEncoding::void::
@ -3007,18 +3007,8 @@ Py_GetCompiler:const char*:::
Py_GetCopyright:const char*:::
Py_GetExecPrefix:wchar_t*:::
Py_GetPath:wchar_t*:::
Py_GetPlatform:const char*:::
Py_GetPrefix:wchar_t*:::
Py_GetProgramFullPath:wchar_t*:::
Py_GetProgramName:wchar_t*:::
Py_GetVersion:const char*:::
Py_INCREF:void:::

View file

@ -323,7 +323,6 @@ func,PyImport_ImportFrozenModuleObject,3.7,,
func,PyImport_ImportModule,3.2,,
func,PyImport_ImportModuleLevel,3.2,,
func,PyImport_ImportModuleLevelObject,3.7,,
func,PyImport_ImportModuleNoBlock,3.2,,
func,PyImport_ReloadModule,3.2,,
func,PyIndex_Check,3.8,,
type,PyInterpreterState,3.2,,opaque
@ -629,7 +628,11 @@ func,PySys_Audit,3.13,,
func,PySys_AuditTuple,3.13,,
func,PySys_FormatStderr,3.2,,
func,PySys_FormatStdout,3.2,,
func,PySys_GetAttr,3.15,,
func,PySys_GetAttrString,3.15,,
func,PySys_GetObject,3.2,,
func,PySys_GetOptionalAttr,3.15,,
func,PySys_GetOptionalAttrString,3.15,,
func,PySys_GetXOptions,3.7,,
func,PySys_ResetWarnOptions,3.2,,
func,PySys_SetArgv,3.2,,
@ -740,11 +743,7 @@ func,PyUnicode_Append,3.2,,
func,PyUnicode_AppendAndDel,3.2,,
func,PyUnicode_AsASCIIString,3.2,,
func,PyUnicode_AsCharmapString,3.2,,
func,PyUnicode_AsDecodedObject,3.2,,
func,PyUnicode_AsDecodedUnicode,3.2,,
func,PyUnicode_AsEncodedObject,3.2,,
func,PyUnicode_AsEncodedString,3.2,,
func,PyUnicode_AsEncodedUnicode,3.2,,
func,PyUnicode_AsLatin1String,3.2,,
func,PyUnicode_AsMBCSString,3.7,on Windows,
func,PyUnicode_AsRawUnicodeEscapeString,3.2,,
@ -862,13 +861,7 @@ func,Py_GetCompiler,3.2,,
func,Py_GetConstant,3.13,,
func,Py_GetConstantBorrowed,3.13,,
func,Py_GetCopyright,3.2,,
func,Py_GetExecPrefix,3.2,,
func,Py_GetPath,3.2,,
func,Py_GetPlatform,3.2,,
func,Py_GetPrefix,3.2,,
func,Py_GetProgramFullPath,3.2,,
func,Py_GetProgramName,3.2,,
func,Py_GetPythonHome,3.2,,
func,Py_GetRecursionLimit,3.2,,
func,Py_GetVersion,3.2,,
data,Py_HasFileSystemDefaultEncoding,3.2,,

View file

@ -2,7 +2,7 @@ Pending removal in Python 3.15
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* The bundled copy of ``libmpdecimal``.
* The :c:func:`PyImport_ImportModuleNoBlock`:
* The :c:func:`!PyImport_ImportModuleNoBlock`:
Use :c:func:`PyImport_ImportModule` instead.
* :c:func:`PyWeakref_GetObject` and :c:func:`PyWeakref_GET_OBJECT`:
Use :c:func:`PyWeakref_GetRef` instead. The `pythoncapi-compat project
@ -22,27 +22,27 @@ Pending removal in Python 3.15
may return a type other than :class:`bytes`, such as :class:`str`.
* Python initialization functions, deprecated in Python 3.13:
* :c:func:`Py_GetPath`:
* :c:func:`!Py_GetPath`:
Use :c:func:`PyConfig_Get("module_search_paths") <PyConfig_Get>`
(:data:`sys.path`) instead.
* :c:func:`Py_GetPrefix`:
* :c:func:`!Py_GetPrefix`:
Use :c:func:`PyConfig_Get("base_prefix") <PyConfig_Get>`
(:data:`sys.base_prefix`) instead. Use :c:func:`PyConfig_Get("prefix")
<PyConfig_Get>` (:data:`sys.prefix`) if :ref:`virtual environments
<venv-def>` need to be handled.
* :c:func:`Py_GetExecPrefix`:
* :c:func:`!Py_GetExecPrefix`:
Use :c:func:`PyConfig_Get("base_exec_prefix") <PyConfig_Get>`
(:data:`sys.base_exec_prefix`) instead. Use
:c:func:`PyConfig_Get("exec_prefix") <PyConfig_Get>`
(:data:`sys.exec_prefix`) if :ref:`virtual environments <venv-def>` need to
be handled.
* :c:func:`Py_GetProgramFullPath`:
* :c:func:`!Py_GetProgramFullPath`:
Use :c:func:`PyConfig_Get("executable") <PyConfig_Get>`
(:data:`sys.executable`) instead.
* :c:func:`Py_GetProgramName`:
* :c:func:`!Py_GetProgramName`:
Use :c:func:`PyConfig_Get("executable") <PyConfig_Get>`
(:data:`sys.executable`) instead.
* :c:func:`Py_GetPythonHome`:
* :c:func:`!Py_GetPythonHome`:
Use :c:func:`PyConfig_Get("home") <PyConfig_Get>` or the
:envvar:`PYTHONHOME` environment variable instead.

View file

@ -5,6 +5,10 @@ Deprecations
.. include:: pending-removal-in-3.16.rst
.. include:: pending-removal-in-3.17.rst
.. include:: pending-removal-in-3.19.rst
.. include:: pending-removal-in-future.rst
C API deprecations
@ -12,4 +16,6 @@ C API deprecations
.. include:: c-api-pending-removal-in-3.15.rst
.. include:: c-api-pending-removal-in-3.18.rst
.. include:: c-api-pending-removal-in-future.rst

View file

@ -78,7 +78,7 @@ Pending removal in Python 3.14
:meth:`~pathlib.PurePath.relative_to`: passing additional arguments is
deprecated.
* :mod:`pkgutil`: :func:`!pkgutil.find_loader` and :func:!pkgutil.get_loader`
* :mod:`pkgutil`: :func:`!pkgutil.find_loader` and :func:`!pkgutil.get_loader`
now raise :exc:`DeprecationWarning`;
use :func:`importlib.util.find_spec` instead.
(Contributed by Nikita Sobolev in :gh:`97850`.)

View file

@ -20,7 +20,7 @@ Pending removal in Python 3.15
* :mod:`http.server`:
* The obsolete and rarely used :class:`~http.server.CGIHTTPRequestHandler`
* The obsolete and rarely used :class:`!CGIHTTPRequestHandler`
has been deprecated since Python 3.13.
No direct replacement exists.
*Anything* is better than CGI to interface
@ -51,7 +51,7 @@ Pending removal in Python 3.15
* :mod:`platform`:
* :func:`~platform.java_ver` has been deprecated since Python 3.13.
* :func:`!platform.java_ver` has been deprecated since Python 3.13.
This function is only useful for Jython support, has a confusing API,
and is largely untested.
@ -85,6 +85,13 @@ Pending removal in Python 3.15
has been deprecated since Python 3.13.
Use the class-based syntax or the functional syntax instead.
* When using the functional syntax of :class:`~typing.TypedDict`\s, failing
to pass a value to the *fields* parameter (``TD = TypedDict("TD")``) or
passing ``None`` (``TD = TypedDict("TD", None)``) has been deprecated
since Python 3.13.
Use ``class TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})``
to create a TypedDict with zero field.
* The :func:`typing.no_type_check_decorator` decorator function
has been deprecated since Python 3.13.
After eight years in the :mod:`typing` module,
@ -92,8 +99,7 @@ Pending removal in Python 3.15
* :mod:`wave`:
* The :meth:`~wave.Wave_read.getmark`, :meth:`!setmark`,
and :meth:`~wave.Wave_read.getmarkers` methods of
* The ``getmark()``, ``setmark()`` and ``getmarkers()`` methods of
the :class:`~wave.Wave_read` and :class:`~wave.Wave_write` classes
have been deprecated since Python 3.13.

View file

@ -61,6 +61,12 @@ Pending removal in Python 3.16
* Calling the Python implementation of :func:`functools.reduce` with *function*
or *sequence* as keyword arguments has been deprecated since Python 3.14.
* :mod:`logging`:
Support for custom logging handlers with the *strm* argument is deprecated
and scheduled for removal in Python 3.16. Define handlers with the *stream*
argument instead. (Contributed by Mariusz Felisiak in :gh:`115032`.)
* :mod:`mimetypes`:
* Valid extensions start with a '.' or are empty for

View file

@ -0,0 +1,10 @@
Pending removal in Python 3.17
------------------------------
* :mod:`typing`:
- Before Python 3.14, old-style unions were implemented using the private class
``typing._UnionGenericAlias``. This class is no longer needed for the implementation,
but it has been retained for backward compatibility, with removal scheduled for Python
3.17. Users should use documented introspection helpers like :func:`typing.get_origin`
and :func:`typing.get_args` instead of relying on private implementation details.

View file

@ -0,0 +1,8 @@
Pending removal in Python 3.19
------------------------------
* :mod:`ctypes`:
* Implicitly switching to the MSVC-compatible struct layout by setting
:attr:`~ctypes.Structure._pack_` but not :attr:`~ctypes.Structure._layout_`
on non-Windows platforms.

View file

@ -23,10 +23,10 @@ instance. See :ref:`initializing-modules` for details.
.. highlight:: python
For modules with ASCII-only names, the function must be named
``PyInit_<modulename>``, with ``<modulename>`` replaced by the name of the
module. When using :ref:`multi-phase-initialization`, non-ASCII module names
: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
``PyInitU_<modulename>``, with ``<modulename>`` encoded using Python's
:samp:`PyInitU_{<name>}`, with ``<name>`` encoded using Python's
*punycode* encoding with hyphens replaced by underscores. In Python::
def initfunc_name(name):

View file

@ -245,21 +245,23 @@ Python extension. For example::
return PyLong_FromLong(numargs);
}
static PyMethodDef EmbMethods[] = {
static PyMethodDef emb_module_methods[] = {
{"numargs", emb_numargs, METH_VARARGS,
"Return the number of arguments received by the process."},
{NULL, NULL, 0, NULL}
};
static PyModuleDef EmbModule = {
PyModuleDef_HEAD_INIT, "emb", NULL, -1, EmbMethods,
NULL, NULL, NULL, NULL
static struct PyModuleDef emb_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "emb",
.m_size = 0,
.m_methods = emb_module_methods,
};
static PyObject*
PyInit_emb(void)
{
return PyModule_Create(&EmbModule);
return PyModuleDef_Init(&emb_module);
}
Insert the above code just above the :c:func:`main` function. Also, insert the

View file

@ -203,31 +203,57 @@ function usually raises :c:data:`PyExc_TypeError`. If you have an argument whos
value must be in a particular range or must satisfy other conditions,
:c:data:`PyExc_ValueError` is appropriate.
You can also define a new exception that is unique to your module. For this, you
usually declare a static object variable at the beginning of your file::
You can also define a new exception that is unique to your module.
The simplest way to do this is to declare a static global object variable at
the beginning of the file::
static PyObject *SpamError;
static PyObject *SpamError = NULL;
and initialize it in your module's initialization function (:c:func:`!PyInit_spam`)
with an exception object::
and initialize it by calling :c:func:`PyErr_NewException` in the module's
:c:data:`Py_mod_exec` function (:c:func:`!spam_module_exec`)::
SpamError = PyErr_NewException("spam.error", NULL, NULL);
Since :c:data:`!SpamError` is a global variable, it will be overwitten every time
the module is reinitialized, when the :c:data:`Py_mod_exec` function is called.
For now, let's avoid the issue: we will block repeated initialization by raising an
:py:exc:`ImportError`::
static PyObject *SpamError = NULL;
static int
spam_module_exec(PyObject *m)
{
if (SpamError != NULL) {
PyErr_SetString(PyExc_ImportError,
"cannot initialize spam module more than once");
return -1;
}
SpamError = PyErr_NewException("spam.error", NULL, NULL);
if (PyModule_AddObjectRef(m, "SpamError", SpamError) < 0) {
return -1;
}
return 0;
}
static PyModuleDef_Slot spam_module_slots[] = {
{Py_mod_exec, spam_module_exec},
{0, NULL}
};
static struct PyModuleDef spam_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "spam",
.m_size = 0, // non-negative
.m_slots = spam_module_slots,
};
PyMODINIT_FUNC
PyInit_spam(void)
{
PyObject *m;
m = PyModule_Create(&spammodule);
if (m == NULL)
return NULL;
SpamError = PyErr_NewException("spam.error", NULL, NULL);
if (PyModule_AddObjectRef(m, "error", SpamError) < 0) {
Py_CLEAR(SpamError);
Py_DECREF(m);
return NULL;
}
return m;
return PyModuleDef_Init(&spam_module);
}
Note that the Python name for the exception object is :exc:`!spam.error`. The
@ -242,6 +268,11 @@ needed to ensure that it will not be discarded, causing :c:data:`!SpamError` to
become a dangling pointer. Should it become a dangling pointer, C code which
raises the exception could cause a core dump or other unintended side effects.
For now, the :c:func:`Py_DECREF` call to remove this reference is missing.
Even when the Python interpreter shuts down, the global :c:data:`!SpamError`
variable will not be garbage-collected. It will "leak".
We did, however, ensure that this will happen at most once per process.
We discuss the use of :c:macro:`PyMODINIT_FUNC` as a function return type later in this
sample.
@ -318,7 +349,7 @@ The Module's Method Table and Initialization Function
I promised to show how :c:func:`!spam_system` is called from Python programs.
First, we need to list its name and address in a "method table"::
static PyMethodDef SpamMethods[] = {
static PyMethodDef spam_methods[] = {
...
{"system", spam_system, METH_VARARGS,
"Execute a shell command."},
@ -343,13 +374,10 @@ function.
The method table must be referenced in the module definition structure::
static struct PyModuleDef spammodule = {
PyModuleDef_HEAD_INIT,
"spam", /* name of module */
spam_doc, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
SpamMethods
static struct PyModuleDef spam_module = {
...
.m_methods = spam_methods,
...
};
This structure, in turn, must be passed to the interpreter in the module's
@ -360,23 +388,17 @@ only non-\ ``static`` item defined in the module file::
PyMODINIT_FUNC
PyInit_spam(void)
{
return PyModule_Create(&spammodule);
return PyModuleDef_Init(&spam_module);
}
Note that :c:macro:`PyMODINIT_FUNC` declares the function as ``PyObject *`` return type,
declares any special linkage declarations required by the platform, and for C++
declares the function as ``extern "C"``.
When the Python program imports module :mod:`!spam` for the first time,
:c:func:`!PyInit_spam` is called. (See below for comments about embedding Python.)
It calls :c:func:`PyModule_Create`, which returns a module object, and
inserts built-in function objects into the newly created module based upon the
table (an array of :c:type:`PyMethodDef` structures) found in the module definition.
:c:func:`PyModule_Create` returns a pointer to the module object
that it creates. It may abort with a fatal error for
certain errors, or return ``NULL`` if the module could not be initialized
satisfactorily. The init function must return the module object to its caller,
so that it then gets inserted into ``sys.modules``.
:c:func:`!PyInit_spam` is called when each interpreter imports its module
:mod:`!spam` for the first time. (See below for comments about embedding Python.)
A pointer to the module definition must be returned via :c:func:`PyModuleDef_Init`,
so that the import machinery can create the module and store it in ``sys.modules``.
When embedding Python, the :c:func:`!PyInit_spam` function is not called
automatically unless there's an entry in the :c:data:`PyImport_Inittab` table.
@ -433,23 +455,19 @@ optionally followed by an import of the module::
.. note::
Removing entries from ``sys.modules`` or importing compiled modules into
multiple interpreters within a process (or following a :c:func:`fork` without an
intervening :c:func:`exec`) can create problems for some extension modules.
Extension module authors should exercise caution when initializing internal data
structures.
If you declare a global variable or a local static one, the module may
experience unintended side-effects on re-initialisation, for example when
removing entries from ``sys.modules`` or importing compiled modules into
multiple interpreters within a process
(or following a :c:func:`fork` without an intervening :c:func:`exec`).
If module state is not yet fully :ref:`isolated <isolating-extensions-howto>`,
authors should consider marking the module as having no support for subinterpreters
(via :c:macro:`Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED`).
A more substantial example module is included in the Python source distribution
as :file:`Modules/xxmodule.c`. This file may be used as a template or simply
as :file:`Modules/xxlimited.c`. This file may be used as a template or simply
read as an example.
.. note::
Unlike our ``spam`` example, ``xxmodule`` uses *multi-phase initialization*
(new in Python 3.5), where a PyModuleDef structure is returned from
``PyInit_spam``, and creation of the module is left to the import machinery.
For details on multi-phase initialization, see :PEP:`489`.
.. _compilation:
@ -790,18 +808,17 @@ Philbrick (philbrick@hks.com)::
{NULL, NULL, 0, NULL} /* sentinel */
};
static struct PyModuleDef keywdargmodule = {
PyModuleDef_HEAD_INIT,
"keywdarg",
NULL,
-1,
keywdarg_methods
static struct PyModuleDef keywdarg_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "keywdarg",
.m_size = 0,
.m_methods = keywdarg_methods,
};
PyMODINIT_FUNC
PyInit_keywdarg(void)
{
return PyModule_Create(&keywdargmodule);
return PyModuleDef_Init(&keywdarg_module);
}
@ -1072,8 +1089,9 @@ why his :meth:`!__del__` methods would fail...
The second case of problems with a borrowed reference is a variant involving
threads. Normally, multiple threads in the Python interpreter can't get in each
other's way, because there is a global lock protecting Python's entire object
space. However, it is possible to temporarily release this lock using the macro
other's way, because there is a :term:`global lock <global interpreter lock>`
protecting Python's entire object space.
However, it is possible to temporarily release this lock using the macro
:c:macro:`Py_BEGIN_ALLOW_THREADS`, and to re-acquire it using
:c:macro:`Py_END_ALLOW_THREADS`. This is common around blocking I/O calls, to
let other threads use the processor while waiting for the I/O to complete.
@ -1259,20 +1277,15 @@ two more lines must be added::
#include "spammodule.h"
The ``#define`` is used to tell the header file that it is being included in the
exporting module, not a client module. Finally, the module's initialization
function must take care of initializing the C API pointer array::
exporting module, not a client module. Finally, the module's :c:data:`mod_exec
<Py_mod_exec>` function must take care of initializing the C API pointer array::
PyMODINIT_FUNC
PyInit_spam(void)
static int
spam_module_exec(PyObject *m)
{
PyObject *m;
static void *PySpam_API[PySpam_API_pointers];
PyObject *c_api_object;
m = PyModule_Create(&spammodule);
if (m == NULL)
return NULL;
/* Initialize the C API pointer array */
PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;
@ -1280,11 +1293,10 @@ function must take care of initializing the C API pointer array::
c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);
if (PyModule_Add(m, "_C_API", c_api_object) < 0) {
Py_DECREF(m);
return NULL;
return -1;
}
return m;
return 0;
}
Note that ``PySpam_API`` is declared ``static``; otherwise the pointer
@ -1343,20 +1355,16 @@ like this::
All that a client module must do in order to have access to the function
:c:func:`!PySpam_System` is to call the function (or rather macro)
:c:func:`!import_spam` in its initialization function::
:c:func:`!import_spam` in its :c:data:`mod_exec <Py_mod_exec>` function::
PyMODINIT_FUNC
PyInit_client(void)
static int
client_module_exec(PyObject *m)
{
PyObject *m;
m = PyModule_Create(&clientmodule);
if (m == NULL)
return NULL;
if (import_spam() < 0)
return NULL;
if (import_spam() < 0) {
return -1;
}
/* additional initialization can happen here */
return m;
return 0;
}
The main disadvantage of this approach is that the file :file:`spammodule.h` is

View file

@ -26,19 +26,9 @@ Recommended third party tools
=============================
This guide only covers the basic tools for creating extensions provided
as part of this version of CPython. Third party tools like
`Cython <https://cython.org/>`_, `cffi <https://cffi.readthedocs.io>`_,
`SWIG <https://www.swig.org>`_ and `Numba <https://numba.pydata.org/>`_
offer both simpler and more sophisticated approaches to creating C and C++
extensions for Python.
.. seealso::
`Python Packaging User Guide: Binary Extensions <https://packaging.python.org/guides/packaging-binary-extensions/>`_
The Python Packaging User Guide not only covers several available
tools that simplify the creation of binary extensions, but also
discusses the various reasons why creating an extension module may be
desirable in the first place.
as part of this version of CPython. Some :ref:`third party tools
<c-api-tools>` offer both simpler and more sophisticated approaches to creating
C and C++ extensions for Python.
Creating extensions without third party tools
@ -49,6 +39,10 @@ assistance from third party tools. It is intended primarily for creators
of those tools, rather than being a recommended way to create your own
C extensions.
.. seealso::
:pep:`489` -- Multi-phase extension module initialization
.. toctree::
:maxdepth: 2
:numbered:

View file

@ -55,8 +55,10 @@ from the previous chapter. This file defines three things:
#. How the :class:`!Custom` **type** behaves: this is the ``CustomType`` struct,
which defines a set of flags and function pointers that the interpreter
inspects when specific operations are requested.
#. How to initialize the :mod:`!custom` module: this is the ``PyInit_custom``
function and the associated ``custommodule`` struct.
#. How to define and execute the :mod:`!custom` module: this is the
``PyInit_custom`` function and the associated ``custom_module`` struct for
defining the module, and the ``custom_module_exec`` function to set up
a fresh module object.
The first bit is::
@ -171,18 +173,18 @@ implementation provided by the API function :c:func:`PyType_GenericNew`. ::
.tp_new = PyType_GenericNew,
Everything else in the file should be familiar, except for some code in
:c:func:`!PyInit_custom`::
:c:func:`!custom_module_exec`::
if (PyType_Ready(&CustomType) < 0)
return;
if (PyType_Ready(&CustomType) < 0) {
return -1;
}
This initializes the :class:`!Custom` type, filling in a number of members
to the appropriate default values, including :c:member:`~PyObject.ob_type` that we initially
set to ``NULL``. ::
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
Py_DECREF(m);
return NULL;
return -1;
}
This adds the type to the module dictionary. This allows us to create
@ -875,27 +877,22 @@ but let the base class handle it by calling its own :c:member:`~PyTypeObject.tp_
The :c:type:`PyTypeObject` struct supports a :c:member:`~PyTypeObject.tp_base`
specifying the type's concrete base class. Due to cross-platform compiler
issues, you can't fill that field directly with a reference to
:c:type:`PyList_Type`; it should be done later in the module initialization
:c:type:`PyList_Type`; it should be done in the :c:data:`Py_mod_exec`
function::
PyMODINIT_FUNC
PyInit_sublist(void)
static int
sublist_module_exec(PyObject *m)
{
PyObject* m;
SubListType.tp_base = &PyList_Type;
if (PyType_Ready(&SubListType) < 0)
return NULL;
m = PyModule_Create(&sublistmodule);
if (m == NULL)
return NULL;
if (PyModule_AddObjectRef(m, "SubList", (PyObject *) &SubListType) < 0) {
Py_DECREF(m);
return NULL;
if (PyType_Ready(&SubListType) < 0) {
return -1;
}
return m;
if (PyModule_AddObjectRef(m, "SubList", (PyObject *) &SubListType) < 0) {
return -1;
}
return 0;
}
Before calling :c:func:`PyType_Ready`, the type structure must have the

View file

@ -420,10 +420,12 @@ strings representing the files in the current directory. Functions which
operate on this output would generally not break if you added another file or
two to the directory.
Tuples are immutable, meaning that once a tuple has been created, you can't
replace any of its elements with a new value. Lists are mutable, meaning that
you can always change a list's elements. Only immutable elements can be used as
dictionary keys, and hence only tuples and not lists can be used as keys.
Tuples are :term:`immutable`, meaning that once a tuple has been created, you can't
replace any of its elements with a new value. Lists are :term:`mutable`, meaning that
you can always change a list's elements. Only :term:`hashable` objects can
be used as dictionary keys. Most immutable types are hashable, which is why
tuples, but not lists, can be used as keys. Note, however, that a tuple is
only hashable if all of its elements are hashable.
How are lists implemented in CPython?

View file

@ -37,24 +37,9 @@ Writing C is hard; are there any alternatives?
----------------------------------------------
There are a number of alternatives to writing your own C extensions, depending
on what you're trying to do.
.. XXX make sure these all work
`Cython <https://cython.org>`_ and its relative `Pyrex
<https://www.csse.canterbury.ac.nz/greg.ewing/python/Pyrex/>`_ are compilers
that accept a slightly modified form of Python and generate the corresponding
C code. Cython and Pyrex make it possible to write an extension without having
to learn Python's C API.
If you need to interface to some C or C++ library for which no Python extension
currently exists, you can try wrapping the library's data types and functions
with a tool such as `SWIG <https://www.swig.org>`_. `SIP
<https://github.com/Python-SIP/sip>`__, `CXX
<https://cxx.sourceforge.net/>`_ `Boost
<https://www.boost.org/libs/python/doc/index.html>`_, or `Weave
<https://github.com/scipy/weave>`_ are also
alternatives for wrapping C++ libraries.
on what you're trying to do. :ref:`Recommended third party tools <c-api-tools>`
offer both simpler and more sophisticated approaches to creating C and C++
extensions for Python.
How can I execute arbitrary Python statements from C?

View file

@ -355,6 +355,12 @@ Glossary
tasks (see :mod:`asyncio`) associate each task with a context which
becomes the current context whenever the task starts or resumes execution.
cyclic isolate
A subgroup of one or more objects that reference each other in a reference
cycle, but are not referenced by objects outside the group. The goal of
the :term:`cyclic garbage collector <garbage collection>` is to identify these groups and break the reference
cycles so that the memory can be reclaimed.
decorator
A function returning another function, usually applied as a function
transformation using the ``@wrapper`` syntax. Common examples for

View file

@ -248,4 +248,9 @@ quirks by using :func:`annotationlib.get_annotations` on Python 3.14+ or
:func:`inspect.get_annotations` on Python 3.10+. On earlier versions of
Python, you can avoid these bugs by accessing the annotations from the
class's :attr:`~type.__dict__`
(e.g., ``cls.__dict__.get('__annotations__', None)``).
(for example, ``cls.__dict__.get('__annotations__', None)``).
In some versions of Python, instances of classes may have an ``__annotations__``
attribute. However, this is not supported functionality. If you need the
annotations of an instance, you can use :func:`type` to access its class
(for example, ``annotationlib.get_annotations(type(myinstance))`` on Python 3.14+).

View file

@ -14,13 +14,11 @@ We recommend the following resources for porting extension modules to Python 3:
module.
* The `Porting guide`_ from the *py3c* project provides opinionated
suggestions with supporting code.
* The `Cython`_ and `CFFI`_ libraries offer abstractions over
Python's C API.
* :ref:`Recommended third party tools <c-api-tools>` offer abstractions over
the Python's C API.
Extensions generally need to be re-written to use one of them,
but the library then handles differences between various Python
versions and implementations.
.. _Migrating C extensions: http://python3porting.com/cextensions.html
.. _Porting guide: https://py3c.readthedocs.io/en/latest/guide.html
.. _Cython: https://cython.org/
.. _CFFI: https://cffi.readthedocs.io/en/latest/

View file

@ -161,6 +161,8 @@ your terminal won't be left in a funny state on exception and you'll be
able to read the exception's message and traceback.
.. _windows-and-pads:
Windows and Pads
================

View file

@ -23,6 +23,14 @@ You can use it to enable code that only runs under the free-threaded build::
/* code that only runs in the free-threaded build */
#endif
.. note::
On Windows, this macro is not defined automatically, but must be specified
to the compiler when building. The :func:`sysconfig.get_config_var` function
can be used to determine whether the current running interpreter had the
macro defined.
Module Initialization
=====================
@ -388,7 +396,7 @@ The wheels, shared libraries, and binaries are indicated by a ``t`` suffix.
free-threaded build, with the ``t`` suffix, such as ``python3.13t``.
* `pypa/cibuildwheel <https://github.com/pypa/cibuildwheel>`_ supports the
free-threaded build if you set
`CIBW_FREE_THREADED_SUPPORT <https://cibuildwheel.pypa.io/en/stable/options/#free-threaded-support>`_.
`CIBW_ENABLE to cpython-freethreading <https://cibuildwheel.pypa.io/en/stable/options/#enable>`_.
Limited C API and Stable ABI
............................

View file

@ -32,7 +32,7 @@ optionally support installing free-threaded Python binaries. The installers
are available at https://www.python.org/downloads/.
For information on other platforms, see the `Installing a Free-Threaded Python
<https://py-free-threading.github.io/installing_cpython/>`_, a
<https://py-free-threading.github.io/installing-cpython/>`_, a
community-maintained installation guide for installing free-threaded Python.
When building CPython from source, the :option:`--disable-gil` configure option

View file

@ -372,8 +372,8 @@ have the form::
for expr2 in sequence2
if condition2
for expr3 in sequence3
...
if condition3
...
for exprN in sequenceN
if conditionN )

View file

@ -215,21 +215,36 @@ multiple interpreters correctly. If this is not yet the case for your
module, you can explicitly make your module loadable only once per
process. For example::
// A process-wide flag
static int loaded = 0;
// Mutex to provide thread safety (only needed for free-threaded Python)
static PyMutex modinit_mutex = {0};
static int
exec_module(PyObject* module)
{
PyMutex_Lock(&modinit_mutex);
if (loaded) {
PyMutex_Unlock(&modinit_mutex);
PyErr_SetString(PyExc_ImportError,
"cannot load module more than once per process");
return -1;
}
loaded = 1;
PyMutex_Unlock(&modinit_mutex);
// ... rest of initialization
}
If your module's :c:member:`PyModuleDef.m_clear` function is able to prepare
for future re-initialization, it should clear the ``loaded`` flag.
In this case, your module won't support multiple instances existing
*concurrently*, but it will, for example, support being loaded after
Python runtime shutdown (:c:func:`Py_FinalizeEx`) and re-initialization
(:c:func:`Py_Initialize`).
Module State Access from Functions
----------------------------------

View file

@ -626,7 +626,7 @@ which, when run, will produce:
of each message with the handler's level, and only passes a message to a
handler if it's appropriate to do so.
.. versionchanged:: next
.. versionchanged:: 3.14
The :class:`QueueListener` can be started (and stopped) via the
:keyword:`with` statement. For example:

View file

@ -738,9 +738,12 @@ given location, they can obviously be matched an infinite number of times.
different: ``\A`` still matches only at the beginning of the string, but ``^``
may match at any location inside the string that follows a newline character.
``\Z``
``\z``
Matches only at the end of the string.
``\Z``
The same as ``\z``. For compatibility with old Python versions.
``\b``
Word boundary. This is a zero-width assertion that matches only at the
beginning or end of a word. A word is defined as a sequence of alphanumeric

View file

@ -16,28 +16,37 @@ static PyTypeObject CustomType = {
.tp_new = PyType_GenericNew,
};
static PyModuleDef custommodule = {
static int
custom_module_exec(PyObject *m)
{
if (PyType_Ready(&CustomType) < 0) {
return -1;
}
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
return -1;
}
return 0;
}
static PyModuleDef_Slot custom_module_slots[] = {
{Py_mod_exec, custom_module_exec},
// Just use this while using static types
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
{0, NULL}
};
static PyModuleDef custom_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "custom",
.m_doc = "Example module that creates an extension type.",
.m_size = -1,
.m_size = 0,
.m_slots = custom_module_slots,
};
PyMODINIT_FUNC
PyInit_custom(void)
{
PyObject *m;
if (PyType_Ready(&CustomType) < 0)
return NULL;
m = PyModule_Create(&custommodule);
if (m == NULL)
return NULL;
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
Py_DECREF(m);
return NULL;
}
return m;
return PyModuleDef_Init(&custom_module);
}

View file

@ -106,28 +106,36 @@ static PyTypeObject CustomType = {
.tp_methods = Custom_methods,
};
static PyModuleDef custommodule = {
.m_base =PyModuleDef_HEAD_INIT,
static int
custom_module_exec(PyObject *m)
{
if (PyType_Ready(&CustomType) < 0) {
return -1;
}
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
return -1;
}
return 0;
}
static PyModuleDef_Slot custom_module_slots[] = {
{Py_mod_exec, custom_module_exec},
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
{0, NULL}
};
static PyModuleDef custom_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "custom2",
.m_doc = "Example module that creates an extension type.",
.m_size = -1,
.m_size = 0,
.m_slots = custom_module_slots,
};
PyMODINIT_FUNC
PyInit_custom2(void)
{
PyObject *m;
if (PyType_Ready(&CustomType) < 0)
return NULL;
m = PyModule_Create(&custommodule);
if (m == NULL)
return NULL;
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
Py_DECREF(m);
return NULL;
}
return m;
return PyModuleDef_Init(&custom_module);
}

View file

@ -151,28 +151,36 @@ static PyTypeObject CustomType = {
.tp_getset = Custom_getsetters,
};
static PyModuleDef custommodule = {
static int
custom_module_exec(PyObject *m)
{
if (PyType_Ready(&CustomType) < 0) {
return -1;
}
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
return -1;
}
return 0;
}
static PyModuleDef_Slot custom_module_slots[] = {
{Py_mod_exec, custom_module_exec},
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
{0, NULL}
};
static PyModuleDef custom_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "custom3",
.m_doc = "Example module that creates an extension type.",
.m_size = -1,
.m_size = 0,
.m_slots = custom_module_slots,
};
PyMODINIT_FUNC
PyInit_custom3(void)
{
PyObject *m;
if (PyType_Ready(&CustomType) < 0)
return NULL;
m = PyModule_Create(&custommodule);
if (m == NULL)
return NULL;
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
Py_DECREF(m);
return NULL;
}
return m;
return PyModuleDef_Init(&custom_module);
}

View file

@ -170,28 +170,36 @@ static PyTypeObject CustomType = {
.tp_getset = Custom_getsetters,
};
static PyModuleDef custommodule = {
static int
custom_module_exec(PyObject *m)
{
if (PyType_Ready(&CustomType) < 0) {
return -1;
}
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
return -1;
}
return 0;
}
static PyModuleDef_Slot custom_module_slots[] = {
{Py_mod_exec, custom_module_exec},
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
{0, NULL}
};
static PyModuleDef custom_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "custom4",
.m_doc = "Example module that creates an extension type.",
.m_size = -1,
.m_size = 0,
.m_slots = custom_module_slots,
};
PyMODINIT_FUNC
PyInit_custom4(void)
{
PyObject *m;
if (PyType_Ready(&CustomType) < 0)
return NULL;
m = PyModule_Create(&custommodule);
if (m == NULL)
return NULL;
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
Py_DECREF(m);
return NULL;
}
return m;
return PyModuleDef_Init(&custom_module);
}

View file

@ -31,7 +31,7 @@ SubList_init(PyObject *op, PyObject *args, PyObject *kwds)
}
static PyTypeObject SubListType = {
PyVarObject_HEAD_INIT(NULL, 0)
.ob_base = PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "sublist.SubList",
.tp_doc = PyDoc_STR("SubList objects"),
.tp_basicsize = sizeof(SubListObject),
@ -41,29 +41,37 @@ static PyTypeObject SubListType = {
.tp_methods = SubList_methods,
};
static PyModuleDef sublistmodule = {
PyModuleDef_HEAD_INIT,
static int
sublist_module_exec(PyObject *m)
{
SubListType.tp_base = &PyList_Type;
if (PyType_Ready(&SubListType) < 0) {
return -1;
}
if (PyModule_AddObjectRef(m, "SubList", (PyObject *) &SubListType) < 0) {
return -1;
}
return 0;
}
static PyModuleDef_Slot sublist_module_slots[] = {
{Py_mod_exec, sublist_module_exec},
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
{0, NULL}
};
static PyModuleDef sublist_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "sublist",
.m_doc = "Example module that creates an extension type.",
.m_size = -1,
.m_size = 0,
.m_slots = sublist_module_slots,
};
PyMODINIT_FUNC
PyInit_sublist(void)
{
PyObject *m;
SubListType.tp_base = &PyList_Type;
if (PyType_Ready(&SubListType) < 0)
return NULL;
m = PyModule_Create(&sublistmodule);
if (m == NULL)
return NULL;
if (PyModule_AddObjectRef(m, "SubList", (PyObject *) &SubListType) < 0) {
Py_DECREF(m);
return NULL;
}
return m;
return PyModuleDef_Init(&sublist_module);
}

View file

@ -40,7 +40,7 @@ The :func:`get_annotations` function is the main entry point for
retrieving annotations. Given a function, class, or module, it returns
an annotations dictionary in the requested format. This module also provides
functionality for working directly with the :term:`annotate function`
that is used to evaluate annotations, such as :func:`get_annotate_function`
that is used to evaluate annotations, such as :func:`get_annotate_from_class_namespace`
and :func:`call_annotate_function`, as well as the
:func:`call_evaluate_function` function for working with
:term:`evaluate functions <evaluate function>`.
@ -127,25 +127,8 @@ Classes
Values are the result of evaluating the annotation expressions.
.. attribute:: FORWARDREF
:value: 2
Values are real annotation values (as per :attr:`Format.VALUE` format)
for defined values, and :class:`ForwardRef` proxies for undefined
values. Real objects may contain references to, :class:`ForwardRef`
proxy objects.
.. attribute:: STRING
:value: 3
Values are the text string of the annotation as it appears in the
source code, up to modifications including, but not restricted to,
whitespace normalizations and constant values optimizations.
The exact values of these strings may change in future versions of Python.
.. attribute:: VALUE_WITH_FAKE_GLOBALS
:value: 4
:value: 2
Special value used to signal that an annotate function is being
evaluated in a special environment with fake globals. When passed this
@ -155,6 +138,23 @@ Classes
This format is only used internally and should not be passed to
the functions in this module.
.. attribute:: FORWARDREF
:value: 3
Values are real annotation values (as per :attr:`Format.VALUE` format)
for defined values, and :class:`ForwardRef` proxies for undefined
values. Real objects may contain references to :class:`ForwardRef`
proxy objects.
.. attribute:: STRING
:value: 4
Values are the text string of the annotation as it appears in the
source code, up to modifications including, but not restricted to,
whitespace normalizations and constant values optimizations.
The exact values of these strings may change in future versions of Python.
.. versionadded:: 3.14
.. class:: ForwardRef
@ -172,14 +172,21 @@ Classes
:class:`~ForwardRef`. The string may not be exactly equivalent
to the original source.
.. method:: evaluate(*, owner=None, globals=None, locals=None, type_params=None)
.. method:: evaluate(*, owner=None, globals=None, locals=None, type_params=None, format=Format.VALUE)
Evaluate the forward reference, returning its value.
This may throw an exception, such as :exc:`NameError`, if the forward
If the *format* argument is :attr:`~Format.VALUE` (the default),
this method may throw an exception, such as :exc:`NameError`, if the forward
reference refers to a name that cannot be resolved. The arguments to this
method can be used to provide bindings for names that would otherwise
be undefined.
be undefined. If the *format* argument is :attr:`~Format.FORWARDREF`,
the method will never throw an exception, but may return a :class:`~ForwardRef`
instance. For example, if the forward reference object contains the code
``list[undefined]``, where ``undefined`` is a name that is not defined,
evaluating it with the :attr:`~Format.FORWARDREF` format will return
``list[ForwardRef('undefined')]``. If the *format* argument is
:attr:`~Format.STRING`, the method will return :attr:`~ForwardRef.__forward_arg__`.
The *owner* parameter provides the preferred mechanism for passing scope
information to this method. The owner of a :class:`~ForwardRef` is the
@ -204,6 +211,10 @@ Classes
means may not have any information about their scope, so passing
arguments to this method may be necessary to evaluate them successfully.
If no *owner*, *globals*, *locals*, or *type_params* are provided and the
:class:`~ForwardRef` does not contain information about its origin,
empty globals and locals dictionaries are used.
.. versionadded:: 3.14
@ -300,15 +311,13 @@ Functions
.. versionadded:: 3.14
.. function:: get_annotate_function(obj)
.. function:: get_annotate_from_class_namespace(namespace)
Retrieve the :term:`annotate function` for *obj*. Return :const:`!None`
if *obj* does not have an annotate function. *obj* may be a class, function,
module, or a namespace dictionary for a class. The last case is useful during
class creation, e.g. in the ``__new__`` method of a metaclass.
This is usually equivalent to accessing the :attr:`~object.__annotate__`
attribute of *obj*, but access through this public function is preferred.
Retrieve the :term:`annotate function` from a class namespace dictionary *namespace*.
Return :const:`!None` if the namespace does not contain an annotate function.
This is primarily useful before the class has been fully created (e.g., in a metaclass);
after the class exists, the annotate function can be retrieved with ``cls.__annotate__``.
See :ref:`below <annotationlib-metaclass>` for an example using this function in a metaclass.
.. versionadded:: 3.14
@ -407,3 +416,190 @@ Functions
.. versionadded:: 3.14
Recipes
-------
.. _annotationlib-metaclass:
Using annotations in a metaclass
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A :ref:`metaclass <metaclasses>` may want to inspect or even modify the annotations
in a class body during class creation. Doing so requires retrieving annotations
from the class namespace dictionary. For classes created with
``from __future__ import annotations``, the annotations will be in the ``__annotations__``
key of the dictionary. For other classes with annotations,
:func:`get_annotate_from_class_namespace` can be used to get the
annotate function, and :func:`call_annotate_function` can be used to call it and
retrieve the annotations. Using the :attr:`~Format.FORWARDREF` format will usually
be best, because this allows the annotations to refer to names that cannot yet be
resolved when the class is created.
To modify the annotations, it is best to create a wrapper annotate function
that calls the original annotate function, makes any necessary adjustments, and
returns the result.
Below is an example of a metaclass that filters out all :class:`typing.ClassVar`
annotations from the class and puts them in a separate attribute:
.. code-block:: python
import annotationlib
import typing
class ClassVarSeparator(type):
def __new__(mcls, name, bases, ns):
if "__annotations__" in ns: # from __future__ import annotations
annotations = ns["__annotations__"]
classvar_keys = {
key for key, value in annotations.items()
# Use string comparison for simplicity; a more robust solution
# could use annotationlib.ForwardRef.evaluate
if value.startswith("ClassVar")
}
classvars = {key: annotations[key] for key in classvar_keys}
ns["__annotations__"] = {
key: value for key, value in annotations.items()
if key not in classvar_keys
}
wrapped_annotate = None
elif annotate := annotationlib.get_annotate_from_class_namespace(ns):
annotations = annotationlib.call_annotate_function(
annotate, format=annotationlib.Format.FORWARDREF
)
classvar_keys = {
key for key, value in annotations.items()
if typing.get_origin(value) is typing.ClassVar
}
classvars = {key: annotations[key] for key in classvar_keys}
def wrapped_annotate(format):
annos = annotationlib.call_annotate_function(annotate, format, owner=typ)
return {key: value for key, value in annos.items() if key not in classvar_keys}
else: # no annotations
classvars = {}
wrapped_annotate = None
typ = super().__new__(mcls, name, bases, ns)
if wrapped_annotate is not None:
# Wrap the original __annotate__ with a wrapper that removes ClassVars
typ.__annotate__ = wrapped_annotate
typ.classvars = classvars # Store the ClassVars in a separate attribute
return typ
Limitations of the ``STRING`` format
------------------------------------
The :attr:`~Format.STRING` format is meant to approximate the source code
of the annotation, but the implementation strategy used means that it is not
always possible to recover the exact source code.
First, the stringifier of course cannot recover any information that is not present in
the compiled code, including comments, whitespace, parenthesization, and operations that
get simplified by the compiler.
Second, the stringifier can intercept almost all operations that involve names looked
up in some scope, but it cannot intercept operations that operate fully on constants.
As a corollary, this also means it is not safe to request the ``STRING`` format on
untrusted code: Python is powerful enough that it is possible to achieve arbitrary
code execution even with no access to any globals or builtins. For example:
.. code-block:: pycon
>>> def f(x: (1).__class__.__base__.__subclasses__()[-1].__init__.__builtins__["print"]("Hello world")): pass
...
>>> annotationlib.get_annotations(f, format=annotationlib.Format.SOURCE)
Hello world
{'x': 'None'}
.. note::
This particular example works as of the time of writing, but it relies on
implementation details and is not guaranteed to work in the future.
Among the different kinds of expressions that exist in Python,
as represented by the :mod:`ast` module, some expressions are supported,
meaning that the ``STRING`` format can generally recover the original source code;
others are unsupported, meaning that they may result in incorrect output or an error.
The following are supported (sometimes with caveats):
* :class:`ast.BinOp`
* :class:`ast.UnaryOp`
* :class:`ast.Invert` (``~``), :class:`ast.UAdd` (``+``), and :class:`ast.USub` (``-``) are supported
* :class:`ast.Not` (``not``) is not supported
* :class:`ast.Dict` (except when using ``**`` unpacking)
* :class:`ast.Set`
* :class:`ast.Compare`
* :class:`ast.Eq` and :class:`ast.NotEq` are supported
* :class:`ast.Lt`, :class:`ast.LtE`, :class:`ast.Gt`, and :class:`ast.GtE` are supported, but the operand may be flipped
* :class:`ast.Is`, :class:`ast.IsNot`, :class:`ast.In`, and :class:`ast.NotIn` are not supported
* :class:`ast.Call` (except when using ``**`` unpacking)
* :class:`ast.Constant` (though not the exact representation of the constant; for example, escape
sequences in strings are lost; hexadecimal numbers are converted to decimal)
* :class:`ast.Attribute` (assuming the value is not a constant)
* :class:`ast.Subscript` (assuming the value is not a constant)
* :class:`ast.Starred` (``*`` unpacking)
* :class:`ast.Name`
* :class:`ast.List`
* :class:`ast.Tuple`
* :class:`ast.Slice`
The following are unsupported, but throw an informative error when encountered by the
stringifier:
* :class:`ast.FormattedValue` (f-strings; error is not detected if conversion specifiers like ``!r``
are used)
* :class:`ast.JoinedStr` (f-strings)
The following are unsupported and result in incorrect output:
* :class:`ast.BoolOp` (``and`` and ``or``)
* :class:`ast.IfExp`
* :class:`ast.Lambda`
* :class:`ast.ListComp`
* :class:`ast.SetComp`
* :class:`ast.DictComp`
* :class:`ast.GeneratorExp`
The following are disallowed in annotation scopes and therefore not relevant:
* :class:`ast.NamedExpr` (``:=``)
* :class:`ast.Await`
* :class:`ast.Yield`
* :class:`ast.YieldFrom`
Limitations of the ``FORWARDREF`` format
----------------------------------------
The :attr:`~Format.FORWARDREF` format aims to produce real values as much
as possible, with anything that cannot be resolved replaced with
:class:`ForwardRef` objects. It is affected by broadly the same Limitations
as the :attr:`~Format.STRING` format: annotations that perform operations on
literals or that use unsupported expression types may raise exceptions when
evaluated using the :attr:`~Format.FORWARDREF` format.
Below are a few examples of the behavior with unsupported expressions:
.. code-block:: pycon
>>> from annotationlib import get_annotations, Format
>>> def zerodiv(x: 1 / 0): ...
>>> get_annotations(zerodiv, format=Format.STRING)
Traceback (most recent call last):
...
ZeroDivisionError: division by zero
>>> get_annotations(zerodiv, format=Format.FORWARDREF)
Traceback (most recent call last):
...
ZeroDivisionError: division by zero
>>> def ifexp(x: 1 if y else 0): ...
>>> get_annotations(ifexp, format=Format.STRING)
{'x': '1'}

View file

@ -5,13 +5,15 @@ Data Compression and Archiving
******************************
The modules described in this chapter support data compression with the zlib,
gzip, bzip2 and lzma algorithms, and the creation of ZIP- and tar-format
gzip, bzip2, lzma, and zstd algorithms, and the creation of ZIP- and tar-format
archives. See also :ref:`archiving-operations` provided by the :mod:`shutil`
module.
.. toctree::
compression.rst
compression.zstd.rst
zlib.rst
gzip.rst
bz2.rst

View file

@ -74,7 +74,7 @@ ArgumentParser objects
prefix_chars='-', fromfile_prefix_chars=None, \
argument_default=None, conflict_handler='error', \
add_help=True, allow_abbrev=True, exit_on_error=True, \
suggest_on_error=False)
*, suggest_on_error=False, color=False)
Create a new :class:`ArgumentParser` object. All parameters should be passed
as keyword arguments. Each parameter has its own more detailed description
@ -111,7 +111,7 @@ ArgumentParser objects
* add_help_ - Add a ``-h/--help`` option to the parser (default: ``True``)
* allow_abbrev_ - Allows long options to be abbreviated if the
abbreviation is unambiguous. (default: ``True``)
abbreviation is unambiguous (default: ``True``)
* exit_on_error_ - Determines whether or not :class:`!ArgumentParser` exits with
error info when an error occurs. (default: ``True``)
@ -119,6 +119,7 @@ ArgumentParser objects
* suggest_on_error_ - Enables suggestions for mistyped argument choices
and subparser names (default: ``False``)
* color_ - Allow color output (default: ``False``)
.. versionchanged:: 3.5
*allow_abbrev* parameter was added.
@ -130,6 +131,9 @@ ArgumentParser objects
.. versionchanged:: 3.9
*exit_on_error* parameter was added.
.. versionchanged:: 3.14
*suggest_on_error* and *color* parameters were added.
The following sections describe how each of these are used.
@ -594,7 +598,8 @@ subparser names, the feature can be enabled by setting ``suggest_on_error`` to
``True``. Note that this only applies for arguments when the choices specified
are strings::
>>> parser = argparse.ArgumentParser(description='Process some integers.', suggest_on_error=True)
>>> parser = argparse.ArgumentParser(description='Process some integers.',
suggest_on_error=True)
>>> parser.add_argument('--action', choices=['sum', 'max'])
>>> parser.add_argument('integers', metavar='N', type=int, nargs='+',
... help='an integer for the accumulator')
@ -612,6 +617,33 @@ keyword argument::
.. versionadded:: 3.14
color
^^^^^
By default, the help message is printed in plain text. If you want to allow
color in help messages, you can enable it by setting ``color`` to ``True``::
>>> parser = argparse.ArgumentParser(description='Process some integers.',
... color=True)
>>> parser.add_argument('--action', choices=['sum', 'max'])
>>> parser.add_argument('integers', metavar='N', type=int, nargs='+',
... help='an integer for the accumulator')
>>> parser.parse_args(['--help'])
Even if a CLI author has enabled color, it can be
:ref:`controlled using environment variables <using-on-controlling-color>`.
If you're writing code that needs to be compatible with older Python versions
and want to opportunistically use ``color`` when it's available, you
can set it as an attribute after initializing the parser instead of using the
keyword argument::
>>> parser = argparse.ArgumentParser(description='Process some integers.')
>>> parser.color = True
.. versionadded:: 3.14
The add_argument() method
-------------------------
@ -2090,12 +2122,15 @@ Partial parsing
.. method:: ArgumentParser.parse_known_args(args=None, namespace=None)
Sometimes a script may only parse a few of the command-line arguments, passing
the remaining arguments on to another script or program. In these cases, the
:meth:`~ArgumentParser.parse_known_args` method can be useful. It works much like
:meth:`~ArgumentParser.parse_args` except that it does not produce an error when
extra arguments are present. Instead, it returns a two item tuple containing
the populated namespace and the list of remaining argument strings.
Sometimes a script only needs to handle a specific set of command-line
arguments, leaving any unrecognized arguments for another script or program.
In these cases, the :meth:`~ArgumentParser.parse_known_args` method can be
useful.
This method works similarly to :meth:`~ArgumentParser.parse_args`, but it does
not raise an error for extra, unrecognized arguments. Instead, it parses the
known arguments and returns a two item tuple that contains the populated
namespace and the list of any unrecognized arguments.
::

View file

@ -1,4 +1,4 @@
:mod:`!ast` --- Abstract Syntax Trees
:mod:`!ast` --- Abstract syntax trees
=====================================
.. module:: ast
@ -29,7 +29,7 @@ compiled into a Python code object using the built-in :func:`compile` function.
.. _abstract-grammar:
Abstract Grammar
Abstract grammar
----------------
The abstract grammar is currently defined as follows:
@ -268,9 +268,9 @@ Literals
.. class:: Constant(value)
A constant value. The ``value`` attribute of the ``Constant`` literal contains the
Python object it represents. The values represented can be simple types
such as a number, string or ``None``, but also immutable container types
(tuples and frozensets) if all of their elements are constant.
Python object it represents. The values represented can be instances of :class:`str`,
:class:`bytes`, :class:`int`, :class:`float`, :class:`complex`, and :class:`bool`,
and the constants :data:`None` and :data:`Ellipsis`.
.. doctest::
@ -2156,10 +2156,10 @@ Async and await
of :class:`ast.operator`, :class:`ast.unaryop`, :class:`ast.cmpop`,
:class:`ast.boolop` and :class:`ast.expr_context`) on the returned tree
will be singletons. Changes to one will be reflected in all other
occurrences of the same value (e.g. :class:`ast.Add`).
occurrences of the same value (for example, :class:`ast.Add`).
:mod:`ast` Helpers
:mod:`ast` helpers
------------------
Apart from the node classes, the :mod:`ast` module defines these utility functions
@ -2484,7 +2484,7 @@ and classes for traversing abstract syntax trees:
.. _ast-compiler-flags:
Compiler Flags
Compiler flags
--------------
The following flags may be passed to :func:`compile` in order to change
@ -2533,7 +2533,7 @@ effects on the compilation of a program:
.. _ast-cli:
Command-Line Usage
Command-line usage
------------------
.. versionadded:: 3.9
@ -2572,6 +2572,28 @@ The following options are accepted:
Indentation of nodes in AST (number of spaces).
.. option:: --feature-version <version>
Python version in the format 3.x (for example, 3.10). Defaults to the
current version of the interpreter.
.. versionadded:: 3.14
.. option:: -O <level>
--optimize <level>
Optimization level for parser. Defaults to no optimization.
.. versionadded:: 3.14
.. option:: --show-empty
Show empty lists and fields that are ``None``. Defaults to not showing empty
objects.
.. versionadded:: 3.14
If :file:`infile` is specified its contents are parsed to AST and dumped
to stdout. Otherwise, the content is read from stdin.

View file

@ -46,10 +46,6 @@ In addition to enabling the debug mode, consider also:
When the debug mode is enabled:
* asyncio checks for :ref:`coroutines that were not awaited
<asyncio-coroutine-not-scheduled>` and logs them; this mitigates
the "forgotten await" pitfall.
* Many non-threadsafe asyncio APIs (such as :meth:`loop.call_soon` and
:meth:`loop.call_at` methods) raise an exception if they are called
from a wrong thread.

View file

@ -361,7 +361,7 @@ Creating Futures and Tasks
.. versionadded:: 3.5.2
.. method:: loop.create_task(coro, *, name=None, context=None)
.. method:: loop.create_task(coro, *, name=None, context=None, eager_start=None, **kwargs)
Schedule the execution of :ref:`coroutine <coroutine>` *coro*.
Return a :class:`Task` object.
@ -370,6 +370,10 @@ Creating Futures and Tasks
for interoperability. In this case, the result type is a subclass
of :class:`Task`.
The full function signature is largely the same as that of the
:class:`Task` constructor (or factory) - all of the keyword arguments to
this function are passed through to that interface.
If the *name* argument is provided and not ``None``, it is set as
the name of the task using :meth:`Task.set_name`.
@ -377,12 +381,27 @@ Creating Futures and Tasks
custom :class:`contextvars.Context` for the *coro* to run in.
The current context copy is created when no *context* is provided.
An optional keyword-only *eager_start* argument allows specifying
if the task should execute eagerly during the call to create_task,
or be scheduled later. If *eager_start* is not passed the mode set
by :meth:`loop.set_task_factory` will be used.
.. versionchanged:: 3.8
Added the *name* parameter.
.. versionchanged:: 3.11
Added the *context* parameter.
.. versionchanged:: 3.13.3
Added ``kwargs`` which passes on arbitrary extra parameters, including ``name`` and ``context``.
.. versionchanged:: 3.13.4
Rolled back the change that passes on *name* and *context* (if it is None),
while still passing on other arbitrary keyword arguments (to avoid breaking backwards compatibility with 3.13.3).
.. versionchanged:: 3.14
All *kwargs* are now passed on. The *eager_start* parameter works with eager task factories.
.. method:: loop.set_task_factory(factory)
Set a task factory that will be used by
@ -394,6 +413,16 @@ Creating Futures and Tasks
event loop, and *coro* is a coroutine object. The callable
must pass on all *kwargs*, and return a :class:`asyncio.Task`-compatible object.
.. versionchanged:: 3.13.3
Required that all *kwargs* are passed on to :class:`asyncio.Task`.
.. versionchanged:: 3.13.4
*name* is no longer passed to task factories. *context* is no longer passed
to task factories if it is ``None``.
.. versionchanged:: 3.14
*name* and *context* are now unconditionally passed on to task factories again.
.. method:: loop.get_task_factory()
Return a task factory or ``None`` if the default one is in use.

View file

@ -171,13 +171,17 @@ and work with streams:
.. function:: start_unix_server(client_connected_cb, path=None, \
*, limit=None, sock=None, backlog=100, ssl=None, \
ssl_handshake_timeout=None, \
ssl_shutdown_timeout=None, start_serving=True)
ssl_shutdown_timeout=None, start_serving=True, cleanup_socket=True)
:async:
Start a Unix socket server.
Similar to :func:`start_server` but works with Unix sockets.
If *cleanup_socket* is true then the Unix socket will automatically
be removed from the filesystem when the server is closed, unless the
socket has been replaced after the server has been created.
See also the documentation of :meth:`loop.create_unix_server`.
.. note::
@ -198,6 +202,9 @@ and work with streams:
.. versionchanged:: 3.11
Added the *ssl_shutdown_timeout* parameter.
.. versionchanged:: 3.13
Added the *cleanup_socket* parameter.
StreamReader
============

View file

@ -238,18 +238,24 @@ Creating Tasks
-----------------------------------------------
.. function:: create_task(coro, *, name=None, context=None)
.. function:: create_task(coro, *, name=None, context=None, eager_start=None, **kwargs)
Wrap the *coro* :ref:`coroutine <coroutine>` into a :class:`Task`
and schedule its execution. Return the Task object.
If *name* is not ``None``, it is set as the name of the task using
:meth:`Task.set_name`.
The full function signature is largely the same as that of the
:class:`Task` constructor (or factory) - all of the keyword arguments to
this function are passed through to that interface.
An optional keyword-only *context* argument allows specifying a
custom :class:`contextvars.Context` for the *coro* to run in.
The current context copy is created when no *context* is provided.
An optional keyword-only *eager_start* argument allows specifying
if the task should execute eagerly during the call to create_task,
or be scheduled later. If *eager_start* is not passed the mode set
by :meth:`loop.set_task_factory` will be used.
The task is executed in the loop returned by :func:`get_running_loop`,
:exc:`RuntimeError` is raised if there is no running loop in
current thread.
@ -290,6 +296,9 @@ Creating Tasks
.. versionchanged:: 3.11
Added the *context* parameter.
.. versionchanged:: 3.14
Added the *eager_start* parameter by passing on all *kwargs*.
Task Cancellation
=================
@ -330,7 +339,7 @@ and reliable way to wait for all tasks in the group to finish.
.. versionadded:: 3.11
.. method:: create_task(coro, *, name=None, context=None)
.. method:: create_task(coro, *, name=None, context=None, eager_start=None, **kwargs)
Create a task in this task group.
The signature matches that of :func:`asyncio.create_task`.
@ -342,6 +351,10 @@ and reliable way to wait for all tasks in the group to finish.
Close the given coroutine if the task group is not active.
.. versionchanged:: 3.14
Passes on all *kwargs* to :meth:`loop.create_task`
Example::
async def main():

View file

@ -48,5 +48,5 @@ public API of CPython:
| ctypes.PyObj_FromPtr | ``obj`` |
+----------------------------+-------------------------------------------+
.. versionadded:: next
.. versionadded:: 3.14
The ``_posixsubprocess.fork_exec`` internal audit event.

View file

@ -15,14 +15,9 @@
This module provides functions for encoding binary data to printable
ASCII characters and decoding such encodings back to binary data.
It provides encoding and decoding functions for the encodings specified in
:rfc:`4648`, which defines the Base16, Base32, and Base64 algorithms,
and for the de-facto standard Ascii85 and Base85 encodings.
The :rfc:`4648` encodings are suitable for encoding binary data so that it can be
safely sent by email, used as parts of URLs, or included as part of an HTTP
POST request. The encoding algorithm is not the same as the
:program:`uuencode` program.
This includes the :ref:`encodings specified in <base64-rfc-4648>`
:rfc:`4648` (Base64, Base32 and Base16)
and the non-standard :ref:`Base85 encodings <base64-base-85>`.
There are two interfaces provided by this module. The modern interface
supports encoding :term:`bytes-like objects <bytes-like object>` to ASCII
@ -30,7 +25,7 @@ supports encoding :term:`bytes-like objects <bytes-like object>` to ASCII
strings containing ASCII to :class:`bytes`. Both base-64 alphabets
defined in :rfc:`4648` (normal, and URL- and filesystem-safe) are supported.
The legacy interface does not support decoding from strings, but it does
The :ref:`legacy interface <base64-legacy>` does not support decoding from strings, but it does
provide functions for encoding and decoding to and from :term:`file objects
<file object>`. It only supports the Base64 standard alphabet, and it adds
newlines every 76 characters as per :rfc:`2045`. Note that if you are looking
@ -46,7 +41,15 @@ package instead.
Any :term:`bytes-like objects <bytes-like object>` are now accepted by all
encoding and decoding functions in this module. Ascii85/Base85 support added.
The modern interface provides:
.. _base64-rfc-4648:
RFC 4648 Encodings
------------------
The :rfc:`4648` encodings are suitable for encoding binary data so that it can be
safely sent by email, used as parts of URLs, or included as part of an HTTP
POST request.
.. function:: b64encode(s, altchars=None)
@ -181,6 +184,26 @@ The modern interface provides:
incorrectly padded or if there are non-alphabet characters present in the
input.
.. _base64-base-85:
Base85 Encodings
-----------------
Base85 encoding is not formally specified but rather a de facto standard,
thus different systems perform the encoding differently.
The :func:`a85encode` and :func:`b85encode` functions in this module are two implementations of
the de facto standard. You should call the function with the Base85
implementation used by the software you intend to work with.
The two functions present in this module differ in how they handle the following:
* Whether to include enclosing ``<~`` and ``~>`` markers
* Whether to include newline characters
* The set of ASCII characters used for encoding
* Handling of null bytes
Refer to the documentation of the individual functions for more information.
.. function:: a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False)
@ -262,7 +285,10 @@ The modern interface provides:
.. versionadded:: 3.13
The legacy interface:
.. _base64-legacy:
Legacy Interface
----------------
.. function:: decode(input, output)

View file

@ -1,3 +1,5 @@
.. _library-cmdline:
++++++++++++++++++++++++++++++++++++
Modules command-line interface (CLI)
++++++++++++++++++++++++++++++++++++
@ -27,7 +29,7 @@ The following modules have a command-line interface.
* :mod:`pdb`
* :ref:`pickle <pickle-cli>`
* :ref:`pickletools <pickletools-cli>`
* :mod:`platform`
* :ref:`platform <platform-cli>`
* :mod:`poplib`
* :ref:`profile <profile-cli>`
* :mod:`pstats`

View file

@ -22,6 +22,12 @@ build applications which provide an interactive interpreter prompt.
it defaults to a newly created dictionary with key ``'__name__'`` set to
``'__console__'`` and key ``'__doc__'`` set to ``None``.
Note that functions and classes objects created under an
:class:`!InteractiveInterpreter` instance will belong to the namespace
specified by *locals*.
They are only pickleable if *locals* is the namespace of an existing
module.
.. class:: InteractiveConsole(locals=None, filename="<console>", local_exit=False)

View file

@ -208,7 +208,7 @@ wider range of codecs when working with binary files:
.. versionchanged:: 3.11
The ``'U'`` mode has been removed.
.. deprecated:: next
.. deprecated:: 3.14
:func:`codecs.open` has been superseded by :func:`open`.

View file

@ -0,0 +1,18 @@
The :mod:`!compression` package
===============================
.. versionadded:: 3.14
The :mod:`!compression` package contains the canonical compression modules
containing interfaces to several different compression algorithms. Some of
these modules have historically been available as separate modules; those will
continue to be available under their original names for compatibility reasons,
and will not be removed without a deprecation cycle. The use of modules in
:mod:`!compression` is encouraged where practical.
* :mod:`!compression.bz2` -- Re-exports :mod:`bz2`
* :mod:`!compression.gzip` -- Re-exports :mod:`gzip`
* :mod:`!compression.lzma` -- Re-exports :mod:`lzma`
* :mod:`!compression.zlib` -- Re-exports :mod:`zlib`
* :mod:`compression.zstd` -- Wrapper for the Zstandard compression library

View file

@ -0,0 +1,858 @@
:mod:`!compression.zstd` --- Compression compatible with the Zstandard format
=============================================================================
.. module:: compression.zstd
:synopsis: Low-level interface to compression and decompression routines in
the zstd library.
.. versionadded:: 3.14
**Source code:** :source:`Lib/compression/zstd/__init__.py`
--------------
This module provides classes and functions for compressing and decompressing
data using the Zstandard (or *zstd*) compression algorithm. The
`zstd manual <https://facebook.github.io/zstd/doc/api_manual_latest.html>`__
describes Zstandard as "a fast lossless compression algorithm, targeting
real-time compression scenarios at zlib-level and better compression ratios."
Also included is a file interface that supports reading and writing the
contents of ``.zst`` files created by the :program:`zstd` utility, as well as
raw zstd compressed streams.
The :mod:`!compression.zstd` module contains:
* The :func:`.open` function and :class:`ZstdFile` class for reading and
writing compressed files.
* The :class:`ZstdCompressor` and :class:`ZstdDecompressor` classes for
incremental (de)compression.
* The :func:`compress` and :func:`decompress` functions for one-shot
(de)compression.
* The :func:`train_dict` and :func:`finalize_dict` functions and the
:class:`ZstdDict` class to train and manage Zstandard dictionaries.
* The :class:`CompressionParameter`, :class:`DecompressionParameter`, and
:class:`Strategy` classes for setting advanced (de)compression parameters.
Exceptions
----------
.. exception:: ZstdError
This exception is raised when an error occurs during compression or
decompression, or while initializing the (de)compressor state.
Reading and writing compressed files
------------------------------------
.. function:: open(file, /, mode='rb', *, level=None, options=None, \
zstd_dict=None, encoding=None, errors=None, newline=None)
Open a Zstandard-compressed file in binary or text mode, returning a
:term:`file object`.
The *file* argument can be either a file name (given as a
:class:`str`, :class:`bytes` or :term:`path-like <path-like object>`
object), in which case the named file is opened, or it can be an existing
file object to read from or write to.
The mode argument can be either ``'rb'`` for reading (default), ``'wb'`` for
overwriting, ``'ab'`` for appending, or ``'xb'`` for exclusive creation.
These can equivalently be given as ``'r'``, ``'w'``, ``'a'``, and ``'x'``
respectively. You may also open in text mode with ``'rt'``, ``'wt'``,
``'at'``, and ``'xt'`` respectively.
When reading, the *options* argument can be a dictionary providing advanced
decompression parameters; see :class:`DecompressionParameter` for detailed
information about supported
parameters. The *zstd_dict* argument is a :class:`ZstdDict` instance to be
used during decompression. When reading, if the *level*
argument is not None, a :exc:`!TypeError` will be raised.
When writing, the *options* argument can be a dictionary
providing advanced decompression parameters; see
:class:`CompressionParameter` for detailed information about supported
parameters. The *level* argument is the compression level to use when
writing compressed data. Only one of *level* or *options* may be non-None.
The *zstd_dict* argument is a :class:`ZstdDict` instance to be used during
compression.
In binary mode, this function is equivalent to the :class:`ZstdFile`
constructor: ``ZstdFile(file, mode, ...)``. In this case, the
*encoding*, *errors*, and *newline* parameters must not be provided.
In text mode, a :class:`ZstdFile` object is created, and wrapped in an
:class:`io.TextIOWrapper` instance with the specified encoding, error
handling behavior, and line endings.
.. class:: ZstdFile(file, /, mode='rb', *, level=None, options=None, \
zstd_dict=None)
Open a Zstandard-compressed file in binary mode.
A :class:`ZstdFile` can wrap an already-open :term:`file object`, or operate
directly on a named file. The *file* argument specifies either the file
object to wrap, or the name of the file to open (as a :class:`str`,
:class:`bytes` or :term:`path-like <path-like object>` object). If
wrapping an existing file object, the wrapped file will not be closed when
the :class:`ZstdFile` is closed.
The *mode* argument can be either ``'rb'`` for reading (default), ``'wb'``
for overwriting, ``'xb'`` for exclusive creation, or ``'ab'`` for appending.
These can equivalently be given as ``'r'``, ``'w'``, ``'x'`` and ``'a'``
respectively.
If *file* is a file object (rather than an actual file name), a mode of
``'w'`` does not truncate the file, and is instead equivalent to ``'a'``.
When reading, the *options* argument can be a dictionary
providing advanced decompression parameters; see
:class:`DecompressionParameter` for detailed information about supported
parameters. The *zstd_dict* argument is a :class:`ZstdDict` instance to be
used during decompression. When reading, if the *level*
argument is not None, a :exc:`!TypeError` will be raised.
When writing, the *options* argument can be a dictionary
providing advanced decompression parameters; see
:class:`CompressionParameter` for detailed information about supported
parameters. The *level* argument is the compression level to use when
writing compressed data. Only one of *level* or *options* may be passed. The
*zstd_dict* argument is a :class:`ZstdDict` instance to be used during
compression.
:class:`!ZstdFile` supports all the members specified by
:class:`io.BufferedIOBase`, except for :meth:`~io.BufferedIOBase.detach`
and :meth:`~io.IOBase.truncate`.
Iteration and the :keyword:`with` statement are supported.
The following method and attributes are also provided:
.. method:: peek(size=-1)
Return buffered data without advancing the file position. At least one
byte of data will be returned, unless EOF has been reached. The exact
number of bytes returned is unspecified (the *size* argument is ignored).
.. note:: While calling :meth:`peek` does not change the file position of
the :class:`ZstdFile`, it may change the position of the underlying
file object (for example, if the :class:`ZstdFile` was constructed by
passing a file object for *file*).
.. attribute:: mode
``'rb'`` for reading and ``'wb'`` for writing.
.. attribute:: name
The name of the Zstandard file. Equivalent to the :attr:`~io.FileIO.name`
attribute of the underlying :term:`file object`.
Compressing and decompressing data in memory
--------------------------------------------
.. function:: compress(data, level=None, options=None, zstd_dict=None)
Compress *data* (a :term:`bytes-like object`), returning the compressed
data as a :class:`bytes` object.
The *level* argument is an integer controlling the level of
compression. *level* is an alternative to setting
:attr:`CompressionParameter.compression_level` in *options*. Use
:meth:`~CompressionParameter.bounds` on
:attr:`~CompressionParameter.compression_level` to get the values that can
be passed for *level*. If advanced compression options are needed, the
*level* argument must be omitted and in the *options* dictionary the
:attr:`!CompressionParameter.compression_level` parameter should be set.
The *options* argument is a Python dictionary containing advanced
compression parameters. The valid keys and values for compression parameters
are documented as part of the :class:`CompressionParameter` documentation.
The *zstd_dict* argument is an instance of :class:`ZstdDict`
containing trained data to improve compression efficiency. The
function :func:`train_dict` can be used to generate a Zstandard dictionary.
.. function:: decompress(data, zstd_dict=None, options=None)
Decompress *data* (a :term:`bytes-like object`), returning the uncompressed
data as a :class:`bytes` object.
The *options* argument is a Python dictionary containing advanced
decompression parameters. The valid keys and values for compression
parameters are documented as part of the :class:`DecompressionParameter`
documentation.
The *zstd_dict* argument is an instance of :class:`ZstdDict`
containing trained data used during compression. This must be
the same Zstandard dictionary used during compression.
If *data* is the concatenation of multiple distinct compressed frames,
decompress all of these frames, and return the concatenation of the results.
.. class:: ZstdCompressor(level=None, options=None, zstd_dict=None)
Create a compressor object, which can be used to compress data
incrementally.
For a more convenient way of compressing a single chunk of data, see the
module-level function :func:`compress`.
The *level* argument is an integer controlling the level of
compression. *level* is an alternative to setting
:attr:`CompressionParameter.compression_level` in *options*. Use
:meth:`~CompressionParameter.bounds` on
:attr:`~CompressionParameter.compression_level` to get the values that can
be passed for *level*. If advanced compression options are needed, the
*level* argument must be omitted and in the *options* dictionary the
:attr:`!CompressionParameter.compression_level` parameter should be set.
The *options* argument is a Python dictionary containing advanced
compression parameters. The valid keys and values for compression parameters
are documented as part of the :class:`CompressionParameter` documentation.
The *zstd_dict* argument is an optional instance of :class:`ZstdDict`
containing trained data to improve compression efficiency. The
function :func:`train_dict` can be used to generate a Zstandard dictionary.
.. method:: compress(data, mode=ZstdCompressor.CONTINUE)
Compress *data* (a :term:`bytes-like object`), returning a :class:`bytes`
object with compressed data if possible, or otherwise an empty
:class:`!bytes` object. Some of *data* may be buffered internally, for
use in later calls to :meth:`!compress` and :meth:`~.flush`. The returned
data should be concatenated with the output of any previous calls to
:meth:`~.compress`.
The *mode* argument is a :class:`ZstdCompressor` attribute, either
:attr:`~.CONTINUE`, :attr:`~.FLUSH_BLOCK`,
or :attr:`~.FLUSH_FRAME`.
When all data has been provided to the compressor, call the
:meth:`~.flush` method to finish the compression process. If
:meth:`~.compress` is called with *mode* set to :attr:`~.FLUSH_FRAME`,
:meth:`~.flush` should not be called, as it would write out a new empty
frame.
.. method:: flush(mode=ZstdCompressor.FLUSH_FRAME)
Finish the compression process, returning a :class:`bytes` object
containing any data stored in the compressor's internal buffers.
The *mode* argument is a :class:`ZstdCompressor` attribute, either
:attr:`~.FLUSH_BLOCK`, or :attr:`~.FLUSH_FRAME`.
.. attribute:: CONTINUE
Collect more data for compression, which may or may not generate output
immediately. This mode optimizes the compression ratio by maximizing the
amount of data per block and frame.
.. attribute:: FLUSH_BLOCK
Complete and write a block to the data stream. The data returned so far
can be immediately decompressed. Past data can still be referenced in
future blocks generated by calls to :meth:`~.compress`,
improving compression.
.. attribute:: FLUSH_FRAME
Complete and write out a frame. Future data provided to
:meth:`~.compress` will be written into a new frame and
*cannot* reference past data.
.. class:: ZstdDecompressor(zstd_dict=None, options=None)
Create a decompressor object, which can be used to decompress data
incrementally.
For a more convenient way of decompressing an entire compressed stream at
once, see the module-level function :func:`decompress`.
The *options* argument is a Python dictionary containing advanced
decompression parameters. The valid keys and values for compression
parameters are documented as part of the :class:`DecompressionParameter`
documentation.
The *zstd_dict* argument is an instance of :class:`ZstdDict`
containing trained data used during compression. This must be
the same Zstandard dictionary used during compression.
.. note::
This class does not transparently handle inputs containing multiple
compressed frames, unlike the :func:`decompress` function and
:class:`ZstdFile` class. To decompress a multi-frame input, you should
use :func:`decompress`, :class:`ZstdFile` if working with a
:term:`file object`, or multiple :class:`!ZstdDecompressor` instances.
.. method:: decompress(data, max_length=-1)
Decompress *data* (a :term:`bytes-like object`), returning
uncompressed data as bytes. Some of *data* may be buffered
internally, for use in later calls to :meth:`!decompress`.
The returned data should be concatenated with the output of any previous
calls to :meth:`!decompress`.
If *max_length* is non-negative, the method returns at most *max_length*
bytes of decompressed data. If this limit is reached and further
output can be produced, the :attr:`~.needs_input` attribute will
be set to ``False``. In this case, the next call to
:meth:`~.decompress` may provide *data* as ``b''`` to obtain
more of the output.
If all of the input data was decompressed and returned (either
because this was less than *max_length* bytes, or because
*max_length* was negative), the :attr:`~.needs_input` attribute
will be set to ``True``.
Attempting to decompress data after the end of a frame will raise a
:exc:`ZstdError`. Any data found after the end of the frame is ignored
and saved in the :attr:`~.unused_data` attribute.
.. attribute:: eof
``True`` if the end-of-stream marker has been reached.
.. attribute:: unused_data
Data found after the end of the compressed stream.
Before the end of the stream is reached, this will be ``b''``.
.. attribute:: needs_input
``False`` if the :meth:`.decompress` method can provide more
decompressed data before requiring new compressed input.
Zstandard dictionaries
----------------------
.. function:: train_dict(samples, dict_size)
Train a Zstandard dictionary, returning a :class:`ZstdDict` instance.
Zstandard dictionaries enable more efficient compression of smaller sizes
of data, which is traditionally difficult to compress due to less
repetition. If you are compressing multiple similar groups of data (such as
similar files), Zstandard dictionaries can improve compression ratios and
speed significantly.
The *samples* argument (an iterable of :class:`bytes` objects), is the
population of samples used to train the Zstandard dictionary.
The *dict_size* argument, an integer, is the maximum size (in bytes) the
Zstandard dictionary should be. The Zstandard documentation suggests an
absolute maximum of no more than 100 KB, but the maximum can often be smaller
depending on the data. Larger dictionaries generally slow down compression,
but improve compression ratios. Smaller dictionaries lead to faster
compression, but reduce the compression ratio.
.. function:: finalize_dict(zstd_dict, /, samples, dict_size, level)
An advanced function for converting a "raw content" Zstandard dictionary into
a regular Zstandard dictionary. "Raw content" dictionaries are a sequence of
bytes that do not need to follow the structure of a normal Zstandard
dictionary.
The *zstd_dict* argument is a :class:`ZstdDict` instance with
the :attr:`~ZstdDict.dict_content` containing the raw dictionary contents.
The *samples* argument (an iterable of :class:`bytes` objects), contains
sample data for generating the Zstandard dictionary.
The *dict_size* argument, an integer, is the maximum size (in bytes) the
Zstandard dictionary should be. See :func:`train_dict` for
suggestions on the maximum dictionary size.
The *level* argument (an integer) is the compression level expected to be
passed to the compressors using this dictionary. The dictionary information
varies for each compression level, so tuning for the proper compression
level can make compression more efficient.
.. class:: ZstdDict(dict_content, /, *, is_raw=False)
A wrapper around Zstandard dictionaries. Dictionaries can be used to improve
the compression of many small chunks of data. Use :func:`train_dict` if you
need to train a new dictionary from sample data.
The *dict_content* argument (a :term:`bytes-like object`), is the already
trained dictionary information.
The *is_raw* argument, a boolean, is an advanced parameter controlling the
meaning of *dict_content*. ``True`` means *dict_content* is a "raw content"
dictionary, without any format restrictions. ``False`` means *dict_content*
is an ordinary Zstandard dictionary, created from Zstandard functions,
for example, :func:`train_dict` or the external :program:`zstd` CLI.
When passing a :class:`!ZstdDict` to a function, the
:attr:`!as_digested_dict` and :attr:`!as_undigested_dict` attributes can
control how the dictionary is loaded by passing them as the ``zstd_dict``
argument, for example, ``compress(data, zstd_dict=zd.as_digested_dict)``.
Digesting a dictionary is a costly operation that occurs when loading a
Zstandard dictionary. When making multiple calls to compression or
decompression, passing a digested dictionary will reduce the overhead of
loading the dictionary.
.. list-table:: Difference for compression
:widths: 10 14 10
:header-rows: 1
* -
- Digested dictionary
- Undigested dictionary
* - Advanced parameters of the compressor which may be overridden by
the dictionary's parameters
- ``window_log``, ``hash_log``, ``chain_log``, ``search_log``,
``min_match``, ``target_length``, ``strategy``,
``enable_long_distance_matching``, ``ldm_hash_log``,
``ldm_min_match``, ``ldm_bucket_size_log``, ``ldm_hash_rate_log``,
and some non-public parameters.
- None
* - :class:`!ZstdDict` internally caches the dictionary
- Yes. It's faster when loading a digested dictionary again with the
same compression level.
- No. If you wish to load an undigested dictionary multiple times,
consider reusing a compressor object.
If passing a :class:`!ZstdDict` without any attribute, an undigested
dictionary is passed by default when compressing and a digested dictionary
is generated if necessary and passed by default when decompressing.
.. attribute:: dict_content
The content of the Zstandard dictionary, a ``bytes`` object. It's the
same as the *dict_content* argument in the ``__init__`` method. It can
be used with other programs, such as the ``zstd`` CLI program.
.. attribute:: dict_id
Identifier of the Zstandard dictionary, a non-negative int value.
Non-zero means the dictionary is ordinary, created by Zstandard
functions and following the Zstandard format.
``0`` means a "raw content" dictionary, free of any format restriction,
used for advanced users.
.. note::
The meaning of ``0`` for :attr:`!ZstdDict.dict_id` is different
from the ``dictionary_id`` attribute to the :func:`get_frame_info`
function.
.. attribute:: as_digested_dict
Load as a digested dictionary.
.. attribute:: as_undigested_dict
Load as an undigested dictionary.
Advanced parameter control
--------------------------
.. class:: CompressionParameter()
An :class:`~enum.IntEnum` containing the advanced compression parameter
keys that can be used when compressing data.
The :meth:`~.bounds` method can be used on any attribute to get the valid
values for that parameter.
Parameters are optional; any omitted parameter will have it's value selected
automatically.
Example getting the lower and upper bound of :attr:`~.compression_level`::
lower, upper = CompressionParameter.compression_level.bounds()
Example setting the :attr:`~.window_log` to the maximum size::
_lower, upper = CompressionParameter.window_log.bounds()
options = {CompressionParameter.window_log: upper}
compress(b'venezuelan beaver cheese', options=options)
.. method:: bounds()
Return the tuple of int bounds, ``(lower, upper)``, of a compression
parameter. This method should be called on the attribute you wish to
retrieve the bounds of. For example, to get the valid values for
:attr:`~.compression_level`, one may check the result of
``CompressionParameter.compression_level.bounds()``.
Both the lower and upper bounds are inclusive.
.. attribute:: compression_level
A high-level means of setting other compression parameters that affect
the speed and ratio of compressing data. Setting the level to zero uses
:attr:`COMPRESSION_LEVEL_DEFAULT`.
.. attribute:: window_log
Maximum allowed back-reference distance the compressor can use when
compressing data, expressed as power of two, ``1 << window_log`` bytes.
This parameter greatly influences the memory usage of compression. Higher
values require more memory but gain better compression values.
A value of zero causes the value to be selected automatically.
.. attribute:: hash_log
Size of the initial probe table, as a power of two. The resulting memory
usage is ``1 << (hash_log+2)`` bytes. Larger tables improve compression
ratio of strategies <= :attr:`~Strategy.dfast`, and improve compression
speed of strategies > :attr:`~Strategy.dfast`.
A value of zero causes the value to be selected automatically.
.. attribute:: chain_log
Size of the multi-probe search table, as a power of two. The resulting
memory usage is ``1 << (chain_log+2)`` bytes. Larger tables result in
better and slower compression. This parameter has no effect for the
:attr:`~Strategy.fast` strategy. It's still useful when using
:attr:`~Strategy.dfast` strategy, in which case it defines a secondary
probe table.
A value of zero causes the value to be selected automatically.
.. attribute:: search_log
Number of search attempts, as a power of two. More attempts result in
better and slower compression. This parameter is useless for
:attr:`~Strategy.fast` and :attr:`~Strategy.dfast` strategies.
A value of zero causes the value to be selected automatically.
.. attribute:: min_match
Minimum size of searched matches. Larger values increase compression and
decompression speed, but decrease ratio. Note that Zstandard can still
find matches of smaller size, it just tweaks its search algorithm to look
for this size and larger. For all strategies < :attr:`~Strategy.btopt`,
the effective minimum is ``4``; for all strategies
> :attr:`~Strategy.fast`, the effective maximum is ``6``.
A value of zero causes the value to be selected automatically.
.. attribute:: target_length
The impact of this field depends on the selected :class:`Strategy`.
For strategies :attr:`~Strategy.btopt`, :attr:`~Strategy.btultra` and
:attr:`~Strategy.btultra2`, the value is the length of a match
considered "good enough" to stop searching. Larger values make
compression ratios better, but compresses slower.
For strategy :attr:`~Strategy.fast`, it is the distance between match
sampling. Larger values make compression faster, but with a worse
compression ratio.
A value of zero causes the value to be selected automatically.
.. attribute:: strategy
The higher the value of selected strategy, the more complex the
compression technique used by zstd, resulting in higher compression
ratios but slower compression.
.. seealso:: :class:`Strategy`
.. attribute:: enable_long_distance_matching
Long distance matching can be used to improve compression for large
inputs by finding large matches at greater distances. It increases memory
usage and window size.
``True`` or ``1`` enable long distance matching while ``False`` or ``0``
disable it.
Enabling this parameter increases default
:attr:`~CompressionParameter.window_log` to 128 MiB except when expressly
set to a different value. This setting is enabled by default if
:attr:`!window_log` >= 128 MiB and the compression
strategy >= :attr:`~Strategy.btopt` (compression level 16+).
.. attribute:: ldm_hash_log
Size of the table for long distance matching, as a power of two. Larger
values increase memory usage and compression ratio, but decrease
compression speed.
A value of zero causes the value to be selected automatically.
.. attribute:: ldm_min_match
Minimum match size for long distance matcher. Larger or too small values
can often decrease the compression ratio.
A value of zero causes the value to be selected automatically.
.. attribute:: ldm_bucket_size_log
Log size of each bucket in the long distance matcher hash table for
collision resolution. Larger values improve collision resolution but
decrease compression speed.
A value of zero causes the value to be selected automatically.
.. attribute:: ldm_hash_rate_log
Frequency of inserting/looking up entries into the long distance matcher
hash table. Larger values improve compression speed. Deviating far from
the default value will likely result in a compression ratio decrease.
A value of zero causes the value to be selected automatically.
.. attribute:: content_size_flag
Write the size of the data to be compressed into the Zstandard frame
header when known prior to compressing.
This flag only takes effect under the following two scenarios:
* Calling :func:`compress` for one-shot compression
* Providing all of the data to be compressed in the frame in a single
:meth:`ZstdCompressor.compress` call, with the
:attr:`ZstdCompressor.FLUSH_FRAME` mode.
All other compression calls may not write the size information into the
frame header.
``True`` or ``1`` enable the content size flag while ``False`` or ``0``
disable it.
.. attribute:: checksum_flag
A four-byte checksum using XXHash64 of the uncompressed content is
written at the end of each frame. Zstandard's decompression code verifies
the checksum. If there is a mismatch a :class:`ZstdError` exception is
raised.
``True`` or ``1`` enable checksum generation while ``False`` or ``0``
disable it.
.. attribute:: dict_id_flag
When compressing with a :class:`ZstdDict`, the dictionary's ID is written
into the frame header.
``True`` or ``1`` enable storing the dictionary ID while ``False`` or
``0`` disable it.
.. attribute:: nb_workers
Select how many threads will be spawned to compress in parallel. When
:attr:`!nb_workers` > 0, enables multi-threaded compression, a value of
``1`` means "one-thread multi-threaded mode". More workers improve speed,
but also increase memory usage and slightly reduce compression ratio.
A value of zero disables multi-threading.
.. attribute:: job_size
Size of a compression job, in bytes. This value is enforced only when
:attr:`~CompressionParameter.nb_workers` >= 1. Each compression job is
completed in parallel, so this value can indirectly impact the number of
active threads.
A value of zero causes the value to be selected automatically.
.. attribute:: overlap_log
Sets how much data is reloaded from previous jobs (threads) for new jobs
to be used by the look behind window during compression. This value is
only used when :attr:`~CompressionParameter.nb_workers` >= 1. Acceptable
values vary from 0 to 9.
* 0 means dynamically set the overlap amount
* 1 means no overlap
* 9 means use a full window size from the previous job
Each increment halves/doubles the overlap size. "8" means an overlap of
``window_size/2``, "7" means an overlap of ``window_size/4``, etc.
.. class:: DecompressionParameter()
An :class:`~enum.IntEnum` containing the advanced decompression parameter
keys that can be used when decompressing data. Parameters are optional; any
omitted parameter will have it's value selected automatically.
The :meth:`~.bounds` method can be used on any attribute to get the valid
values for that parameter.
Example setting the :attr:`~.window_log_max` to the maximum size::
data = compress(b'Some very long buffer of bytes...')
_lower, upper = DecompressionParameter.window_log_max.bounds()
options = {DecompressionParameter.window_log_max: upper}
decompress(data, options=options)
.. method:: bounds()
Return the tuple of int bounds, ``(lower, upper)``, of a decompression
parameter. This method should be called on the attribute you wish to
retrieve the bounds of.
Both the lower and upper bounds are inclusive.
.. attribute:: window_log_max
The base-two logarithm of the maximum size of the window used during
decompression. This can be useful to limit the amount of memory used when
decompressing data. A larger maximum window size leads to faster
decompression.
A value of zero causes the value to be selected automatically.
.. class:: Strategy()
An :class:`~enum.IntEnum` containing strategies for compression.
Higher-numbered strategies correspond to more complex and slower
compression.
.. note::
The values of attributes of :class:`!Strategy` are not necessarily stable
across zstd versions. Only the ordering of the attributes may be relied
upon. The attributes are listed below in order.
The following strategies are available:
.. attribute:: fast
.. attribute:: dfast
.. attribute:: greedy
.. attribute:: lazy
.. attribute:: lazy2
.. attribute:: btlazy2
.. attribute:: btopt
.. attribute:: btultra
.. attribute:: btultra2
Miscellaneous
-------------
.. function:: get_frame_info(frame_buffer)
Retrieve a :class:`FrameInfo` object containing metadata about a Zstandard
frame. Frames contain metadata related to the compressed data they hold.
.. class:: FrameInfo
Metadata related to a Zstandard frame.
.. attribute:: decompressed_size
The size of the decompressed contents of the frame.
.. attribute:: dictionary_id
An integer representing the Zstandard dictionary ID needed for
decompressing the frame. ``0`` means the dictionary ID was not
recorded in the frame header. This may mean that a Zstandard dictionary
is not needed, or that the ID of a required dictionary was not recorded.
.. attribute:: COMPRESSION_LEVEL_DEFAULT
The default compression level for Zstandard: ``3``.
.. attribute:: zstd_version_info
Version number of the runtime zstd library as a tuple of integers
(major, minor, release).
Examples
--------
Reading in a compressed file:
.. code-block:: python
from compression import zstd
with zstd.open("file.zst") as f:
file_content = f.read()
Creating a compressed file:
.. code-block:: python
from compression import zstd
data = b"Insert Data Here"
with zstd.open("file.zst", "w") as f:
f.write(data)
Compressing data in memory:
.. code-block:: python
from compression import zstd
data_in = b"Insert Data Here"
data_out = zstd.compress(data_in)
Incremental compression:
.. code-block:: python
from compression import zstd
comp = zstd.ZstdCompressor()
out1 = comp.compress(b"Some data\n")
out2 = comp.compress(b"Another piece of data\n")
out3 = comp.compress(b"Even more data\n")
out4 = comp.flush()
# Concatenate all the partial results:
result = b"".join([out1, out2, out3, out4])
Writing compressed data to an already-open file:
.. code-block:: python
from compression import zstd
with open("myfile", "wb") as f:
f.write(b"This data will not be compressed\n")
with zstd.open(f, "w") as zstf:
zstf.write(b"This *will* be compressed\n")
f.write(b"Not compressed\n")
Creating a compressed file using compression parameters:
.. code-block:: python
from compression import zstd
options = {
zstd.CompressionParameter.checksum_flag: 1
}
with zstd.open("file.zst", "w", options=options) as f:
f.write(b"Mind if I squeeze in?")

View file

@ -6,8 +6,9 @@
.. versionadded:: 3.2
**Source code:** :source:`Lib/concurrent/futures/thread.py`
and :source:`Lib/concurrent/futures/process.py`
**Source code:** :source:`Lib/concurrent/futures/thread.py`,
:source:`Lib/concurrent/futures/process.py`,
and :source:`Lib/concurrent/futures/interpreter.py`
--------------

View file

@ -122,6 +122,8 @@ and only supports named tuples created by :func:`~collections.namedtuple`,
This method should create a new object of the same type,
replacing fields with values from *changes*.
.. versionadded:: 3.13
.. seealso::

View file

@ -2031,35 +2031,55 @@ Utility functions
pointer.
.. function:: create_string_buffer(init_or_size, size=None)
.. function:: create_string_buffer(init, size=None)
create_string_buffer(size)
This function creates a mutable character buffer. The returned object is a
ctypes array of :class:`c_char`.
*init_or_size* must be an integer which specifies the size of the array, or a
bytes object which will be used to initialize the array items.
If *size* is given (and not ``None``), it must be an :class:`int`.
It specifies the size of the returned array.
If a bytes object is specified as first argument, the buffer is made one item
larger than its length so that the last element in the array is a NUL
termination character. An integer can be passed as second argument which allows
specifying the size of the array if the length of the bytes should not be used.
If the *init* argument is given, it must be :class:`bytes`. It is used
to initialize the array items. Bytes not initialized this way are
set to zero (NUL).
If *size* is not given (or if it is ``None``), the buffer is made one element
larger than *init*, effectively adding a NUL terminator.
If both arguments are given, *size* must not be less than ``len(init)``.
.. warning::
If *size* is equal to ``len(init)``, a NUL terminator is
not added. Do not treat such a buffer as a C string.
For example::
>>> bytes(create_string_buffer(2))
b'\x00\x00'
>>> bytes(create_string_buffer(b'ab'))
b'ab\x00'
>>> bytes(create_string_buffer(b'ab', 2))
b'ab'
>>> bytes(create_string_buffer(b'ab', 4))
b'ab\x00\x00'
>>> bytes(create_string_buffer(b'abcdef', 2))
Traceback (most recent call last):
...
ValueError: byte string too long
.. audit-event:: ctypes.create_string_buffer init,size ctypes.create_string_buffer
.. function:: create_unicode_buffer(init_or_size, size=None)
.. function:: create_unicode_buffer(init, size=None)
create_unicode_buffer(size)
This function creates a mutable unicode character buffer. The returned object is
a ctypes array of :class:`c_wchar`.
*init_or_size* must be an integer which specifies the size of the array, or a
string which will be used to initialize the array items.
If a string is specified as first argument, the buffer is made one item
larger than the length of the string so that the last element in the array is a
NUL termination character. An integer can be passed as second argument which
allows specifying the size of the array if the length of the string should not
be used.
The function takes the same arguments as :func:`~create_string_buffer` except
*init* must be a string and *size* counts :class:`c_wchar`.
.. audit-event:: ctypes.create_unicode_buffer init,size ctypes.create_unicode_buffer
@ -2172,10 +2192,20 @@ Utility functions
.. function:: POINTER(type, /)
Create and return a new ctypes pointer type. Pointer types are cached and
Create or return a ctypes pointer type. Pointer types are cached and
reused internally, so calling this function repeatedly is cheap.
*type* must be a ctypes type.
.. impl-detail::
The resulting pointer type is cached in the ``__pointer_type__``
attribute of *type*.
It is possible to set this attribute before the first call to
``POINTER`` in order to set a custom pointer type.
However, doing this is discouraged: manually creating a suitable
pointer type is difficult without relying on implementation
details that may change in future Python versions.
.. function:: pointer(obj, /)
@ -2340,6 +2370,16 @@ Data types
library. *name* is the name of the symbol that exports the data, *library*
is the loaded shared library.
Common class variables of ctypes data types:
.. attribute:: __pointer_type__
The pointer type that was created by calling
:func:`POINTER` for corresponding ctypes data type. If a pointer type
was not yet created, the attribute is missing.
.. versionadded:: 3.14
Common instance variables of ctypes data types:
.. attribute:: _b_base_
@ -2734,6 +2774,16 @@ fields, or any other data types containing pointer type fields.
when :attr:`_fields_` is assigned, otherwise it will have no effect.
Setting this attribute to 0 is the same as not setting it at all.
This is only implemented for the MSVC-compatible memory layout.
.. deprecated-removed:: 3.14 3.19
For historical reasons, if :attr:`!_pack_` is non-zero,
the MSVC-compatible layout will be used by default.
On non-Windows platforms, this default is deprecated and is slated to
become an error in Python 3.19.
If it is intended, set :attr:`~Structure._layout_` to ``'ms'``
explicitly.
.. attribute:: _align_
@ -2762,12 +2812,15 @@ fields, or any other data types containing pointer type fields.
Currently the default will be:
- On Windows: ``"ms"``
- When :attr:`~Structure._pack_` is specified: ``"ms"``
- When :attr:`~Structure._pack_` is specified: ``"ms"``.
(This is deprecated; see :attr:`~Structure._pack_` documentation.)
- Otherwise: ``"gcc-sysv"``
:attr:`!_layout_` must already be defined when
:attr:`~Structure._fields_` is assigned, otherwise it will have no effect.
.. versionadded:: 3.14
.. attribute:: _anonymous_
An optional sequence that lists the names of unnamed (anonymous) fields.

View file

@ -68,6 +68,21 @@ The module :mod:`curses` defines the following exception:
The module :mod:`curses` defines the following functions:
.. function:: assume_default_colors(fg, bg, /)
Allow use of default values for colors on terminals supporting this feature.
Use this to support transparency in your application.
* Assign terminal default foreground/background colors to color number ``-1``.
So ``init_pair(x, COLOR_RED, -1)`` will initialize pair *x* as red
on default background and ``init_pair(x, -1, COLOR_BLUE)`` will
initialize pair *x* as default foreground on blue.
* Change the definition of the color-pair ``0`` to ``(fg, bg)``.
.. versionadded:: 3.14
.. function:: baudrate()
Return the output speed of the terminal in bits per second. On software
@ -290,9 +305,11 @@ The module :mod:`curses` defines the following functions:
Change the definition of a color-pair. It takes three arguments: the number of
the color-pair to be changed, the foreground color number, and the background
color number. The value of *pair_number* must be between ``1`` and
``COLOR_PAIRS - 1`` (the ``0`` color pair is wired to white on black and cannot
be changed). The value of *fg* and *bg* arguments must be between ``0`` and
``COLORS - 1``, or, after calling :func:`use_default_colors`, ``-1``.
``COLOR_PAIRS - 1`` (the ``0`` color pair can only be changed by
:func:`use_default_colors` and :func:`assume_default_colors`).
The value of *fg* and *bg* arguments must be between ``0`` and
``COLORS - 1``, or, after calling :func:`!use_default_colors` or
:func:`!assume_default_colors`, ``-1``.
If the color-pair was previously initialized, the screen is
refreshed and all occurrences of that color-pair are changed to the new
definition.
@ -678,11 +695,7 @@ The module :mod:`curses` defines the following functions:
.. function:: use_default_colors()
Allow use of default values for colors on terminals supporting this feature. Use
this to support transparency in your application. The default color is assigned
to the color number ``-1``. After calling this function, ``init_pair(x,
curses.COLOR_RED, -1)`` initializes, for instance, color pair *x* to a red
foreground color on the default background.
Equivalent to ``assume_default_colors(-1, -1)``.
.. function:: wrapper(func, /, *args, **kwargs)
@ -975,6 +988,10 @@ the following methods and attributes:
window.getstr(y, x, n)
Read a bytes object from the user, with primitive line editing capacity.
The maximum value for *n* is 2047.
.. versionchanged:: 3.14
The maximum value for *n* was increased from 1023 to 2047.
.. method:: window.getyx()
@ -1066,6 +1083,10 @@ the following methods and attributes:
current cursor position, or at *y*, *x* if specified. Attributes are stripped
from the characters. If *n* is specified, :meth:`instr` returns a string
at most *n* characters long (exclusive of the trailing NUL).
The maximum value for *n* is 2047.
.. versionchanged:: 3.14
The maximum value for *n* was increased from 1023 to 2047.
.. method:: window.is_linetouched(line)

View file

@ -304,9 +304,9 @@ Module contents
.. versionadded:: 3.10
- ``doc``: optional docstring for this field.
- *doc*: optional docstring for this field.
.. versionadded:: 3.13
.. versionadded:: 3.14
If the default value of a field is specified by a call to
:func:`!field`, then the class attribute for this field will be

View file

@ -261,6 +261,22 @@ A :class:`timedelta` object represents a duration, the difference between two
>>> (d.days, d.seconds, d.microseconds)
(-1, 86399, 999999)
Since the string representation of :class:`!timedelta` objects can be confusing,
use the following recipe to produce a more readable format:
.. code-block:: pycon
>>> def pretty_timedelta(td):
... if td.days >= 0:
... return str(td)
... return f'-({-td!s})'
...
>>> d = timedelta(hours=-1)
>>> str(d) # not human-friendly
'-1 day, 23:00:00'
>>> pretty_timedelta(d)
'-(1:00:00)'
Class attributes:
@ -1486,11 +1502,11 @@ Instance methods:
returned by :func:`time.time`.
Naive :class:`.datetime` instances are assumed to represent local
time and this method relies on the platform C :c:func:`mktime`
function to perform the conversion. Since :class:`.datetime`
supports wider range of values than :c:func:`mktime` on many
platforms, this method may raise :exc:`OverflowError` or :exc:`OSError`
for times far in the past or far in the future.
time and this method relies on platform C functions to perform
the conversion. Since :class:`.datetime` supports a wider range of
values than the platform C functions on many platforms, this
method may raise :exc:`OverflowError` or :exc:`OSError` for times
far in the past or far in the future.
For aware :class:`.datetime` instances, the return value is computed
as::
@ -1503,6 +1519,10 @@ Instance methods:
The :meth:`timestamp` method uses the :attr:`.fold` attribute to
disambiguate the times during a repeated interval.
.. versionchanged:: 3.6
This method no longer relies on the platform C :c:func:`mktime`
function to perform conversions.
.. note::
There is no method to obtain the POSIX timestamp directly from a

View file

@ -2,7 +2,7 @@
=====================================================================
.. module:: decimal
:synopsis: Implementation of the General Decimal Arithmetic Specification.
:synopsis: Implementation of the General Decimal Arithmetic Specification.
.. moduleauthor:: Eric Price <eprice at tjhsst.edu>
.. moduleauthor:: Facundo Batista <facundo at taniquetil.com.ar>
@ -121,7 +121,7 @@ reset them before monitoring a calculation.
.. _decimal-tutorial:
Quick-start Tutorial
Quick-start tutorial
--------------------
The usual start to using decimals is importing the module, viewing the current
@ -1037,7 +1037,7 @@ function to temporarily change the active context.
IEEE interchange formats. The argument must be a multiple of 32 and less
than :const:`IEEE_CONTEXT_MAX_BITS`.
.. versionadded:: next
.. versionadded:: 3.14
New contexts can also be created using the :class:`Context` constructor
described below. In addition, the module provides three pre-made contexts:
@ -1096,40 +1096,52 @@ In addition to the three supplied contexts, new contexts can be created with the
default values are copied from the :const:`DefaultContext`. If the *flags*
field is not specified or is :const:`None`, all flags are cleared.
*prec* is an integer in the range [``1``, :const:`MAX_PREC`] that sets
the precision for arithmetic operations in the context.
.. attribute:: prec
The *rounding* option is one of the constants listed in the section
`Rounding Modes`_.
An integer in the range [``1``, :const:`MAX_PREC`] that sets
the precision for arithmetic operations in the context.
The *traps* and *flags* fields list any signals to be set. Generally, new
contexts should only set traps and leave the flags clear.
.. attribute:: rounding
The *Emin* and *Emax* fields are integers specifying the outer limits allowable
for exponents. *Emin* must be in the range [:const:`MIN_EMIN`, ``0``],
*Emax* in the range [``0``, :const:`MAX_EMAX`].
One of the constants listed in the section `Rounding Modes`_.
The *capitals* field is either ``0`` or ``1`` (the default). If set to
``1``, exponents are printed with a capital ``E``; otherwise, a
lowercase ``e`` is used: ``Decimal('6.02e+23')``.
.. attribute:: traps
flags
The *clamp* field is either ``0`` (the default) or ``1``.
If set to ``1``, the exponent ``e`` of a :class:`Decimal`
instance representable in this context is strictly limited to the
range ``Emin - prec + 1 <= e <= Emax - prec + 1``. If *clamp* is
``0`` then a weaker condition holds: the adjusted exponent of
the :class:`Decimal` instance is at most :attr:`~Context.Emax`. When *clamp* is
``1``, a large normal number will, where possible, have its
exponent reduced and a corresponding number of zeros added to its
coefficient, in order to fit the exponent constraints; this
preserves the value of the number but loses information about
significant trailing zeros. For example::
Lists of any signals to be set. Generally, new contexts should only set
traps and leave the flags clear.
>>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999')
Decimal('1.23000E+999')
.. attribute:: Emin
Emax
A *clamp* value of ``1`` allows compatibility with the
fixed-width decimal interchange formats specified in IEEE 754.
Integers specifying the outer limits allowable for exponents. *Emin* must
be in the range [:const:`MIN_EMIN`, ``0``], *Emax* in the range
[``0``, :const:`MAX_EMAX`].
.. attribute:: capitals
Either ``0`` or ``1`` (the default). If set to
``1``, exponents are printed with a capital ``E``; otherwise, a
lowercase ``e`` is used: ``Decimal('6.02e+23')``.
.. attribute:: clamp
Either ``0`` (the default) or ``1``. If set to ``1``, the exponent ``e``
of a :class:`Decimal` instance representable in this context is strictly
limited to the range ``Emin - prec + 1 <= e <= Emax - prec + 1``.
If *clamp* is ``0`` then a weaker condition holds: the adjusted exponent of
the :class:`Decimal` instance is at most :attr:`~Context.Emax`. When *clamp* is
``1``, a large normal number will, where possible, have its
exponent reduced and a corresponding number of zeros added to its
coefficient, in order to fit the exponent constraints; this
preserves the value of the number but loses information about
significant trailing zeros. For example::
>>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999')
Decimal('1.23000E+999')
A *clamp* value of ``1`` allows compatibility with the
fixed-width decimal interchange formats specified in IEEE 754.
The :class:`Context` class defines several general purpose methods as well as
a large number of methods for doing arithmetic directly in a given context.
@ -1769,7 +1781,7 @@ The following table summarizes the hierarchy of signals::
.. _decimal-notes:
Floating-Point Notes
Floating-point notes
--------------------

View file

@ -436,7 +436,7 @@ The following exceptions are the exceptions that are usually raised.
.. versionadded:: 3.13
Previously, a plain :exc:`RuntimeError` was raised.
.. versionchanged:: next
.. versionchanged:: 3.14
:meth:`threading.Thread.join` can now raise this exception.

View file

@ -69,7 +69,7 @@ Dumping the traceback
Dumping the C stack
-------------------
.. versionadded:: next
.. versionadded:: 3.14
.. function:: dump_c_stack(file=sys.stderr)
@ -130,7 +130,7 @@ Fault handler state
Only the current thread is dumped if the :term:`GIL` is disabled to
prevent the risk of data races.
.. versionchanged:: next
.. versionchanged:: 3.14
The dump now displays the C stack trace if *c_stack* is true.
.. function:: disable()

View file

@ -79,7 +79,7 @@ descriptor.
On macOS and NetBSD, the :mod:`!fcntl` module exposes the ``F_GETNOSIGPIPE``
and ``F_SETNOSIGPIPE`` constant.
.. versionchanged:: next
.. versionchanged:: 3.14
On Linux >= 6.1, the :mod:`!fcntl` module exposes the ``F_DUPFD_QUERY``
to query a file descriptor pointing to the same file.
@ -107,24 +107,27 @@ The module defines the following functions:
passed to the C :c:func:`fcntl` call. The return value after a successful
call is the contents of the buffer, converted to a :class:`bytes` object.
The length of the returned object will be the same as the length of the
*arg* argument. This is limited to 1024 bytes.
*arg* argument.
If the :c:func:`fcntl` call fails, an :exc:`OSError` is raised.
.. note::
If the type or the size of *arg* does not match the type or size
of the argument of the operation (for example, if an integer is
If the type or size of *arg* does not match the type or size
of the operation's argument (for example, if an integer is
passed when a pointer is expected, or the information returned in
the buffer by the operating system is larger than 1024 bytes),
the buffer by the operating system is larger than the size of *arg*),
this is most likely to result in a segmentation violation or
a more subtle data corruption.
.. audit-event:: fcntl.fcntl fd,cmd,arg fcntl.fcntl
.. versionchanged:: next
.. versionchanged:: 3.14
Add support of arbitrary :term:`bytes-like objects <bytes-like object>`,
not only :class:`bytes`.
.. versionchanged:: next
The size of bytes-like objects is no longer limited to 1024 bytes.
.. function:: ioctl(fd, request, arg=0, mutate_flag=True, /)
@ -161,8 +164,7 @@ The module defines the following functions:
If the type or size of *arg* does not match the type or size
of the operation's argument (for example, if an integer is
passed when a pointer is expected, or the information returned in
the buffer by the operating system is larger than 1024 bytes,
or the size of the mutable bytes-like object is too small),
the buffer by the operating system is larger than the size of *arg*),
this is most likely to result in a segmentation violation or
a more subtle data corruption.
@ -181,10 +183,14 @@ The module defines the following functions:
.. audit-event:: fcntl.ioctl fd,request,arg fcntl.ioctl
.. versionchanged:: next
.. versionchanged:: 3.14
The GIL is always released during a system call.
System calls failing with EINTR are automatically retried.
.. versionchanged:: next
The size of not mutated bytes-like objects is no longer
limited to 1024 bytes.
.. function:: flock(fd, operation, /)
Perform the lock operation *operation* on file descriptor *fd* (file objects providing

View file

@ -111,7 +111,7 @@ functions: :func:`fnmatch`, :func:`fnmatchcase`, :func:`.filter`.
>>>
>>> regex = fnmatch.translate('*.txt')
>>> regex
'(?s:.*\\.txt)\\Z'
'(?s:.*\\.txt)\\z'
>>> reobj = re.compile(regex)
>>> reobj.match('foobar.txt')
<re.Match object; span=(0, 10), match='foobar.txt'>

View file

@ -1154,44 +1154,44 @@ are always available. They are listed here in alphabetical order.
.. function:: locals()
Return a mapping object representing the current local symbol table, with
variable names as the keys, and their currently bound references as the
values.
Return a mapping object representing the current local symbol table, with
variable names as the keys, and their currently bound references as the
values.
At module scope, as well as when using :func:`exec` or :func:`eval` with
a single namespace, this function returns the same namespace as
:func:`globals`.
At module scope, as well as when using :func:`exec` or :func:`eval` with
a single namespace, this function returns the same namespace as
:func:`globals`.
At class scope, it returns the namespace that will be passed to the
metaclass constructor.
At class scope, it returns the namespace that will be passed to the
metaclass constructor.
When using ``exec()`` or ``eval()`` with separate local and global
arguments, it returns the local namespace passed in to the function call.
When using ``exec()`` or ``eval()`` with separate local and global
arguments, it returns the local namespace passed in to the function call.
In all of the above cases, each call to ``locals()`` in a given frame of
execution will return the *same* mapping object. Changes made through
the mapping object returned from ``locals()`` will be visible as assigned,
reassigned, or deleted local variables, and assigning, reassigning, or
deleting local variables will immediately affect the contents of the
returned mapping object.
In all of the above cases, each call to ``locals()`` in a given frame of
execution will return the *same* mapping object. Changes made through
the mapping object returned from ``locals()`` will be visible as assigned,
reassigned, or deleted local variables, and assigning, reassigning, or
deleting local variables will immediately affect the contents of the
returned mapping object.
In an :term:`optimized scope` (including functions, generators, and
coroutines), each call to ``locals()`` instead returns a fresh dictionary
containing the current bindings of the function's local variables and any
nonlocal cell references. In this case, name binding changes made via the
returned dict are *not* written back to the corresponding local variables
or nonlocal cell references, and assigning, reassigning, or deleting local
variables and nonlocal cell references does *not* affect the contents
of previously returned dictionaries.
In an :term:`optimized scope` (including functions, generators, and
coroutines), each call to ``locals()`` instead returns a fresh dictionary
containing the current bindings of the function's local variables and any
nonlocal cell references. In this case, name binding changes made via the
returned dict are *not* written back to the corresponding local variables
or nonlocal cell references, and assigning, reassigning, or deleting local
variables and nonlocal cell references does *not* affect the contents
of previously returned dictionaries.
Calling ``locals()`` as part of a comprehension in a function, generator, or
coroutine is equivalent to calling it in the containing scope, except that
the comprehension's initialised iteration variables will be included. In
other scopes, it behaves as if the comprehension were running as a nested
function.
Calling ``locals()`` as part of a comprehension in a function, generator, or
coroutine is equivalent to calling it in the containing scope, except that
the comprehension's initialised iteration variables will be included. In
other scopes, it behaves as if the comprehension were running as a nested
function.
Calling ``locals()`` as part of a generator expression is equivalent to
calling it in a nested generator function.
Calling ``locals()`` as part of a generator expression is equivalent to
calling it in a nested generator function.
.. versionchanged:: 3.12
The behaviour of ``locals()`` in a comprehension has been updated as

View file

@ -403,8 +403,7 @@ The :mod:`functools` module defines the following functions:
>>> remove_first_dear(message)
'Hello, dear world!'
:data:`!Placeholder` has no special treatment when used in a keyword
argument to :func:`!partial`.
:data:`!Placeholder` cannot be passed to :func:`!partial` as a keyword argument.
.. versionchanged:: 3.14
Added support for :data:`Placeholder` in positional arguments.

View file

@ -128,6 +128,11 @@ The :mod:`gc` module provides the following functions:
starts. For each collection, all the objects in the young generation and some
fraction of the old generation is collected.
In the free-threaded build, the increase in process memory usage is also
checked before running the collector. If the memory usage has not increased
by 10% since the last collection and the net number of object allocations
has not exceeded 40 times *threshold0*, the collection is not run.
The fraction of the old generation that is collected is **inversely** proportional
to *threshold1*. The larger *threshold1* is, the slower objects in the old generation
are collected.

View file

@ -16,7 +16,7 @@
The :mod:`getpass` module provides two functions:
.. function:: getpass(prompt='Password: ', stream=None)
.. function:: getpass(prompt='Password: ', stream=None, *, echo_char=None)
Prompt the user for a password without echoing. The user is prompted using
the string *prompt*, which defaults to ``'Password: '``. On Unix, the
@ -25,6 +25,12 @@ The :mod:`getpass` module provides two functions:
(:file:`/dev/tty`) or if that is unavailable to ``sys.stderr`` (this
argument is ignored on Windows).
The *echo_char* argument controls how user input is displayed while typing.
If *echo_char* is ``None`` (default), input remains hidden. Otherwise,
*echo_char* must be a printable ASCII string and each typed character
is replaced by it. For example, ``echo_char='*'`` will display
asterisks instead of the actual input.
If echo free input is unavailable getpass() falls back to printing
a warning message to *stream* and reading from ``sys.stdin`` and
issuing a :exc:`GetPassWarning`.
@ -33,6 +39,9 @@ The :mod:`getpass` module provides two functions:
If you call getpass from within IDLE, the input may be done in the
terminal you launched IDLE from rather than the idle window itself.
.. versionchanged:: 3.14
Added the *echo_char* parameter for keyboard feedback.
.. exception:: GetPassWarning
A :exc:`UserWarning` subclass issued when password input may be echoed.

View file

@ -134,7 +134,7 @@ The :mod:`glob` module defines the following functions:
>>>
>>> regex = glob.translate('**/*.txt', recursive=True, include_hidden=True)
>>> regex
'(?s:(?:.+/)?[^/]*\\.txt)\\Z'
'(?s:(?:.+/)?[^/]*\\.txt)\\z'
>>> reobj = re.compile(regex)
>>> reobj.match('foo/bar/baz.txt')
<re.Match object; span=(0, 15), match='foo/bar/baz.txt'>

View file

@ -284,7 +284,7 @@ a file or file-like object.
Example:
>>> import io, hashlib, hmac
>>> with open(hashlib.__file__, "rb") as f:
>>> with open("library/hashlib.rst", "rb") as f:
... digest = hashlib.file_digest(f, "sha256")
...
>>> digest.hexdigest() # doctest: +ELLIPSIS
@ -302,7 +302,7 @@ a file or file-like object.
.. versionadded:: 3.11
.. versionchanged:: next
.. versionchanged:: 3.14
Now raises a :exc:`BlockingIOError` if the file is opened in blocking
mode. Previously, spurious null bytes were added to the digest.

View file

@ -0,0 +1,211 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="89.9 70 450.78 193.82">
<defs>
<g>
<g id="glyph-0-0">
<path d="M 4.578125 -3.1875 C 4.578125 -3.984375 4.53125 -4.78125 4.1875 -5.515625 C 3.734375 -6.484375 2.90625 -6.640625 2.5 -6.640625 C 1.890625 -6.640625 1.171875 -6.375 0.75 -5.453125 C 0.4375 -4.765625 0.390625 -3.984375 0.390625 -3.1875 C 0.390625 -2.4375 0.421875 -1.546875 0.84375 -0.78125 C 1.265625 0.015625 2 0.21875 2.484375 0.21875 C 3.015625 0.21875 3.78125 0.015625 4.21875 -0.9375 C 4.53125 -1.625 4.578125 -2.40625 4.578125 -3.1875 Z M 2.484375 0 C 2.09375 0 1.5 -0.25 1.328125 -1.203125 C 1.21875 -1.796875 1.21875 -2.71875 1.21875 -3.3125 C 1.21875 -3.953125 1.21875 -4.609375 1.296875 -5.140625 C 1.484375 -6.328125 2.234375 -6.421875 2.484375 -6.421875 C 2.8125 -6.421875 3.46875 -6.234375 3.65625 -5.25 C 3.765625 -4.6875 3.765625 -3.9375 3.765625 -3.3125 C 3.765625 -2.5625 3.765625 -1.890625 3.65625 -1.25 C 3.5 -0.296875 2.9375 0 2.484375 0 Z M 2.484375 0 "/>
</g>
<g id="glyph-0-1">
<path d="M 2.9375 -6.375 C 2.9375 -6.625 2.9375 -6.640625 2.703125 -6.640625 C 2.078125 -6 1.203125 -6 0.890625 -6 L 0.890625 -5.6875 C 1.09375 -5.6875 1.671875 -5.6875 2.1875 -5.953125 L 2.1875 -0.78125 C 2.1875 -0.421875 2.15625 -0.3125 1.265625 -0.3125 L 0.953125 -0.3125 L 0.953125 0 C 1.296875 -0.03125 2.15625 -0.03125 2.5625 -0.03125 C 2.953125 -0.03125 3.828125 -0.03125 4.171875 0 L 4.171875 -0.3125 L 3.859375 -0.3125 C 2.953125 -0.3125 2.9375 -0.421875 2.9375 -0.78125 Z M 2.9375 -6.375 "/>
</g>
<g id="glyph-0-2">
<path d="M 2.890625 -3.515625 C 3.703125 -3.78125 4.28125 -4.46875 4.28125 -5.265625 C 4.28125 -6.078125 3.40625 -6.640625 2.453125 -6.640625 C 1.453125 -6.640625 0.6875 -6.046875 0.6875 -5.28125 C 0.6875 -4.953125 0.90625 -4.765625 1.203125 -4.765625 C 1.5 -4.765625 1.703125 -4.984375 1.703125 -5.28125 C 1.703125 -5.765625 1.234375 -5.765625 1.09375 -5.765625 C 1.390625 -6.265625 2.046875 -6.390625 2.40625 -6.390625 C 2.828125 -6.390625 3.375 -6.171875 3.375 -5.28125 C 3.375 -5.15625 3.34375 -4.578125 3.09375 -4.140625 C 2.796875 -3.65625 2.453125 -3.625 2.203125 -3.625 C 2.125 -3.609375 1.890625 -3.59375 1.8125 -3.59375 C 1.734375 -3.578125 1.671875 -3.5625 1.671875 -3.46875 C 1.671875 -3.359375 1.734375 -3.359375 1.90625 -3.359375 L 2.34375 -3.359375 C 3.15625 -3.359375 3.53125 -2.6875 3.53125 -1.703125 C 3.53125 -0.34375 2.84375 -0.0625 2.40625 -0.0625 C 1.96875 -0.0625 1.21875 -0.234375 0.875 -0.8125 C 1.21875 -0.765625 1.53125 -0.984375 1.53125 -1.359375 C 1.53125 -1.71875 1.265625 -1.921875 0.984375 -1.921875 C 0.734375 -1.921875 0.421875 -1.78125 0.421875 -1.34375 C 0.421875 -0.4375 1.34375 0.21875 2.4375 0.21875 C 3.65625 0.21875 4.5625 -0.6875 4.5625 -1.703125 C 4.5625 -2.515625 3.921875 -3.296875 2.890625 -3.515625 Z M 2.890625 -3.515625 "/>
</g>
<g id="glyph-0-3">
<path d="M 4.75 -6.078125 C 4.828125 -6.1875 4.828125 -6.203125 4.828125 -6.421875 L 2.40625 -6.421875 C 1.203125 -6.421875 1.171875 -6.546875 1.140625 -6.734375 L 0.890625 -6.734375 L 0.5625 -4.6875 L 0.8125 -4.6875 C 0.84375 -4.84375 0.921875 -5.46875 1.0625 -5.59375 C 1.125 -5.65625 1.90625 -5.65625 2.03125 -5.65625 L 4.09375 -5.65625 C 3.984375 -5.5 3.203125 -4.40625 2.984375 -4.078125 C 2.078125 -2.734375 1.75 -1.34375 1.75 -0.328125 C 1.75 -0.234375 1.75 0.21875 2.21875 0.21875 C 2.671875 0.21875 2.671875 -0.234375 2.671875 -0.328125 L 2.671875 -0.84375 C 2.671875 -1.390625 2.703125 -1.9375 2.78125 -2.46875 C 2.828125 -2.703125 2.953125 -3.5625 3.40625 -4.171875 Z M 4.75 -6.078125 "/>
</g>
<g id="glyph-0-4">
<path d="M 4.46875 -2 C 4.46875 -3.1875 3.65625 -4.1875 2.578125 -4.1875 C 2.109375 -4.1875 1.671875 -4.03125 1.3125 -3.671875 L 1.3125 -5.625 C 1.515625 -5.5625 1.84375 -5.5 2.15625 -5.5 C 3.390625 -5.5 4.09375 -6.40625 4.09375 -6.53125 C 4.09375 -6.59375 4.0625 -6.640625 3.984375 -6.640625 C 3.984375 -6.640625 3.953125 -6.640625 3.90625 -6.609375 C 3.703125 -6.515625 3.21875 -6.3125 2.546875 -6.3125 C 2.15625 -6.3125 1.6875 -6.390625 1.21875 -6.59375 C 1.140625 -6.625 1.125 -6.625 1.109375 -6.625 C 1 -6.625 1 -6.546875 1 -6.390625 L 1 -3.4375 C 1 -3.265625 1 -3.1875 1.140625 -3.1875 C 1.21875 -3.1875 1.234375 -3.203125 1.28125 -3.265625 C 1.390625 -3.421875 1.75 -3.96875 2.5625 -3.96875 C 3.078125 -3.96875 3.328125 -3.515625 3.40625 -3.328125 C 3.5625 -2.953125 3.59375 -2.578125 3.59375 -2.078125 C 3.59375 -1.71875 3.59375 -1.125 3.34375 -0.703125 C 3.109375 -0.3125 2.734375 -0.0625 2.28125 -0.0625 C 1.5625 -0.0625 0.984375 -0.59375 0.8125 -1.171875 C 0.84375 -1.171875 0.875 -1.15625 0.984375 -1.15625 C 1.3125 -1.15625 1.484375 -1.40625 1.484375 -1.640625 C 1.484375 -1.890625 1.3125 -2.140625 0.984375 -2.140625 C 0.84375 -2.140625 0.5 -2.0625 0.5 -1.609375 C 0.5 -0.75 1.1875 0.21875 2.296875 0.21875 C 3.453125 0.21875 4.46875 -0.734375 4.46875 -2 Z M 4.46875 -2 "/>
</g>
<g id="glyph-0-5">
<path d="M 1.3125 -3.265625 L 1.3125 -3.515625 C 1.3125 -6.03125 2.546875 -6.390625 3.0625 -6.390625 C 3.296875 -6.390625 3.71875 -6.328125 3.9375 -5.984375 C 3.78125 -5.984375 3.390625 -5.984375 3.390625 -5.546875 C 3.390625 -5.234375 3.625 -5.078125 3.84375 -5.078125 C 4 -5.078125 4.3125 -5.171875 4.3125 -5.5625 C 4.3125 -6.15625 3.875 -6.640625 3.046875 -6.640625 C 1.765625 -6.640625 0.421875 -5.359375 0.421875 -3.15625 C 0.421875 -0.484375 1.578125 0.21875 2.5 0.21875 C 3.609375 0.21875 4.5625 -0.71875 4.5625 -2.03125 C 4.5625 -3.296875 3.671875 -4.25 2.5625 -4.25 C 1.890625 -4.25 1.515625 -3.75 1.3125 -3.265625 Z M 2.5 -0.0625 C 1.875 -0.0625 1.578125 -0.65625 1.515625 -0.8125 C 1.328125 -1.28125 1.328125 -2.078125 1.328125 -2.25 C 1.328125 -3.03125 1.65625 -4.03125 2.546875 -4.03125 C 2.71875 -4.03125 3.171875 -4.03125 3.484375 -3.40625 C 3.65625 -3.046875 3.65625 -2.53125 3.65625 -2.046875 C 3.65625 -1.5625 3.65625 -1.0625 3.484375 -0.703125 C 3.1875 -0.109375 2.734375 -0.0625 2.5 -0.0625 Z M 2.5 -0.0625 "/>
</g>
<g id="glyph-0-6">
<path d="M 1.625 -4.5625 C 1.171875 -4.859375 1.125 -5.1875 1.125 -5.359375 C 1.125 -5.96875 1.78125 -6.390625 2.484375 -6.390625 C 3.203125 -6.390625 3.84375 -5.875 3.84375 -5.15625 C 3.84375 -4.578125 3.453125 -4.109375 2.859375 -3.765625 Z M 3.078125 -3.609375 C 3.796875 -3.984375 4.28125 -4.5 4.28125 -5.15625 C 4.28125 -6.078125 3.40625 -6.640625 2.5 -6.640625 C 1.5 -6.640625 0.6875 -5.90625 0.6875 -4.96875 C 0.6875 -4.796875 0.703125 -4.34375 1.125 -3.875 C 1.234375 -3.765625 1.609375 -3.515625 1.859375 -3.34375 C 1.28125 -3.046875 0.421875 -2.5 0.421875 -1.5 C 0.421875 -0.453125 1.4375 0.21875 2.484375 0.21875 C 3.609375 0.21875 4.5625 -0.609375 4.5625 -1.671875 C 4.5625 -2.03125 4.453125 -2.484375 4.0625 -2.90625 C 3.875 -3.109375 3.71875 -3.203125 3.078125 -3.609375 Z M 2.078125 -3.1875 L 3.3125 -2.40625 C 3.59375 -2.21875 4.0625 -1.921875 4.0625 -1.3125 C 4.0625 -0.578125 3.3125 -0.0625 2.5 -0.0625 C 1.640625 -0.0625 0.921875 -0.671875 0.921875 -1.5 C 0.921875 -2.078125 1.234375 -2.71875 2.078125 -3.1875 Z M 2.078125 -3.1875 "/>
</g>
<g id="glyph-0-7">
<path d="M 2.9375 -1.640625 L 2.9375 -0.78125 C 2.9375 -0.421875 2.90625 -0.3125 2.171875 -0.3125 L 1.96875 -0.3125 L 1.96875 0 C 2.375 -0.03125 2.890625 -0.03125 3.3125 -0.03125 C 3.734375 -0.03125 4.25 -0.03125 4.671875 0 L 4.671875 -0.3125 L 4.453125 -0.3125 C 3.71875 -0.3125 3.703125 -0.421875 3.703125 -0.78125 L 3.703125 -1.640625 L 4.6875 -1.640625 L 4.6875 -1.953125 L 3.703125 -1.953125 L 3.703125 -6.484375 C 3.703125 -6.6875 3.703125 -6.75 3.53125 -6.75 C 3.453125 -6.75 3.421875 -6.75 3.34375 -6.625 L 0.28125 -1.953125 L 0.28125 -1.640625 Z M 2.984375 -1.953125 L 0.5625 -1.953125 L 2.984375 -5.671875 Z M 2.984375 -1.953125 "/>
</g>
<g id="glyph-0-8">
<path d="M 3.65625 -3.171875 L 3.65625 -2.84375 C 3.65625 -0.515625 2.625 -0.0625 2.046875 -0.0625 C 1.875 -0.0625 1.328125 -0.078125 1.0625 -0.421875 C 1.5 -0.421875 1.578125 -0.703125 1.578125 -0.875 C 1.578125 -1.1875 1.34375 -1.328125 1.125 -1.328125 C 0.96875 -1.328125 0.671875 -1.25 0.671875 -0.859375 C 0.671875 -0.1875 1.203125 0.21875 2.046875 0.21875 C 3.34375 0.21875 4.5625 -1.140625 4.5625 -3.28125 C 4.5625 -5.96875 3.40625 -6.640625 2.515625 -6.640625 C 1.96875 -6.640625 1.484375 -6.453125 1.0625 -6.015625 C 0.640625 -5.5625 0.421875 -5.140625 0.421875 -4.390625 C 0.421875 -3.15625 1.296875 -2.171875 2.40625 -2.171875 C 3.015625 -2.171875 3.421875 -2.59375 3.65625 -3.171875 Z M 2.421875 -2.40625 C 2.265625 -2.40625 1.796875 -2.40625 1.5 -3.03125 C 1.3125 -3.40625 1.3125 -3.890625 1.3125 -4.390625 C 1.3125 -4.921875 1.3125 -5.390625 1.53125 -5.765625 C 1.796875 -6.265625 2.171875 -6.390625 2.515625 -6.390625 C 2.984375 -6.390625 3.3125 -6.046875 3.484375 -5.609375 C 3.59375 -5.28125 3.640625 -4.65625 3.640625 -4.203125 C 3.640625 -3.375 3.296875 -2.40625 2.421875 -2.40625 Z M 2.421875 -2.40625 "/>
</g>
<g id="glyph-0-9">
<path d="M 1.265625 -0.765625 L 2.328125 -1.796875 C 3.875 -3.171875 4.46875 -3.703125 4.46875 -4.703125 C 4.46875 -5.84375 3.578125 -6.640625 2.359375 -6.640625 C 1.234375 -6.640625 0.5 -5.71875 0.5 -4.828125 C 0.5 -4.28125 1 -4.28125 1.03125 -4.28125 C 1.203125 -4.28125 1.546875 -4.390625 1.546875 -4.8125 C 1.546875 -5.0625 1.359375 -5.328125 1.015625 -5.328125 C 0.9375 -5.328125 0.921875 -5.328125 0.890625 -5.3125 C 1.109375 -5.96875 1.65625 -6.328125 2.234375 -6.328125 C 3.140625 -6.328125 3.5625 -5.515625 3.5625 -4.703125 C 3.5625 -3.90625 3.078125 -3.125 2.515625 -2.5 L 0.609375 -0.375 C 0.5 -0.265625 0.5 -0.234375 0.5 0 L 4.203125 0 L 4.46875 -1.734375 L 4.234375 -1.734375 C 4.171875 -1.4375 4.109375 -1 4 -0.84375 C 3.9375 -0.765625 3.28125 -0.765625 3.0625 -0.765625 Z M 1.265625 -0.765625 "/>
</g>
</g>
</defs>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 8.754781 -0.000125 C 8.754781 4.835813 4.832906 8.753781 0.000875 8.753781 C -4.835062 8.753781 -8.753031 4.835813 -8.753031 -0.000125 C -8.753031 -4.836062 -4.835062 -8.754031 0.000875 -8.754031 C 4.832906 -8.754031 8.754781 -4.836062 8.754781 -0.000125 Z M 8.754781 -0.000125 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-0" x="312.806" y="84.163"/>
</g>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -104.635844 -42.519656 C -104.635844 -37.687625 -108.553812 -33.76575 -113.385844 -33.76575 C -118.221781 -33.76575 -122.13975 -37.687625 -122.13975 -42.519656 C -122.13975 -47.355594 -118.221781 -51.273562 -113.385844 -51.273562 C -108.553812 -51.273562 -104.635844 -47.355594 -104.635844 -42.519656 Z M -104.635844 -42.519656 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-1" x="199.42" y="126.682"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -8.381937 -3.144656 L -105.006937 -39.375125 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -161.32725 -85.039187 C -161.32725 -80.207156 -165.245219 -76.289187 -170.081156 -76.289187 C -174.917094 -76.289187 -178.835062 -80.207156 -178.835062 -85.039187 C -178.835062 -89.875125 -174.917094 -93.793094 -170.081156 -93.793094 C -165.245219 -93.793094 -161.32725 -89.875125 -161.32725 -85.039187 Z M -161.32725 -85.039187 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-2" x="142.727" y="169.202"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -120.549906 -47.89075 L -162.921 -79.668094 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -189.674906 -127.558719 C -189.674906 -122.726687 -193.592875 -118.808719 -198.428812 -118.808719 C -203.260844 -118.808719 -207.182719 -122.726687 -207.182719 -127.558719 C -207.182719 -132.394656 -203.260844 -136.312625 -198.428812 -136.312625 C -193.592875 -136.312625 -189.674906 -132.394656 -189.674906 -127.558719 Z M -189.674906 -127.558719 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-3" x="114.38" y="211.722"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -175.046 -92.488406 L -193.463969 -120.113406 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -202.026469 -170.082156 C -202.026469 -164.242312 -206.760844 -159.507937 -212.600687 -159.507937 C -218.440531 -159.507937 -223.174906 -164.242312 -223.174906 -170.082156 C -223.174906 -175.922 -218.440531 -180.652469 -212.600687 -180.652469 C -206.760844 -180.652469 -202.026469 -175.922 -202.026469 -170.082156 Z M -202.026469 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-1" x="97.717" y="254.241"/>
<use xlink:href="#glyph-0-4" x="102.6983" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -201.256937 -136.054812 L -209.194437 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -173.678812 -170.082156 C -173.678812 -164.242312 -178.413187 -159.507937 -184.253031 -159.507937 C -190.092875 -159.507937 -194.82725 -164.242312 -194.82725 -170.082156 C -194.82725 -175.922 -190.092875 -180.652469 -184.253031 -180.652469 C -178.413187 -180.652469 -173.678812 -175.922 -173.678812 -170.082156 Z M -173.678812 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-1" x="126.063" y="254.241"/>
<use xlink:href="#glyph-0-5" x="131.0443" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -195.596781 -136.054812 L -187.659281 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -132.979594 -127.558719 C -132.979594 -122.726687 -136.901469 -118.808719 -141.7335 -118.808719 C -146.569437 -118.808719 -150.487406 -122.726687 -150.487406 -127.558719 C -150.487406 -132.394656 -146.569437 -136.312625 -141.7335 -136.312625 C -136.901469 -136.312625 -132.979594 -132.394656 -132.979594 -127.558719 Z M -132.979594 -127.558719 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-6" x="171.073" y="211.722"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -165.116312 -92.488406 L -146.698344 -120.113406 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -145.335062 -170.082156 C -145.335062 -164.242312 -150.069437 -159.507937 -155.909281 -159.507937 C -161.745219 -159.507937 -166.479594 -164.242312 -166.479594 -170.082156 C -166.479594 -175.922 -161.745219 -180.652469 -155.909281 -180.652469 C -150.069437 -180.652469 -145.335062 -175.922 -145.335062 -170.082156 Z M -145.335062 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-1" x="154.409" y="254.241"/>
<use xlink:href="#glyph-0-3" x="159.3903" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -144.565531 -136.054812 L -152.499125 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -116.987406 -170.082156 C -116.987406 -164.242312 -121.721781 -159.507937 -127.561625 -159.507937 C -133.401469 -159.507937 -138.135844 -164.242312 -138.135844 -170.082156 C -138.135844 -175.922 -133.401469 -180.652469 -127.561625 -180.652469 C -121.721781 -180.652469 -116.987406 -175.922 -116.987406 -170.082156 Z M -116.987406 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-1" x="182.756" y="254.241"/>
<use xlink:href="#glyph-0-6" x="187.7373" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -138.901469 -136.054812 L -130.967875 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -47.940531 -85.039187 C -47.940531 -80.207156 -51.8585 -76.289187 -56.694437 -76.289187 C -61.526469 -76.289187 -65.448344 -80.207156 -65.448344 -85.039187 C -65.448344 -89.875125 -61.526469 -93.793094 -56.694437 -93.793094 C -51.8585 -93.793094 -47.940531 -89.875125 -47.940531 -85.039187 Z M -47.940531 -85.039187 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-7" x="256.113" y="169.202"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -106.225687 -47.89075 L -63.854594 -79.668094 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -76.288187 -127.558719 C -76.288187 -122.726687 -80.206156 -118.808719 -85.042094 -118.808719 C -89.874125 -118.808719 -93.792094 -122.726687 -93.792094 -127.558719 C -93.792094 -132.394656 -89.874125 -136.312625 -85.042094 -136.312625 C -80.206156 -136.312625 -76.288187 -132.394656 -76.288187 -127.558719 Z M -76.288187 -127.558719 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-8" x="227.766" y="211.722"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -61.659281 -92.488406 L -80.073344 -120.113406 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -88.63975 -170.082156 C -88.63975 -164.242312 -93.374125 -159.507937 -99.213969 -159.507937 C -105.053812 -159.507937 -109.788187 -164.242312 -109.788187 -170.082156 C -109.788187 -175.922 -105.053812 -180.652469 -99.213969 -180.652469 C -93.374125 -180.652469 -88.63975 -175.922 -88.63975 -170.082156 Z M -88.63975 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-1" x="211.102" y="254.241"/>
<use xlink:href="#glyph-0-8" x="216.0833" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -87.870219 -136.054812 L -95.807719 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -60.292094 -170.082156 C -60.292094 -164.242312 -65.026469 -159.507937 -70.866312 -159.507937 C -76.706156 -159.507937 -81.440531 -164.242312 -81.440531 -170.082156 C -81.440531 -175.922 -76.706156 -180.652469 -70.866312 -180.652469 C -65.026469 -180.652469 -60.292094 -175.922 -60.292094 -170.082156 Z M -60.292094 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-9" x="239.449" y="254.241"/>
<use xlink:href="#glyph-0-0" x="244.4303" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -82.210062 -136.054812 L -74.272562 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -17.772562 -127.558719 C -17.772562 -121.722781 -22.506937 -116.988406 -28.346781 -116.988406 C -34.186625 -116.988406 -38.921 -121.722781 -38.921 -127.558719 C -38.921 -133.398562 -34.186625 -138.132937 -28.346781 -138.132937 C -22.506937 -138.132937 -17.772562 -133.398562 -17.772562 -127.558719 Z M -17.772562 -127.558719 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-1" x="281.968" y="211.722"/>
<use xlink:href="#glyph-0-0" x="286.9493" y="211.722"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -51.729594 -92.488406 L -34.323344 -118.597781 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -31.948344 -170.082156 C -31.948344 -164.242312 -36.678812 -159.507937 -42.518656 -159.507937 C -48.3585 -159.507937 -53.092875 -164.242312 -53.092875 -170.082156 C -53.092875 -175.922 -48.3585 -180.652469 -42.518656 -180.652469 C -36.678812 -180.652469 -31.948344 -175.922 -31.948344 -170.082156 Z M -31.948344 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-9" x="267.795" y="254.241"/>
<use xlink:href="#glyph-0-1" x="272.7763" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -31.753031 -137.781375 L -39.112406 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M -3.600687 -170.082156 C -3.600687 -164.242312 -8.335062 -159.507937 -14.174906 -159.507937 C -20.01475 -159.507937 -24.745219 -164.242312 -24.745219 -170.082156 C -24.745219 -175.922 -20.01475 -180.652469 -14.174906 -180.652469 C -8.335062 -180.652469 -3.600687 -175.922 -3.600687 -170.082156 Z M -3.600687 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-9" x="296.142" y="254.241"/>
<use xlink:href="#glyph-0-9" x="301.1233" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M -24.940531 -137.781375 L -17.581156 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 122.1415 -42.519656 C 122.1415 -37.687625 118.223531 -33.76575 113.387594 -33.76575 C 108.551656 -33.76575 104.633688 -37.687625 104.633688 -42.519656 C 104.633688 -47.355594 108.551656 -51.273562 113.387594 -51.273562 C 118.223531 -51.273562 122.1415 -47.355594 122.1415 -42.519656 Z M 122.1415 -42.519656 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-9" x="426.191" y="126.682"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 8.383688 -3.144656 L 105.004781 -39.375125 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 65.446188 -85.039187 C 65.446188 -80.207156 61.528219 -76.289187 56.692281 -76.289187 C 51.86025 -76.289187 47.942281 -80.207156 47.942281 -85.039187 C 47.942281 -89.875125 51.86025 -93.793094 56.692281 -93.793094 C 61.528219 -93.793094 65.446188 -89.875125 65.446188 -85.039187 Z M 65.446188 -85.039187 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-4" x="369.498" y="169.202"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 106.227438 -47.89075 L 63.856344 -79.668094 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 38.918844 -127.558719 C 38.918844 -121.722781 34.188375 -116.988406 28.348531 -116.988406 C 22.508688 -116.988406 17.774313 -121.722781 17.774313 -127.558719 C 17.774313 -133.398562 22.508688 -138.132937 28.348531 -138.132937 C 34.188375 -138.132937 38.918844 -133.398562 38.918844 -127.558719 Z M 38.918844 -127.558719 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-1" x="338.661" y="211.722"/>
<use xlink:href="#glyph-0-1" x="343.6423" y="211.722"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 51.727438 -92.488406 L 34.321188 -118.597781 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 24.746969 -170.082156 C 24.746969 -164.242312 20.012594 -159.507937 14.17275 -159.507937 C 8.332906 -159.507937 3.598531 -164.242312 3.598531 -170.082156 C 3.598531 -175.922 8.332906 -180.652469 14.17275 -180.652469 C 20.012594 -180.652469 24.746969 -175.922 24.746969 -170.082156 Z M 24.746969 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-9" x="324.488" y="254.241"/>
<use xlink:href="#glyph-0-2" x="329.4693" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 24.942281 -137.781375 L 17.579 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 53.094625 -170.082156 C 53.094625 -164.242312 48.36025 -159.507937 42.520406 -159.507937 C 36.680563 -159.507937 31.946188 -164.242312 31.946188 -170.082156 C 31.946188 -175.922 36.680563 -180.652469 42.520406 -180.652469 C 48.36025 -180.652469 53.094625 -175.922 53.094625 -170.082156 Z M 53.094625 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-9" x="352.835" y="254.241"/>
<use xlink:href="#glyph-0-7" x="357.8163" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 31.754781 -137.781375 L 39.114156 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 95.614156 -127.558719 C 95.614156 -121.722781 90.879781 -116.988406 85.039938 -116.988406 C 79.200094 -116.988406 74.465719 -121.722781 74.465719 -127.558719 C 74.465719 -133.398562 79.200094 -138.132937 85.039938 -138.132937 C 90.879781 -138.132937 95.614156 -133.398562 95.614156 -127.558719 Z M 95.614156 -127.558719 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-1" x="395.354" y="211.722"/>
<use xlink:href="#glyph-0-9" x="400.3353" y="211.722"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 61.661031 -92.488406 L 79.063375 -118.597781 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 81.442281 -170.082156 C 81.442281 -164.242312 76.707906 -159.507937 70.868063 -159.507937 C 65.028219 -159.507937 60.293844 -164.242312 60.293844 -170.082156 C 60.293844 -175.922 65.028219 -180.652469 70.868063 -180.652469 C 76.707906 -180.652469 81.442281 -175.922 81.442281 -170.082156 Z M 81.442281 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-9" x="381.181" y="254.241"/>
<use xlink:href="#glyph-0-4" x="386.1623" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 81.633688 -137.781375 L 74.274313 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 109.786031 -170.082156 C 109.786031 -164.242312 105.051656 -159.507937 99.215719 -159.507937 C 93.375875 -159.507937 88.6415 -164.242312 88.6415 -170.082156 C 88.6415 -175.922 93.375875 -180.652469 99.215719 -180.652469 C 105.051656 -180.652469 109.786031 -175.922 109.786031 -170.082156 Z M 109.786031 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-9" x="409.527" y="254.241"/>
<use xlink:href="#glyph-0-5" x="414.5083" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 88.446188 -137.781375 L 95.805563 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 178.832906 -85.039187 C 178.832906 -80.207156 174.914938 -76.289187 170.079 -76.289187 C 165.246969 -76.289187 161.329 -80.207156 161.329 -85.039187 C 161.329 -89.875125 165.246969 -93.793094 170.079 -93.793094 C 174.914938 -93.793094 178.832906 -89.875125 178.832906 -85.039187 Z M 178.832906 -85.039187 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-5" x="482.884" y="169.202"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 120.54775 -47.89075 L 162.918844 -79.668094 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 152.309469 -127.558719 C 152.309469 -121.722781 147.575094 -116.988406 141.73525 -116.988406 C 135.895406 -116.988406 131.161031 -121.722781 131.161031 -127.558719 C 131.161031 -133.398562 135.895406 -138.132937 141.73525 -138.132937 C 147.575094 -138.132937 152.309469 -133.398562 152.309469 -127.558719 Z M 152.309469 -127.558719 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-1" x="452.047" y="211.722"/>
<use xlink:href="#glyph-0-2" x="457.0283" y="211.722"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 165.114156 -92.488406 L 147.707906 -118.597781 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 138.133688 -170.082156 C 138.133688 -164.242312 133.399313 -159.507937 127.559469 -159.507937 C 121.719625 -159.507937 116.989156 -164.242312 116.989156 -170.082156 C 116.989156 -175.922 121.719625 -180.652469 127.559469 -180.652469 C 133.399313 -180.652469 138.133688 -175.922 138.133688 -170.082156 Z M 138.133688 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-9" x="437.874" y="254.241"/>
<use xlink:href="#glyph-0-3" x="442.8553" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 138.329 -137.781375 L 130.965719 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 166.481344 -170.082156 C 166.481344 -164.242312 161.746969 -159.507937 155.907125 -159.507937 C 150.067281 -159.507937 145.332906 -164.242312 145.332906 -170.082156 C 145.332906 -175.922 150.067281 -180.652469 155.907125 -180.652469 C 161.746969 -180.652469 166.481344 -175.922 166.481344 -170.082156 Z M 166.481344 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-9" x="466.22" y="254.241"/>
<use xlink:href="#glyph-0-6" x="471.2013" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 145.1415 -137.781375 L 152.500875 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 209.000875 -127.558719 C 209.000875 -121.722781 204.2665 -116.988406 198.426656 -116.988406 C 192.586813 -116.988406 187.852438 -121.722781 187.852438 -127.558719 C 187.852438 -133.398562 192.586813 -138.132937 198.426656 -138.132937 C 204.2665 -138.132937 209.000875 -133.398562 209.000875 -127.558719 Z M 209.000875 -127.558719 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-1" x="508.74" y="211.722"/>
<use xlink:href="#glyph-0-7" x="513.7213" y="211.722"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 175.04775 -92.488406 L 192.454 -118.597781 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 194.829 -170.082156 C 194.829 -164.242312 190.094625 -159.507937 184.254781 -159.507937 C 178.414938 -159.507937 173.680563 -164.242312 173.680563 -170.082156 C 173.680563 -175.922 178.414938 -180.652469 184.254781 -180.652469 C 190.094625 -180.652469 194.829 -175.922 194.829 -170.082156 Z M 194.829 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-9" x="494.567" y="254.241"/>
<use xlink:href="#glyph-0-8" x="499.5483" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 195.020406 -137.781375 L 187.661031 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<path fill-rule="nonzero" fill="rgb(79.998779%, 79.998779%, 100%)" fill-opacity="1" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 100%)" stroke-opacity="1" stroke-miterlimit="10" d="M 223.176656 -170.082156 C 223.176656 -164.242312 218.442281 -159.507937 212.602438 -159.507937 C 206.762594 -159.507937 202.028219 -164.242312 202.028219 -170.082156 C 202.028219 -175.922 206.762594 -180.652469 212.602438 -180.652469 C 218.442281 -180.652469 223.176656 -175.922 223.176656 -170.082156 Z M 223.176656 -170.082156 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
<g fill="rgb(0%, 0%, 0%)" fill-opacity="1">
<use xlink:href="#glyph-0-2" x="522.913" y="254.241"/>
<use xlink:href="#glyph-0-0" x="527.8943" y="254.241"/>
</g>
<path fill="none" stroke-width="0.3985" stroke-linecap="butt" stroke-linejoin="miter" stroke="rgb(0%, 0%, 0%)" stroke-opacity="1" stroke-miterlimit="10" d="M 201.832906 -137.781375 L 209.196188 -159.8595 " transform="matrix(1, 0, 0, -1, 315.296, 80.953)"/>
</svg>

After

Width:  |  Height:  |  Size: 40 KiB

View file

@ -16,40 +16,56 @@
This module provides an implementation of the heap queue algorithm, also known
as the priority queue algorithm.
Heaps are binary trees for which every parent node has a value less than or
equal to any of its children. We refer to this condition as the heap invariant.
Min-heaps are binary trees for which every parent node has a value less than
or equal to any of its children.
We refer to this condition as the heap invariant.
This implementation uses arrays for which
``heap[k] <= heap[2*k+1]`` and ``heap[k] <= heap[2*k+2]`` for all *k*, counting
elements from zero. For the sake of comparison, non-existing elements are
considered to be infinite. The interesting property of a heap is that its
smallest element is always the root, ``heap[0]``.
For min-heaps, this implementation uses lists for which
``heap[k] <= heap[2*k+1]`` and ``heap[k] <= heap[2*k+2]`` for all *k* for which
the compared elements exist. Elements are counted from zero. The interesting
property of a min-heap is that its smallest element is always the root,
``heap[0]``.
The API below differs from textbook heap algorithms in two aspects: (a) We use
zero-based indexing. This makes the relationship between the index for a node
and the indexes for its children slightly less obvious, but is more suitable
since Python uses zero-based indexing. (b) Our pop method returns the smallest
item, not the largest (called a "min heap" in textbooks; a "max heap" is more
common in texts because of its suitability for in-place sorting).
Max-heaps satisfy the reverse invariant: every parent node has a value
*greater* than any of its children. These are implemented as lists for which
``maxheap[2*k+1] <= maxheap[k]`` and ``maxheap[2*k+2] <= maxheap[k]`` for all
*k* for which the compared elements exist.
The root, ``maxheap[0]``, contains the *largest* element;
``heap.sort(reverse=True)`` maintains the max-heap invariant.
These two make it possible to view the heap as a regular Python list without
surprises: ``heap[0]`` is the smallest item, and ``heap.sort()`` maintains the
heap invariant!
The :mod:`!heapq` API differs from textbook heap algorithms in two aspects: (a)
We use zero-based indexing. This makes the relationship between the index for
a node and the indexes for its children slightly less obvious, but is more
suitable since Python uses zero-based indexing. (b) Textbooks often focus on
max-heaps, due to their suitability for in-place sorting. Our implementation
favors min-heaps as they better correspond to Python :class:`lists <list>`.
To create a heap, use a list initialized to ``[]``, or you can transform a
populated list into a heap via function :func:`heapify`.
These two aspects make it possible to view the heap as a regular Python list
without surprises: ``heap[0]`` is the smallest item, and ``heap.sort()``
maintains the heap invariant!
The following functions are provided:
Like :meth:`list.sort`, this implementation uses only the ``<`` operator
for comparisons, for both min-heaps and max-heaps.
In the API below, and in this documentation, the unqualified term *heap*
generally refers to a min-heap.
The API for max-heaps is named using a ``_max`` suffix.
To create a heap, use a list initialized as ``[]``, or transform an existing list
into a min-heap or max-heap using the :func:`heapify` or :func:`heapify_max`
functions, respectively.
The following functions are provided for min-heaps:
.. function:: heappush(heap, item)
Push the value *item* onto the *heap*, maintaining the heap invariant.
Push the value *item* onto the *heap*, maintaining the min-heap invariant.
.. function:: heappop(heap)
Pop and return the smallest item from the *heap*, maintaining the heap
Pop and return the smallest item from the *heap*, maintaining the min-heap
invariant. If the heap is empty, :exc:`IndexError` is raised. To access the
smallest item without popping it, use ``heap[0]``.
@ -63,7 +79,7 @@ The following functions are provided:
.. function:: heapify(x)
Transform list *x* into a heap, in-place, in linear time.
Transform list *x* into a min-heap, in-place, in linear time.
.. function:: heapreplace(heap, item)
@ -82,6 +98,56 @@ The following functions are provided:
on the heap.
For max-heaps, the following functions are provided:
.. function:: heapify_max(x)
Transform list *x* into a max-heap, in-place, in linear time.
.. versionadded:: 3.14
.. function:: heappush_max(heap, item)
Push the value *item* onto the max-heap *heap*, maintaining the max-heap
invariant.
.. versionadded:: 3.14
.. function:: heappop_max(heap)
Pop and return the largest item from the max-heap *heap*, maintaining the
max-heap invariant. If the max-heap is empty, :exc:`IndexError` is raised.
To access the largest item without popping it, use ``maxheap[0]``.
.. versionadded:: 3.14
.. function:: heappushpop_max(heap, item)
Push *item* on the max-heap *heap*, then pop and return the largest item
from *heap*.
The combined action runs more efficiently than :func:`heappush_max`
followed by a separate call to :func:`heappop_max`.
.. versionadded:: 3.14
.. function:: heapreplace_max(heap, item)
Pop and return the largest item from the max-heap *heap* and also push the
new *item*.
The max-heap size doesn't change. If the max-heap is empty,
:exc:`IndexError` is raised.
The value returned may be smaller than the *item* added. Refer to the
analogous function :func:`heapreplace` for detailed usage notes.
.. versionadded:: 3.14
The module also offers three general purpose functions based on heaps.
@ -246,17 +312,12 @@ elements are considered to be infinite. The interesting property of a heap is
that ``a[0]`` is always its smallest element.
The strange invariant above is meant to be an efficient memory representation
for a tournament. The numbers below are *k*, not ``a[k]``::
for a tournament. The numbers below are *k*, not ``a[k]``:
0
1 2
3 4 5 6
7 8 9 10 11 12 13 14
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
.. figure:: heapq-binary-tree.svg
:class: invert-in-dark-mode
:align: center
:alt: Example (min-heap) binary tree.
In the tree above, each cell *k* is topping ``2*k+1`` and ``2*k+2``. In a usual
binary tournament we see in sports, each cell is the winner over the two cells

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