mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
Merge branch 'main' into fix-issue-42550
This commit is contained in:
commit
7146d5b226
1201 changed files with 50215 additions and 17956 deletions
|
@ -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
2
.gitattributes
vendored
|
@ -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
14
.github/CODEOWNERS
vendored
|
@ -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
|
||||
|
|
1
.github/ISSUE_TEMPLATE/bug.yml
vendored
1
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
@ -40,6 +40,7 @@ body:
|
|||
- "3.12"
|
||||
- "3.13"
|
||||
- "3.14"
|
||||
- "3.15"
|
||||
- "CPython main branch"
|
||||
validations:
|
||||
required: true
|
||||
|
|
1
.github/ISSUE_TEMPLATE/crash.yml
vendored
1
.github/ISSUE_TEMPLATE/crash.yml
vendored
|
@ -33,6 +33,7 @@ body:
|
|||
- "3.12"
|
||||
- "3.13"
|
||||
- "3.14"
|
||||
- "3.15"
|
||||
- "CPython main branch"
|
||||
validations:
|
||||
required: true
|
||||
|
|
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
|
@ -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:
|
||||
|
|
55
.github/workflows/jit.yml
vendored
55
.github/workflows/jit.yml
vendored
|
@ -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
|
||||
|
|
8
.github/workflows/mypy.yml
vendored
8
.github/workflows/mypy.yml
vendored
|
@ -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
|
||||
|
|
3
.github/workflows/reusable-context.yml
vendored
3
.github/workflows/reusable-context.yml
vendored
|
@ -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
|
||||
|
|
1
.github/workflows/tail-call.yml
vendored
1
.github/workflows/tail-call.yml
vendored
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -32,4 +32,3 @@ build:
|
|||
- make -C Doc venv html
|
||||
- mkdir _readthedocs
|
||||
- mv Doc/build/html _readthedocs/html
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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::
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
156
Doc/c-api/lifecycle.dot
Normal 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"
|
||||
]
|
||||
}
|
21
Doc/c-api/lifecycle.dot.css
Normal file
21
Doc/c-api/lifecycle.dot.css
Normal 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
BIN
Doc/c-api/lifecycle.dot.pdf
Normal file
Binary file not shown.
374
Doc/c-api/lifecycle.dot.svg
generated
Normal file
374
Doc/c-api/lifecycle.dot.svg
generated
Normal 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->tp_new -->
|
||||
<g id="life_events_graph_edge1" class="edge">
|
||||
<title>start->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-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">    type call  </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->tp_alloc -->
|
||||
<g id="life_events_graph_edge2" class="edge">
|
||||
<title>tp_new->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-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">  direct call  </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->tp_init -->
|
||||
<g id="life_events_graph_edge3" class="edge">
|
||||
<title>tp_new->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->reachable -->
|
||||
<g id="life_events_graph_edge4" class="edge">
|
||||
<title>tp_init->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->tp_init -->
|
||||
<g id="life_events_graph_edge7" class="edge">
|
||||
<title>reachable->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->tp_traverse -->
|
||||
<g id="life_events_graph_edge5" class="edge">
|
||||
<title>reachable->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-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">  not in a  </text>
|
||||
<text text-anchor="start" x="59.67" y="-609.85" font-family="serif,serif" font-style="italic" font-size="12.00">  cyclic  </text>
|
||||
<text text-anchor="start" x="57.05" y="-595.6" font-family="serif,serif" font-style="italic" font-size="12.00">  isolate  </text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- reachable->tp_traverse -->
|
||||
<g id="life_events_graph_edge6" class="edge">
|
||||
<title>reachable->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-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">  periodic  </text>
|
||||
<text text-anchor="start" x="138.05" y="-609.85" font-family="serif,serif" font-style="italic" font-size="12.00">  cyclic isolate   </text>
|
||||
<text text-anchor="start" x="151.17" y="-595.6" font-family="serif,serif" font-style="italic" font-size="12.00">  detection  </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->finalized? -->
|
||||
<g id="life_events_graph_edge10" class="edge">
|
||||
<title>reachable->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-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">  no refs  </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->tp_finalize -->
|
||||
<g id="life_events_graph_edge8" class="edge">
|
||||
<title>reachable->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-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">  resurrected  </text>
|
||||
<text text-anchor="start" x="22.43" y="-513.1" font-family="serif,serif" font-style="italic" font-size="12.00">  (maybe remove  </text>
|
||||
<text text-anchor="start" x="23.18" y="-498.85" font-family="serif,serif" font-style="italic" font-size="12.00">  finalized mark)  </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->uncollectable -->
|
||||
<g id="life_events_graph_edge19" class="edge">
|
||||
<title>reachable->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-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">  cyclic  </text>
|
||||
<text text-anchor="start" x="332.42" y="-379.35" font-family="serif,serif" font-style="italic" font-size="12.00">  isolate  </text>
|
||||
<text text-anchor="start" x="331.3" y="-365.1" font-family="serif,serif" font-style="italic" font-size="12.00">  (no GC  </text>
|
||||
<text text-anchor="start" x="326.8" y="-350.85" font-family="serif,serif" font-style="italic" font-size="12.00">  support)  </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->tp_dealloc -->
|
||||
<g id="life_events_graph_edge20" class="edge">
|
||||
<title>reachable->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-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">  no refs</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- tp_traverse->finalized? -->
|
||||
<g id="life_events_graph_edge9" class="edge">
|
||||
<title>tp_traverse->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-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">  cyclic  </text>
|
||||
<text text-anchor="start" x="169.22" y="-505.98" font-family="serif,serif" font-style="italic" font-size="12.00">  isolate  </text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- finalized?->tp_finalize -->
|
||||
<g id="life_events_graph_edge11" class="edge">
|
||||
<title>finalized?->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-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">  no (mark  </text>
|
||||
<text text-anchor="start" x="162.05" y="-365.1" font-family="serif,serif" font-style="italic" font-size="12.00">  as finalized)  </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?->tp_clear -->
|
||||
<g id="life_events_graph_edge12" class="edge">
|
||||
<title>finalized?->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-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">  yes  </text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- tp_finalize->tp_clear -->
|
||||
<g id="life_events_graph_edge13" class="edge">
|
||||
<title>tp_finalize->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-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">  no refs or   </text>
|
||||
<text text-anchor="start" x="156.8" y="-268.35" font-family="serif,serif" font-style="italic" font-size="12.00">  cyclic isolate  </text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- tp_finalize->tp_dealloc -->
|
||||
<g id="life_events_graph_edge14" class="edge">
|
||||
<title>tp_finalize->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-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">  recommended</text>
|
||||
<text text-anchor="start" x="25.8" y="-185.85" font-family="serif,serif" font-style="italic" font-size="12.00">  call (see</text>
|
||||
<text text-anchor="start" x="13.05" y="-171.6" font-family="serif,serif" font-style="italic" font-size="12.00">  explanation)</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- tp_finalize->tp_dealloc -->
|
||||
<g id="life_events_graph_edge15" class="edge">
|
||||
<title>tp_finalize->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-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">   no refs  </text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- tp_clear->uncollectable -->
|
||||
<g id="life_events_graph_edge17" class="edge">
|
||||
<title>tp_clear->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-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">  cyclic  </text>
|
||||
<text text-anchor="start" x="258.05" y="-178.72" font-family="serif,serif" font-style="italic" font-size="12.00">  isolate  </text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- tp_clear->tp_dealloc -->
|
||||
<g id="life_events_graph_edge16" class="edge">
|
||||
<title>tp_clear->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-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">  no refs  </text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- uncollectable->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->tp_free -->
|
||||
<g id="life_events_graph_edge21" class="edge">
|
||||
<title>tp_dealloc->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-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">    direct call  </text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 21 KiB |
273
Doc/c-api/lifecycle.rst
Normal file
273
Doc/c-api/lifecycle.rst
Normal 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.
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -12,6 +12,7 @@ object types.
|
|||
.. toctree::
|
||||
|
||||
allocation.rst
|
||||
lifecycle.rst
|
||||
structures.rst
|
||||
typeobj.rst
|
||||
gcsupport.rst
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
]
|
||||
|
||||
|
|
|
@ -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:::
|
||||
|
|
15
Doc/data/stable_abi.dat
generated
15
Doc/data/stable_abi.dat
generated
|
@ -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,,
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`.)
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
10
Doc/deprecations/pending-removal-in-3.17.rst
Normal file
10
Doc/deprecations/pending-removal-in-3.17.rst
Normal 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.
|
8
Doc/deprecations/pending-removal-in-3.19.rst
Normal file
8
Doc/deprecations/pending-removal-in-3.19.rst
Normal 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.
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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+).
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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
|
||||
================
|
||||
|
||||
|
|
|
@ -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
|
||||
............................
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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
|
||||
----------------------------------
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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'}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
::
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
============
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -48,5 +48,5 @@ public API of CPython:
|
|||
| ctypes.PyObj_FromPtr | ``obj`` |
|
||||
+----------------------------+-------------------------------------------+
|
||||
|
||||
.. versionadded:: next
|
||||
.. versionadded:: 3.14
|
||||
The ``_posixsubprocess.fork_exec`` internal audit event.
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
||||
|
|
18
Doc/library/compression.rst
Normal file
18
Doc/library/compression.rst
Normal 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
|
||||
|
858
Doc/library/compression.zstd.rst
Normal file
858
Doc/library/compression.zstd.rst
Normal 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?")
|
|
@ -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`
|
||||
|
||||
--------------
|
||||
|
||||
|
|
|
@ -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::
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
--------------------
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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'>
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
211
Doc/library/heapq-binary-tree.svg
Normal file
211
Doc/library/heapq-binary-tree.svg
Normal 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 |
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue