diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml
index b5b2765e438..d3e842d9f31 100644
--- a/.azure-pipelines/ci.yml
+++ b/.azure-pipelines/ci.yml
@@ -1,4 +1,4 @@
-trigger: ['main', '3.12', '3.11', '3.10', '3.9', '3.8', '3.7']
+trigger: ['main', '3.13', '3.12', '3.11', '3.10', '3.9', '3.8']
jobs:
- job: Prebuild
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 6f8fe005621..a4ada1b66bf 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -2,11 +2,11 @@ FROM docker.io/library/fedora:40
ENV CC=clang
-ENV WASI_SDK_VERSION=21
+ENV WASI_SDK_VERSION=22
ENV WASI_SDK_PATH=/opt/wasi-sdk
ENV WASMTIME_HOME=/opt/wasmtime
-ENV WASMTIME_VERSION=18.0.3
+ENV WASMTIME_VERSION=22.0.0
ENV WASMTIME_CPU_ARCH=x86_64
RUN dnf -y --nodocs --setopt=install_weak_deps=False install /usr/bin/{blurb,clang,curl,git,ln,tar,xz} 'dnf-command(builddep)' && \
diff --git a/.gitattributes b/.gitattributes
index 5b81d2cb3c9..2f5a030981f 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -27,8 +27,6 @@ Lib/test/cjkencodings/* noeol
Lib/test/tokenizedata/coding20731.py noeol
Lib/test/decimaltestdata/*.decTest noeol
Lib/test/test_email/data/*.txt noeol
-Lib/test/test_importlib/resources/data01/* noeol
-Lib/test/test_importlib/resources/namespacedata01/* noeol
Lib/test/xmltestdata/* noeol
# Shell scripts should have LF even on Windows because of Cygwin
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 86349355fc6..4462bfa54a1 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,8 +1,5 @@
name: Tests
-# gh-84728: "paths-ignore" is not used to skip documentation-only PRs, because
-# it prevents to mark a job as mandatory. A PR cannot be merged if a job is
-# mandatory but not scheduled because of "paths-ignore".
on:
workflow_dispatch:
push:
@@ -23,92 +20,68 @@ concurrency:
jobs:
check_source:
- name: 'Check for source changes'
+ name: Change detection
+ # To use boolean outputs from this job, parse them as JSON.
+ # Here's some examples:
+ #
+ # if: fromJSON(needs.check_source.outputs.run-docs)
+ #
+ # ${{
+ # fromJSON(needs.check_source.outputs.run_tests)
+ # && 'truthy-branch'
+ # || 'falsy-branch'
+ # }}
+ #
+ uses: ./.github/workflows/reusable-change-detection.yml
+
+ check-docs:
+ name: Docs
+ needs: check_source
+ if: fromJSON(needs.check_source.outputs.run-docs)
+ uses: ./.github/workflows/reusable-docs.yml
+
+ check_abi:
+ name: 'Check if the ABI has changed'
runs-on: ubuntu-latest
- timeout-minutes: 10
- outputs:
- run-docs: ${{ steps.docs-changes.outputs.run-docs || false }}
- run_tests: ${{ steps.check.outputs.run_tests }}
- run_hypothesis: ${{ steps.check.outputs.run_hypothesis }}
- run_cifuzz: ${{ steps.check.outputs.run_cifuzz }}
- config_hash: ${{ steps.config_hash.outputs.hash }}
+ needs: check_source
+ if: needs.check_source.outputs.run_tests == 'true'
steps:
- uses: actions/checkout@v4
- - name: Check for source changes
+ - uses: actions/setup-python@v5
+ - name: Install dependencies
+ run: |
+ sudo ./.github/workflows/posix-deps-apt.sh
+ sudo apt-get install -yq abigail-tools
+ - name: Build CPython
+ env:
+ CFLAGS: -g3 -O0
+ run: |
+ # Build Python with the libpython dynamic library
+ ./configure --enable-shared
+ make -j4
+ - name: Check for changes in the ABI
id: check
run: |
- if [ -z "$GITHUB_BASE_REF" ]; then
- echo "run_tests=true" >> $GITHUB_OUTPUT
- else
- git fetch origin $GITHUB_BASE_REF --depth=1
- # git diff "origin/$GITHUB_BASE_REF..." (3 dots) may be more
- # reliable than git diff "origin/$GITHUB_BASE_REF.." (2 dots),
- # but it requires to download more commits (this job uses
- # "git fetch --depth=1").
- #
- # git diff "origin/$GITHUB_BASE_REF..." (3 dots) works with Git
- # 2.26, but Git 2.28 is stricter and fails with "no merge base".
- #
- # git diff "origin/$GITHUB_BASE_REF.." (2 dots) should be enough on
- # GitHub, since GitHub starts by merging origin/$GITHUB_BASE_REF
- # into the PR branch anyway.
- #
- # https://github.com/python/core-workflow/issues/373
- git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qvE '(\.rst$|^Doc|^Misc|^\.pre-commit-config\.yaml$|\.ruff\.toml$|\.md$|mypy\.ini$)' && echo "run_tests=true" >> $GITHUB_OUTPUT || true
- fi
-
- # Check if we should run hypothesis tests
- GIT_BRANCH=${GITHUB_BASE_REF:-${GITHUB_REF#refs/heads/}}
- echo $GIT_BRANCH
- if $(echo "$GIT_BRANCH" | grep -q -w '3\.\(8\|9\|10\|11\)'); then
- echo "Branch too old for hypothesis tests"
- echo "run_hypothesis=false" >> $GITHUB_OUTPUT
- else
- echo "Run hypothesis tests"
- echo "run_hypothesis=true" >> $GITHUB_OUTPUT
- fi
-
- # oss-fuzz maintains a configuration for fuzzing the main branch of
- # CPython, so CIFuzz should be run only for code that is likely to be
- # merged into the main branch; compatibility with older branches may
- # be broken.
- FUZZ_RELEVANT_FILES='(\.c$|\.h$|\.cpp$|^configure$|^\.github/workflows/build\.yml$|^Modules/_xxtestfuzz)'
- if [ "$GITHUB_BASE_REF" = "main" ] && [ "$(git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qE $FUZZ_RELEVANT_FILES; echo $?)" -eq 0 ]; then
- # The tests are pretty slow so they are executed only for PRs
- # changing relevant files.
- echo "Run CIFuzz tests"
- echo "run_cifuzz=true" >> $GITHUB_OUTPUT
- else
- echo "Branch too old for CIFuzz tests; or no C files were changed"
- echo "run_cifuzz=false" >> $GITHUB_OUTPUT
+ if ! make check-abidump; then
+ echo "Generated ABI file is not up to date."
+ echo "Please add the release manager of this branch as a reviewer of this PR."
+ echo ""
+ echo "The up to date ABI file should be attached to this build as an artifact."
+ echo ""
+ echo "To learn more about this check: https://devguide.python.org/getting-started/setup-building/index.html#regenerate-the-abi-dump"
+ echo ""
+ exit 1
fi
- - name: Compute hash for config cache key
- id: config_hash
+ - name: Generate updated ABI files
+ if: ${{ failure() && steps.check.conclusion == 'failure' }}
run: |
- echo "hash=${{ hashFiles('configure', 'configure.ac', '.github/workflows/build.yml') }}" >> $GITHUB_OUTPUT
- - name: Get a list of the changed documentation-related files
- if: github.event_name == 'pull_request'
- id: changed-docs-files
- uses: Ana06/get-changed-files@v2.3.0
+ make regen-abidump
+ - uses: actions/upload-artifact@v4
+ name: Publish updated ABI files
+ if: ${{ failure() && steps.check.conclusion == 'failure' }}
with:
- filter: |
- Doc/**
- Misc/**
- .github/workflows/reusable-docs.yml
- format: csv # works for paths with spaces
- - name: Check for docs changes
- if: >-
- github.event_name == 'pull_request'
- && steps.changed-docs-files.outputs.added_modified_renamed != ''
- id: docs-changes
- run: |
- echo "run-docs=true" >> "${GITHUB_OUTPUT}"
-
- check-docs:
- name: Docs
- needs: check_source
- if: fromJSON(needs.check_source.outputs.run-docs)
- uses: ./.github/workflows/reusable-docs.yml
+ name: abi-data
+ path: ./Doc/data/*.abi
check_generated_files:
name: 'Check if generated files are up to date'
@@ -179,79 +152,101 @@ jobs:
run: make check-c-globals
build_windows:
- name: 'Windows'
- needs: check_source
- if: needs.check_source.outputs.run_tests == 'true'
- uses: ./.github/workflows/reusable-windows.yml
-
- build_windows_free_threading:
- name: 'Windows (free-threading)'
+ name: >-
+ Windows
+ ${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
needs: check_source
- if: needs.check_source.outputs.run_tests == 'true'
+ if: fromJSON(needs.check_source.outputs.run_tests)
+ strategy:
+ matrix:
+ arch:
+ - Win32
+ - x64
+ - arm64
+ free-threading:
+ - false
+ - true
uses: ./.github/workflows/reusable-windows.yml
with:
- free-threading: true
+ arch: ${{ matrix.arch }}
+ free-threading: ${{ matrix.free-threading }}
- build_macos:
- name: 'macOS'
+ build_windows_msi:
+ name: >- # ${{ '' } is a hack to nest jobs under the same sidebar category
+ Windows MSI${{ '' }}
needs: check_source
- if: needs.check_source.outputs.run_tests == 'true'
- uses: ./.github/workflows/reusable-macos.yml
+ if: fromJSON(needs.check_source.outputs.run-win-msi)
+ strategy:
+ matrix:
+ arch:
+ - x86
+ - x64
+ - arm64
+ uses: ./.github/workflows/reusable-windows-msi.yml
with:
- config_hash: ${{ needs.check_source.outputs.config_hash }}
- # Cirrus and macos-14 are M1, macos-13 is default GHA Intel.
- # Cirrus used for upstream, macos-14 for forks.
- os-matrix: '["ghcr.io/cirruslabs/macos-runner:sonoma", "macos-14", "macos-13"]'
+ arch: ${{ matrix.arch }}
- build_macos_free_threading:
- name: 'macOS (free-threading)'
+ build_macos:
+ name: >-
+ macOS
+ ${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
needs: check_source
if: needs.check_source.outputs.run_tests == 'true'
+ strategy:
+ fail-fast: false
+ matrix:
+ # Cirrus and macos-14 are M1, macos-13 is default GHA Intel.
+ # macOS 13 only runs tests against the GIL-enabled CPython.
+ # Cirrus used for upstream, macos-14 for forks.
+ os:
+ - ghcr.io/cirruslabs/macos-runner:sonoma
+ - macos-14
+ - macos-13
+ is-fork: # only used for the exclusion trick
+ - ${{ github.repository_owner != 'python' }}
+ free-threading:
+ - false
+ - true
+ exclude:
+ - os: ghcr.io/cirruslabs/macos-runner:sonoma
+ is-fork: true
+ - os: macos-14
+ is-fork: false
+ - os: macos-13
+ free-threading: true
uses: ./.github/workflows/reusable-macos.yml
with:
config_hash: ${{ needs.check_source.outputs.config_hash }}
- free-threading: true
- # Cirrus and macos-14 are M1.
- # Cirrus used for upstream, macos-14 for forks.
- os-matrix: '["ghcr.io/cirruslabs/macos-runner:sonoma", "macos-14"]'
+ free-threading: ${{ matrix.free-threading }}
+ os: ${{ matrix.os }}
build_ubuntu:
- name: 'Ubuntu'
- needs: check_source
- if: needs.check_source.outputs.run_tests == 'true'
- uses: ./.github/workflows/reusable-ubuntu.yml
- with:
- config_hash: ${{ needs.check_source.outputs.config_hash }}
- options: |
- ../cpython-ro-srcdir/configure \
- --config-cache \
- --with-pydebug \
- --with-openssl=$OPENSSL_DIR
-
- build_ubuntu_free_threading:
- name: 'Ubuntu (free-threading)'
+ name: >-
+ Ubuntu
+ ${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
needs: check_source
if: needs.check_source.outputs.run_tests == 'true'
+ strategy:
+ matrix:
+ free-threading:
+ - false
+ - true
uses: ./.github/workflows/reusable-ubuntu.yml
with:
config_hash: ${{ needs.check_source.outputs.config_hash }}
- options: |
- ../cpython-ro-srcdir/configure \
- --config-cache \
- --with-pydebug \
- --with-openssl=$OPENSSL_DIR \
- --disable-gil
+ free-threading: ${{ matrix.free-threading }}
build_ubuntu_ssltests:
name: 'Ubuntu SSL tests with OpenSSL'
- runs-on: ubuntu-22.04
+ runs-on: ${{ matrix.os }}
timeout-minutes: 60
needs: check_source
if: needs.check_source.outputs.run_tests == 'true'
strategy:
fail-fast: false
matrix:
- openssl_ver: [1.1.1w, 3.0.13, 3.1.5, 3.2.1]
+ os: [ubuntu-22.04]
+ openssl_ver: [3.0.15, 3.1.7, 3.2.3, 3.3.2]
env:
OPENSSL_VER: ${{ matrix.openssl_ver }}
MULTISSL_DIR: ${{ github.workspace }}/multissl
@@ -280,7 +275,7 @@ jobs:
uses: actions/cache@v4
with:
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
- key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
+ key: ${{ matrix.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
- name: Install OpenSSL
if: steps.cache-openssl.outputs.cache-hit != 'true'
run: python3 Tools/ssl/multissltests.py --steps=library --base-directory $MULTISSL_DIR --openssl $OPENSSL_VER --system Linux
@@ -315,7 +310,7 @@ jobs:
needs: check_source
if: needs.check_source.outputs.run_tests == 'true' && needs.check_source.outputs.run_hypothesis == 'true'
env:
- OPENSSL_VER: 3.0.13
+ OPENSSL_VER: 3.0.15
PYTHONSTRICTEXTENSIONBUILD: 1
steps:
- uses: actions/checkout@v4
@@ -393,7 +388,7 @@ jobs:
path: ./hypothesis
key: hypothesis-database-${{ github.head_ref || github.run_id }}
restore-keys: |
- - hypothesis-database-
+ hypothesis-database-
- name: "Run tests"
working-directory: ${{ env.CPYTHON_BUILDDIR }}
run: |
@@ -428,7 +423,7 @@ jobs:
needs: check_source
if: needs.check_source.outputs.run_tests == 'true'
env:
- OPENSSL_VER: 3.0.13
+ OPENSSL_VER: 3.0.15
PYTHONSTRICTEXTENSIONBUILD: 1
ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0
steps:
@@ -458,7 +453,7 @@ jobs:
uses: actions/cache@v4
with:
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
- key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
+ key: ${{ matrix.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
- name: Install OpenSSL
if: steps.cache-openssl.outputs.cache-hit != 'true'
run: python3 Tools/ssl/multissltests.py --steps=library --base-directory $MULTISSL_DIR --openssl $OPENSSL_VER --system Linux
@@ -550,13 +545,11 @@ jobs:
- check-docs
- check_generated_files
- build_macos
- - build_macos_free_threading
- build_ubuntu
- - build_ubuntu_free_threading
- build_ubuntu_ssltests
- build_wasi
- build_windows
- - build_windows_free_threading
+ - build_windows_msi
- test_hypothesis
- build_asan
- build_tsan
@@ -571,6 +564,7 @@ jobs:
with:
allowed-failures: >-
build_ubuntu_ssltests,
+ build_windows_msi,
cifuzz,
test_hypothesis,
allowed-skips: >-
@@ -586,13 +580,10 @@ jobs:
&& '
check_generated_files,
build_macos,
- build_macos_free_threading,
build_ubuntu,
- build_ubuntu_free_threading,
build_ubuntu_ssltests,
build_wasi,
build_windows,
- build_windows_free_threading,
build_asan,
build_tsan,
build_tsan_free_threading,
diff --git a/.github/workflows/build_msi.yml b/.github/workflows/build_msi.yml
deleted file mode 100644
index 65d32c734e7..00000000000
--- a/.github/workflows/build_msi.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-name: TestsMSI
-
-on:
- workflow_dispatch:
- push:
- branches:
- - 'main'
- - '3.*'
- paths:
- - 'Tools/msi/**'
- - '.github/workflows/build_msi.yml'
- pull_request:
- branches:
- - 'main'
- - '3.*'
- paths:
- - 'Tools/msi/**'
- - '.github/workflows/build_msi.yml'
-
-permissions:
- contents: read
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
- cancel-in-progress: true
-
-jobs:
- build:
- name: Windows Installer
- runs-on: windows-latest
- timeout-minutes: 60
- strategy:
- matrix:
- type: [x86, x64, arm64]
- env:
- IncludeFreethreaded: true
- steps:
- - uses: actions/checkout@v4
- - name: Build CPython installer
- run: .\Tools\msi\build.bat --doc -${{ matrix.type }}
diff --git a/.github/workflows/reusable-change-detection.yml b/.github/workflows/reusable-change-detection.yml
new file mode 100644
index 00000000000..6f599f75547
--- /dev/null
+++ b/.github/workflows/reusable-change-detection.yml
@@ -0,0 +1,158 @@
+---
+
+name: Change detection
+
+on: # yamllint disable-line rule:truthy
+ workflow_call:
+ outputs:
+ # Some of the referenced steps set outputs conditionally and there may be
+ # cases when referencing them evaluates to empty strings. It is nice to
+ # work with proper booleans so they have to be evaluated through JSON
+ # conversion in the expressions. However, empty strings used like that
+ # may trigger all sorts of undefined and hard-to-debug behaviors in
+ # GitHub Actions CI/CD. To help with this, all of the outputs set here
+ # that are meant to be used as boolean flags (and not arbitrary strings),
+ # MUST have fallbacks with default values set. A common pattern would be
+ # to add ` || false` to all such expressions here, in the output
+ # definitions. They can then later be safely used through the following
+ # idiom in job conditionals and other expressions. Here's some examples:
+ #
+ # if: fromJSON(needs.change-detection.outputs.run-docs)
+ #
+ # ${{
+ # fromJSON(needs.change-detection.outputs.run-tests)
+ # && 'truthy-branch'
+ # || 'falsy-branch'
+ # }}
+ #
+ config_hash:
+ description: Config hash value for use in cache keys
+ value: ${{ jobs.compute-changes.outputs.config-hash }} # str
+ run-docs:
+ description: Whether to build the docs
+ value: ${{ jobs.compute-changes.outputs.run-docs || false }} # bool
+ run_tests:
+ description: Whether to run the regular tests
+ value: ${{ jobs.compute-changes.outputs.run-tests || false }} # bool
+ run-win-msi:
+ description: Whether to run the MSI installer smoke tests
+ value: >- # bool
+ ${{ jobs.compute-changes.outputs.run-win-msi || false }}
+ run_hypothesis:
+ description: Whether to run the Hypothesis tests
+ value: >- # bool
+ ${{ jobs.compute-changes.outputs.run-hypothesis || false }}
+ run_cifuzz:
+ description: Whether to run the CIFuzz job
+ value: >- # bool
+ ${{ jobs.compute-changes.outputs.run-cifuzz || false }}
+
+jobs:
+ compute-changes:
+ name: Compute changed files
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ outputs:
+ config-hash: ${{ steps.config-hash.outputs.hash }}
+ run-cifuzz: ${{ steps.check.outputs.run-cifuzz }}
+ run-docs: ${{ steps.docs-changes.outputs.run-docs }}
+ run-hypothesis: ${{ steps.check.outputs.run-hypothesis }}
+ run-tests: ${{ steps.check.outputs.run-tests }}
+ run-win-msi: ${{ steps.win-msi-changes.outputs.run-win-msi }}
+ steps:
+ - run: >-
+ echo '${{ github.event_name }}'
+ - uses: actions/checkout@v4
+ - name: Check for source changes
+ id: check
+ run: |
+ if [ -z "$GITHUB_BASE_REF" ]; then
+ echo "run-tests=true" >> $GITHUB_OUTPUT
+ else
+ git fetch origin $GITHUB_BASE_REF --depth=1
+ # git diff "origin/$GITHUB_BASE_REF..." (3 dots) may be more
+ # reliable than git diff "origin/$GITHUB_BASE_REF.." (2 dots),
+ # but it requires to download more commits (this job uses
+ # "git fetch --depth=1").
+ #
+ # git diff "origin/$GITHUB_BASE_REF..." (3 dots) works with Git
+ # 2.26, but Git 2.28 is stricter and fails with "no merge base".
+ #
+ # git diff "origin/$GITHUB_BASE_REF.." (2 dots) should be enough on
+ # GitHub, since GitHub starts by merging origin/$GITHUB_BASE_REF
+ # into the PR branch anyway.
+ #
+ # https://github.com/python/core-workflow/issues/373
+ git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qvE '(\.rst$|^Doc|^Misc|^\.pre-commit-config\.yaml$|\.ruff\.toml$|\.md$|mypy\.ini$)' && echo "run-tests=true" >> $GITHUB_OUTPUT || true
+ fi
+
+ # Check if we should run hypothesis tests
+ GIT_BRANCH=${GITHUB_BASE_REF:-${GITHUB_REF#refs/heads/}}
+ echo $GIT_BRANCH
+ if $(echo "$GIT_BRANCH" | grep -q -w '3\.\(8\|9\|10\|11\)'); then
+ echo "Branch too old for hypothesis tests"
+ echo "run-hypothesis=false" >> $GITHUB_OUTPUT
+ else
+ echo "Run hypothesis tests"
+ echo "run-hypothesis=true" >> $GITHUB_OUTPUT
+ fi
+
+ # oss-fuzz maintains a configuration for fuzzing the main branch of
+ # CPython, so CIFuzz should be run only for code that is likely to be
+ # merged into the main branch; compatibility with older branches may
+ # be broken.
+ FUZZ_RELEVANT_FILES='(\.c$|\.h$|\.cpp$|^configure$|^\.github/workflows/build\.yml$|^Modules/_xxtestfuzz)'
+ if [ "$GITHUB_BASE_REF" = "main" ] && [ "$(git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qE $FUZZ_RELEVANT_FILES; echo $?)" -eq 0 ]; then
+ # The tests are pretty slow so they are executed only for PRs
+ # changing relevant files.
+ echo "Run CIFuzz tests"
+ echo "run-cifuzz=true" >> $GITHUB_OUTPUT
+ else
+ echo "Branch too old for CIFuzz tests; or no C files were changed"
+ echo "run-cifuzz=false" >> $GITHUB_OUTPUT
+ fi
+ - name: Compute hash for config cache key
+ id: config-hash
+ run: |
+ echo "hash=${{ hashFiles('configure', 'configure.ac', '.github/workflows/build.yml') }}" >> $GITHUB_OUTPUT
+ - name: Get a list of the changed documentation-related files
+ if: github.event_name == 'pull_request'
+ id: changed-docs-files
+ uses: Ana06/get-changed-files@v2.3.0
+ with:
+ filter: |
+ Doc/**
+ Misc/**
+ .github/workflows/reusable-docs.yml
+ format: csv # works for paths with spaces
+ - name: Check for docs changes
+ # We only want to run this on PRs when related files are changed,
+ # or when user triggers manual workflow run.
+ if: >-
+ (
+ github.event_name == 'pull_request'
+ && steps.changed-docs-files.outputs.added_modified_renamed != ''
+ ) || github.event_name == 'workflow_dispatch'
+ id: docs-changes
+ run: |
+ echo "run-docs=true" >> "${GITHUB_OUTPUT}"
+ - name: Get a list of the MSI installer-related files
+ if: github.event_name == 'pull_request'
+ id: changed-win-msi-files
+ uses: Ana06/get-changed-files@v2.3.0
+ with:
+ filter: |
+ Tools/msi/**
+ .github/workflows/reusable-windows-msi.yml
+ format: csv # works for paths with spaces
+ - name: Check for changes in MSI installer-related files
+ # We only want to run this on PRs when related files are changed,
+ # or when user triggers manual workflow run.
+ if: >-
+ (
+ github.event_name == 'pull_request'
+ && steps.changed-win-msi-files.outputs.added_modified_renamed != ''
+ ) || github.event_name == 'workflow_dispatch'
+ id: win-msi-changes
+ run: |
+ echo "run-win-msi=true" >> "${GITHUB_OUTPUT}"
diff --git a/.github/workflows/reusable-docs.yml b/.github/workflows/reusable-docs.yml
index 859f78d043b..4b021b3dc32 100644
--- a/.github/workflows/reusable-docs.yml
+++ b/.github/workflows/reusable-docs.yml
@@ -11,6 +11,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
+env:
+ FORCE_COLOR: 1
+
jobs:
build_doc:
name: 'Docs'
@@ -25,9 +28,15 @@ jobs:
- name: 'Check out latest PR branch commit'
uses: actions/checkout@v4
with:
- ref: ${{ github.event.pull_request.head.sha }}
+ ref: >-
+ ${{
+ github.event_name == 'pull_request'
+ && github.event.pull_request.head.sha
+ || ''
+ }}
# Adapted from https://github.com/actions/checkout/issues/520#issuecomment-1167205721
- name: 'Fetch commits to get branch diff'
+ if: github.event_name == 'pull_request'
run: |
# Fetch enough history to find a common ancestor commit (aka merge-base):
git fetch origin ${{ env.refspec_pr }} --depth=$(( ${{ github.event.pull_request.commits }} + 1 )) \
diff --git a/.github/workflows/reusable-macos.yml b/.github/workflows/reusable-macos.yml
index f825d1a7b3f..eef6be75003 100644
--- a/.github/workflows/reusable-macos.yml
+++ b/.github/workflows/reusable-macos.yml
@@ -8,13 +8,14 @@ on:
required: false
type: boolean
default: false
- os-matrix:
- required: false
+ os:
+ description: OS to run the job
+ required: true
type: string
jobs:
build_macos:
- name: build and test (${{ matrix.os }})
+ name: build and test (${{ inputs.os }})
timeout-minutes: 60
env:
HOMEBREW_NO_ANALYTICS: 1
@@ -23,18 +24,7 @@ jobs:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
PYTHONSTRICTEXTENSIONBUILD: 1
TERM: linux
- strategy:
- fail-fast: false
- matrix:
- os: ${{fromJson(inputs.os-matrix)}}
- is-fork:
- - ${{ github.repository_owner != 'python' }}
- exclude:
- - os: "ghcr.io/cirruslabs/macos-runner:sonoma"
- is-fork: true
- - os: "macos-14"
- is-fork: false
- runs-on: ${{ matrix.os }}
+ runs-on: ${{ inputs.os }}
steps:
- uses: actions/checkout@v4
- name: Runner image version
@@ -43,7 +33,7 @@ jobs:
uses: actions/cache@v4
with:
path: config.cache
- key: ${{ github.job }}-${{ matrix.os }}-${{ env.IMAGE_VERSION }}-${{ inputs.config_hash }}
+ key: ${{ github.job }}-${{ inputs.os }}-${{ env.IMAGE_VERSION }}-${{ inputs.config_hash }}
- name: Install Homebrew dependencies
run: brew install pkg-config openssl@3.0 xz gdbm tcl-tk
- name: Configure CPython
diff --git a/.github/workflows/reusable-tsan.yml b/.github/workflows/reusable-tsan.yml
index b6d5d8fa1c7..27f4eacd86f 100644
--- a/.github/workflows/reusable-tsan.yml
+++ b/.github/workflows/reusable-tsan.yml
@@ -36,11 +36,11 @@ jobs:
# Install clang-18
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
- sudo ./llvm.sh 18
- sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-18 100
- sudo update-alternatives --set clang /usr/bin/clang-18
- sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-18 100
- sudo update-alternatives --set clang++ /usr/bin/clang++-18
+ sudo ./llvm.sh 17 # gh-121946: llvm-18 package is temporarily broken
+ sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-17 100
+ sudo update-alternatives --set clang /usr/bin/clang-17
+ sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-17 100
+ sudo update-alternatives --set clang++ /usr/bin/clang++-17
# Reduce ASLR to avoid TSAN crashing
sudo sysctl -w vm.mmap_rnd_bits=28
- name: TSAN Option Setup
diff --git a/.github/workflows/reusable-ubuntu.yml b/.github/workflows/reusable-ubuntu.yml
index fa450ed3376..753d51712f5 100644
--- a/.github/workflows/reusable-ubuntu.yml
+++ b/.github/workflows/reusable-ubuntu.yml
@@ -4,18 +4,24 @@ on:
config_hash:
required: true
type: string
- options:
- required: true
- type: string
+ free-threading:
+ description: Whether to use free-threaded mode
+ required: false
+ type: boolean
+ default: false
jobs:
build_ubuntu_reusable:
name: 'build and test'
timeout-minutes: 60
- runs-on: ubuntu-22.04
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-22.04]
env:
FORCE_COLOR: 1
- OPENSSL_VER: 3.0.13
+ OPENSSL_VER: 3.0.15
PYTHONSTRICTEXTENSIONBUILD: 1
TERM: linux
steps:
@@ -34,7 +40,7 @@ jobs:
uses: actions/cache@v4
with:
path: ./multissl/openssl/${{ env.OPENSSL_VER }}
- key: ${{ runner.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
+ key: ${{ matrix.os }}-multissl-openssl-${{ env.OPENSSL_VER }}
- name: Install OpenSSL
if: steps.cache-openssl.outputs.cache-hit != 'true'
run: python3 Tools/ssl/multissltests.py --steps=library --base-directory $MULTISSL_DIR --openssl $OPENSSL_VER --system Linux
@@ -63,7 +69,12 @@ jobs:
key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ inputs.config_hash }}
- name: Configure CPython out-of-tree
working-directory: ${{ env.CPYTHON_BUILDDIR }}
- run: ${{ inputs.options }}
+ run: >-
+ ../cpython-ro-srcdir/configure
+ --config-cache
+ --with-pydebug
+ --with-openssl=$OPENSSL_DIR
+ ${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }}
- name: Build CPython out-of-tree
working-directory: ${{ env.CPYTHON_BUILDDIR }}
run: make -j4
diff --git a/.github/workflows/reusable-wasi.yml b/.github/workflows/reusable-wasi.yml
index c389fe9e173..ffa143b3457 100644
--- a/.github/workflows/reusable-wasi.yml
+++ b/.github/workflows/reusable-wasi.yml
@@ -11,8 +11,8 @@ jobs:
timeout-minutes: 60
runs-on: ubuntu-22.04
env:
- WASMTIME_VERSION: 18.0.3
- WASI_SDK_VERSION: 21
+ WASMTIME_VERSION: 22.0.0
+ WASI_SDK_VERSION: 22
WASI_SDK_PATH: /opt/wasi-sdk
CROSS_BUILD_PYTHON: cross-build/build
CROSS_BUILD_WASI: cross-build/wasm32-wasi
@@ -20,9 +20,9 @@ jobs:
- uses: actions/checkout@v4
# No problem resolver registered as one doesn't currently exist for Clang.
- name: "Install wasmtime"
- uses: jcbhmr/setup-wasmtime@v2
+ uses: bytecodealliance/actions/wasmtime/setup@v1
with:
- wasmtime-version: ${{ env.WASMTIME_VERSION }}
+ version: ${{ env.WASMTIME_VERSION }}
- name: "Restore WASI SDK"
id: cache-wasi-sdk
uses: actions/cache@v4
@@ -50,8 +50,10 @@ jobs:
uses: actions/cache@v4
with:
path: ${{ env.CROSS_BUILD_PYTHON }}/config.cache
- # Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python
- key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ inputs.config_hash }}-${{ env.pythonLocation }}
+ # Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python.
+ # Include the hash of `Tools/wasm/wasi.py` as it may change the environment variables.
+ # (Make sure to keep the key in sync with the other config.cache step below.)
+ key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ env.WASI_SDK_VERSION }}-${{ env.WASMTIME_VERSION }}-${{ inputs.config_hash }}-${{ hashFiles('Tools/wasm/wasi.py') }}-${{ env.pythonLocation }}
- name: "Configure build Python"
run: python3 Tools/wasm/wasi.py configure-build-python -- --config-cache --with-pydebug
- name: "Make build Python"
@@ -60,8 +62,8 @@ jobs:
uses: actions/cache@v4
with:
path: ${{ env.CROSS_BUILD_WASI }}/config.cache
- # Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python
- key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-wasi-sdk-${{ env.WASI_SDK_VERSION }}-${{ inputs.config_hash }}-${{ env.pythonLocation }}
+ # Should be kept in sync with the other config.cache step above.
+ key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ env.WASI_SDK_VERSION }}-${{ env.WASMTIME_VERSION }}-${{ inputs.config_hash }}-${{ hashFiles('Tools/wasm/wasi.py') }}-${{ env.pythonLocation }}
- name: "Configure host"
# `--with-pydebug` inferred from configure-build-python
run: python3 Tools/wasm/wasi.py configure-host -- --config-cache
diff --git a/.github/workflows/reusable-windows-msi.yml b/.github/workflows/reusable-windows-msi.yml
new file mode 100644
index 00000000000..fc34ab7c3eb
--- /dev/null
+++ b/.github/workflows/reusable-windows-msi.yml
@@ -0,0 +1,24 @@
+name: TestsMSI
+
+on:
+ workflow_call:
+ inputs:
+ arch:
+ description: CPU architecture
+ required: true
+ type: string
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ name: installer for ${{ inputs.arch }}
+ runs-on: windows-latest
+ timeout-minutes: 60
+ env:
+ IncludeFreethreaded: true
+ steps:
+ - uses: actions/checkout@v4
+ - name: Build CPython installer
+ run: .\Tools\msi\build.bat --doc -${{ inputs.arch }}
diff --git a/.github/workflows/reusable-windows.yml b/.github/workflows/reusable-windows.yml
index c0209e0e1c9..e9c3c8e05a8 100644
--- a/.github/workflows/reusable-windows.yml
+++ b/.github/workflows/reusable-windows.yml
@@ -1,53 +1,45 @@
on:
workflow_call:
inputs:
+ arch:
+ description: CPU architecture
+ required: true
+ type: string
free-threading:
+ description: Whether to compile CPython in free-threading mode
required: false
type: boolean
default: false
-jobs:
- build_win32:
- name: 'build and test (x86)'
- runs-on: windows-latest
- timeout-minutes: 60
- env:
- IncludeUwp: 'true'
- steps:
- - uses: actions/checkout@v4
- - name: Build CPython
- run: .\PCbuild\build.bat -e -d -v -p Win32 ${{ inputs.free-threading && '--disable-gil' || '' }}
- - name: Display build info
- run: .\python.bat -m test.pythoninfo
- - name: Tests
- run: .\PCbuild\rt.bat -p Win32 -d -q --fast-ci ${{ inputs.free-threading && '--disable-gil' || '' }}
+env:
+ IncludeUwp: >-
+ true
- build_win_amd64:
- name: 'build and test (x64)'
+jobs:
+ build:
+ name: >-
+ build${{ inputs.arch != 'arm64' && ' and test' || '' }}
+ (${{ inputs.arch }})
runs-on: windows-latest
timeout-minutes: 60
- env:
- IncludeUwp: 'true'
steps:
- uses: actions/checkout@v4
- name: Register MSVC problem matcher
+ if: inputs.arch != 'Win32'
run: echo "::add-matcher::.github/problem-matchers/msvc.json"
- name: Build CPython
- run: .\PCbuild\build.bat -e -d -v -p x64 ${{ inputs.free-threading && '--disable-gil' || '' }}
+ run: >-
+ .\PCbuild\build.bat
+ -e -d -v
+ -p ${{ inputs.arch }}
+ ${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }}
- name: Display build info
+ if: inputs.arch != 'arm64'
run: .\python.bat -m test.pythoninfo
- name: Tests
- run: .\PCbuild\rt.bat -p x64 -d -q --fast-ci ${{ inputs.free-threading && '--disable-gil' || '' }}
-
- build_win_arm64:
- name: 'build (arm64)'
- runs-on: windows-latest
- timeout-minutes: 60
- env:
- IncludeUwp: 'true'
- steps:
- - uses: actions/checkout@v4
- - name: Register MSVC problem matcher
- run: echo "::add-matcher::.github/problem-matchers/msvc.json"
- - name: Build CPython
- run: .\PCbuild\build.bat -e -d -v -p arm64 ${{ inputs.free-threading && '--disable-gil' || '' }}
+ if: inputs.arch != 'arm64'
+ run: >-
+ .\PCbuild\rt.bat
+ -p ${{ inputs.arch }}
+ -d -q --fast-ci
+ ${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }}
diff --git a/.gitignore b/.gitignore
index 8872e9d5508..1248d6dbcbe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -169,5 +169,3 @@ Python/frozen_modules/MANIFEST
/python
!/Python/
-# main branch only: ABI files are not checked/maintained.
-Doc/data/python*.abi
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index fde9d9149bf..7e0bdd50b51 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,15 +1,23 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.3.4
+ rev: v0.6.7
hooks:
- id: ruff
- name: Run Ruff on Lib/test/
+ name: Run Ruff (lint) on Doc/
+ args: [--exit-non-zero-on-fix]
+ files: ^Doc/
+ - id: ruff
+ name: Run Ruff (lint) on Lib/test/
args: [--exit-non-zero-on-fix]
files: ^Lib/test/
- id: ruff
- name: Run Ruff on Argument Clinic
+ name: Run Ruff (lint) on Argument Clinic
args: [--exit-non-zero-on-fix, --config=Tools/clinic/.ruff.toml]
files: ^Tools/clinic/|Lib/test/test_clinic.py
+ - id: ruff-format
+ name: Run Ruff (format) on Doc/
+ args: [--check]
+ files: ^Doc/
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.4.2
diff --git a/.readthedocs.yml b/.readthedocs.yml
index d0d0c3b93ed..a57de00544e 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -8,7 +8,7 @@ sphinx:
configuration: Doc/conf.py
build:
- os: ubuntu-22.04
+ os: ubuntu-24.04
tools:
python: "3"
diff --git a/Android/README.md b/Android/README.md
index f5f463ca116..3daa545cc93 100644
--- a/Android/README.md
+++ b/Android/README.md
@@ -1,19 +1,19 @@
# Python for Android
These instructions are only needed if you're planning to compile Python for
-Android yourself. Most users should *not* need to do this. If you're looking to
-use Python on Android, one of the following tools will provide a much more
-approachable user experience:
-
-* [Briefcase](https://briefcase.readthedocs.io), from the BeeWare project
-* [Buildozer](https://buildozer.readthedocs.io), from the Kivy project
-* [Chaquopy](https://chaquo.com/chaquopy/)
+Android yourself. Most users should *not* need to do this. Instead, use one of
+the tools listed in `Doc/using/android.rst`, which will provide a much easier
+experience.
## Prerequisites
-Export the `ANDROID_HOME` environment variable to point at your Android SDK. If
-you don't already have the SDK, here's how to install it:
+First, make sure you have all the usual tools and libraries needed to build
+Python for your development machine.
+
+Second, you'll need an Android SDK. If you already have the SDK installed,
+export the `ANDROID_HOME` environment variable to point at its location.
+Otherwise, here's how to install it:
* Download the "Command line tools" from .
* Create a directory `android-sdk/cmdline-tools`, and unzip the command line
@@ -25,7 +25,7 @@ you don't already have the SDK, here's how to install it:
The `android.py` script also requires the following commands to be on the `PATH`:
* `curl`
-* `java`
+* `java` (or set the `JAVA_HOME` environment variable)
* `tar`
* `unzip`
@@ -37,11 +37,6 @@ development tools, which currently means Linux or macOS. This involves doing a
cross-build where you use a "build" Python (for your development machine) to
help produce a "host" Python for Android.
-First, make sure you have all the usual tools and libraries needed to build
-Python for your development machine. The only Android tool you need to install
-is the command line tools package above: the build script will download the
-rest.
-
The easiest way to do a build is to use the `android.py` script. You can either
have it perform the entire build process from start to finish in one step, or
you can do it in discrete steps that mirror running `configure` and `make` for
@@ -80,18 +75,62 @@ call. For example, if you want a pydebug build that also caches the results from
## Testing
-To run the Python test suite on Android:
-
-* Install Android Studio, if you don't already have it.
-* Follow the instructions in the previous section to build all supported
- architectures.
-* Run `./android.py setup-testbed` to download the Gradle wrapper.
-* Open the `testbed` directory in Android Studio.
-* In the *Device Manager* dock, connect a device or start an emulator.
- Then select it from the drop-down list in the toolbar.
-* Click the "Run" button in the toolbar.
-* The testbed app displays nothing on screen while running. To see its output,
- open the [Logcat window](https://developer.android.com/studio/debug/logcat).
-
-To run specific tests, or pass any other arguments to the test suite, edit the
-command line in testbed/app/src/main/python/main.py.
+The test suite can be run on Linux, macOS, or Windows:
+
+* On Linux, the emulator needs access to the KVM virtualization interface, and
+ a DISPLAY environment variable pointing at an X server.
+* On Windows, you won't be able to do the build on the same machine, so you'll
+ have to copy the `cross-build/HOST` directory from somewhere else.
+
+The test suite can usually be run on a device with 2 GB of RAM, but this is
+borderline, so you may need to increase it to 4 GB. As of Android
+Studio Koala, 2 GB is the default for all emulators, although the user interface
+may indicate otherwise. Locate the emulator's directory under `~/.android/avd`,
+and find `hw.ramSize` in both config.ini and hardware-qemu.ini. Either set these
+manually to the same value, or use the Android Studio Device Manager, which will
+update both files.
+
+Before running the test suite, follow the instructions in the previous section
+to build the architecture you want to test. Then run the test script in one of
+the following modes:
+
+* In `--connected` mode, it runs on a device or emulator you have already
+ connected to the build machine. List the available devices with
+ `$ANDROID_HOME/platform-tools/adb devices -l`, then pass a device ID to the
+ script like this:
+
+ ```sh
+ ./android.py test --connected emulator-5554
+ ```
+
+* In `--managed` mode, it uses a temporary headless emulator defined in the
+ `managedDevices` section of testbed/app/build.gradle.kts. This mode is slower,
+ but more reproducible.
+
+ We currently define two devices: `minVersion` and `maxVersion`, corresponding
+ to our minimum and maximum supported Android versions. For example:
+
+ ```sh
+ ./android.py test --managed maxVersion
+ ```
+
+By default, the only messages the script will show are Python's own stdout and
+stderr. Add the `-v` option to also show Gradle output, and non-Python logcat
+messages.
+
+Any other arguments on the `android.py test` command line will be passed through
+to `python -m test` – use `--` to separate them from android.py's own options.
+See the [Python Developer's
+Guide](https://devguide.python.org/testing/run-write-tests/) for common options
+– most of them will work on Android, except for those that involve subprocesses,
+such as `-j`.
+
+Every time you run `android.py test`, changes in pure-Python files in the
+repository's `Lib` directory will be picked up immediately. Changes in C files,
+and architecture-specific files such as sysconfigdata, will not take effect
+until you re-run `android.py make-host` or `build`.
+
+
+## Using in your own app
+
+See `Doc/using/android.rst`.
diff --git a/Android/android-env.sh b/Android/android-env.sh
index 545d559d93a..93372e3fe1c 100644
--- a/Android/android-env.sh
+++ b/Android/android-env.sh
@@ -28,7 +28,7 @@ ndk_version=26.2.11394342
ndk=$ANDROID_HOME/ndk/$ndk_version
if ! [ -e $ndk ]; then
- log "Installing NDK: this may take several minutes"
+ log "Installing NDK - this may take several minutes"
yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "ndk;$ndk_version"
fi
diff --git a/Android/android.py b/Android/android.py
index 0a1393e61dd..8696d9eaeca 100755
--- a/Android/android.py
+++ b/Android/android.py
@@ -1,31 +1,67 @@
#!/usr/bin/env python3
+import asyncio
import argparse
+from glob import glob
import os
import re
+import shlex
import shutil
+import signal
import subprocess
import sys
import sysconfig
+from asyncio import wait_for
+from contextlib import asynccontextmanager
from os.path import basename, relpath
from pathlib import Path
+from subprocess import CalledProcessError
from tempfile import TemporaryDirectory
+
SCRIPT_NAME = Path(__file__).name
CHECKOUT = Path(__file__).resolve().parent.parent
+ANDROID_DIR = CHECKOUT / "Android"
+TESTBED_DIR = ANDROID_DIR / "testbed"
CROSS_BUILD_DIR = CHECKOUT / "cross-build"
+APP_ID = "org.python.testbed"
+DECODE_ARGS = ("UTF-8", "backslashreplace")
+
+
+try:
+ android_home = Path(os.environ['ANDROID_HOME'])
+except KeyError:
+ sys.exit("The ANDROID_HOME environment variable is required.")
+
+adb = Path(
+ f"{android_home}/platform-tools/adb"
+ + (".exe" if os.name == "nt" else "")
+)
+
+gradlew = Path(
+ f"{TESTBED_DIR}/gradlew"
+ + (".bat" if os.name == "nt" else "")
+)
+
+logcat_started = False
-def delete_if_exists(path):
- if path.exists():
+
+def delete_glob(pattern):
+ # Path.glob doesn't accept non-relative patterns.
+ for path in glob(str(pattern)):
+ path = Path(path)
print(f"Deleting {path} ...")
- shutil.rmtree(path)
+ if path.is_dir() and not path.is_symlink():
+ shutil.rmtree(path)
+ else:
+ path.unlink()
def subdir(name, *, clean=None):
path = CROSS_BUILD_DIR / name
if clean:
- delete_if_exists(path)
+ delete_glob(path)
if not path.exists():
if clean is None:
sys.exit(
@@ -36,10 +72,14 @@ def subdir(name, *, clean=None):
return path
-def run(command, *, host=None, **kwargs):
- env = os.environ.copy()
+def run(command, *, host=None, env=None, log=True, **kwargs):
+ kwargs.setdefault("check", True)
+ if env is None:
+ env = os.environ.copy()
+ original_env = env.copy()
+
if host:
- env_script = CHECKOUT / "Android/android-env.sh"
+ env_script = ANDROID_DIR / "android-env.sh"
env_output = subprocess.run(
f"set -eu; "
f"HOST={host}; "
@@ -60,15 +100,13 @@ def run(command, *, host=None, **kwargs):
print(line)
env[key] = value
- if env == os.environ:
+ if env == original_env:
raise ValueError(f"Found no variables in {env_script.name} output:\n"
+ env_output)
- print(">", " ".join(map(str, command)))
- try:
- subprocess.run(command, check=True, env=env, **kwargs)
- except subprocess.CalledProcessError as e:
- sys.exit(e)
+ if log:
+ print(">", " ".join(map(str, command)))
+ return subprocess.run(command, env=env, **kwargs)
def build_python_path():
@@ -100,7 +138,7 @@ def make_build_python(context):
def unpack_deps(host):
deps_url = "https://github.com/beeware/cpython-android-source-deps/releases/download"
- for name_ver in ["bzip2-1.0.8-1", "libffi-3.4.4-2", "openssl-3.0.13-1",
+ for name_ver in ["bzip2-1.0.8-1", "libffi-3.4.4-2", "openssl-3.0.15-0",
"sqlite-3.45.1-0", "xz-5.4.6-0"]:
filename = f"{name_ver}-{host}.tar.gz"
download(f"{deps_url}/{name_ver}/{filename}")
@@ -150,10 +188,17 @@ def configure_host_python(context):
def make_host_python(context):
+ # The CFLAGS and LDFLAGS set in android-env include the prefix dir, so
+ # delete any previously-installed Python libs and include files to prevent
+ # them being used during the build.
host_dir = subdir(context.host)
+ prefix_dir = host_dir / "prefix"
+ delete_glob(f"{prefix_dir}/include/python*")
+ delete_glob(f"{prefix_dir}/lib/libpython*")
+
os.chdir(host_dir / "build")
run(["make", "-j", str(os.cpu_count())], host=context.host)
- run(["make", "install", f"prefix={host_dir}/prefix"], host=context.host)
+ run(["make", "install", f"prefix={prefix_dir}"], host=context.host)
def build_all(context):
@@ -164,34 +209,344 @@ def build_all(context):
def clean_all(context):
- delete_if_exists(CROSS_BUILD_DIR)
+ delete_glob(CROSS_BUILD_DIR)
+
+
+def setup_sdk():
+ sdkmanager = android_home / (
+ "cmdline-tools/latest/bin/sdkmanager"
+ + (".bat" if os.name == "nt" else "")
+ )
+
+ # Gradle will fail if it needs to install an SDK package whose license
+ # hasn't been accepted, so pre-accept all licenses.
+ if not all((android_home / "licenses" / path).exists() for path in [
+ "android-sdk-arm-dbt-license", "android-sdk-license"
+ ]):
+ run([sdkmanager, "--licenses"], text=True, input="y\n" * 100)
+
+ # Gradle may install this automatically, but we can't rely on that because
+ # we need to run adb within the logcat task.
+ if not adb.exists():
+ run([sdkmanager, "platform-tools"])
# To avoid distributing compiled artifacts without corresponding source code,
# the Gradle wrapper is not included in the CPython repository. Instead, we
# extract it from the Gradle release.
-def setup_testbed(context):
+def setup_testbed():
+ if all((TESTBED_DIR / path).exists() for path in [
+ "gradlew", "gradlew.bat", "gradle/wrapper/gradle-wrapper.jar",
+ ]):
+ return
+
ver_long = "8.7.0"
ver_short = ver_long.removesuffix(".0")
- testbed_dir = CHECKOUT / "Android/testbed"
for filename in ["gradlew", "gradlew.bat"]:
out_path = download(
f"https://raw.githubusercontent.com/gradle/gradle/v{ver_long}/{filename}",
- testbed_dir)
+ TESTBED_DIR)
os.chmod(out_path, 0o755)
with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir:
- os.chdir(temp_dir)
bin_zip = download(
- f"https://services.gradle.org/distributions/gradle-{ver_short}-bin.zip")
+ f"https://services.gradle.org/distributions/gradle-{ver_short}-bin.zip",
+ temp_dir)
outer_jar = f"gradle-{ver_short}/lib/plugins/gradle-wrapper-{ver_short}.jar"
- run(["unzip", bin_zip, outer_jar])
- run(["unzip", "-o", "-d", f"{testbed_dir}/gradle/wrapper", outer_jar,
- "gradle-wrapper.jar"])
+ run(["unzip", "-d", temp_dir, bin_zip, outer_jar])
+ run(["unzip", "-o", "-d", f"{TESTBED_DIR}/gradle/wrapper",
+ f"{temp_dir}/{outer_jar}", "gradle-wrapper.jar"])
-def main():
+# run_testbed will build the app automatically, but it's useful to have this as
+# a separate command to allow running the app outside of this script.
+def build_testbed(context):
+ setup_sdk()
+ setup_testbed()
+ run(
+ [gradlew, "--console", "plain", "packageDebug", "packageDebugAndroidTest"],
+ cwd=TESTBED_DIR,
+ )
+
+
+# Work around a bug involving sys.exit and TaskGroups
+# (https://github.com/python/cpython/issues/101515).
+def exit(*args):
+ raise MySystemExit(*args)
+
+
+class MySystemExit(Exception):
+ pass
+
+
+# The `test` subcommand runs all subprocesses through this context manager so
+# that no matter what happens, they can always be cancelled from another task,
+# and they will always be cleaned up on exit.
+@asynccontextmanager
+async def async_process(*args, **kwargs):
+ process = await asyncio.create_subprocess_exec(*args, **kwargs)
+ try:
+ yield process
+ finally:
+ if process.returncode is None:
+ # Allow a reasonably long time for Gradle to clean itself up,
+ # because we don't want stale emulators left behind.
+ timeout = 10
+ process.terminate()
+ try:
+ await wait_for(process.wait(), timeout)
+ except TimeoutError:
+ print(
+ f"Command {args} did not terminate after {timeout} seconds "
+ f" - sending SIGKILL"
+ )
+ process.kill()
+
+ # Even after killing the process we must still wait for it,
+ # otherwise we'll get the warning "Exception ignored in __del__".
+ await wait_for(process.wait(), timeout=1)
+
+
+async def async_check_output(*args, **kwargs):
+ async with async_process(
+ *args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs
+ ) as process:
+ stdout, stderr = await process.communicate()
+ if process.returncode == 0:
+ return stdout.decode(*DECODE_ARGS)
+ else:
+ raise CalledProcessError(
+ process.returncode, args,
+ stdout.decode(*DECODE_ARGS), stderr.decode(*DECODE_ARGS)
+ )
+
+
+# Return a list of the serial numbers of connected devices. Emulators will have
+# serials of the form "emulator-5678".
+async def list_devices():
+ serials = []
+ header_found = False
+
+ lines = (await async_check_output(adb, "devices")).splitlines()
+ for line in lines:
+ # Ignore blank lines, and all lines before the header.
+ line = line.strip()
+ if line == "List of devices attached":
+ header_found = True
+ elif header_found and line:
+ try:
+ serial, status = line.split()
+ except ValueError:
+ raise ValueError(f"failed to parse {line!r}")
+ if status == "device":
+ serials.append(serial)
+
+ if not header_found:
+ raise ValueError(f"failed to parse {lines}")
+ return serials
+
+
+async def find_device(context, initial_devices):
+ if context.managed:
+ print("Waiting for managed device - this may take several minutes")
+ while True:
+ new_devices = set(await list_devices()).difference(initial_devices)
+ if len(new_devices) == 0:
+ await asyncio.sleep(1)
+ elif len(new_devices) == 1:
+ serial = new_devices.pop()
+ print(f"Serial: {serial}")
+ return serial
+ else:
+ exit(f"Found more than one new device: {new_devices}")
+ else:
+ return context.connected
+
+
+# An older version of this script in #121595 filtered the logs by UID instead.
+# But logcat can't filter by UID until API level 31. If we ever switch back to
+# filtering by UID, we'll also have to filter by time so we only show messages
+# produced after the initial call to `stop_app`.
+#
+# We're more likely to miss the PID because it's shorter-lived, so there's a
+# workaround in PythonSuite.kt to stop it being *too* short-lived.
+async def find_pid(serial):
+ print("Waiting for app to start - this may take several minutes")
+ shown_error = False
+ while True:
+ try:
+ # `pidof` requires API level 24 or higher. The level 23 emulator
+ # includes it, but it doesn't work (it returns all processes).
+ pid = (await async_check_output(
+ adb, "-s", serial, "shell", "pidof", "-s", APP_ID
+ )).strip()
+ except CalledProcessError as e:
+ # If the app isn't running yet, pidof gives no output. So if there
+ # is output, there must have been some other error. However, this
+ # sometimes happens transiently, especially when running a managed
+ # emulator for the first time, so don't make it fatal.
+ if (e.stdout or e.stderr) and not shown_error:
+ print_called_process_error(e)
+ print("This may be transient, so continuing to wait")
+ shown_error = True
+ else:
+ # Some older devices (e.g. Nexus 4) return zero even when no process
+ # was found, so check whether we actually got any output.
+ if pid:
+ print(f"PID: {pid}")
+ return pid
+
+ # Loop fairly rapidly to avoid missing a short-lived process.
+ await asyncio.sleep(0.2)
+
+
+async def logcat_task(context, initial_devices):
+ # Gradle may need to do some large downloads of libraries and emulator
+ # images. This will happen during find_device in --managed mode, or find_pid
+ # in --connected mode.
+ startup_timeout = 600
+ serial = await wait_for(find_device(context, initial_devices), startup_timeout)
+ pid = await wait_for(find_pid(serial), startup_timeout)
+
+ # `--pid` requires API level 24 or higher.
+ args = [adb, "-s", serial, "logcat", "--pid", pid, "--format", "tag"]
+ hidden_output = []
+ async with async_process(
+ *args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ ) as process:
+ while line := (await process.stdout.readline()).decode(*DECODE_ARGS):
+ if match := re.fullmatch(r"([A-Z])/(.*)", line, re.DOTALL):
+ level, message = match.groups()
+ else:
+ # If the regex doesn't match, this is probably the second or
+ # subsequent line of a multi-line message. Python won't produce
+ # such messages, but other components might.
+ level, message = None, line
+
+ # Exclude high-volume messages which are rarely useful.
+ if context.verbose < 2 and "from python test_syslog" in message:
+ continue
+
+ # Put high-level messages on stderr so they're highlighted in the
+ # buildbot logs. This will include Python's own stderr.
+ stream = (
+ sys.stderr
+ if level in ["W", "E", "F"] # WARNING, ERROR, FATAL (aka ASSERT)
+ else sys.stdout
+ )
+
+ # To simplify automated processing of the output, e.g. a buildbot
+ # posting a failure notice on a GitHub PR, we strip the level and
+ # tag indicators from Python's stdout and stderr.
+ for prefix in ["python.stdout: ", "python.stderr: "]:
+ if message.startswith(prefix):
+ global logcat_started
+ logcat_started = True
+ stream.write(message.removeprefix(prefix))
+ break
+ else:
+ if context.verbose:
+ # Non-Python messages add a lot of noise, but they may
+ # sometimes help explain a failure.
+ stream.write(line)
+ else:
+ hidden_output.append(line)
+
+ # If the device disconnects while logcat is running, which always
+ # happens in --managed mode, some versions of adb return non-zero.
+ # Distinguish this from a logcat startup error by checking whether we've
+ # received a message from Python yet.
+ status = await wait_for(process.wait(), timeout=1)
+ if status != 0 and not logcat_started:
+ raise CalledProcessError(status, args, "".join(hidden_output))
+
+
+def stop_app(serial):
+ run([adb, "-s", serial, "shell", "am", "force-stop", APP_ID], log=False)
+
+
+async def gradle_task(context):
+ env = os.environ.copy()
+ if context.managed:
+ task_prefix = context.managed
+ else:
+ task_prefix = "connected"
+ env["ANDROID_SERIAL"] = context.connected
+
+ args = [
+ gradlew, "--console", "plain", f"{task_prefix}DebugAndroidTest",
+ "-Pandroid.testInstrumentationRunnerArguments.pythonArgs="
+ + shlex.join(context.args),
+ ]
+ hidden_output = []
+ try:
+ async with async_process(
+ *args, cwd=TESTBED_DIR, env=env,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ ) as process:
+ while line := (await process.stdout.readline()).decode(*DECODE_ARGS):
+ # Gradle may take several minutes to install SDK packages, so
+ # it's worth showing those messages even in non-verbose mode.
+ if context.verbose or line.startswith('Preparing "Install'):
+ sys.stdout.write(line)
+ else:
+ hidden_output.append(line)
+
+ status = await wait_for(process.wait(), timeout=1)
+ if status == 0:
+ exit(0)
+ else:
+ raise CalledProcessError(status, args)
+ finally:
+ # If logcat never started, then something has gone badly wrong, so the
+ # user probably wants to see the Gradle output even in non-verbose mode.
+ if hidden_output and not logcat_started:
+ sys.stdout.write("".join(hidden_output))
+
+ # Gradle does not stop the tests when interrupted.
+ if context.connected:
+ stop_app(context.connected)
+
+
+async def run_testbed(context):
+ setup_sdk()
+ setup_testbed()
+
+ if context.managed:
+ # In this mode, Gradle will create a device with an unpredictable name.
+ # So we save a list of the running devices before starting Gradle, and
+ # find_device then waits for a new device to appear.
+ initial_devices = await list_devices()
+ else:
+ # In case the previous shutdown was unclean, make sure the app isn't
+ # running, otherwise we might show logs from a previous run. This is
+ # unnecessary in --managed mode, because Gradle creates a new emulator
+ # every time.
+ stop_app(context.connected)
+ initial_devices = None
+
+ try:
+ async with asyncio.TaskGroup() as tg:
+ tg.create_task(logcat_task(context, initial_devices))
+ tg.create_task(gradle_task(context))
+ except* MySystemExit as e:
+ raise SystemExit(*e.exceptions[0].args) from None
+ except* CalledProcessError as e:
+ # Extract it from the ExceptionGroup so it can be handled by `main`.
+ raise e.exceptions[0]
+
+
+# Handle SIGTERM the same way as SIGINT. This ensures that if we're terminated
+# by the buildbot worker, we'll make an attempt to clean up our subprocesses.
+def install_signal_handler():
+ def signal_handler(*args):
+ os.kill(os.getpid(), signal.SIGINT)
+
+ signal.signal(signal.SIGTERM, signal_handler)
+
+
+def parse_args():
parser = argparse.ArgumentParser()
subcommands = parser.add_subparsers(dest="subcommand")
build = subcommands.add_parser("build", help="Build everything")
@@ -206,8 +561,6 @@ def main():
help="Run `make` for Android")
subcommands.add_parser(
"clean", help="Delete the cross-build directory")
- subcommands.add_parser(
- "setup-testbed", help="Download the testbed Gradle wrapper")
for subcommand in build, configure_build, configure_host:
subcommand.add_argument(
@@ -222,15 +575,74 @@ def main():
subcommand.add_argument("args", nargs="*",
help="Extra arguments to pass to `configure`")
- context = parser.parse_args()
+ subcommands.add_parser(
+ "build-testbed", help="Build the testbed app")
+ test = subcommands.add_parser(
+ "test", help="Run the test suite")
+ test.add_argument(
+ "-v", "--verbose", action="count", default=0,
+ help="Show Gradle output, and non-Python logcat messages. "
+ "Use twice to include high-volume messages which are rarely useful.")
+ device_group = test.add_mutually_exclusive_group(required=True)
+ device_group.add_argument(
+ "--connected", metavar="SERIAL", help="Run on a connected device. "
+ "Connect it yourself, then get its serial from `adb devices`.")
+ device_group.add_argument(
+ "--managed", metavar="NAME", help="Run on a Gradle-managed device. "
+ "These are defined in `managedDevices` in testbed/app/build.gradle.kts.")
+ test.add_argument(
+ "args", nargs="*", help=f"Arguments for `python -m test`. "
+ f"Separate them from {SCRIPT_NAME}'s own arguments with `--`.")
+
+ return parser.parse_args()
+
+
+def main():
+ install_signal_handler()
+
+ # Under the buildbot, stdout is not a TTY, but we must still flush after
+ # every line to make sure our output appears in the correct order relative
+ # to the output of our subprocesses.
+ for stream in [sys.stdout, sys.stderr]:
+ stream.reconfigure(line_buffering=True)
+
+ context = parse_args()
dispatch = {"configure-build": configure_build_python,
"make-build": make_build_python,
"configure-host": configure_host_python,
"make-host": make_host_python,
"build": build_all,
"clean": clean_all,
- "setup-testbed": setup_testbed}
- dispatch[context.subcommand](context)
+ "build-testbed": build_testbed,
+ "test": run_testbed}
+
+ try:
+ result = dispatch[context.subcommand](context)
+ if asyncio.iscoroutine(result):
+ asyncio.run(result)
+ except CalledProcessError as e:
+ print_called_process_error(e)
+ sys.exit(1)
+
+
+def print_called_process_error(e):
+ for stream_name in ["stdout", "stderr"]:
+ content = getattr(e, stream_name)
+ stream = getattr(sys, stream_name)
+ if content:
+ stream.write(content)
+ if not content.endswith("\n"):
+ stream.write("\n")
+
+ # Format the command so it can be copied into a shell. shlex uses single
+ # quotes, so we surround the whole command with double quotes.
+ args_joined = (
+ e.cmd if isinstance(e.cmd, str)
+ else " ".join(shlex.quote(str(arg)) for arg in e.cmd)
+ )
+ print(
+ f'Command "{args_joined}" returned exit status {e.returncode}'
+ )
if __name__ == "__main__":
diff --git a/Android/testbed/app/build.gradle.kts b/Android/testbed/app/build.gradle.kts
index 7690d3fd86b..7e0bef58ed8 100644
--- a/Android/testbed/app/build.gradle.kts
+++ b/Android/testbed/app/build.gradle.kts
@@ -1,18 +1,26 @@
import com.android.build.api.variant.*
+import kotlin.math.max
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
-val PYTHON_DIR = File(projectDir, "../../..").canonicalPath
+val PYTHON_DIR = file("../../..").canonicalPath
val PYTHON_CROSS_DIR = "$PYTHON_DIR/cross-build"
+
val ABIS = mapOf(
"arm64-v8a" to "aarch64-linux-android",
"x86_64" to "x86_64-linux-android",
-)
+).filter { file("$PYTHON_CROSS_DIR/${it.value}").exists() }
+if (ABIS.isEmpty()) {
+ throw GradleException(
+ "No Android ABIs found in $PYTHON_CROSS_DIR: see Android/README.md " +
+ "for building instructions."
+ )
+}
-val PYTHON_VERSION = File("$PYTHON_DIR/Include/patchlevel.h").useLines {
+val PYTHON_VERSION = file("$PYTHON_DIR/Include/patchlevel.h").useLines {
for (line in it) {
val match = """#define PY_VERSION\s+"(\d+\.\d+)""".toRegex().find(line)
if (match != null) {
@@ -22,6 +30,16 @@ val PYTHON_VERSION = File("$PYTHON_DIR/Include/patchlevel.h").useLines {
throw GradleException("Failed to find Python version")
}
+android.ndkVersion = file("../../android-env.sh").useLines {
+ for (line in it) {
+ val match = """ndk_version=(\S+)""".toRegex().find(line)
+ if (match != null) {
+ return@useLines match.groupValues[1]
+ }
+ }
+ throw GradleException("Failed to find NDK version")
+}
+
android {
namespace = "org.python.testbed"
@@ -38,6 +56,8 @@ android {
externalNativeBuild.cmake.arguments(
"-DPYTHON_CROSS_DIR=$PYTHON_CROSS_DIR",
"-DPYTHON_VERSION=$PYTHON_VERSION")
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
externalNativeBuild.cmake {
@@ -55,41 +75,81 @@ android {
kotlinOptions {
jvmTarget = "1.8"
}
+
+ testOptions {
+ managedDevices {
+ localDevices {
+ create("minVersion") {
+ device = "Small Phone"
+
+ // Managed devices have a minimum API level of 27.
+ apiLevel = max(27, defaultConfig.minSdk!!)
+
+ // ATD devices are smaller and faster, but have a minimum
+ // API level of 30.
+ systemImageSource = if (apiLevel >= 30) "aosp-atd" else "aosp"
+ }
+
+ create("maxVersion") {
+ device = "Small Phone"
+ apiLevel = defaultConfig.targetSdk!!
+ systemImageSource = "aosp-atd"
+ }
+ }
+
+ // If the previous test run succeeded and nothing has changed,
+ // Gradle thinks there's no need to run it again. Override that.
+ afterEvaluate {
+ (localDevices.names + listOf("connected")).forEach {
+ tasks.named("${it}DebugAndroidTest") {
+ outputs.upToDateWhen { false }
+ }
+ }
+ }
+ }
+ }
}
dependencies {
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.11.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
+ androidTestImplementation("androidx.test.ext:junit:1.1.5")
+ androidTestImplementation("androidx.test:rules:1.5.0")
}
// Create some custom tasks to copy Python and its standard library from
// elsewhere in the repository.
androidComponents.onVariants { variant ->
+ val pyPlusVer = "python$PYTHON_VERSION"
generateTask(variant, variant.sources.assets!!) {
into("python") {
- for (triplet in ABIS.values) {
- for (subDir in listOf("include", "lib")) {
- into(subDir) {
- from("$PYTHON_CROSS_DIR/$triplet/prefix/$subDir")
- include("python$PYTHON_VERSION/**")
- duplicatesStrategy = DuplicatesStrategy.EXCLUDE
- }
+ into("include/$pyPlusVer") {
+ for (triplet in ABIS.values) {
+ from("$PYTHON_CROSS_DIR/$triplet/prefix/include/$pyPlusVer")
}
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
- into("lib/python$PYTHON_VERSION") {
- // Uncomment this to pick up edits from the source directory
- // without having to rerun `make install`.
- // from("$PYTHON_DIR/Lib")
- // duplicatesStrategy = DuplicatesStrategy.INCLUDE
+
+ into("lib/$pyPlusVer") {
+ // To aid debugging, the source directory takes priority.
+ from("$PYTHON_DIR/Lib")
+
+ // The cross-build directory provides ABI-specific files such as
+ // sysconfigdata.
+ for (triplet in ABIS.values) {
+ from("$PYTHON_CROSS_DIR/$triplet/prefix/lib/$pyPlusVer")
+ }
into("site-packages") {
from("$projectDir/src/main/python")
}
+
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+ exclude("**/__pycache__")
}
}
- exclude("**/__pycache__")
}
generateTask(variant, variant.sources.jniLibs!!) {
diff --git a/Android/testbed/app/src/androidTest/java/org/python/testbed/PythonSuite.kt b/Android/testbed/app/src/androidTest/java/org/python/testbed/PythonSuite.kt
new file mode 100644
index 00000000000..0e888ab71d8
--- /dev/null
+++ b/Android/testbed/app/src/androidTest/java/org/python/testbed/PythonSuite.kt
@@ -0,0 +1,35 @@
+package org.python.testbed
+
+import androidx.test.annotation.UiThreadTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+
+@RunWith(AndroidJUnit4::class)
+class PythonSuite {
+ @Test
+ @UiThreadTest
+ fun testPython() {
+ val start = System.currentTimeMillis()
+ try {
+ val context =
+ InstrumentationRegistry.getInstrumentation().targetContext
+ val args =
+ InstrumentationRegistry.getArguments().getString("pythonArgs", "")
+ val status = PythonTestRunner(context).run(args)
+ assertEquals(0, status)
+ } finally {
+ // Make sure the process lives long enough for the test script to
+ // detect it (see `find_pid` in android.py).
+ val delay = 2000 - (System.currentTimeMillis() - start)
+ if (delay > 0) {
+ Thread.sleep(delay)
+ }
+ }
+ }
+}
diff --git a/Android/testbed/app/src/main/c/main_activity.c b/Android/testbed/app/src/main/c/main_activity.c
index 73aba4164d0..53470904899 100644
--- a/Android/testbed/app/src/main/c/main_activity.c
+++ b/Android/testbed/app/src/main/c/main_activity.c
@@ -84,7 +84,7 @@ static char *redirect_stream(StreamInfo *si) {
return 0;
}
-JNIEXPORT void JNICALL Java_org_python_testbed_MainActivity_redirectStdioToLogcat(
+JNIEXPORT void JNICALL Java_org_python_testbed_PythonTestRunner_redirectStdioToLogcat(
JNIEnv *env, jobject obj
) {
for (StreamInfo *si = STREAMS; si->file; si++) {
@@ -115,7 +115,7 @@ static void throw_status(JNIEnv *env, PyStatus status) {
throw_runtime_exception(env, status.err_msg ? status.err_msg : "");
}
-JNIEXPORT void JNICALL Java_org_python_testbed_MainActivity_runPython(
+JNIEXPORT int JNICALL Java_org_python_testbed_PythonTestRunner_runPython(
JNIEnv *env, jobject obj, jstring home, jstring runModule
) {
PyConfig config;
@@ -125,13 +125,13 @@ JNIEXPORT void JNICALL Java_org_python_testbed_MainActivity_runPython(
status = set_config_string(env, &config, &config.home, home);
if (PyStatus_Exception(status)) {
throw_status(env, status);
- return;
+ return 1;
}
status = set_config_string(env, &config, &config.run_module, runModule);
if (PyStatus_Exception(status)) {
throw_status(env, status);
- return;
+ return 1;
}
// Some tests generate SIGPIPE and SIGXFSZ, which should be ignored.
@@ -140,8 +140,8 @@ JNIEXPORT void JNICALL Java_org_python_testbed_MainActivity_runPython(
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
throw_status(env, status);
- return;
+ return 1;
}
- Py_RunMain();
+ return Py_RunMain();
}
diff --git a/Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt b/Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt
index 5a590d5d04e..c4bf6cbe83d 100644
--- a/Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt
+++ b/Android/testbed/app/src/main/java/org/python/testbed/MainActivity.kt
@@ -1,38 +1,56 @@
package org.python.testbed
+import android.content.Context
import android.os.*
import android.system.Os
import android.widget.TextView
import androidx.appcompat.app.*
import java.io.*
+
+// Launching the tests from an activity is OK for a quick check, but for
+// anything more complicated it'll be more convenient to use `android.py test`
+// to launch the tests via PythonSuite.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
+ val status = PythonTestRunner(this).run("-W -uall")
+ findViewById(R.id.tvHello).text = "Exit status $status"
+ }
+}
+
+
+class PythonTestRunner(val context: Context) {
+ /** @param args Extra arguments for `python -m test`.
+ * @return The Python exit status: zero if the tests passed, nonzero if
+ * they failed. */
+ fun run(args: String = "") : Int {
+ Os.setenv("PYTHON_ARGS", args, true)
// Python needs this variable to help it find the temporary directory,
// but Android only sets it on API level 33 and later.
- Os.setenv("TMPDIR", cacheDir.toString(), false)
+ Os.setenv("TMPDIR", context.cacheDir.toString(), false)
val pythonHome = extractAssets()
System.loadLibrary("main_activity")
redirectStdioToLogcat()
- runPython(pythonHome.toString(), "main")
- findViewById(R.id.tvHello).text = "Python complete"
+
+ // The main module is in src/main/python/main.py.
+ return runPython(pythonHome.toString(), "main")
}
private fun extractAssets() : File {
- val pythonHome = File(filesDir, "python")
+ val pythonHome = File(context.filesDir, "python")
if (pythonHome.exists() && !pythonHome.deleteRecursively()) {
throw RuntimeException("Failed to delete $pythonHome")
}
- extractAssetDir("python", filesDir)
+ extractAssetDir("python", context.filesDir)
return pythonHome
}
private fun extractAssetDir(path: String, targetDir: File) {
- val names = assets.list(path)
+ val names = context.assets.list(path)
?: throw RuntimeException("Failed to list $path")
val targetSubdir = File(targetDir, path)
if (!targetSubdir.mkdirs()) {
@@ -43,7 +61,7 @@ class MainActivity : AppCompatActivity() {
val subPath = "$path/$name"
val input: InputStream
try {
- input = assets.open(subPath)
+ input = context.assets.open(subPath)
} catch (e: FileNotFoundException) {
extractAssetDir(subPath, targetDir)
continue
@@ -57,5 +75,5 @@ class MainActivity : AppCompatActivity() {
}
private external fun redirectStdioToLogcat()
- private external fun runPython(home: String, runModule: String)
-}
\ No newline at end of file
+ private external fun runPython(home: String, runModule: String) : Int
+}
diff --git a/Android/testbed/app/src/main/python/main.py b/Android/testbed/app/src/main/python/main.py
index a1b6def34ed..d6941b14412 100644
--- a/Android/testbed/app/src/main/python/main.py
+++ b/Android/testbed/app/src/main/python/main.py
@@ -1,17 +1,32 @@
+import os
import runpy
+import shlex
import signal
import sys
# Some tests use SIGUSR1, but that's blocked by default in an Android app in
-# order to make it available to `sigwait` in the "Signal Catcher" thread. That
-# thread's functionality is only relevant to the JVM ("forcing GC (no HPROF) and
-# profile save"), so disabling it should not weaken the tests.
+# order to make it available to `sigwait` in the Signal Catcher thread.
+# (https://cs.android.com/android/platform/superproject/+/android14-qpr3-release:art/runtime/signal_catcher.cc).
+# That thread's functionality is only useful for debugging the JVM, so disabling
+# it should not weaken the tests.
+#
+# There's no safe way of stopping the thread completely (#123982), but simply
+# unblocking SIGUSR1 is enough to fix most tests.
+#
+# However, in tests that generate multiple different signals in quick
+# succession, it's possible for SIGUSR1 to arrive while the main thread is busy
+# running the C-level handler for a different signal. In that case, the SIGUSR1
+# may be sent to the Signal Catcher thread instead, which will generate a log
+# message containing the text "reacting to signal".
+#
+# Such tests may need to be changed in one of the following ways:
+# * Use a signal other than SIGUSR1 (e.g. test_stress_delivery_simultaneous in
+# test_signal.py).
+# * Send the signal to a specific thread rather than the whole process (e.g.
+# test_signals in test_threadsignals.py.
signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGUSR1])
-# To run specific tests, or pass any other arguments to the test suite, edit
-# this command line.
-sys.argv[1:] = [
- "--use", "all,-cpu",
- "--verbose3",
-]
+sys.argv[1:] = shlex.split(os.environ["PYTHON_ARGS"])
+
+# The test module will call sys.exit to indicate whether the tests passed.
runpy.run_module("test")
diff --git a/Android/testbed/build.gradle.kts b/Android/testbed/build.gradle.kts
index 53f4a67287f..2dad1501c24 100644
--- a/Android/testbed/build.gradle.kts
+++ b/Android/testbed/build.gradle.kts
@@ -1,5 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
- id("com.android.application") version "8.2.2" apply false
+ id("com.android.application") version "8.4.2" apply false
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
-}
\ No newline at end of file
+}
diff --git a/Android/testbed/gradle.properties b/Android/testbed/gradle.properties
index 3c5031eb7d6..e9f345c8c26 100644
--- a/Android/testbed/gradle.properties
+++ b/Android/testbed/gradle.properties
@@ -20,4 +20,9 @@ kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
-android.nonTransitiveRClass=true
\ No newline at end of file
+android.nonTransitiveRClass=true
+
+# By default, the app will be uninstalled after the tests finish (apparently
+# after 10 seconds in case of an unclean shutdown). We disable this, because
+# when using android.py it can conflict with the installation of the next run.
+android.injected.androidTest.leaveApksInstalledAfterRun=true
diff --git a/Android/testbed/gradle/wrapper/gradle-wrapper.properties b/Android/testbed/gradle/wrapper/gradle-wrapper.properties
index 2dc3339a3ef..57b2f57cc86 100644
--- a/Android/testbed/gradle/wrapper/gradle-wrapper.properties
+++ b/Android/testbed/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Mon Feb 19 20:29:06 GMT 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/Doc/.ruff.toml b/Doc/.ruff.toml
new file mode 100644
index 00000000000..111ce03b91d
--- /dev/null
+++ b/Doc/.ruff.toml
@@ -0,0 +1,42 @@
+target-version = "py312" # Align with the version in oldest_supported_sphinx
+fix = true
+output-format = "full"
+line-length = 79
+extend-exclude = [
+ "includes/*",
+ # Temporary exclusions:
+ "tools/extensions/pyspecific.py",
+]
+
+[lint]
+preview = true
+select = [
+ "C4", # flake8-comprehensions
+ "B", # flake8-bugbear
+ "E", # pycodestyle
+ "F", # pyflakes
+ "FA", # flake8-future-annotations
+ "FLY", # flynt
+ "FURB", # refurb
+ "G", # flake8-logging-format
+ "I", # isort
+ "LOG", # flake8-logging
+ "N", # pep8-naming
+ "PERF", # perflint
+ "PGH", # pygrep-hooks
+ "PT", # flake8-pytest-style
+ "TCH", # flake8-type-checking
+ "UP", # pyupgrade
+ "W", # pycodestyle
+]
+ignore = [
+ "E501", # Ignore line length errors (we use auto-formatting)
+]
+
+[format]
+preview = true
+quote-style = "preserve"
+docstring-code-format = true
+exclude = [
+ "tools/extensions/lexers/*",
+]
diff --git a/Doc/Makefile b/Doc/Makefile
index c7076875483..a090ee5ba92 100644
--- a/Doc/Makefile
+++ b/Doc/Makefile
@@ -6,6 +6,7 @@
# You can set these variables from the command line.
PYTHON = python3
VENVDIR = ./venv
+UV = uv
SPHINXBUILD = PATH=$(VENVDIR)/bin:$$PATH sphinx-build
BLURB = PATH=$(VENVDIR)/bin:$$PATH blurb
JOBS = auto
@@ -143,21 +144,17 @@ pydoc-topics: build
.PHONY: gettext
gettext: BUILDER = gettext
-gettext: SPHINXOPTS += '-d build/doctrees-gettext'
+gettext: SPHINXOPTS += -d build/doctrees-gettext
gettext: build
.PHONY: htmlview
htmlview: html
$(PYTHON) -c "import os, webbrowser; webbrowser.open('file://' + os.path.realpath('build/html/index.html'))"
-.PHONY: ensure-sphinx-autobuild
-ensure-sphinx-autobuild: venv
- $(call ensure_package,sphinx-autobuild)
-
.PHONY: htmllive
-htmllive: SPHINXBUILD = $(VENVDIR)/bin/sphinx-autobuild
+htmllive: SPHINXBUILD = PATH=$(VENVDIR)/bin:$$PATH sphinx-autobuild
htmllive: SPHINXOPTS = --re-ignore="/venv/" --open-browser --delay 0
-htmllive: ensure-sphinx-autobuild html
+htmllive: _ensure-sphinx-autobuild html
.PHONY: clean
clean: clean-venv
@@ -174,83 +171,125 @@ venv:
echo "To recreate it, remove it first with \`make clean-venv'."; \
else \
echo "Creating venv in $(VENVDIR)"; \
- if uv --version > /dev/null; then \
- uv venv $(VENVDIR); \
- VIRTUAL_ENV=$(VENVDIR) uv pip install -r $(REQUIREMENTS); \
+ if $(UV) --version >/dev/null 2>&1; then \
+ $(UV) venv $(VENVDIR); \
+ VIRTUAL_ENV=$(VENVDIR) $(UV) pip install -r $(REQUIREMENTS); \
else \
$(PYTHON) -m venv $(VENVDIR); \
$(VENVDIR)/bin/python3 -m pip install --upgrade pip; \
$(VENVDIR)/bin/python3 -m pip install -r $(REQUIREMENTS); \
- echo "The venv has been created in the $(VENVDIR) directory"; \
fi; \
+ echo "The venv has been created in the $(VENVDIR) directory"; \
fi
+.PHONY: dist-no-html
+dist-no-html: dist-text dist-pdf dist-epub dist-texinfo
+
.PHONY: dist
dist:
rm -rf dist
mkdir -p dist
-
+ $(MAKE) dist-html
+ $(MAKE) dist-text
+ $(MAKE) dist-pdf
+ $(MAKE) dist-epub
+ $(MAKE) dist-texinfo
+
+.PHONY: dist-html
+dist-html:
# archive the HTML
- make html
+ @echo "Building HTML..."
+ mkdir -p dist
+ rm -rf build/html
+ find dist -name 'python-$(DISTVERSION)-docs-html*' -exec rm -rf {} \;
+ $(MAKE) html
cp -pPR build/html dist/python-$(DISTVERSION)-docs-html
tar -C dist -cf dist/python-$(DISTVERSION)-docs-html.tar python-$(DISTVERSION)-docs-html
bzip2 -9 -k dist/python-$(DISTVERSION)-docs-html.tar
(cd dist; zip -q -r -9 python-$(DISTVERSION)-docs-html.zip python-$(DISTVERSION)-docs-html)
rm -r dist/python-$(DISTVERSION)-docs-html
rm dist/python-$(DISTVERSION)-docs-html.tar
+ @echo "Build finished and archived!"
+.PHONY: dist-text
+dist-text:
# archive the text build
- make text
+ @echo "Building text..."
+ mkdir -p dist
+ rm -rf build/text
+ find dist -name 'python-$(DISTVERSION)-docs-text*' -exec rm -rf {} \;
+ $(MAKE) text
cp -pPR build/text dist/python-$(DISTVERSION)-docs-text
tar -C dist -cf dist/python-$(DISTVERSION)-docs-text.tar python-$(DISTVERSION)-docs-text
bzip2 -9 -k dist/python-$(DISTVERSION)-docs-text.tar
(cd dist; zip -q -r -9 python-$(DISTVERSION)-docs-text.zip python-$(DISTVERSION)-docs-text)
rm -r dist/python-$(DISTVERSION)-docs-text
rm dist/python-$(DISTVERSION)-docs-text.tar
+ @echo "Build finished and archived!"
+.PHONY: dist-pdf
+dist-pdf:
# archive the A4 latex
+ @echo "Building LaTeX (A4 paper)..."
+ mkdir -p dist
rm -rf build/latex
- make latex PAPER=a4
- -sed -i 's/makeindex/makeindex -q/' build/latex/Makefile
- (cd build/latex; make clean && make all-pdf && make FMT=pdf zip bz2)
+ find dist -name 'python-$(DISTVERSION)-docs-pdf*' -exec rm -rf {} \;
+ $(MAKE) latex PAPER=a4
+ # remove zip & bz2 dependency on all-pdf,
+ # as otherwise the full latexmk process is run twice.
+ # ($$ is needed to escape the $; https://www.gnu.org/software/make/manual/make.html#Basics-of-Variable-References)
+ -sed -i 's/: all-$$(FMT)/:/' build/latex/Makefile
+ (cd build/latex; $(MAKE) clean && $(MAKE) --jobs=$$((`nproc`+1)) --output-sync LATEXMKOPTS='-quiet' all-pdf && $(MAKE) FMT=pdf zip bz2)
cp build/latex/docs-pdf.zip dist/python-$(DISTVERSION)-docs-pdf-a4.zip
cp build/latex/docs-pdf.tar.bz2 dist/python-$(DISTVERSION)-docs-pdf-a4.tar.bz2
+ @echo "Build finished and archived!"
- # archive the letter latex
- rm -rf build/latex
- make latex PAPER=letter
- -sed -i 's/makeindex/makeindex -q/' build/latex/Makefile
- (cd build/latex; make clean && make all-pdf && make FMT=pdf zip bz2)
- cp build/latex/docs-pdf.zip dist/python-$(DISTVERSION)-docs-pdf-letter.zip
- cp build/latex/docs-pdf.tar.bz2 dist/python-$(DISTVERSION)-docs-pdf-letter.tar.bz2
-
+.PHONY: dist-epub
+dist-epub:
# copy the epub build
+ @echo "Building EPUB..."
+ mkdir -p dist
rm -rf build/epub
- make epub
+ rm -f dist/python-$(DISTVERSION)-docs.epub
+ $(MAKE) epub
cp -pPR build/epub/Python.epub dist/python-$(DISTVERSION)-docs.epub
+ @echo "Build finished and archived!"
+.PHONY: dist-texinfo
+dist-texinfo:
# archive the texinfo build
+ @echo "Building Texinfo..."
+ mkdir -p dist
rm -rf build/texinfo
- make texinfo
- make info --directory=build/texinfo
+ find dist -name 'python-$(DISTVERSION)-docs-texinfo*' -exec rm -rf {} \;
+ $(MAKE) texinfo
+ $(MAKE) info --directory=build/texinfo
cp -pPR build/texinfo dist/python-$(DISTVERSION)-docs-texinfo
tar -C dist -cf dist/python-$(DISTVERSION)-docs-texinfo.tar python-$(DISTVERSION)-docs-texinfo
bzip2 -9 -k dist/python-$(DISTVERSION)-docs-texinfo.tar
(cd dist; zip -q -r -9 python-$(DISTVERSION)-docs-texinfo.zip python-$(DISTVERSION)-docs-texinfo)
rm -r dist/python-$(DISTVERSION)-docs-texinfo
rm dist/python-$(DISTVERSION)-docs-texinfo.tar
+ @echo "Build finished and archived!"
-define ensure_package
- if uv --version > /dev/null; then \
- $(VENVDIR)/bin/python3 -m $(1) --version > /dev/null || VIRTUAL_ENV=$(VENVDIR) uv pip install $(1); \
+.PHONY: _ensure-package
+_ensure-package: venv
+ if $(UV) --version >/dev/null 2>&1; then \
+ VIRTUAL_ENV=$(VENVDIR) $(UV) pip install $(PACKAGE); \
else \
- $(VENVDIR)/bin/python3 -m $(1) --version > /dev/null || $(VENVDIR)/bin/python3 -m pip install $(1); \
+ $(VENVDIR)/bin/python3 -m pip install $(PACKAGE); \
fi
-endef
+
+.PHONY: _ensure-pre-commit
+_ensure-pre-commit:
+ $(MAKE) _ensure-package PACKAGE=pre-commit
+
+.PHONY: _ensure-sphinx-autobuild
+_ensure-sphinx-autobuild:
+ $(MAKE) _ensure-package PACKAGE=sphinx-autobuild
.PHONY: check
-check: venv
- $(call ensure_package,pre_commit)
+check: _ensure-pre-commit
$(VENVDIR)/bin/python3 -m pre_commit run --all-files
.PHONY: serve
@@ -266,13 +305,15 @@ serve:
# for development releases: always build
.PHONY: autobuild-dev
+autobuild-dev: DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py --short)
autobuild-dev:
- make dist SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1'
+ $(MAKE) dist-no-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1' DISTVERSION=$(DISTVERSION)
-# for quick rebuilds (HTML only)
+# for HTML-only rebuilds
.PHONY: autobuild-dev-html
+autobuild-dev-html: DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py --short)
autobuild-dev-html:
- make html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1'
+ $(MAKE) dist-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1' DISTVERSION=$(DISTVERSION)
# for stable releases: only build if not in pre-release stage (alpha, beta)
# release candidate downloads are okay, since the stable tree can be in that stage
@@ -282,7 +323,7 @@ autobuild-stable:
echo "Not building; $(DISTVERSION) is not a release version."; \
exit 1;; \
esac
- @make autobuild-dev
+ @$(MAKE) autobuild-dev
.PHONY: autobuild-stable-html
autobuild-stable-html:
@@ -290,4 +331,4 @@ autobuild-stable-html:
echo "Not building; $(DISTVERSION) is not a release version."; \
exit 1;; \
esac
- @make autobuild-dev-html
+ @$(MAKE) autobuild-dev-html
diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst
index 834aae9372f..3201bdc8269 100644
--- a/Doc/c-api/arg.rst
+++ b/Doc/c-api/arg.rst
@@ -280,10 +280,10 @@ Numbers
length 1, to a C :c:expr:`int`.
``f`` (:class:`float`) [float]
- Convert a Python floating point number to a C :c:expr:`float`.
+ Convert a Python floating-point number to a C :c:expr:`float`.
``d`` (:class:`float`) [double]
- Convert a Python floating point number to a C :c:expr:`double`.
+ Convert a Python floating-point number to a C :c:expr:`double`.
``D`` (:class:`complex`) [Py_complex]
Convert a Python complex number to a C :c:type:`Py_complex` structure.
@@ -642,10 +642,10 @@ Building values
object of length 1.
``d`` (:class:`float`) [double]
- Convert a C :c:expr:`double` to a Python floating point number.
+ Convert a C :c:expr:`double` to a Python floating-point number.
``f`` (:class:`float`) [float]
- Convert a C :c:expr:`float` to a Python floating point number.
+ Convert a C :c:expr:`float` to a Python floating-point number.
``D`` (:class:`complex`) [Py_complex \*]
Convert a C :c:type:`Py_complex` structure to a Python complex number.
diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst
index 9500fe465c7..dc43a3d5fcb 100644
--- a/Doc/c-api/buffer.rst
+++ b/Doc/c-api/buffer.rst
@@ -244,7 +244,6 @@ The following fields are not influenced by *flags* and must always be filled in
with the correct values: :c:member:`~Py_buffer.obj`, :c:member:`~Py_buffer.buf`,
:c:member:`~Py_buffer.len`, :c:member:`~Py_buffer.itemsize`, :c:member:`~Py_buffer.ndim`.
-
readonly, format
~~~~~~~~~~~~~~~~
@@ -253,7 +252,8 @@ readonly, format
Controls the :c:member:`~Py_buffer.readonly` field. If set, the exporter
MUST provide a writable buffer or else report failure. Otherwise, the
exporter MAY provide either a read-only or writable buffer, but the choice
- MUST be consistent for all consumers.
+ MUST be consistent for all consumers. For example, :c:expr:`PyBUF_SIMPLE | PyBUF_WRITABLE`
+ can be used to request a simple writable buffer.
.. c:macro:: PyBUF_FORMAT
@@ -265,8 +265,9 @@ readonly, format
Since :c:macro:`PyBUF_SIMPLE` is defined as 0, :c:macro:`PyBUF_WRITABLE`
can be used as a stand-alone flag to request a simple writable buffer.
-:c:macro:`PyBUF_FORMAT` can be \|'d to any of the flags except :c:macro:`PyBUF_SIMPLE`.
-The latter already implies format ``B`` (unsigned bytes).
+:c:macro:`PyBUF_FORMAT` must be \|'d to any of the flags except :c:macro:`PyBUF_SIMPLE`, because
+the latter already implies format ``B`` (unsigned bytes). :c:macro:`!PyBUF_FORMAT` cannot be
+used on its own.
shape, strides, suboffsets
diff --git a/Doc/c-api/bytearray.rst b/Doc/c-api/bytearray.rst
index 456f7d89bca..9045689a6be 100644
--- a/Doc/c-api/bytearray.rst
+++ b/Doc/c-api/bytearray.rst
@@ -42,17 +42,22 @@ Direct API functions
Return a new bytearray object from any object, *o*, that implements the
:ref:`buffer protocol `.
+ On failure, return ``NULL`` with an exception set.
+
.. c:function:: PyObject* PyByteArray_FromStringAndSize(const char *string, Py_ssize_t len)
- Create a new bytearray object from *string* and its length, *len*. On
- failure, ``NULL`` is returned.
+ Create a new bytearray object from *string* and its length, *len*.
+
+ On failure, return ``NULL`` with an exception set.
.. c:function:: PyObject* PyByteArray_Concat(PyObject *a, PyObject *b)
Concat bytearrays *a* and *b* and return a new bytearray with the result.
+ On failure, return ``NULL`` with an exception set.
+
.. c:function:: Py_ssize_t PyByteArray_Size(PyObject *bytearray)
diff --git a/Doc/c-api/cell.rst b/Doc/c-api/cell.rst
index f8cd0344fdd..61eb994c370 100644
--- a/Doc/c-api/cell.rst
+++ b/Doc/c-api/cell.rst
@@ -39,7 +39,8 @@ Cell objects are not likely to be useful elsewhere.
.. c:function:: PyObject* PyCell_Get(PyObject *cell)
- Return the contents of the cell *cell*.
+ Return the contents of the cell *cell*, which can be ``NULL``.
+ If *cell* is not a cell object, returns ``NULL`` with an exception set.
.. c:function:: PyObject* PyCell_GET(PyObject *cell)
@@ -52,8 +53,10 @@ Cell objects are not likely to be useful elsewhere.
Set the contents of the cell object *cell* to *value*. This releases the
reference to any current content of the cell. *value* may be ``NULL``. *cell*
- must be non-``NULL``; if it is not a cell object, ``-1`` will be returned. On
- success, ``0`` will be returned.
+ must be non-``NULL``.
+
+ On success, return ``0``.
+ If *cell* is not a cell object, set an exception and return ``-1``.
.. c:function:: void PyCell_SET(PyObject *cell, PyObject *value)
diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst
index 968c472219c..6ae6bfe4aa6 100644
--- a/Doc/c-api/code.rst
+++ b/Doc/c-api/code.rst
@@ -96,8 +96,8 @@ bound into a function.
Return the line number of the instruction that occurs on or before ``byte_offset`` and ends after it.
If you just need the line number of a frame, use :c:func:`PyFrame_GetLineNumber` instead.
- For efficiently iterating over the line numbers in a code object, use `the API described in PEP 626
- `_.
+ For efficiently iterating over the line numbers in a code object, use :pep:`the API described in PEP 626
+ <0626#out-of-process-debuggers-and-profilers>`.
.. c:function:: int PyCode_Addr2Location(PyObject *co, int byte_offset, int *start_line, int *start_column, int *end_line, int *end_column)
diff --git a/Doc/c-api/complex.rst b/Doc/c-api/complex.rst
index 5a047486907..67d0c5f144e 100644
--- a/Doc/c-api/complex.rst
+++ b/Doc/c-api/complex.rst
@@ -25,12 +25,16 @@ pointers. This is consistent throughout the API.
The C structure which corresponds to the value portion of a Python complex
number object. Most of the functions for dealing with complex number objects
- use structures of this type as input or output values, as appropriate. It is
- defined as::
+ use structures of this type as input or output values, as appropriate.
+
+ .. c:member:: double real
+ double imag
+
+ The structure is defined as::
typedef struct {
- double real;
- double imag;
+ double real;
+ double imag;
} Py_complex;
@@ -106,11 +110,13 @@ Complex Numbers as Python Objects
.. c:function:: PyObject* PyComplex_FromCComplex(Py_complex v)
Create a new Python complex number object from a C :c:type:`Py_complex` value.
+ Return ``NULL`` with an exception set on error.
.. c:function:: PyObject* PyComplex_FromDoubles(double real, double imag)
Return a new :c:type:`PyComplexObject` object from *real* and *imag*.
+ Return ``NULL`` with an exception set on error.
.. c:function:: double PyComplex_RealAsDouble(PyObject *op)
@@ -121,7 +127,9 @@ Complex Numbers as Python Objects
:meth:`~object.__complex__` method, this method will first be called to
convert *op* to a Python complex number object. If :meth:`!__complex__` is
not defined then it falls back to call :c:func:`PyFloat_AsDouble` and
- returns its result. Upon failure, this method returns ``-1.0``, so one
+ returns its result.
+
+ Upon failure, this method returns ``-1.0`` with an exception set, so one
should call :c:func:`PyErr_Occurred` to check for errors.
.. versionchanged:: 3.13
@@ -135,8 +143,10 @@ Complex Numbers as Python Objects
:meth:`~object.__complex__` method, this method will first be called to
convert *op* to a Python complex number object. If :meth:`!__complex__` is
not defined then it falls back to call :c:func:`PyFloat_AsDouble` and
- returns ``0.0`` on success. Upon failure, this method returns ``-1.0``, so
- one should call :c:func:`PyErr_Occurred` to check for errors.
+ returns ``0.0`` on success.
+
+ Upon failure, this method returns ``-1.0`` with an exception set, so one
+ should call :c:func:`PyErr_Occurred` to check for errors.
.. versionchanged:: 3.13
Use :meth:`~object.__complex__` if available.
@@ -149,8 +159,11 @@ Complex Numbers as Python Objects
method, this method will first be called to convert *op* to a Python complex
number object. If :meth:`!__complex__` is not defined then it falls back to
:meth:`~object.__float__`. If :meth:`!__float__` is not defined then it falls back
- to :meth:`~object.__index__`. Upon failure, this method returns ``-1.0`` as a real
- value.
+ to :meth:`~object.__index__`.
+
+ Upon failure, this method returns :c:type:`Py_complex`
+ with :c:member:`~Py_complex.real` set to ``-1.0`` and with an exception set, so one
+ should call :c:func:`PyErr_Occurred` to check for errors.
.. versionchanged:: 3.8
Use :meth:`~object.__index__` if available.
diff --git a/Doc/c-api/datetime.rst b/Doc/c-api/datetime.rst
index 97522da7734..d2d4d5309c7 100644
--- a/Doc/c-api/datetime.rst
+++ b/Doc/c-api/datetime.rst
@@ -318,10 +318,10 @@ Macros for the convenience of modules implementing the DB API:
.. c:function:: PyObject* PyDateTime_FromTimestamp(PyObject *args)
Create and return a new :class:`datetime.datetime` object given an argument
- tuple suitable for passing to :meth:`datetime.datetime.fromtimestamp()`.
+ tuple suitable for passing to :meth:`datetime.datetime.fromtimestamp`.
.. c:function:: PyObject* PyDate_FromTimestamp(PyObject *args)
Create and return a new :class:`datetime.date` object given an argument
- tuple suitable for passing to :meth:`datetime.date.fromtimestamp()`.
+ tuple suitable for passing to :meth:`datetime.date.fromtimestamp`.
diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst
index 499bfb47cc4..fc2336d120c 100644
--- a/Doc/c-api/exceptions.rst
+++ b/Doc/c-api/exceptions.rst
@@ -34,7 +34,7 @@ propagated, additional calls into the Python/C API may not behave as intended
and may fail in mysterious ways.
.. note::
- The error indicator is **not** the result of :func:`sys.exc_info()`.
+ The error indicator is **not** the result of :func:`sys.exc_info`.
The former corresponds to an exception that is not yet caught (and is
therefore still propagating), while the latter returns an exception after
it is caught (and has therefore stopped propagating).
@@ -733,7 +733,7 @@ Exception Classes
This creates a class object derived from :exc:`Exception` (accessible in C as
:c:data:`PyExc_Exception`).
- The :attr:`!__module__` attribute of the new class is set to the first part (up
+ The :attr:`~type.__module__` attribute of the new class is set to the first part (up
to the last dot) of the *name* argument, and the class name is set to the last
part (after the last dot). The *base* argument can be used to specify alternate
base classes; it can either be only one class or a tuple of classes. The *dict*
@@ -1004,6 +1004,7 @@ the variables:
single: PyExc_OverflowError (C var)
single: PyExc_PermissionError (C var)
single: PyExc_ProcessLookupError (C var)
+ single: PyExc_PythonFinalizationError (C var)
single: PyExc_RecursionError (C var)
single: PyExc_ReferenceError (C var)
single: PyExc_RuntimeError (C var)
@@ -1096,6 +1097,8 @@ the variables:
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_ProcessLookupError` | :exc:`ProcessLookupError` | |
+-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_PythonFinalizationError` | :exc:`PythonFinalizationError` | |
++-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_RecursionError` | :exc:`RecursionError` | |
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_ReferenceError` | :exc:`ReferenceError` | |
diff --git a/Doc/c-api/float.rst b/Doc/c-api/float.rst
index 4f6ac0d8175..1da37a5bcae 100644
--- a/Doc/c-api/float.rst
+++ b/Doc/c-api/float.rst
@@ -2,20 +2,20 @@
.. _floatobjects:
-Floating Point Objects
+Floating-Point Objects
======================
-.. index:: pair: object; floating point
+.. index:: pair: object; floating-point
.. c:type:: PyFloatObject
- This subtype of :c:type:`PyObject` represents a Python floating point object.
+ This subtype of :c:type:`PyObject` represents a Python floating-point object.
.. c:var:: PyTypeObject PyFloat_Type
- This instance of :c:type:`PyTypeObject` represents the Python floating point
+ This instance of :c:type:`PyTypeObject` represents the Python floating-point
type. This is the same object as :class:`float` in the Python layer.
@@ -45,7 +45,7 @@ Floating Point Objects
.. c:function:: double PyFloat_AsDouble(PyObject *pyfloat)
Return a C :c:expr:`double` representation of the contents of *pyfloat*. If
- *pyfloat* is not a Python floating point object but has a :meth:`~object.__float__`
+ *pyfloat* is not a Python floating-point object but has a :meth:`~object.__float__`
method, this method will first be called to convert *pyfloat* into a float.
If :meth:`!__float__` is not defined then it falls back to :meth:`~object.__index__`.
This method returns ``-1.0`` upon failure, so one should call
diff --git a/Doc/c-api/import.rst b/Doc/c-api/import.rst
index 1054b38cb92..8108a5015be 100644
--- a/Doc/c-api/import.rst
+++ b/Doc/c-api/import.rst
@@ -190,7 +190,7 @@ Importing Modules
.. versionadded:: 3.2
.. versionchanged:: 3.3
- Uses :func:`!imp.source_from_cache()` in calculating the source path if
+ Uses :func:`!imp.source_from_cache` in calculating the source path if
only the bytecode path is provided.
.. versionchanged:: 3.12
No longer uses the removed :mod:`!imp` module.
diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst
index 1fab3f577f2..fd97d1d6ec3 100644
--- a/Doc/c-api/init.rst
+++ b/Doc/c-api/init.rst
@@ -1218,7 +1218,7 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
.. c:function:: void PyThreadState_DeleteCurrent(void)
Destroy the current thread state and release the global interpreter lock.
- Like :c:func:`PyThreadState_Delete`, the global interpreter lock need not
+ Like :c:func:`PyThreadState_Delete`, the global interpreter lock must
be held. The thread state must have been reset with a previous call
to :c:func:`PyThreadState_Clear`.
diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst
index 5195f6cccfe..918c8669e8f 100644
--- a/Doc/c-api/init_config.rst
+++ b/Doc/c-api/init_config.rst
@@ -321,7 +321,7 @@ PyPreConfig
* Set :c:member:`PyConfig.filesystem_encoding` to ``"mbcs"``,
* Set :c:member:`PyConfig.filesystem_errors` to ``"replace"``.
- Initialized the from :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment
+ Initialized from the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment
variable value.
Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
@@ -509,7 +509,7 @@ PyConfig
The :c:func:`PyConfig_Read` function only parses
:c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
is set to ``2`` after arguments are parsed. Since Python arguments are
- strippped from :c:member:`PyConfig.argv`, parsing arguments twice would
+ stripped from :c:member:`PyConfig.argv`, parsing arguments twice would
parse the application options as Python options.
:ref:`Preinitialize Python ` if needed.
@@ -1041,7 +1041,7 @@ PyConfig
The :c:func:`PyConfig_Read` function only parses
:c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
is set to ``2`` after arguments are parsed. Since Python arguments are
- strippped from :c:member:`PyConfig.argv`, parsing arguments twice would
+ stripped from :c:member:`PyConfig.argv`, parsing arguments twice would
parse the application options as Python options.
Default: ``1`` in Python mode, ``0`` in isolated mode.
diff --git a/Doc/c-api/list.rst b/Doc/c-api/list.rst
index 53eb54d3e10..758415a76e5 100644
--- a/Doc/c-api/list.rst
+++ b/Doc/c-api/list.rst
@@ -38,9 +38,12 @@ List Objects
.. note::
If *len* is greater than zero, the returned list object's items are
- set to ``NULL``. Thus you cannot use abstract API functions such as
- :c:func:`PySequence_SetItem` or expose the object to Python code before
- setting all items to a real object with :c:func:`PyList_SetItem`.
+ set to ``NULL``. Thus you cannot use abstract API functions such as
+ :c:func:`PySequence_SetItem` or expose the object to Python code before
+ setting all items to a real object with :c:func:`PyList_SetItem` or
+ :c:func:`PyList_SET_ITEM()`. The following APIs are safe APIs before
+ the list is fully initialized: :c:func:`PyList_SetItem()` and :c:func:`PyList_SET_ITEM()`.
+
.. c:function:: Py_ssize_t PyList_Size(PyObject *list)
diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst
index 522c028cfb8..c9e277680ab 100644
--- a/Doc/c-api/long.rst
+++ b/Doc/c-api/long.rst
@@ -139,7 +139,6 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
.. versionadded:: 3.13
-.. XXX alias PyLong_AS_LONG (for now)
.. c:function:: long PyLong_AsLong(PyObject *obj)
.. index::
@@ -161,6 +160,16 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
.. versionchanged:: 3.10
This function will no longer use :meth:`~object.__int__`.
+ .. c:namespace:: NULL
+
+ .. c:function:: long PyLong_AS_LONG(PyObject *obj)
+
+ A :term:`soft deprecated` alias.
+ Exactly equivalent to the preferred ``PyLong_AsLong``. In particular,
+ it can fail with :exc:`OverflowError` or another exception.
+
+ .. deprecated:: 3.14
+ The function is soft deprecated.
.. c:function:: int PyLong_AsInt(PyObject *obj)
@@ -405,14 +414,13 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
Passing zero to *n_bytes* will return the size of a buffer that would
be large enough to hold the value. This may be larger than technically
- necessary, but not unreasonably so.
+ necessary, but not unreasonably so. If *n_bytes=0*, *buffer* may be
+ ``NULL``.
.. note::
Passing *n_bytes=0* to this function is not an accurate way to determine
- the bit length of a value.
-
- If *n_bytes=0*, *buffer* may be ``NULL``.
+ the bit length of the value.
To get at the entire Python value of an unknown size, the function can be
called twice: first to determine the buffer size, then to fill it::
@@ -453,6 +461,8 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
Currently, ``-1`` corresponds to
``Py_ASNATIVEBYTES_NATIVE_ENDIAN | Py_ASNATIVEBYTES_UNSIGNED_BUFFER``.
+ .. c:namespace:: NULL
+
============================================= ======
Flag Value
============================================= ======
@@ -462,6 +472,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
.. c:macro:: Py_ASNATIVEBYTES_NATIVE_ENDIAN ``3``
.. c:macro:: Py_ASNATIVEBYTES_UNSIGNED_BUFFER ``4``
.. c:macro:: Py_ASNATIVEBYTES_REJECT_NEGATIVE ``8``
+ .. c:macro:: Py_ASNATIVEBYTES_ALLOW_INDEX ``16``
============================================= ======
Specifying ``Py_ASNATIVEBYTES_NATIVE_ENDIAN`` will override any other endian
@@ -483,6 +494,13 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
provided there is enough space for at least one sign bit, regardless of
whether ``Py_ASNATIVEBYTES_UNSIGNED_BUFFER`` was specified.
+ If ``Py_ASNATIVEBYTES_ALLOW_INDEX`` is specified and a non-integer value is
+ passed, its :meth:`~object.__index__` method will be called first. This may
+ result in Python code executing and other threads being allowed to run, which
+ could cause changes to other objects or values in use. When *flags* is
+ ``-1``, this option is not set, and non-integer values will raise
+ :exc:`TypeError`.
+
.. note::
With the default *flags* (``-1``, or *UNSIGNED_BUFFER* without
@@ -494,6 +512,17 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
.. versionadded:: 3.13
+.. c:function:: PyObject* PyLong_GetInfo(void)
+
+ On success, return a read only :term:`named tuple`, that holds
+ information about Python's internal representation of integers.
+ See :data:`sys.int_info` for description of individual fields.
+
+ On failure, return ``NULL`` with an exception set.
+
+ .. versionadded:: 3.1
+
+
.. c:function:: int PyUnstable_Long_IsCompact(const PyLongObject* op)
Return 1 if *op* is compact, 0 otherwise.
diff --git a/Doc/c-api/marshal.rst b/Doc/c-api/marshal.rst
index 489f1580a41..b9085ad3ec3 100644
--- a/Doc/c-api/marshal.rst
+++ b/Doc/c-api/marshal.rst
@@ -15,7 +15,7 @@ Numeric values are stored with the least significant byte first.
The module supports two versions of the data format: version 0 is the
historical version, version 1 shares interned strings in the file, and upon
-unmarshalling. Version 2 uses a binary format for floating point numbers.
+unmarshalling. Version 2 uses a binary format for floating-point numbers.
``Py_MARSHAL_VERSION`` indicates the current file format (currently 2).
diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst
index 9da09a21607..f7618a025ba 100644
--- a/Doc/c-api/memory.rst
+++ b/Doc/c-api/memory.rst
@@ -102,30 +102,38 @@ All allocating functions belong to one of three different "domains" (see also
strategies and are optimized for different purposes. The specific details on
how every domain allocates memory or what internal functions each domain calls
is considered an implementation detail, but for debugging purposes a simplified
-table can be found at :ref:`here `. There is no hard
-requirement to use the memory returned by the allocation functions belonging to
-a given domain for only the purposes hinted by that domain (although this is the
-recommended practice). For example, one could use the memory returned by
-:c:func:`PyMem_RawMalloc` for allocating Python objects or the memory returned
-by :c:func:`PyObject_Malloc` for allocating memory for buffers.
+table can be found at :ref:`here `.
+The APIs used to allocate and free a block of memory must be from the same domain.
+For example, :c:func:`PyMem_Free` must be used to free memory allocated using :c:func:`PyMem_Malloc`.
The three allocation domains are:
* Raw domain: intended for allocating memory for general-purpose memory
buffers where the allocation *must* go to the system allocator or where the
allocator can operate without the :term:`GIL`. The memory is requested directly
- to the system.
+ from the system. See :ref:`Raw Memory Interface `.
* "Mem" domain: intended for allocating memory for Python buffers and
general-purpose memory buffers where the allocation must be performed with
the :term:`GIL` held. The memory is taken from the Python private heap.
+ See :ref:`Memory Interface `.
-* Object domain: intended for allocating memory belonging to Python objects. The
- memory is taken from the Python private heap.
+* Object domain: intended for allocating memory for Python objects. The
+ memory is taken from the Python private heap. See :ref:`Object allocators `.
-When freeing memory previously allocated by the allocating functions belonging to a
-given domain,the matching specific deallocating functions must be used. For example,
-:c:func:`PyMem_Free` must be used to free memory allocated using :c:func:`PyMem_Malloc`.
+.. note::
+
+ The :term:`free-threaded ` build requires that only Python objects are allocated using the "object" domain
+ and that all Python objects are allocated using that domain. This differs from the prior Python versions,
+ where this was only a best practice and not a hard requirement.
+
+ For example, buffers (non-Python objects) should be allocated using :c:func:`PyMem_Malloc`,
+ :c:func:`PyMem_RawMalloc`, or :c:func:`malloc`, but not :c:func:`PyObject_Malloc`.
+
+ See :ref:`Memory Allocation APIs `.
+
+
+.. _raw-memoryinterface:
Raw Memory Interface
====================
@@ -299,6 +307,8 @@ versions and is therefore deprecated in extension modules.
* ``PyMem_DEL(ptr)``
+.. _objectinterface:
+
Object allocators
=================
diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst
index 63e3bed6727..ec61be284ca 100644
--- a/Doc/c-api/module.rst
+++ b/Doc/c-api/module.rst
@@ -43,6 +43,8 @@ Module Objects
to ``None``); the caller is responsible for providing a :attr:`__file__`
attribute.
+ Return ``NULL`` with an exception set on error.
+
.. versionadded:: 3.3
.. versionchanged:: 3.4
@@ -265,6 +267,8 @@ of the following two module creation functions:
API version *module_api_version*. If that version does not match the version
of the running interpreter, a :exc:`RuntimeWarning` is emitted.
+ Return ``NULL`` with an exception set on error.
+
.. note::
Most uses of this function should be using :c:func:`PyModule_Create`
@@ -338,7 +342,8 @@ The available slot types are:
The *value* pointer of this slot must point to a function of the signature:
.. c:function:: PyObject* create_module(PyObject *spec, PyModuleDef *def)
- :noindex:
+ :no-index-entry:
+ :no-contents-entry:
The function receives a :py:class:`~importlib.machinery.ModuleSpec`
instance, as defined in :PEP:`451`, and the module definition.
@@ -373,7 +378,8 @@ The available slot types are:
The signature of the function is:
.. c:function:: int exec_module(PyObject* module)
- :noindex:
+ :no-index-entry:
+ :no-contents-entry:
If multiple ``Py_mod_exec`` slots are specified, they are processed in the
order they appear in the *m_slots* array.
@@ -415,6 +421,8 @@ The available slot types are:
Specifies one of the following values:
+ .. c:namespace:: NULL
+
.. c:macro:: Py_MOD_GIL_USED
The module depends on the presence of the global interpreter lock (GIL),
@@ -427,7 +435,7 @@ The available slot types are:
This slot is ignored by Python builds not configured with
:option:`--disable-gil`. Otherwise, it determines whether or not importing
this module will cause the GIL to be automatically enabled. See
- :ref:`free-threaded-cpython` for more detail.
+ :ref:`whatsnew313-free-threaded-cpython` for more detail.
Multiple ``Py_mod_gil`` slots may not be specified in one module definition.
@@ -461,6 +469,8 @@ objects dynamically. Note that both ``PyModule_FromDefAndSpec`` and
If that version does not match the version of the running interpreter,
a :exc:`RuntimeWarning` is emitted.
+ Return ``NULL`` with an exception set on error.
+
.. note::
Most uses of this function should be using :c:func:`PyModule_FromDefAndSpec`
@@ -511,7 +521,7 @@ state:
On success, return ``0``. On error, raise an exception and return ``-1``.
- Return ``NULL`` if *value* is ``NULL``. It must be called with an exception
+ Return ``-1`` if *value* is ``NULL``. It must be called with an exception
raised in this case.
Example usage::
@@ -543,6 +553,14 @@ state:
Note that ``Py_XDECREF()`` should be used instead of ``Py_DECREF()`` in
this case, since *obj* can be ``NULL``.
+ The number of different *name* strings passed to this function
+ should be kept small, usually by only using statically allocated strings
+ as *name*.
+ For names that aren't known at compile time, prefer calling
+ :c:func:`PyUnicode_FromString` and :c:func:`PyObject_SetAttr` directly.
+ For more details, see :c:func:`PyUnicode_InternFromString`, which may be
+ used internally to create a key object.
+
.. versionadded:: 3.10
@@ -601,15 +619,23 @@ state:
.. c:function:: int PyModule_AddIntConstant(PyObject *module, const char *name, long value)
Add an integer constant to *module* as *name*. This convenience function can be
- used from the module's initialization function. Return ``-1`` on error, ``0`` on
- success.
+ used from the module's initialization function.
+ Return ``-1`` with an exception set on error, ``0`` on success.
+
+ This is a convenience function that calls :c:func:`PyLong_FromLong` and
+ :c:func:`PyModule_AddObjectRef`; see their documentation for details.
.. c:function:: int PyModule_AddStringConstant(PyObject *module, const char *name, const char *value)
Add a string constant to *module* as *name*. This convenience function can be
used from the module's initialization function. The string *value* must be
- ``NULL``-terminated. Return ``-1`` on error, ``0`` on success.
+ ``NULL``-terminated.
+ Return ``-1`` with an exception set on error, ``0`` on success.
+
+ This is a convenience function that calls
+ :c:func:`PyUnicode_InternFromString` and :c:func:`PyModule_AddObjectRef`;
+ see their documentation for details.
.. c:macro:: PyModule_AddIntMacro(module, macro)
@@ -617,7 +643,7 @@ state:
Add an int constant to *module*. The name and the value are taken from
*macro*. For example ``PyModule_AddIntMacro(module, AF_INET)`` adds the int
constant *AF_INET* with the value of *AF_INET* to *module*.
- Return ``-1`` on error, ``0`` on success.
+ Return ``-1`` with an exception set on error, ``0`` on success.
.. c:macro:: PyModule_AddStringMacro(module, macro)
@@ -630,7 +656,7 @@ state:
The type object is finalized by calling internally :c:func:`PyType_Ready`.
The name of the type object is taken from the last component of
:c:member:`~PyTypeObject.tp_name` after dot.
- Return ``-1`` on error, ``0`` on success.
+ Return ``-1`` with an exception set on error, ``0`` on success.
.. versionadded:: 3.9
@@ -643,7 +669,7 @@ state:
import machinery assumes the module does not support running without the
GIL. This function is only available in Python builds configured with
:option:`--disable-gil`.
- Return ``-1`` on error, ``0`` on success.
+ Return ``-1`` with an exception set on error, ``0`` on success.
.. versionadded:: 3.13
@@ -682,14 +708,14 @@ since multiple such modules can be created from a single definition.
The caller must hold the GIL.
- Return 0 on success or -1 on failure.
+ Return ``-1`` with an exception set on error, ``0`` on success.
.. versionadded:: 3.3
.. c:function:: int PyState_RemoveModule(PyModuleDef *def)
Removes the module object created from *def* from the interpreter state.
- Return 0 on success or -1 on failure.
+ Return ``-1`` with an exception set on error, ``0`` on success.
The caller must hold the GIL.
diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst
index b34035b5548..285ddb2889a 100644
--- a/Doc/c-api/monitoring.rst
+++ b/Doc/c-api/monitoring.rst
@@ -1,6 +1,6 @@
.. highlight:: c
-.. _monitoring:
+.. _c-api-monitoring:
Monitoring C API
================
@@ -133,7 +133,7 @@ Managing the Monitoring State
Monitoring states can be managed with the help of monitoring scopes. A scope
would typically correspond to a python function.
-.. :c:function:: int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length)
+.. c:function:: int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length)
Enter a monitored scope. ``event_types`` is an array of the event IDs for
events that may be fired from the scope. For example, the ID of a ``PY_START``
@@ -141,24 +141,52 @@ would typically correspond to a python function.
to the base-2 logarithm of ``sys.monitoring.events.PY_START``.
``state_array`` is an array with a monitoring state entry for each event in
``event_types``, it is allocated by the user but populated by
- ``PyMonitoring_EnterScope`` with information about the activation state of
+ :c:func:`!PyMonitoring_EnterScope` with information about the activation state of
the event. The size of ``event_types`` (and hence also of ``state_array``)
is given in ``length``.
The ``version`` argument is a pointer to a value which should be allocated
by the user together with ``state_array`` and initialized to 0,
- and then set only by ``PyMonitoring_EnterScope`` itelf. It allows this
+ and then set only by :c:func:`!PyMonitoring_EnterScope` itelf. It allows this
function to determine whether event states have changed since the previous call,
and to return quickly if they have not.
The scopes referred to here are lexical scopes: a function, class or method.
- ``PyMonitoring_EnterScope`` should be called whenever the lexical scope is
+ :c:func:`!PyMonitoring_EnterScope` should be called whenever the lexical scope is
entered. Scopes can be reentered, reusing the same *state_array* and *version*,
in situations like when emulating a recursive Python function. When a code-like's
execution is paused, such as when emulating a generator, the scope needs to
be exited and re-entered.
-
-.. :c:function:: int PyMonitoring_ExitScope(void)
-
- Exit the last scope that was entered with ``PyMonitoring_EnterScope``.
+ The macros for *event_types* are:
+
+ .. c:namespace:: NULL
+
+ .. The table is here to make the docs searchable, and to allow automatic
+ links to the identifiers.
+
+ ================================================== =====================================
+ Macro Event
+ ================================================== =====================================
+ .. c:macro:: PY_MONITORING_EVENT_BRANCH :monitoring-event:`BRANCH`
+ .. c:macro:: PY_MONITORING_EVENT_CALL :monitoring-event:`CALL`
+ .. c:macro:: PY_MONITORING_EVENT_C_RAISE :monitoring-event:`C_RAISE`
+ .. c:macro:: PY_MONITORING_EVENT_C_RETURN :monitoring-event:`C_RETURN`
+ .. c:macro:: PY_MONITORING_EVENT_EXCEPTION_HANDLED :monitoring-event:`EXCEPTION_HANDLED`
+ .. c:macro:: PY_MONITORING_EVENT_INSTRUCTION :monitoring-event:`INSTRUCTION`
+ .. c:macro:: PY_MONITORING_EVENT_JUMP :monitoring-event:`JUMP`
+ .. c:macro:: PY_MONITORING_EVENT_LINE :monitoring-event:`LINE`
+ .. c:macro:: PY_MONITORING_EVENT_PY_RESUME :monitoring-event:`PY_RESUME`
+ .. c:macro:: PY_MONITORING_EVENT_PY_RETURN :monitoring-event:`PY_RETURN`
+ .. c:macro:: PY_MONITORING_EVENT_PY_START :monitoring-event:`PY_START`
+ .. c:macro:: PY_MONITORING_EVENT_PY_THROW :monitoring-event:`PY_THROW`
+ .. c:macro:: PY_MONITORING_EVENT_PY_UNWIND :monitoring-event:`PY_UNWIND`
+ .. c:macro:: PY_MONITORING_EVENT_PY_YIELD :monitoring-event:`PY_YIELD`
+ .. c:macro:: PY_MONITORING_EVENT_RAISE :monitoring-event:`RAISE`
+ .. c:macro:: PY_MONITORING_EVENT_RERAISE :monitoring-event:`RERAISE`
+ .. c:macro:: PY_MONITORING_EVENT_STOP_ITERATION :monitoring-event:`STOP_ITERATION`
+ ================================================== =====================================
+
+.. c:function:: int PyMonitoring_ExitScope(void)
+
+ Exit the last scope that was entered with :c:func:`!PyMonitoring_EnterScope`.
diff --git a/Doc/c-api/number.rst b/Doc/c-api/number.rst
index 13d3c5af956..ad8b5935258 100644
--- a/Doc/c-api/number.rst
+++ b/Doc/c-api/number.rst
@@ -51,8 +51,8 @@ Number Protocol
Return a reasonable approximation for the mathematical value of *o1* divided by
*o2*, or ``NULL`` on failure. The return value is "approximate" because binary
- floating point numbers are approximate; it is not possible to represent all real
- numbers in base two. This function can return a floating point value when
+ floating-point numbers are approximate; it is not possible to represent all real
+ numbers in base two. This function can return a floating-point value when
passed two integers. This is the equivalent of the Python expression ``o1 / o2``.
@@ -177,8 +177,8 @@ Number Protocol
Return a reasonable approximation for the mathematical value of *o1* divided by
*o2*, or ``NULL`` on failure. The return value is "approximate" because binary
- floating point numbers are approximate; it is not possible to represent all real
- numbers in base two. This function can return a floating point value when
+ floating-point numbers are approximate; it is not possible to represent all real
+ numbers in base two. This function can return a floating-point value when
passed two integers. The operation is done *in-place* when *o1* supports it.
This is the equivalent of the Python statement ``o1 /= o2``.
diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst
index 8eeac3fc8a1..630114a4339 100644
--- a/Doc/c-api/object.rst
+++ b/Doc/c-api/object.rst
@@ -52,6 +52,7 @@ Object Protocol
The reference is borrowed from the interpreter, and is valid until the
interpreter finalization.
+
.. versionadded:: 3.13
@@ -205,6 +206,13 @@ Object Protocol
If *v* is ``NULL``, the attribute is deleted, but this feature is
deprecated in favour of using :c:func:`PyObject_DelAttrString`.
+ The number of different attribute names passed to this function
+ should be kept small, usually by using a statically allocated string
+ as *attr_name*.
+ For attribute names that aren't known at compile time, prefer calling
+ :c:func:`PyUnicode_FromString` and :c:func:`PyObject_SetAttr` directly.
+ For more details, see :c:func:`PyUnicode_InternFromString`, which may be
+ used internally to create a key object.
.. c:function:: int PyObject_GenericSetAttr(PyObject *o, PyObject *name, PyObject *value)
@@ -230,6 +238,14 @@ Object Protocol
specified as a :c:expr:`const char*` UTF-8 encoded bytes string,
rather than a :c:expr:`PyObject*`.
+ The number of different attribute names passed to this function
+ should be kept small, usually by using a statically allocated string
+ as *attr_name*.
+ For attribute names that aren't known at compile time, prefer calling
+ :c:func:`PyUnicode_FromString` and :c:func:`PyObject_DelAttr` directly.
+ For more details, see :c:func:`PyUnicode_InternFromString`, which may be
+ used internally to create a key object for lookup.
+
.. c:function:: PyObject* PyObject_GenericGetDict(PyObject *o, void *context)
@@ -351,14 +367,14 @@ Object Protocol
The result will be ``1`` when at least one of the checks returns ``1``,
otherwise it will be ``0``.
- If *cls* has a :meth:`~class.__subclasscheck__` method, it will be called to
+ If *cls* has a :meth:`~type.__subclasscheck__` method, it will be called to
determine the subclass status as described in :pep:`3119`. Otherwise,
*derived* is a subclass of *cls* if it is a direct or indirect subclass,
- i.e. contained in ``cls.__mro__``.
+ i.e. contained in :attr:`cls.__mro__ `.
Normally only class objects, i.e. instances of :class:`type` or a derived
class, are considered classes. However, objects can override this by having
- a :attr:`~class.__bases__` attribute (which must be a tuple of base classes).
+ a :attr:`~type.__bases__` attribute (which must be a tuple of base classes).
.. c:function:: int PyObject_IsInstance(PyObject *inst, PyObject *cls)
@@ -370,15 +386,15 @@ Object Protocol
The result will be ``1`` when at least one of the checks returns ``1``,
otherwise it will be ``0``.
- If *cls* has a :meth:`~class.__instancecheck__` method, it will be called to
+ If *cls* has a :meth:`~type.__instancecheck__` method, it will be called to
determine the subclass status as described in :pep:`3119`. Otherwise, *inst*
is an instance of *cls* if its class is a subclass of *cls*.
An instance *inst* can override what is considered its class by having a
- :attr:`~instance.__class__` attribute.
+ :attr:`~object.__class__` attribute.
An object *cls* can override if it is considered a class, and what its base
- classes are, by having a :attr:`~class.__bases__` attribute (which must be a tuple
+ classes are, by having a :attr:`~type.__bases__` attribute (which must be a tuple
of base classes).
diff --git a/Doc/c-api/refcounting.rst b/Doc/c-api/refcounting.rst
index bf50107347e..d75dad737bc 100644
--- a/Doc/c-api/refcounting.rst
+++ b/Doc/c-api/refcounting.rst
@@ -62,7 +62,7 @@ of Python objects.
``NULL``, use :c:func:`Py_XINCREF`.
Do not expect this function to actually modify *o* in any way.
- For at least `some objects `_,
+ For at least :pep:`some objects <0683>`,
this function has no effect.
.. versionchanged:: 3.12
@@ -130,7 +130,7 @@ of Python objects.
use :c:func:`Py_XDECREF`.
Do not expect this function to actually modify *o* in any way.
- For at least `some objects `_,
+ For at least :pep:`some objects <683>`,
this function has no effect.
.. warning::
diff --git a/Doc/c-api/slice.rst b/Doc/c-api/slice.rst
index 27a1757c745..8adf6a96137 100644
--- a/Doc/c-api/slice.rst
+++ b/Doc/c-api/slice.rst
@@ -23,7 +23,9 @@ Slice Objects
Return a new slice object with the given values. The *start*, *stop*, and
*step* parameters are used as the values of the slice object attributes of
the same names. Any of the values may be ``NULL``, in which case the
- ``None`` will be used for the corresponding attribute. Return ``NULL`` if
+ ``None`` will be used for the corresponding attribute.
+
+ Return ``NULL`` with an exception set if
the new object could not be allocated.
@@ -52,7 +54,7 @@ Slice Objects
of bounds indices are clipped in a manner consistent with the handling of
normal slices.
- Returns ``0`` on success and ``-1`` on error with exception set.
+ Return ``0`` on success and ``-1`` on error with an exception set.
.. note::
This function is considered not safe for resizable sequences.
@@ -95,7 +97,7 @@ Slice Objects
``PY_SSIZE_T_MIN`` to ``PY_SSIZE_T_MIN``, and silently boost the step
values less than ``-PY_SSIZE_T_MAX`` to ``-PY_SSIZE_T_MAX``.
- Return ``-1`` on error, ``0`` on success.
+ Return ``-1`` with an exception set on error, ``0`` on success.
.. versionadded:: 3.6.1
diff --git a/Doc/c-api/time.rst b/Doc/c-api/time.rst
index 5cfdef71b3e..7032cc48aa6 100644
--- a/Doc/c-api/time.rst
+++ b/Doc/c-api/time.rst
@@ -1,5 +1,7 @@
.. highlight:: c
+.. _c-api-time:
+
PyTime C API
============
diff --git a/Doc/c-api/tuple.rst b/Doc/c-api/tuple.rst
index 0d68a360f34..a2c3a75daa6 100644
--- a/Doc/c-api/tuple.rst
+++ b/Doc/c-api/tuple.rst
@@ -33,12 +33,14 @@ Tuple Objects
.. c:function:: PyObject* PyTuple_New(Py_ssize_t len)
- Return a new tuple object of size *len*, or ``NULL`` on failure.
+ Return a new tuple object of size *len*,
+ or ``NULL`` with an exception set on failure.
.. c:function:: PyObject* PyTuple_Pack(Py_ssize_t n, ...)
- Return a new tuple object of size *n*, or ``NULL`` on failure. The tuple values
+ Return a new tuple object of size *n*,
+ or ``NULL`` with an exception set on failure. The tuple values
are initialized to the subsequent *n* C arguments pointing to Python objects.
``PyTuple_Pack(2, a, b)`` is equivalent to ``Py_BuildValue("(OO)", a, b)``.
@@ -46,12 +48,12 @@ Tuple Objects
.. c:function:: Py_ssize_t PyTuple_Size(PyObject *p)
Take a pointer to a tuple object, and return the size of that tuple.
+ On error, return ``-1`` and with an exception set.
.. c:function:: Py_ssize_t PyTuple_GET_SIZE(PyObject *p)
- Return the size of the tuple *p*, which must be non-``NULL`` and point to a tuple;
- no error checking is performed.
+ Like :c:func:`PyTuple_Size`, but without error checking.
.. c:function:: PyObject* PyTuple_GetItem(PyObject *p, Py_ssize_t pos)
@@ -74,8 +76,10 @@ Tuple Objects
.. c:function:: PyObject* PyTuple_GetSlice(PyObject *p, Py_ssize_t low, Py_ssize_t high)
Return the slice of the tuple pointed to by *p* between *low* and *high*,
- or ``NULL`` on failure. This is the equivalent of the Python expression
- ``p[low:high]``. Indexing from the end of the tuple is not supported.
+ or ``NULL`` with an exception set on failure.
+
+ This is the equivalent of the Python expression ``p[low:high]``.
+ Indexing from the end of the tuple is not supported.
.. c:function:: int PyTuple_SetItem(PyObject *p, Py_ssize_t pos, PyObject *o)
@@ -135,6 +139,8 @@ type.
Create a new struct sequence type from the data in *desc*, described below. Instances
of the resulting type can be created with :c:func:`PyStructSequence_New`.
+ Return ``NULL`` with an exception set on failure.
+
.. c:function:: void PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
@@ -143,8 +149,8 @@ type.
.. c:function:: int PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc)
- The same as ``PyStructSequence_InitType``, but returns ``0`` on success and ``-1`` on
- failure.
+ Like :c:func:`PyStructSequence_InitType`, but returns ``0`` on success
+ and ``-1`` with an exception set on failure.
.. versionadded:: 3.4
@@ -201,6 +207,8 @@ type.
Creates an instance of *type*, which must have been created with
:c:func:`PyStructSequence_NewType`.
+ Return ``NULL`` with an exception set on failure.
+
.. c:function:: PyObject* PyStructSequence_GetItem(PyObject *p, Py_ssize_t pos)
diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst
index 0cae5c09505..2a18733138d 100644
--- a/Doc/c-api/type.rst
+++ b/Doc/c-api/type.rst
@@ -53,7 +53,8 @@ Type Objects
.. c:function:: PyObject* PyType_GetDict(PyTypeObject* type)
Return the type object's internal namespace, which is otherwise only
- exposed via a read-only proxy (``cls.__dict__``). This is a
+ exposed via a read-only proxy (:attr:`cls.__dict__ `).
+ This is a
replacement for accessing :c:member:`~PyTypeObject.tp_dict` directly.
The returned dictionary must be treated as read-only.
@@ -140,7 +141,7 @@ Type Objects
Return true if *a* is a subtype of *b*.
This function only checks for actual subtypes, which means that
- :meth:`~class.__subclasscheck__` is not called on *b*. Call
+ :meth:`~type.__subclasscheck__` is not called on *b*. Call
:c:func:`PyObject_IsSubclass` to do the same check that :func:`issubclass`
would do.
@@ -174,29 +175,30 @@ Type Objects
.. c:function:: PyObject* PyType_GetName(PyTypeObject *type)
- Return the type's name. Equivalent to getting the type's ``__name__`` attribute.
+ Return the type's name. Equivalent to getting the type's
+ :attr:`~type.__name__` attribute.
.. versionadded:: 3.11
.. c:function:: PyObject* PyType_GetQualName(PyTypeObject *type)
Return the type's qualified name. Equivalent to getting the
- type's ``__qualname__`` attribute.
+ type's :attr:`~type.__qualname__` attribute.
.. versionadded:: 3.11
.. c:function:: PyObject* PyType_GetFullyQualifiedName(PyTypeObject *type)
Return the type's fully qualified name. Equivalent to
- ``f"{type.__module__}.{type.__qualname__}"``, or ``type.__qualname__`` if
- ``type.__module__`` is not a string or is equal to ``"builtins"``.
+ ``f"{type.__module__}.{type.__qualname__}"``, or :attr:`type.__qualname__`
+ if :attr:`type.__module__` is not a string or is equal to ``"builtins"``.
.. versionadded:: 3.13
.. c:function:: PyObject* PyType_GetModuleName(PyTypeObject *type)
- Return the type's module name. Equivalent to getting the ``type.__module__``
- attribute.
+ Return the type's module name. Equivalent to getting the
+ :attr:`type.__module__` attribute.
.. versionadded:: 3.13
diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst
index c9ef076c78c..be3effb0efe 100644
--- a/Doc/c-api/typeobj.rst
+++ b/Doc/c-api/typeobj.rst
@@ -567,12 +567,12 @@ and :c:data:`PyType_Type` effectively act as defaults.)
For :ref:`statically allocated type objects `,
the *tp_name* field should contain a dot.
- Everything before the last dot is made accessible as the :attr:`__module__`
+ Everything before the last dot is made accessible as the :attr:`~type.__module__`
attribute, and everything after the last dot is made accessible as the
- :attr:`~definition.__name__` attribute.
+ :attr:`~type.__name__` attribute.
If no dot is present, the entire :c:member:`~PyTypeObject.tp_name` field is made accessible as the
- :attr:`~definition.__name__` attribute, and the :attr:`__module__` attribute is undefined
+ :attr:`~type.__name__` attribute, and the :attr:`~type.__module__` attribute is undefined
(unless explicitly set in the dictionary, as explained above). This means your
type will be impossible to pickle. Additionally, it will not be listed in
module documentations created with pydoc.
@@ -1131,7 +1131,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 ``__dict__``
+ This bit indicates that instances of the class have a `~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.
@@ -1335,8 +1335,8 @@ and :c:data:`PyType_Type` effectively act as defaults.)
.. c:member:: const char* PyTypeObject.tp_doc
An optional pointer to a NUL-terminated C string giving the docstring for this
- type object. This is exposed as the :attr:`__doc__` attribute on the type and
- instances of the type.
+ type object. This is exposed as the :attr:`~type.__doc__` attribute on the
+ type and instances of the type.
**Inheritance:**
@@ -1592,7 +1592,7 @@ and :c:data:`PyType_Type` effectively act as defaults.)
weak references to the type object itself.
It is an error to set both the :c:macro:`Py_TPFLAGS_MANAGED_WEAKREF` bit and
- :c:member:`~PyTypeObject.tp_weaklist`.
+ :c:member:`~PyTypeObject.tp_weaklistoffset`.
**Inheritance:**
@@ -1604,7 +1604,7 @@ and :c:data:`PyType_Type` effectively act as defaults.)
**Default:**
If the :c:macro:`Py_TPFLAGS_MANAGED_WEAKREF` bit is set in the
- :c:member:`~PyTypeObject.tp_dict` field, then
+ :c:member:`~PyTypeObject.tp_flags` field, then
:c:member:`~PyTypeObject.tp_weaklistoffset` will be set to a negative value,
to indicate that it is unsafe to use this field.
@@ -2036,7 +2036,7 @@ and :c:data:`PyType_Type` effectively act as defaults.)
A collection of subclasses. Internal use only. May be an invalid pointer.
To get a list of subclasses, call the Python method
- :py:meth:`~class.__subclasses__`.
+ :py:meth:`~type.__subclasses__`.
.. versionchanged:: 3.12
diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
index 7320d035bab..d0a1b9ca126 100644
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -317,7 +317,7 @@ These APIs can be used to work with surrogates:
.. c:function:: Py_UCS4 Py_UNICODE_JOIN_SURROGATES(Py_UCS4 high, Py_UCS4 low)
- Join two surrogate characters and return a single :c:type:`Py_UCS4` value.
+ Join two surrogate code points and return a single :c:type:`Py_UCS4` value.
*high* and *low* are respectively the leading and trailing surrogates in a
surrogate pair. *high* must be in the range [0xD800; 0xDBFF] and *low* must
be in the range [0xDC00; 0xDFFF].
@@ -338,6 +338,8 @@ APIs:
This is the recommended way to allocate a new Unicode object. Objects
created using this function are not resizable.
+ On error, set an exception and return ``NULL``.
+
.. versionadded:: 3.3
@@ -614,6 +616,8 @@ APIs:
Return the length of the Unicode object, in code points.
+ On error, set an exception and return ``-1``.
+
.. versionadded:: 3.3
@@ -657,6 +661,8 @@ APIs:
not out of bounds, and that the object can be modified safely (i.e. that it
its reference count is one).
+ Return ``0`` on success, ``-1`` on error with an exception set.
+
.. versionadded:: 3.3
@@ -666,6 +672,8 @@ APIs:
Unicode object and the index is not out of bounds, in contrast to
:c:func:`PyUnicode_READ_CHAR`, which performs no error checking.
+ Return character on success, ``-1`` on error with an exception set.
+
.. versionadded:: 3.3
@@ -674,6 +682,7 @@ APIs:
Return a substring of *unicode*, from character index *start* (included) to
character index *end* (excluded). Negative indices are not supported.
+ On error, set an exception and return ``NULL``.
.. versionadded:: 3.3
@@ -990,6 +999,9 @@ These are the UTF-8 codec APIs:
object. Error handling is "strict". Return ``NULL`` if an exception was
raised by the codec.
+ The function fails if the string contains surrogate code points
+ (``U+D800`` - ``U+DFFF``).
+
.. c:function:: const char* PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *size)
@@ -1002,6 +1014,9 @@ These are the UTF-8 codec APIs:
On error, set an exception, set *size* to ``-1`` (if it's not NULL) and
return ``NULL``.
+ The function fails if the string contains surrogate code points
+ (``U+D800`` - ``U+DFFF``).
+
This caches the UTF-8 representation of the string in the Unicode object, and
subsequent calls will return a pointer to the same buffer. The caller is not
responsible for deallocating the buffer. The buffer is deallocated and
@@ -1429,8 +1444,9 @@ They all return ``NULL`` or ``-1`` if an exception occurs.
Compare a Unicode object with a char buffer which is interpreted as
being UTF-8 or ASCII encoded and return true (``1``) if they are equal,
or false (``0``) otherwise.
- If the Unicode object contains surrogate characters or
- the C string is not valid UTF-8, false (``0``) is returned.
+ If the Unicode object contains surrogate code points
+ (``U+D800`` - ``U+DFFF``) or the C string is not valid UTF-8,
+ false (``0``) is returned.
This function does not raise exceptions.
@@ -1490,15 +1506,41 @@ They all return ``NULL`` or ``-1`` if an exception occurs.
existing interned string that is the same as :c:expr:`*p_unicode`, it sets :c:expr:`*p_unicode` to
it (releasing the reference to the old string object and creating a new
:term:`strong reference` to the interned string object), otherwise it leaves
- :c:expr:`*p_unicode` alone and interns it (creating a new :term:`strong reference`).
+ :c:expr:`*p_unicode` alone and interns it.
+
(Clarification: even though there is a lot of talk about references, think
- of this function as reference-neutral; you own the object after the call
- if and only if you owned it before the call.)
+ of this function as reference-neutral. You must own the object you pass in;
+ after the call you no longer own the passed-in reference, but you newly own
+ the result.)
+
+ This function never raises an exception.
+ On error, it leaves its argument unchanged without interning it.
+
+ Instances of subclasses of :py:class:`str` may not be interned, that is,
+ :c:expr:`PyUnicode_CheckExact(*p_unicode)` must be true. If it is not,
+ then -- as with any other error -- the argument is left unchanged.
+
+ Note that interned strings are not “immortal”.
+ You must keep a reference to the result to benefit from interning.
.. c:function:: PyObject* PyUnicode_InternFromString(const char *str)
A combination of :c:func:`PyUnicode_FromString` and
- :c:func:`PyUnicode_InternInPlace`, returning either a new Unicode string
- object that has been interned, or a new ("owned") reference to an earlier
- interned string object with the same value.
+ :c:func:`PyUnicode_InternInPlace`, meant for statically allocated strings.
+
+ Return a new ("owned") reference to either a new Unicode string object
+ that has been interned, or an earlier interned string object with the
+ same value.
+
+ Python may keep a reference to the result, or make it :term:`immortal`,
+ preventing it from being garbage-collected promptly.
+ For interning an unbounded number of different strings, such as ones coming
+ 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`.
+
+
diff --git a/Doc/conf.py b/Doc/conf.py
index 8a14646801e..5f22340ac43 100644
--- a/Doc/conf.py
+++ b/Doc/conf.py
@@ -6,9 +6,11 @@
# The contents of this file are pickled, so don't put values in the namespace
# that aren't pickleable (module imports are okay, they're removed automatically).
+import importlib
import os
import sys
import time
+
sys.path.append(os.path.abspath('tools/extensions'))
sys.path.append(os.path.abspath('includes'))
@@ -18,11 +20,10 @@
# ---------------------
extensions = [
- 'asdl_highlight',
+ 'audit_events',
'c_annotations',
- 'escape4chm',
'glossary_search',
- 'peg_highlight',
+ 'lexers',
'pyspecific',
'sphinx.ext.coverage',
'sphinx.ext.doctest',
@@ -31,13 +32,13 @@
# Skip if downstream redistributors haven't installed them
try:
- import notfound.extension
+ import notfound.extension # noqa: F401
except ImportError:
pass
else:
extensions.append('notfound.extension')
try:
- import sphinxext.opengraph
+ import sphinxext.opengraph # noqa: F401
except ImportError:
pass
else:
@@ -64,8 +65,8 @@
# We look for the Include/patchlevel.h file in the current Python source tree
# and replace the values accordingly.
-import patchlevel
-version, release = patchlevel.get_version_info()
+# See Doc/tools/extensions/patchlevel.py
+version, release = importlib.import_module('patchlevel').get_version_info()
rst_epilog = f"""
.. |python_version_literal| replace:: ``Python {version}``
@@ -83,7 +84,7 @@
highlight_language = 'python3'
# Minimum version of sphinx required
-needs_sphinx = '4.2'
+needs_sphinx = '6.2.1'
# Create table of contents entries for domain objects (e.g. functions, classes,
# attributes, etc.). Default is True.
@@ -131,6 +132,8 @@
('c:func', 'vsnprintf'),
# Standard C types
('c:type', 'FILE'),
+ ('c:type', 'int8_t'),
+ ('c:type', 'int16_t'),
('c:type', 'int32_t'),
('c:type', 'int64_t'),
('c:type', 'intmax_t'),
@@ -140,6 +143,9 @@
('c:type', 'size_t'),
('c:type', 'ssize_t'),
('c:type', 'time_t'),
+ ('c:type', 'uint8_t'),
+ ('c:type', 'uint16_t'),
+ ('c:type', 'uint32_t'),
('c:type', 'uint64_t'),
('c:type', 'uintmax_t'),
('c:type', 'uintptr_t'),
@@ -242,6 +248,7 @@
('c:data', 'PyExc_OverflowError'),
('c:data', 'PyExc_PermissionError'),
('c:data', 'PyExc_ProcessLookupError'),
+ ('c:data', 'PyExc_PythonFinalizationError'),
('c:data', 'PyExc_RecursionError'),
('c:data', 'PyExc_ReferenceError'),
('c:data', 'PyExc_RuntimeError'),
@@ -272,6 +279,9 @@
('c:data', 'PyExc_UnicodeWarning'),
('c:data', 'PyExc_UserWarning'),
('c:data', 'PyExc_Warning'),
+ # Undocumented public C macros
+ ('c:macro', 'Py_BUILD_ASSERT'),
+ ('c:macro', 'Py_BUILD_ASSERT_EXPR'),
# Do not error nit-picky mode builds when _SubParsersAction.add_parser cannot
# be resolved, as the method is currently undocumented. For context, see
# https://github.com/python/cpython/pull/103289.
@@ -296,7 +306,8 @@
# Disable Docutils smartquotes for several translations
smartquotes_excludes = {
- 'languages': ['ja', 'fr', 'zh_TW', 'zh_CN'], 'builders': ['man', 'text'],
+ 'languages': ['ja', 'fr', 'zh_TW', 'zh_CN'],
+ 'builders': ['man', 'text'],
}
# Avoid a warning with Sphinx >= 4.0
@@ -305,6 +316,7 @@
# Allow translation of index directives
gettext_additional_targets = [
'index',
+ 'literal-block',
]
# Options for HTML output
@@ -317,11 +329,13 @@
'collapsiblesidebar': True,
'issues_url': '/bugs.html',
'license_url': '/license.html',
- 'root_include_title': False # We use the version switcher instead.
+ 'root_include_title': False, # We use the version switcher instead.
}
if os.getenv("READTHEDOCS"):
- html_theme_options["hosted_on"] = 'Read the Docs'
+ html_theme_options["hosted_on"] = (
+ 'Read the Docs'
+ )
# Override stylesheet fingerprinting for Windows CHM htmlhelp to fix GH-91207
# https://github.com/python/cpython/issues/91207
@@ -335,16 +349,21 @@
# Deployment preview information
# (See .readthedocs.yml and https://docs.readthedocs.io/en/stable/reference/environment-variables.html)
-repository_url = os.getenv("READTHEDOCS_GIT_CLONE_URL")
+is_deployment_preview = os.getenv("READTHEDOCS_VERSION_TYPE") == "external"
+repository_url = os.getenv("READTHEDOCS_GIT_CLONE_URL", "")
+repository_url = repository_url.removesuffix(".git")
html_context = {
- "is_deployment_preview": os.getenv("READTHEDOCS_VERSION_TYPE") == "external",
- "repository_url": repository_url.removesuffix(".git") if repository_url else None,
+ "is_deployment_preview": is_deployment_preview,
+ "repository_url": repository_url or None,
"pr_id": os.getenv("READTHEDOCS_VERSION"),
"enable_analytics": os.getenv("PYTHON_DOCS_ENABLE_ANALYTICS"),
}
# This 'Last updated on:' timestamp is inserted at the bottom of every page.
-html_last_updated_fmt = time.strftime('%b %d, %Y (%H:%M UTC)', time.gmtime())
+html_time = int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))
+html_last_updated_fmt = time.strftime(
+ '%b %d, %Y (%H:%M UTC)', time.gmtime(html_time)
+)
# Path to find HTML templates.
templates_path = ['tools/templates']
@@ -394,8 +413,8 @@
\let\endVerbatim=\endOriginalVerbatim
\setcounter{tocdepth}{2}
''',
- # The paper size ('letter' or 'a4').
- 'papersize': 'a4',
+ # The paper size ('letterpaper' or 'a4paper').
+ 'papersize': 'a4paper',
# The font size ('10pt', '11pt' or '12pt').
'pointsize': '10pt',
}
@@ -404,30 +423,70 @@
# (source start file, target name, title, author, document class [howto/manual]).
_stdauthor = 'Guido van Rossum and the Python development team'
latex_documents = [
- ('c-api/index', 'c-api.tex',
- 'The Python/C API', _stdauthor, 'manual'),
- ('extending/index', 'extending.tex',
- 'Extending and Embedding Python', _stdauthor, 'manual'),
- ('installing/index', 'installing.tex',
- 'Installing Python Modules', _stdauthor, 'manual'),
- ('library/index', 'library.tex',
- 'The Python Library Reference', _stdauthor, 'manual'),
- ('reference/index', 'reference.tex',
- 'The Python Language Reference', _stdauthor, 'manual'),
- ('tutorial/index', 'tutorial.tex',
- 'Python Tutorial', _stdauthor, 'manual'),
- ('using/index', 'using.tex',
- 'Python Setup and Usage', _stdauthor, 'manual'),
- ('faq/index', 'faq.tex',
- 'Python Frequently Asked Questions', _stdauthor, 'manual'),
- ('whatsnew/' + version, 'whatsnew.tex',
- 'What\'s New in Python', 'A. M. Kuchling', 'howto'),
+ ('c-api/index', 'c-api.tex', 'The Python/C API', _stdauthor, 'manual'),
+ (
+ 'extending/index',
+ 'extending.tex',
+ 'Extending and Embedding Python',
+ _stdauthor,
+ 'manual',
+ ),
+ (
+ 'installing/index',
+ 'installing.tex',
+ 'Installing Python Modules',
+ _stdauthor,
+ 'manual',
+ ),
+ (
+ 'library/index',
+ 'library.tex',
+ 'The Python Library Reference',
+ _stdauthor,
+ 'manual',
+ ),
+ (
+ 'reference/index',
+ 'reference.tex',
+ 'The Python Language Reference',
+ _stdauthor,
+ 'manual',
+ ),
+ (
+ 'tutorial/index',
+ 'tutorial.tex',
+ 'Python Tutorial',
+ _stdauthor,
+ 'manual',
+ ),
+ (
+ 'using/index',
+ 'using.tex',
+ 'Python Setup and Usage',
+ _stdauthor,
+ 'manual',
+ ),
+ (
+ 'faq/index',
+ 'faq.tex',
+ 'Python Frequently Asked Questions',
+ _stdauthor,
+ 'manual',
+ ),
+ (
+ 'whatsnew/' + version,
+ 'whatsnew.tex',
+ 'What\'s New in Python',
+ 'A. M. Kuchling',
+ 'howto',
+ ),
]
# Collect all HOWTOs individually
-latex_documents.extend(('howto/' + fn[:-4], 'howto-' + fn[:-4] + '.tex',
- '', _stdauthor, 'howto')
- for fn in os.listdir('howto')
- if fn.endswith('.rst') and fn != 'index.rst')
+latex_documents.extend(
+ ('howto/' + fn[:-4], 'howto-' + fn[:-4] + '.tex', '', _stdauthor, 'howto')
+ for fn in os.listdir('howto')
+ if fn.endswith('.rst') and fn != 'index.rst'
+)
# Documents to append as an appendix to all manuals.
latex_appendices = ['glossary', 'about', 'license', 'copyright']
@@ -455,8 +514,7 @@
'test($|_)',
]
-coverage_ignore_classes = [
-]
+coverage_ignore_classes = []
# Glob patterns for C source files for C API coverage, relative to this directory.
coverage_c_path = [
@@ -473,7 +531,7 @@
# The coverage checker will ignore all C items whose names match these regexes
# (using re.match) -- the keys must be the same as in coverage_c_regexes.
coverage_ignore_c_items = {
-# 'cfunction': [...]
+ # 'cfunction': [...]
}
@@ -495,9 +553,15 @@
r'https://msdn.microsoft.com/.*': 'https://learn.microsoft.com/.*',
r'https://docs.microsoft.com/.*': 'https://learn.microsoft.com/.*',
r'https://go.microsoft.com/fwlink/\?LinkID=\d+': 'https://learn.microsoft.com/.*',
+ # Debian's man page redirects to its current stable version
+ r'https://manpages.debian.org/\w+\(\d(\w+)?\)': r'https://manpages.debian.org/\w+/[\w/\-\.]*\.\d(\w+)?\.en\.html',
# Language redirects
r'https://toml.io': 'https://toml.io/en/',
r'https://www.redhat.com': 'https://www.redhat.com/en',
+ # pypi.org project name normalization (upper to lowercase, underscore to hyphen)
+ r'https://pypi.org/project/[A-Za-z\d_\-\.]+/': r'https://pypi.org/project/[a-z\d\-\.]+/',
+ # Discourse title name expansion (text changes when title is edited)
+ r'https://discuss\.python\.org/t/\d+': r'https://discuss\.python\.org/t/.*/\d+',
# Other redirects
r'https://www.boost.org/libs/.+': r'https://www.boost.org/doc/libs/\d_\d+_\d/.+',
r'https://support.microsoft.com/en-us/help/\d+': 'https://support.microsoft.com/en-us/topic/.+',
@@ -538,14 +602,16 @@
}
extlinks_detect_hardcoded_links = True
-# Options for extensions
-# ----------------------
+# Options for c_annotations
+# -------------------------
# Relative filename of the data files
refcount_file = 'data/refcounts.dat'
stable_abi_file = 'data/stable_abi.dat'
-# sphinxext-opengraph config
+# Options for sphinxext-opengraph
+# -------------------------------
+
ogp_site_url = 'https://docs.python.org/3/'
ogp_site_name = 'Python documentation'
ogp_image = '_static/og-image.png'
diff --git a/Doc/constraints.txt b/Doc/constraints.txt
index 147de1271eb..26ac1862dba 100644
--- a/Doc/constraints.txt
+++ b/Doc/constraints.txt
@@ -7,18 +7,20 @@
# Direct dependencies of Sphinx
babel<3
colorama<0.5
-imagesize<1.5
-Jinja2<3.2
-packaging<24
-Pygments>=2.16.1,<3
+imagesize<2
+Jinja2<4
+packaging<25
+Pygments<3
requests<3
snowballstemmer<3
-sphinxcontrib-applehelp<1.1
-sphinxcontrib-devhelp<1.1
-sphinxcontrib-htmlhelp<2.1
-sphinxcontrib-jsmath<1.1
-sphinxcontrib-qthelp<1.1
-sphinxcontrib-serializinghtml<1.2
+# keep lower-bounds until Sphinx 8.1 is released
+# https://github.com/sphinx-doc/sphinx/pull/12756
+sphinxcontrib-applehelp>=1.0.7,<3
+sphinxcontrib-devhelp>=1.0.6,<3
+sphinxcontrib-htmlhelp>=2.0.6,<3
+sphinxcontrib-jsmath>=1.0.1,<2
+sphinxcontrib-qthelp>=1.0.6,<3
+sphinxcontrib-serializinghtml>=1.1.9,<3
# Direct dependencies of Jinja2 (Jinja is a dependency of Sphinx, see above)
-MarkupSafe<2.2
+MarkupSafe<3
diff --git a/Doc/contents.rst b/Doc/contents.rst
index 24ceacb0076..b57f4b09a5d 100644
--- a/Doc/contents.rst
+++ b/Doc/contents.rst
@@ -14,6 +14,7 @@
installing/index.rst
howto/index.rst
faq/index.rst
+ deprecations/index.rst
glossary.rst
about.rst
diff --git a/Doc/data/python3.13.abi b/Doc/data/python3.13.abi
new file mode 100644
index 00000000000..55112e1e43c
--- /dev/null
+++ b/Doc/data/python3.13.abi
@@ -0,0 +1,29385 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat
index 9c17223a49a..75bc5ea9456 100644
--- a/Doc/data/stable_abi.dat
+++ b/Doc/data/stable_abi.dat
@@ -1,887 +1,887 @@
role,name,added,ifdef_note,struct_abi_kind
macro,PY_VECTORCALL_ARGUMENTS_OFFSET,3.12,,
-function,PyAIter_Check,3.10,,
-function,PyArg_Parse,3.2,,
-function,PyArg_ParseTuple,3.2,,
-function,PyArg_ParseTupleAndKeywords,3.2,,
-function,PyArg_UnpackTuple,3.2,,
-function,PyArg_VaParse,3.2,,
-function,PyArg_VaParseTupleAndKeywords,3.2,,
-function,PyArg_ValidateKeywordArguments,3.2,,
-var,PyBaseObject_Type,3.2,,
-function,PyBool_FromLong,3.2,,
-var,PyBool_Type,3.2,,
-function,PyBuffer_FillContiguousStrides,3.11,,
-function,PyBuffer_FillInfo,3.11,,
-function,PyBuffer_FromContiguous,3.11,,
-function,PyBuffer_GetPointer,3.11,,
-function,PyBuffer_IsContiguous,3.11,,
-function,PyBuffer_Release,3.11,,
-function,PyBuffer_SizeFromFormat,3.11,,
-function,PyBuffer_ToContiguous,3.11,,
-var,PyByteArrayIter_Type,3.2,,
-function,PyByteArray_AsString,3.2,,
-function,PyByteArray_Concat,3.2,,
-function,PyByteArray_FromObject,3.2,,
-function,PyByteArray_FromStringAndSize,3.2,,
-function,PyByteArray_Resize,3.2,,
-function,PyByteArray_Size,3.2,,
-var,PyByteArray_Type,3.2,,
-var,PyBytesIter_Type,3.2,,
-function,PyBytes_AsString,3.2,,
-function,PyBytes_AsStringAndSize,3.2,,
-function,PyBytes_Concat,3.2,,
-function,PyBytes_ConcatAndDel,3.2,,
-function,PyBytes_DecodeEscape,3.2,,
-function,PyBytes_FromFormat,3.2,,
-function,PyBytes_FromFormatV,3.2,,
-function,PyBytes_FromObject,3.2,,
-function,PyBytes_FromString,3.2,,
-function,PyBytes_FromStringAndSize,3.2,,
-function,PyBytes_Repr,3.2,,
-function,PyBytes_Size,3.2,,
-var,PyBytes_Type,3.2,,
+func,PyAIter_Check,3.10,,
+func,PyArg_Parse,3.2,,
+func,PyArg_ParseTuple,3.2,,
+func,PyArg_ParseTupleAndKeywords,3.2,,
+func,PyArg_UnpackTuple,3.2,,
+func,PyArg_VaParse,3.2,,
+func,PyArg_VaParseTupleAndKeywords,3.2,,
+func,PyArg_ValidateKeywordArguments,3.2,,
+data,PyBaseObject_Type,3.2,,
+func,PyBool_FromLong,3.2,,
+data,PyBool_Type,3.2,,
+func,PyBuffer_FillContiguousStrides,3.11,,
+func,PyBuffer_FillInfo,3.11,,
+func,PyBuffer_FromContiguous,3.11,,
+func,PyBuffer_GetPointer,3.11,,
+func,PyBuffer_IsContiguous,3.11,,
+func,PyBuffer_Release,3.11,,
+func,PyBuffer_SizeFromFormat,3.11,,
+func,PyBuffer_ToContiguous,3.11,,
+data,PyByteArrayIter_Type,3.2,,
+func,PyByteArray_AsString,3.2,,
+func,PyByteArray_Concat,3.2,,
+func,PyByteArray_FromObject,3.2,,
+func,PyByteArray_FromStringAndSize,3.2,,
+func,PyByteArray_Resize,3.2,,
+func,PyByteArray_Size,3.2,,
+data,PyByteArray_Type,3.2,,
+data,PyBytesIter_Type,3.2,,
+func,PyBytes_AsString,3.2,,
+func,PyBytes_AsStringAndSize,3.2,,
+func,PyBytes_Concat,3.2,,
+func,PyBytes_ConcatAndDel,3.2,,
+func,PyBytes_DecodeEscape,3.2,,
+func,PyBytes_FromFormat,3.2,,
+func,PyBytes_FromFormatV,3.2,,
+func,PyBytes_FromObject,3.2,,
+func,PyBytes_FromString,3.2,,
+func,PyBytes_FromStringAndSize,3.2,,
+func,PyBytes_Repr,3.2,,
+func,PyBytes_Size,3.2,,
+data,PyBytes_Type,3.2,,
type,PyCFunction,3.2,,
type,PyCFunctionFast,3.13,,
type,PyCFunctionFastWithKeywords,3.13,,
type,PyCFunctionWithKeywords,3.2,,
-function,PyCFunction_GetFlags,3.2,,
-function,PyCFunction_GetFunction,3.2,,
-function,PyCFunction_GetSelf,3.2,,
-function,PyCFunction_New,3.4,,
-function,PyCFunction_NewEx,3.2,,
-var,PyCFunction_Type,3.2,,
-function,PyCMethod_New,3.9,,
-function,PyCallIter_New,3.2,,
-var,PyCallIter_Type,3.2,,
-function,PyCallable_Check,3.2,,
+func,PyCFunction_GetFlags,3.2,,
+func,PyCFunction_GetFunction,3.2,,
+func,PyCFunction_GetSelf,3.2,,
+func,PyCFunction_New,3.4,,
+func,PyCFunction_NewEx,3.2,,
+data,PyCFunction_Type,3.2,,
+func,PyCMethod_New,3.9,,
+func,PyCallIter_New,3.2,,
+data,PyCallIter_Type,3.2,,
+func,PyCallable_Check,3.2,,
type,PyCapsule_Destructor,3.2,,
-function,PyCapsule_GetContext,3.2,,
-function,PyCapsule_GetDestructor,3.2,,
-function,PyCapsule_GetName,3.2,,
-function,PyCapsule_GetPointer,3.2,,
-function,PyCapsule_Import,3.2,,
-function,PyCapsule_IsValid,3.2,,
-function,PyCapsule_New,3.2,,
-function,PyCapsule_SetContext,3.2,,
-function,PyCapsule_SetDestructor,3.2,,
-function,PyCapsule_SetName,3.2,,
-function,PyCapsule_SetPointer,3.2,,
-var,PyCapsule_Type,3.2,,
-var,PyClassMethodDescr_Type,3.2,,
-function,PyCodec_BackslashReplaceErrors,3.2,,
-function,PyCodec_Decode,3.2,,
-function,PyCodec_Decoder,3.2,,
-function,PyCodec_Encode,3.2,,
-function,PyCodec_Encoder,3.2,,
-function,PyCodec_IgnoreErrors,3.2,,
-function,PyCodec_IncrementalDecoder,3.2,,
-function,PyCodec_IncrementalEncoder,3.2,,
-function,PyCodec_KnownEncoding,3.2,,
-function,PyCodec_LookupError,3.2,,
-function,PyCodec_NameReplaceErrors,3.7,,
-function,PyCodec_Register,3.2,,
-function,PyCodec_RegisterError,3.2,,
-function,PyCodec_ReplaceErrors,3.2,,
-function,PyCodec_StreamReader,3.2,,
-function,PyCodec_StreamWriter,3.2,,
-function,PyCodec_StrictErrors,3.2,,
-function,PyCodec_Unregister,3.10,,
-function,PyCodec_XMLCharRefReplaceErrors,3.2,,
-function,PyComplex_FromDoubles,3.2,,
-function,PyComplex_ImagAsDouble,3.2,,
-function,PyComplex_RealAsDouble,3.2,,
-var,PyComplex_Type,3.2,,
-function,PyDescr_NewClassMethod,3.2,,
-function,PyDescr_NewGetSet,3.2,,
-function,PyDescr_NewMember,3.2,,
-function,PyDescr_NewMethod,3.2,,
-var,PyDictItems_Type,3.2,,
-var,PyDictIterItem_Type,3.2,,
-var,PyDictIterKey_Type,3.2,,
-var,PyDictIterValue_Type,3.2,,
-var,PyDictKeys_Type,3.2,,
-function,PyDictProxy_New,3.2,,
-var,PyDictProxy_Type,3.2,,
-var,PyDictRevIterItem_Type,3.8,,
-var,PyDictRevIterKey_Type,3.8,,
-var,PyDictRevIterValue_Type,3.8,,
-var,PyDictValues_Type,3.2,,
-function,PyDict_Clear,3.2,,
-function,PyDict_Contains,3.2,,
-function,PyDict_Copy,3.2,,
-function,PyDict_DelItem,3.2,,
-function,PyDict_DelItemString,3.2,,
-function,PyDict_GetItem,3.2,,
-function,PyDict_GetItemRef,3.13,,
-function,PyDict_GetItemString,3.2,,
-function,PyDict_GetItemStringRef,3.13,,
-function,PyDict_GetItemWithError,3.2,,
-function,PyDict_Items,3.2,,
-function,PyDict_Keys,3.2,,
-function,PyDict_Merge,3.2,,
-function,PyDict_MergeFromSeq2,3.2,,
-function,PyDict_New,3.2,,
-function,PyDict_Next,3.2,,
-function,PyDict_SetItem,3.2,,
-function,PyDict_SetItemString,3.2,,
-function,PyDict_Size,3.2,,
-var,PyDict_Type,3.2,,
-function,PyDict_Update,3.2,,
-function,PyDict_Values,3.2,,
-var,PyEllipsis_Type,3.2,,
-var,PyEnum_Type,3.2,,
-function,PyErr_BadArgument,3.2,,
-function,PyErr_BadInternalCall,3.2,,
-function,PyErr_CheckSignals,3.2,,
-function,PyErr_Clear,3.2,,
-function,PyErr_Display,3.2,,
-function,PyErr_DisplayException,3.12,,
-function,PyErr_ExceptionMatches,3.2,,
-function,PyErr_Fetch,3.2,,
-function,PyErr_Format,3.2,,
-function,PyErr_FormatV,3.5,,
-function,PyErr_GetExcInfo,3.7,,
-function,PyErr_GetHandledException,3.11,,
-function,PyErr_GetRaisedException,3.12,,
-function,PyErr_GivenExceptionMatches,3.2,,
-function,PyErr_NewException,3.2,,
-function,PyErr_NewExceptionWithDoc,3.2,,
-function,PyErr_NoMemory,3.2,,
-function,PyErr_NormalizeException,3.2,,
-function,PyErr_Occurred,3.2,,
-function,PyErr_Print,3.2,,
-function,PyErr_PrintEx,3.2,,
-function,PyErr_ProgramText,3.2,,
-function,PyErr_ResourceWarning,3.6,,
-function,PyErr_Restore,3.2,,
-function,PyErr_SetExcFromWindowsErr,3.7,on Windows,
-function,PyErr_SetExcFromWindowsErrWithFilename,3.7,on Windows,
-function,PyErr_SetExcFromWindowsErrWithFilenameObject,3.7,on Windows,
-function,PyErr_SetExcFromWindowsErrWithFilenameObjects,3.7,on Windows,
-function,PyErr_SetExcInfo,3.7,,
-function,PyErr_SetFromErrno,3.2,,
-function,PyErr_SetFromErrnoWithFilename,3.2,,
-function,PyErr_SetFromErrnoWithFilenameObject,3.2,,
-function,PyErr_SetFromErrnoWithFilenameObjects,3.7,,
-function,PyErr_SetFromWindowsErr,3.7,on Windows,
-function,PyErr_SetFromWindowsErrWithFilename,3.7,on Windows,
-function,PyErr_SetHandledException,3.11,,
-function,PyErr_SetImportError,3.7,,
-function,PyErr_SetImportErrorSubclass,3.6,,
-function,PyErr_SetInterrupt,3.2,,
-function,PyErr_SetInterruptEx,3.10,,
-function,PyErr_SetNone,3.2,,
-function,PyErr_SetObject,3.2,,
-function,PyErr_SetRaisedException,3.12,,
-function,PyErr_SetString,3.2,,
-function,PyErr_SyntaxLocation,3.2,,
-function,PyErr_SyntaxLocationEx,3.7,,
-function,PyErr_WarnEx,3.2,,
-function,PyErr_WarnExplicit,3.2,,
-function,PyErr_WarnFormat,3.2,,
-function,PyErr_WriteUnraisable,3.2,,
-function,PyEval_AcquireThread,3.2,,
-function,PyEval_EvalCode,3.2,,
-function,PyEval_EvalCodeEx,3.2,,
-function,PyEval_EvalFrame,3.2,,
-function,PyEval_EvalFrameEx,3.2,,
-function,PyEval_GetBuiltins,3.2,,
-function,PyEval_GetFrame,3.2,,
-function,PyEval_GetFrameBuiltins,3.13,,
-function,PyEval_GetFrameGlobals,3.13,,
-function,PyEval_GetFrameLocals,3.13,,
-function,PyEval_GetFuncDesc,3.2,,
-function,PyEval_GetFuncName,3.2,,
-function,PyEval_GetGlobals,3.2,,
-function,PyEval_GetLocals,3.2,,
-function,PyEval_InitThreads,3.2,,
-function,PyEval_ReleaseThread,3.2,,
-function,PyEval_RestoreThread,3.2,,
-function,PyEval_SaveThread,3.2,,
-var,PyExc_ArithmeticError,3.2,,
-var,PyExc_AssertionError,3.2,,
-var,PyExc_AttributeError,3.2,,
-var,PyExc_BaseException,3.2,,
-var,PyExc_BaseExceptionGroup,3.11,,
-var,PyExc_BlockingIOError,3.7,,
-var,PyExc_BrokenPipeError,3.7,,
-var,PyExc_BufferError,3.2,,
-var,PyExc_BytesWarning,3.2,,
-var,PyExc_ChildProcessError,3.7,,
-var,PyExc_ConnectionAbortedError,3.7,,
-var,PyExc_ConnectionError,3.7,,
-var,PyExc_ConnectionRefusedError,3.7,,
-var,PyExc_ConnectionResetError,3.7,,
-var,PyExc_DeprecationWarning,3.2,,
-var,PyExc_EOFError,3.2,,
-var,PyExc_EncodingWarning,3.10,,
-var,PyExc_EnvironmentError,3.2,,
-var,PyExc_Exception,3.2,,
-var,PyExc_FileExistsError,3.7,,
-var,PyExc_FileNotFoundError,3.7,,
-var,PyExc_FloatingPointError,3.2,,
-var,PyExc_FutureWarning,3.2,,
-var,PyExc_GeneratorExit,3.2,,
-var,PyExc_IOError,3.2,,
-var,PyExc_ImportError,3.2,,
-var,PyExc_ImportWarning,3.2,,
-var,PyExc_IndentationError,3.2,,
-var,PyExc_IndexError,3.2,,
-var,PyExc_InterruptedError,3.7,,
-var,PyExc_IsADirectoryError,3.7,,
-var,PyExc_KeyError,3.2,,
-var,PyExc_KeyboardInterrupt,3.2,,
-var,PyExc_LookupError,3.2,,
-var,PyExc_MemoryError,3.2,,
-var,PyExc_ModuleNotFoundError,3.6,,
-var,PyExc_NameError,3.2,,
-var,PyExc_NotADirectoryError,3.7,,
-var,PyExc_NotImplementedError,3.2,,
-var,PyExc_OSError,3.2,,
-var,PyExc_OverflowError,3.2,,
-var,PyExc_PendingDeprecationWarning,3.2,,
-var,PyExc_PermissionError,3.7,,
-var,PyExc_ProcessLookupError,3.7,,
-var,PyExc_RecursionError,3.7,,
-var,PyExc_ReferenceError,3.2,,
-var,PyExc_ResourceWarning,3.7,,
-var,PyExc_RuntimeError,3.2,,
-var,PyExc_RuntimeWarning,3.2,,
-var,PyExc_StopAsyncIteration,3.7,,
-var,PyExc_StopIteration,3.2,,
-var,PyExc_SyntaxError,3.2,,
-var,PyExc_SyntaxWarning,3.2,,
-var,PyExc_SystemError,3.2,,
-var,PyExc_SystemExit,3.2,,
-var,PyExc_TabError,3.2,,
-var,PyExc_TimeoutError,3.7,,
-var,PyExc_TypeError,3.2,,
-var,PyExc_UnboundLocalError,3.2,,
-var,PyExc_UnicodeDecodeError,3.2,,
-var,PyExc_UnicodeEncodeError,3.2,,
-var,PyExc_UnicodeError,3.2,,
-var,PyExc_UnicodeTranslateError,3.2,,
-var,PyExc_UnicodeWarning,3.2,,
-var,PyExc_UserWarning,3.2,,
-var,PyExc_ValueError,3.2,,
-var,PyExc_Warning,3.2,,
-var,PyExc_WindowsError,3.7,on Windows,
-var,PyExc_ZeroDivisionError,3.2,,
-function,PyExceptionClass_Name,3.8,,
-function,PyException_GetArgs,3.12,,
-function,PyException_GetCause,3.2,,
-function,PyException_GetContext,3.2,,
-function,PyException_GetTraceback,3.2,,
-function,PyException_SetArgs,3.12,,
-function,PyException_SetCause,3.2,,
-function,PyException_SetContext,3.2,,
-function,PyException_SetTraceback,3.2,,
-function,PyFile_FromFd,3.2,,
-function,PyFile_GetLine,3.2,,
-function,PyFile_WriteObject,3.2,,
-function,PyFile_WriteString,3.2,,
-var,PyFilter_Type,3.2,,
-function,PyFloat_AsDouble,3.2,,
-function,PyFloat_FromDouble,3.2,,
-function,PyFloat_FromString,3.2,,
-function,PyFloat_GetInfo,3.2,,
-function,PyFloat_GetMax,3.2,,
-function,PyFloat_GetMin,3.2,,
-var,PyFloat_Type,3.2,,
+func,PyCapsule_GetContext,3.2,,
+func,PyCapsule_GetDestructor,3.2,,
+func,PyCapsule_GetName,3.2,,
+func,PyCapsule_GetPointer,3.2,,
+func,PyCapsule_Import,3.2,,
+func,PyCapsule_IsValid,3.2,,
+func,PyCapsule_New,3.2,,
+func,PyCapsule_SetContext,3.2,,
+func,PyCapsule_SetDestructor,3.2,,
+func,PyCapsule_SetName,3.2,,
+func,PyCapsule_SetPointer,3.2,,
+data,PyCapsule_Type,3.2,,
+data,PyClassMethodDescr_Type,3.2,,
+func,PyCodec_BackslashReplaceErrors,3.2,,
+func,PyCodec_Decode,3.2,,
+func,PyCodec_Decoder,3.2,,
+func,PyCodec_Encode,3.2,,
+func,PyCodec_Encoder,3.2,,
+func,PyCodec_IgnoreErrors,3.2,,
+func,PyCodec_IncrementalDecoder,3.2,,
+func,PyCodec_IncrementalEncoder,3.2,,
+func,PyCodec_KnownEncoding,3.2,,
+func,PyCodec_LookupError,3.2,,
+func,PyCodec_NameReplaceErrors,3.7,,
+func,PyCodec_Register,3.2,,
+func,PyCodec_RegisterError,3.2,,
+func,PyCodec_ReplaceErrors,3.2,,
+func,PyCodec_StreamReader,3.2,,
+func,PyCodec_StreamWriter,3.2,,
+func,PyCodec_StrictErrors,3.2,,
+func,PyCodec_Unregister,3.10,,
+func,PyCodec_XMLCharRefReplaceErrors,3.2,,
+func,PyComplex_FromDoubles,3.2,,
+func,PyComplex_ImagAsDouble,3.2,,
+func,PyComplex_RealAsDouble,3.2,,
+data,PyComplex_Type,3.2,,
+func,PyDescr_NewClassMethod,3.2,,
+func,PyDescr_NewGetSet,3.2,,
+func,PyDescr_NewMember,3.2,,
+func,PyDescr_NewMethod,3.2,,
+data,PyDictItems_Type,3.2,,
+data,PyDictIterItem_Type,3.2,,
+data,PyDictIterKey_Type,3.2,,
+data,PyDictIterValue_Type,3.2,,
+data,PyDictKeys_Type,3.2,,
+func,PyDictProxy_New,3.2,,
+data,PyDictProxy_Type,3.2,,
+data,PyDictRevIterItem_Type,3.8,,
+data,PyDictRevIterKey_Type,3.8,,
+data,PyDictRevIterValue_Type,3.8,,
+data,PyDictValues_Type,3.2,,
+func,PyDict_Clear,3.2,,
+func,PyDict_Contains,3.2,,
+func,PyDict_Copy,3.2,,
+func,PyDict_DelItem,3.2,,
+func,PyDict_DelItemString,3.2,,
+func,PyDict_GetItem,3.2,,
+func,PyDict_GetItemRef,3.13,,
+func,PyDict_GetItemString,3.2,,
+func,PyDict_GetItemStringRef,3.13,,
+func,PyDict_GetItemWithError,3.2,,
+func,PyDict_Items,3.2,,
+func,PyDict_Keys,3.2,,
+func,PyDict_Merge,3.2,,
+func,PyDict_MergeFromSeq2,3.2,,
+func,PyDict_New,3.2,,
+func,PyDict_Next,3.2,,
+func,PyDict_SetItem,3.2,,
+func,PyDict_SetItemString,3.2,,
+func,PyDict_Size,3.2,,
+data,PyDict_Type,3.2,,
+func,PyDict_Update,3.2,,
+func,PyDict_Values,3.2,,
+data,PyEllipsis_Type,3.2,,
+data,PyEnum_Type,3.2,,
+func,PyErr_BadArgument,3.2,,
+func,PyErr_BadInternalCall,3.2,,
+func,PyErr_CheckSignals,3.2,,
+func,PyErr_Clear,3.2,,
+func,PyErr_Display,3.2,,
+func,PyErr_DisplayException,3.12,,
+func,PyErr_ExceptionMatches,3.2,,
+func,PyErr_Fetch,3.2,,
+func,PyErr_Format,3.2,,
+func,PyErr_FormatV,3.5,,
+func,PyErr_GetExcInfo,3.7,,
+func,PyErr_GetHandledException,3.11,,
+func,PyErr_GetRaisedException,3.12,,
+func,PyErr_GivenExceptionMatches,3.2,,
+func,PyErr_NewException,3.2,,
+func,PyErr_NewExceptionWithDoc,3.2,,
+func,PyErr_NoMemory,3.2,,
+func,PyErr_NormalizeException,3.2,,
+func,PyErr_Occurred,3.2,,
+func,PyErr_Print,3.2,,
+func,PyErr_PrintEx,3.2,,
+func,PyErr_ProgramText,3.2,,
+func,PyErr_ResourceWarning,3.6,,
+func,PyErr_Restore,3.2,,
+func,PyErr_SetExcFromWindowsErr,3.7,on Windows,
+func,PyErr_SetExcFromWindowsErrWithFilename,3.7,on Windows,
+func,PyErr_SetExcFromWindowsErrWithFilenameObject,3.7,on Windows,
+func,PyErr_SetExcFromWindowsErrWithFilenameObjects,3.7,on Windows,
+func,PyErr_SetExcInfo,3.7,,
+func,PyErr_SetFromErrno,3.2,,
+func,PyErr_SetFromErrnoWithFilename,3.2,,
+func,PyErr_SetFromErrnoWithFilenameObject,3.2,,
+func,PyErr_SetFromErrnoWithFilenameObjects,3.7,,
+func,PyErr_SetFromWindowsErr,3.7,on Windows,
+func,PyErr_SetFromWindowsErrWithFilename,3.7,on Windows,
+func,PyErr_SetHandledException,3.11,,
+func,PyErr_SetImportError,3.7,,
+func,PyErr_SetImportErrorSubclass,3.6,,
+func,PyErr_SetInterrupt,3.2,,
+func,PyErr_SetInterruptEx,3.10,,
+func,PyErr_SetNone,3.2,,
+func,PyErr_SetObject,3.2,,
+func,PyErr_SetRaisedException,3.12,,
+func,PyErr_SetString,3.2,,
+func,PyErr_SyntaxLocation,3.2,,
+func,PyErr_SyntaxLocationEx,3.7,,
+func,PyErr_WarnEx,3.2,,
+func,PyErr_WarnExplicit,3.2,,
+func,PyErr_WarnFormat,3.2,,
+func,PyErr_WriteUnraisable,3.2,,
+func,PyEval_AcquireThread,3.2,,
+func,PyEval_EvalCode,3.2,,
+func,PyEval_EvalCodeEx,3.2,,
+func,PyEval_EvalFrame,3.2,,
+func,PyEval_EvalFrameEx,3.2,,
+func,PyEval_GetBuiltins,3.2,,
+func,PyEval_GetFrame,3.2,,
+func,PyEval_GetFrameBuiltins,3.13,,
+func,PyEval_GetFrameGlobals,3.13,,
+func,PyEval_GetFrameLocals,3.13,,
+func,PyEval_GetFuncDesc,3.2,,
+func,PyEval_GetFuncName,3.2,,
+func,PyEval_GetGlobals,3.2,,
+func,PyEval_GetLocals,3.2,,
+func,PyEval_InitThreads,3.2,,
+func,PyEval_ReleaseThread,3.2,,
+func,PyEval_RestoreThread,3.2,,
+func,PyEval_SaveThread,3.2,,
+data,PyExc_ArithmeticError,3.2,,
+data,PyExc_AssertionError,3.2,,
+data,PyExc_AttributeError,3.2,,
+data,PyExc_BaseException,3.2,,
+data,PyExc_BaseExceptionGroup,3.11,,
+data,PyExc_BlockingIOError,3.7,,
+data,PyExc_BrokenPipeError,3.7,,
+data,PyExc_BufferError,3.2,,
+data,PyExc_BytesWarning,3.2,,
+data,PyExc_ChildProcessError,3.7,,
+data,PyExc_ConnectionAbortedError,3.7,,
+data,PyExc_ConnectionError,3.7,,
+data,PyExc_ConnectionRefusedError,3.7,,
+data,PyExc_ConnectionResetError,3.7,,
+data,PyExc_DeprecationWarning,3.2,,
+data,PyExc_EOFError,3.2,,
+data,PyExc_EncodingWarning,3.10,,
+data,PyExc_EnvironmentError,3.2,,
+data,PyExc_Exception,3.2,,
+data,PyExc_FileExistsError,3.7,,
+data,PyExc_FileNotFoundError,3.7,,
+data,PyExc_FloatingPointError,3.2,,
+data,PyExc_FutureWarning,3.2,,
+data,PyExc_GeneratorExit,3.2,,
+data,PyExc_IOError,3.2,,
+data,PyExc_ImportError,3.2,,
+data,PyExc_ImportWarning,3.2,,
+data,PyExc_IndentationError,3.2,,
+data,PyExc_IndexError,3.2,,
+data,PyExc_InterruptedError,3.7,,
+data,PyExc_IsADirectoryError,3.7,,
+data,PyExc_KeyError,3.2,,
+data,PyExc_KeyboardInterrupt,3.2,,
+data,PyExc_LookupError,3.2,,
+data,PyExc_MemoryError,3.2,,
+data,PyExc_ModuleNotFoundError,3.6,,
+data,PyExc_NameError,3.2,,
+data,PyExc_NotADirectoryError,3.7,,
+data,PyExc_NotImplementedError,3.2,,
+data,PyExc_OSError,3.2,,
+data,PyExc_OverflowError,3.2,,
+data,PyExc_PendingDeprecationWarning,3.2,,
+data,PyExc_PermissionError,3.7,,
+data,PyExc_ProcessLookupError,3.7,,
+data,PyExc_RecursionError,3.7,,
+data,PyExc_ReferenceError,3.2,,
+data,PyExc_ResourceWarning,3.7,,
+data,PyExc_RuntimeError,3.2,,
+data,PyExc_RuntimeWarning,3.2,,
+data,PyExc_StopAsyncIteration,3.7,,
+data,PyExc_StopIteration,3.2,,
+data,PyExc_SyntaxError,3.2,,
+data,PyExc_SyntaxWarning,3.2,,
+data,PyExc_SystemError,3.2,,
+data,PyExc_SystemExit,3.2,,
+data,PyExc_TabError,3.2,,
+data,PyExc_TimeoutError,3.7,,
+data,PyExc_TypeError,3.2,,
+data,PyExc_UnboundLocalError,3.2,,
+data,PyExc_UnicodeDecodeError,3.2,,
+data,PyExc_UnicodeEncodeError,3.2,,
+data,PyExc_UnicodeError,3.2,,
+data,PyExc_UnicodeTranslateError,3.2,,
+data,PyExc_UnicodeWarning,3.2,,
+data,PyExc_UserWarning,3.2,,
+data,PyExc_ValueError,3.2,,
+data,PyExc_Warning,3.2,,
+data,PyExc_WindowsError,3.7,on Windows,
+data,PyExc_ZeroDivisionError,3.2,,
+func,PyExceptionClass_Name,3.8,,
+func,PyException_GetArgs,3.12,,
+func,PyException_GetCause,3.2,,
+func,PyException_GetContext,3.2,,
+func,PyException_GetTraceback,3.2,,
+func,PyException_SetArgs,3.12,,
+func,PyException_SetCause,3.2,,
+func,PyException_SetContext,3.2,,
+func,PyException_SetTraceback,3.2,,
+func,PyFile_FromFd,3.2,,
+func,PyFile_GetLine,3.2,,
+func,PyFile_WriteObject,3.2,,
+func,PyFile_WriteString,3.2,,
+data,PyFilter_Type,3.2,,
+func,PyFloat_AsDouble,3.2,,
+func,PyFloat_FromDouble,3.2,,
+func,PyFloat_FromString,3.2,,
+func,PyFloat_GetInfo,3.2,,
+func,PyFloat_GetMax,3.2,,
+func,PyFloat_GetMin,3.2,,
+data,PyFloat_Type,3.2,,
type,PyFrameObject,3.2,,opaque
-function,PyFrame_GetCode,3.10,,
-function,PyFrame_GetLineNumber,3.10,,
-function,PyFrozenSet_New,3.2,,
-var,PyFrozenSet_Type,3.2,,
-function,PyGC_Collect,3.2,,
-function,PyGC_Disable,3.10,,
-function,PyGC_Enable,3.10,,
-function,PyGC_IsEnabled,3.10,,
-function,PyGILState_Ensure,3.2,,
-function,PyGILState_GetThisThreadState,3.2,,
-function,PyGILState_Release,3.2,,
+func,PyFrame_GetCode,3.10,,
+func,PyFrame_GetLineNumber,3.10,,
+func,PyFrozenSet_New,3.2,,
+data,PyFrozenSet_Type,3.2,,
+func,PyGC_Collect,3.2,,
+func,PyGC_Disable,3.10,,
+func,PyGC_Enable,3.10,,
+func,PyGC_IsEnabled,3.10,,
+func,PyGILState_Ensure,3.2,,
+func,PyGILState_GetThisThreadState,3.2,,
+func,PyGILState_Release,3.2,,
type,PyGILState_STATE,3.2,,
type,PyGetSetDef,3.2,,full-abi
-var,PyGetSetDescr_Type,3.2,,
-function,PyImport_AddModule,3.2,,
-function,PyImport_AddModuleObject,3.7,,
-function,PyImport_AddModuleRef,3.13,,
-function,PyImport_AppendInittab,3.2,,
-function,PyImport_ExecCodeModule,3.2,,
-function,PyImport_ExecCodeModuleEx,3.2,,
-function,PyImport_ExecCodeModuleObject,3.7,,
-function,PyImport_ExecCodeModuleWithPathnames,3.2,,
-function,PyImport_GetImporter,3.2,,
-function,PyImport_GetMagicNumber,3.2,,
-function,PyImport_GetMagicTag,3.2,,
-function,PyImport_GetModule,3.8,,
-function,PyImport_GetModuleDict,3.2,,
-function,PyImport_Import,3.2,,
-function,PyImport_ImportFrozenModule,3.2,,
-function,PyImport_ImportFrozenModuleObject,3.7,,
-function,PyImport_ImportModule,3.2,,
-function,PyImport_ImportModuleLevel,3.2,,
-function,PyImport_ImportModuleLevelObject,3.7,,
-function,PyImport_ImportModuleNoBlock,3.2,,
-function,PyImport_ReloadModule,3.2,,
-function,PyIndex_Check,3.8,,
+data,PyGetSetDescr_Type,3.2,,
+func,PyImport_AddModule,3.2,,
+func,PyImport_AddModuleObject,3.7,,
+func,PyImport_AddModuleRef,3.13,,
+func,PyImport_AppendInittab,3.2,,
+func,PyImport_ExecCodeModule,3.2,,
+func,PyImport_ExecCodeModuleEx,3.2,,
+func,PyImport_ExecCodeModuleObject,3.7,,
+func,PyImport_ExecCodeModuleWithPathnames,3.2,,
+func,PyImport_GetImporter,3.2,,
+func,PyImport_GetMagicNumber,3.2,,
+func,PyImport_GetMagicTag,3.2,,
+func,PyImport_GetModule,3.8,,
+func,PyImport_GetModuleDict,3.2,,
+func,PyImport_Import,3.2,,
+func,PyImport_ImportFrozenModule,3.2,,
+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
-function,PyInterpreterState_Clear,3.2,,
-function,PyInterpreterState_Delete,3.2,,
-function,PyInterpreterState_Get,3.9,,
-function,PyInterpreterState_GetDict,3.8,,
-function,PyInterpreterState_GetID,3.7,,
-function,PyInterpreterState_New,3.2,,
-function,PyIter_Check,3.8,,
-function,PyIter_Next,3.2,,
-function,PyIter_Send,3.10,,
-var,PyListIter_Type,3.2,,
-var,PyListRevIter_Type,3.2,,
-function,PyList_Append,3.2,,
-function,PyList_AsTuple,3.2,,
-function,PyList_GetItem,3.2,,
-function,PyList_GetItemRef,3.13,,
-function,PyList_GetSlice,3.2,,
-function,PyList_Insert,3.2,,
-function,PyList_New,3.2,,
-function,PyList_Reverse,3.2,,
-function,PyList_SetItem,3.2,,
-function,PyList_SetSlice,3.2,,
-function,PyList_Size,3.2,,
-function,PyList_Sort,3.2,,
-var,PyList_Type,3.2,,
+func,PyInterpreterState_Clear,3.2,,
+func,PyInterpreterState_Delete,3.2,,
+func,PyInterpreterState_Get,3.9,,
+func,PyInterpreterState_GetDict,3.8,,
+func,PyInterpreterState_GetID,3.7,,
+func,PyInterpreterState_New,3.2,,
+func,PyIter_Check,3.8,,
+func,PyIter_Next,3.2,,
+func,PyIter_Send,3.10,,
+data,PyListIter_Type,3.2,,
+data,PyListRevIter_Type,3.2,,
+func,PyList_Append,3.2,,
+func,PyList_AsTuple,3.2,,
+func,PyList_GetItem,3.2,,
+func,PyList_GetItemRef,3.13,,
+func,PyList_GetSlice,3.2,,
+func,PyList_Insert,3.2,,
+func,PyList_New,3.2,,
+func,PyList_Reverse,3.2,,
+func,PyList_SetItem,3.2,,
+func,PyList_SetSlice,3.2,,
+func,PyList_Size,3.2,,
+func,PyList_Sort,3.2,,
+data,PyList_Type,3.2,,
type,PyLongObject,3.2,,opaque
-var,PyLongRangeIter_Type,3.2,,
-function,PyLong_AsDouble,3.2,,
-function,PyLong_AsInt,3.13,,
-function,PyLong_AsLong,3.2,,
-function,PyLong_AsLongAndOverflow,3.2,,
-function,PyLong_AsLongLong,3.2,,
-function,PyLong_AsLongLongAndOverflow,3.2,,
-function,PyLong_AsSize_t,3.2,,
-function,PyLong_AsSsize_t,3.2,,
-function,PyLong_AsUnsignedLong,3.2,,
-function,PyLong_AsUnsignedLongLong,3.2,,
-function,PyLong_AsUnsignedLongLongMask,3.2,,
-function,PyLong_AsUnsignedLongMask,3.2,,
-function,PyLong_AsVoidPtr,3.2,,
-function,PyLong_FromDouble,3.2,,
-function,PyLong_FromLong,3.2,,
-function,PyLong_FromLongLong,3.2,,
-function,PyLong_FromSize_t,3.2,,
-function,PyLong_FromSsize_t,3.2,,
-function,PyLong_FromString,3.2,,
-function,PyLong_FromUnsignedLong,3.2,,
-function,PyLong_FromUnsignedLongLong,3.2,,
-function,PyLong_FromVoidPtr,3.2,,
-function,PyLong_GetInfo,3.2,,
-var,PyLong_Type,3.2,,
-var,PyMap_Type,3.2,,
-function,PyMapping_Check,3.2,,
-function,PyMapping_GetItemString,3.2,,
-function,PyMapping_GetOptionalItem,3.13,,
-function,PyMapping_GetOptionalItemString,3.13,,
-function,PyMapping_HasKey,3.2,,
-function,PyMapping_HasKeyString,3.2,,
-function,PyMapping_HasKeyStringWithError,3.13,,
-function,PyMapping_HasKeyWithError,3.13,,
-function,PyMapping_Items,3.2,,
-function,PyMapping_Keys,3.2,,
-function,PyMapping_Length,3.2,,
-function,PyMapping_SetItemString,3.2,,
-function,PyMapping_Size,3.2,,
-function,PyMapping_Values,3.2,,
-function,PyMem_Calloc,3.7,,
-function,PyMem_Free,3.2,,
-function,PyMem_Malloc,3.2,,
-function,PyMem_RawCalloc,3.13,,
-function,PyMem_RawFree,3.13,,
-function,PyMem_RawMalloc,3.13,,
-function,PyMem_RawRealloc,3.13,,
-function,PyMem_Realloc,3.2,,
+data,PyLongRangeIter_Type,3.2,,
+func,PyLong_AsDouble,3.2,,
+func,PyLong_AsInt,3.13,,
+func,PyLong_AsLong,3.2,,
+func,PyLong_AsLongAndOverflow,3.2,,
+func,PyLong_AsLongLong,3.2,,
+func,PyLong_AsLongLongAndOverflow,3.2,,
+func,PyLong_AsSize_t,3.2,,
+func,PyLong_AsSsize_t,3.2,,
+func,PyLong_AsUnsignedLong,3.2,,
+func,PyLong_AsUnsignedLongLong,3.2,,
+func,PyLong_AsUnsignedLongLongMask,3.2,,
+func,PyLong_AsUnsignedLongMask,3.2,,
+func,PyLong_AsVoidPtr,3.2,,
+func,PyLong_FromDouble,3.2,,
+func,PyLong_FromLong,3.2,,
+func,PyLong_FromLongLong,3.2,,
+func,PyLong_FromSize_t,3.2,,
+func,PyLong_FromSsize_t,3.2,,
+func,PyLong_FromString,3.2,,
+func,PyLong_FromUnsignedLong,3.2,,
+func,PyLong_FromUnsignedLongLong,3.2,,
+func,PyLong_FromVoidPtr,3.2,,
+func,PyLong_GetInfo,3.2,,
+data,PyLong_Type,3.2,,
+data,PyMap_Type,3.2,,
+func,PyMapping_Check,3.2,,
+func,PyMapping_GetItemString,3.2,,
+func,PyMapping_GetOptionalItem,3.13,,
+func,PyMapping_GetOptionalItemString,3.13,,
+func,PyMapping_HasKey,3.2,,
+func,PyMapping_HasKeyString,3.2,,
+func,PyMapping_HasKeyStringWithError,3.13,,
+func,PyMapping_HasKeyWithError,3.13,,
+func,PyMapping_Items,3.2,,
+func,PyMapping_Keys,3.2,,
+func,PyMapping_Length,3.2,,
+func,PyMapping_SetItemString,3.2,,
+func,PyMapping_Size,3.2,,
+func,PyMapping_Values,3.2,,
+func,PyMem_Calloc,3.7,,
+func,PyMem_Free,3.2,,
+func,PyMem_Malloc,3.2,,
+func,PyMem_RawCalloc,3.13,,
+func,PyMem_RawFree,3.13,,
+func,PyMem_RawMalloc,3.13,,
+func,PyMem_RawRealloc,3.13,,
+func,PyMem_Realloc,3.2,,
type,PyMemberDef,3.2,,full-abi
-var,PyMemberDescr_Type,3.2,,
-function,PyMember_GetOne,3.2,,
-function,PyMember_SetOne,3.2,,
-function,PyMemoryView_FromBuffer,3.11,,
-function,PyMemoryView_FromMemory,3.7,,
-function,PyMemoryView_FromObject,3.2,,
-function,PyMemoryView_GetContiguous,3.2,,
-var,PyMemoryView_Type,3.2,,
+data,PyMemberDescr_Type,3.2,,
+func,PyMember_GetOne,3.2,,
+func,PyMember_SetOne,3.2,,
+func,PyMemoryView_FromBuffer,3.11,,
+func,PyMemoryView_FromMemory,3.7,,
+func,PyMemoryView_FromObject,3.2,,
+func,PyMemoryView_GetContiguous,3.2,,
+data,PyMemoryView_Type,3.2,,
type,PyMethodDef,3.2,,full-abi
-var,PyMethodDescr_Type,3.2,,
+data,PyMethodDescr_Type,3.2,,
type,PyModuleDef,3.2,,full-abi
type,PyModuleDef_Base,3.2,,full-abi
-function,PyModuleDef_Init,3.5,,
-var,PyModuleDef_Type,3.5,,
-function,PyModule_Add,3.13,,
-function,PyModule_AddFunctions,3.7,,
-function,PyModule_AddIntConstant,3.2,,
-function,PyModule_AddObject,3.2,,
-function,PyModule_AddObjectRef,3.10,,
-function,PyModule_AddStringConstant,3.2,,
-function,PyModule_AddType,3.10,,
-function,PyModule_Create2,3.2,,
-function,PyModule_ExecDef,3.7,,
-function,PyModule_FromDefAndSpec2,3.7,,
-function,PyModule_GetDef,3.2,,
-function,PyModule_GetDict,3.2,,
-function,PyModule_GetFilename,3.2,,
-function,PyModule_GetFilenameObject,3.2,,
-function,PyModule_GetName,3.2,,
-function,PyModule_GetNameObject,3.7,,
-function,PyModule_GetState,3.2,,
-function,PyModule_New,3.2,,
-function,PyModule_NewObject,3.7,,
-function,PyModule_SetDocString,3.7,,
-var,PyModule_Type,3.2,,
-function,PyNumber_Absolute,3.2,,
-function,PyNumber_Add,3.2,,
-function,PyNumber_And,3.2,,
-function,PyNumber_AsSsize_t,3.2,,
-function,PyNumber_Check,3.2,,
-function,PyNumber_Divmod,3.2,,
-function,PyNumber_Float,3.2,,
-function,PyNumber_FloorDivide,3.2,,
-function,PyNumber_InPlaceAdd,3.2,,
-function,PyNumber_InPlaceAnd,3.2,,
-function,PyNumber_InPlaceFloorDivide,3.2,,
-function,PyNumber_InPlaceLshift,3.2,,
-function,PyNumber_InPlaceMatrixMultiply,3.7,,
-function,PyNumber_InPlaceMultiply,3.2,,
-function,PyNumber_InPlaceOr,3.2,,
-function,PyNumber_InPlacePower,3.2,,
-function,PyNumber_InPlaceRemainder,3.2,,
-function,PyNumber_InPlaceRshift,3.2,,
-function,PyNumber_InPlaceSubtract,3.2,,
-function,PyNumber_InPlaceTrueDivide,3.2,,
-function,PyNumber_InPlaceXor,3.2,,
-function,PyNumber_Index,3.2,,
-function,PyNumber_Invert,3.2,,
-function,PyNumber_Long,3.2,,
-function,PyNumber_Lshift,3.2,,
-function,PyNumber_MatrixMultiply,3.7,,
-function,PyNumber_Multiply,3.2,,
-function,PyNumber_Negative,3.2,,
-function,PyNumber_Or,3.2,,
-function,PyNumber_Positive,3.2,,
-function,PyNumber_Power,3.2,,
-function,PyNumber_Remainder,3.2,,
-function,PyNumber_Rshift,3.2,,
-function,PyNumber_Subtract,3.2,,
-function,PyNumber_ToBase,3.2,,
-function,PyNumber_TrueDivide,3.2,,
-function,PyNumber_Xor,3.2,,
-function,PyOS_AfterFork,3.2,on platforms with fork(),
-function,PyOS_AfterFork_Child,3.7,on platforms with fork(),
-function,PyOS_AfterFork_Parent,3.7,on platforms with fork(),
-function,PyOS_BeforeFork,3.7,on platforms with fork(),
-function,PyOS_CheckStack,3.7,on platforms with USE_STACKCHECK,
-function,PyOS_FSPath,3.6,,
-var,PyOS_InputHook,3.2,,
-function,PyOS_InterruptOccurred,3.2,,
-function,PyOS_double_to_string,3.2,,
-function,PyOS_getsig,3.2,,
-function,PyOS_mystricmp,3.2,,
-function,PyOS_mystrnicmp,3.2,,
-function,PyOS_setsig,3.2,,
+func,PyModuleDef_Init,3.5,,
+data,PyModuleDef_Type,3.5,,
+func,PyModule_Add,3.13,,
+func,PyModule_AddFunctions,3.7,,
+func,PyModule_AddIntConstant,3.2,,
+func,PyModule_AddObject,3.2,,
+func,PyModule_AddObjectRef,3.10,,
+func,PyModule_AddStringConstant,3.2,,
+func,PyModule_AddType,3.10,,
+func,PyModule_Create2,3.2,,
+func,PyModule_ExecDef,3.7,,
+func,PyModule_FromDefAndSpec2,3.7,,
+func,PyModule_GetDef,3.2,,
+func,PyModule_GetDict,3.2,,
+func,PyModule_GetFilename,3.2,,
+func,PyModule_GetFilenameObject,3.2,,
+func,PyModule_GetName,3.2,,
+func,PyModule_GetNameObject,3.7,,
+func,PyModule_GetState,3.2,,
+func,PyModule_New,3.2,,
+func,PyModule_NewObject,3.7,,
+func,PyModule_SetDocString,3.7,,
+data,PyModule_Type,3.2,,
+func,PyNumber_Absolute,3.2,,
+func,PyNumber_Add,3.2,,
+func,PyNumber_And,3.2,,
+func,PyNumber_AsSsize_t,3.2,,
+func,PyNumber_Check,3.2,,
+func,PyNumber_Divmod,3.2,,
+func,PyNumber_Float,3.2,,
+func,PyNumber_FloorDivide,3.2,,
+func,PyNumber_InPlaceAdd,3.2,,
+func,PyNumber_InPlaceAnd,3.2,,
+func,PyNumber_InPlaceFloorDivide,3.2,,
+func,PyNumber_InPlaceLshift,3.2,,
+func,PyNumber_InPlaceMatrixMultiply,3.7,,
+func,PyNumber_InPlaceMultiply,3.2,,
+func,PyNumber_InPlaceOr,3.2,,
+func,PyNumber_InPlacePower,3.2,,
+func,PyNumber_InPlaceRemainder,3.2,,
+func,PyNumber_InPlaceRshift,3.2,,
+func,PyNumber_InPlaceSubtract,3.2,,
+func,PyNumber_InPlaceTrueDivide,3.2,,
+func,PyNumber_InPlaceXor,3.2,,
+func,PyNumber_Index,3.2,,
+func,PyNumber_Invert,3.2,,
+func,PyNumber_Long,3.2,,
+func,PyNumber_Lshift,3.2,,
+func,PyNumber_MatrixMultiply,3.7,,
+func,PyNumber_Multiply,3.2,,
+func,PyNumber_Negative,3.2,,
+func,PyNumber_Or,3.2,,
+func,PyNumber_Positive,3.2,,
+func,PyNumber_Power,3.2,,
+func,PyNumber_Remainder,3.2,,
+func,PyNumber_Rshift,3.2,,
+func,PyNumber_Subtract,3.2,,
+func,PyNumber_ToBase,3.2,,
+func,PyNumber_TrueDivide,3.2,,
+func,PyNumber_Xor,3.2,,
+func,PyOS_AfterFork,3.2,on platforms with fork(),
+func,PyOS_AfterFork_Child,3.7,on platforms with fork(),
+func,PyOS_AfterFork_Parent,3.7,on platforms with fork(),
+func,PyOS_BeforeFork,3.7,on platforms with fork(),
+func,PyOS_CheckStack,3.7,on platforms with USE_STACKCHECK,
+func,PyOS_FSPath,3.6,,
+data,PyOS_InputHook,3.2,,
+func,PyOS_InterruptOccurred,3.2,,
+func,PyOS_double_to_string,3.2,,
+func,PyOS_getsig,3.2,,
+func,PyOS_mystricmp,3.2,,
+func,PyOS_mystrnicmp,3.2,,
+func,PyOS_setsig,3.2,,
type,PyOS_sighandler_t,3.2,,
-function,PyOS_snprintf,3.2,,
-function,PyOS_string_to_double,3.2,,
-function,PyOS_strtol,3.2,,
-function,PyOS_strtoul,3.2,,
-function,PyOS_vsnprintf,3.2,,
+func,PyOS_snprintf,3.2,,
+func,PyOS_string_to_double,3.2,,
+func,PyOS_strtol,3.2,,
+func,PyOS_strtoul,3.2,,
+func,PyOS_vsnprintf,3.2,,
type,PyObject,3.2,,members
member,PyObject.ob_refcnt,3.2,,
member,PyObject.ob_type,3.2,,
-function,PyObject_ASCII,3.2,,
-function,PyObject_AsFileDescriptor,3.2,,
-function,PyObject_Bytes,3.2,,
-function,PyObject_Call,3.2,,
-function,PyObject_CallFunction,3.2,,
-function,PyObject_CallFunctionObjArgs,3.2,,
-function,PyObject_CallMethod,3.2,,
-function,PyObject_CallMethodObjArgs,3.2,,
-function,PyObject_CallNoArgs,3.10,,
-function,PyObject_CallObject,3.2,,
-function,PyObject_Calloc,3.7,,
-function,PyObject_CheckBuffer,3.11,,
-function,PyObject_ClearWeakRefs,3.2,,
-function,PyObject_CopyData,3.11,,
-function,PyObject_DelAttr,3.13,,
-function,PyObject_DelAttrString,3.13,,
-function,PyObject_DelItem,3.2,,
-function,PyObject_DelItemString,3.2,,
-function,PyObject_Dir,3.2,,
-function,PyObject_Format,3.2,,
-function,PyObject_Free,3.2,,
-function,PyObject_GC_Del,3.2,,
-function,PyObject_GC_IsFinalized,3.9,,
-function,PyObject_GC_IsTracked,3.9,,
-function,PyObject_GC_Track,3.2,,
-function,PyObject_GC_UnTrack,3.2,,
-function,PyObject_GenericGetAttr,3.2,,
-function,PyObject_GenericGetDict,3.10,,
-function,PyObject_GenericSetAttr,3.2,,
-function,PyObject_GenericSetDict,3.7,,
-function,PyObject_GetAIter,3.10,,
-function,PyObject_GetAttr,3.2,,
-function,PyObject_GetAttrString,3.2,,
-function,PyObject_GetBuffer,3.11,,
-function,PyObject_GetItem,3.2,,
-function,PyObject_GetIter,3.2,,
-function,PyObject_GetOptionalAttr,3.13,,
-function,PyObject_GetOptionalAttrString,3.13,,
-function,PyObject_GetTypeData,3.12,,
-function,PyObject_HasAttr,3.2,,
-function,PyObject_HasAttrString,3.2,,
-function,PyObject_HasAttrStringWithError,3.13,,
-function,PyObject_HasAttrWithError,3.13,,
-function,PyObject_Hash,3.2,,
-function,PyObject_HashNotImplemented,3.2,,
-function,PyObject_Init,3.2,,
-function,PyObject_InitVar,3.2,,
-function,PyObject_IsInstance,3.2,,
-function,PyObject_IsSubclass,3.2,,
-function,PyObject_IsTrue,3.2,,
-function,PyObject_Length,3.2,,
-function,PyObject_Malloc,3.2,,
-function,PyObject_Not,3.2,,
-function,PyObject_Realloc,3.2,,
-function,PyObject_Repr,3.2,,
-function,PyObject_RichCompare,3.2,,
-function,PyObject_RichCompareBool,3.2,,
-function,PyObject_SelfIter,3.2,,
-function,PyObject_SetAttr,3.2,,
-function,PyObject_SetAttrString,3.2,,
-function,PyObject_SetItem,3.2,,
-function,PyObject_Size,3.2,,
-function,PyObject_Str,3.2,,
-function,PyObject_Type,3.2,,
-function,PyObject_Vectorcall,3.12,,
-function,PyObject_VectorcallMethod,3.12,,
-var,PyProperty_Type,3.2,,
-var,PyRangeIter_Type,3.2,,
-var,PyRange_Type,3.2,,
-var,PyReversed_Type,3.2,,
-function,PySeqIter_New,3.2,,
-var,PySeqIter_Type,3.2,,
-function,PySequence_Check,3.2,,
-function,PySequence_Concat,3.2,,
-function,PySequence_Contains,3.2,,
-function,PySequence_Count,3.2,,
-function,PySequence_DelItem,3.2,,
-function,PySequence_DelSlice,3.2,,
-function,PySequence_Fast,3.2,,
-function,PySequence_GetItem,3.2,,
-function,PySequence_GetSlice,3.2,,
-function,PySequence_In,3.2,,
-function,PySequence_InPlaceConcat,3.2,,
-function,PySequence_InPlaceRepeat,3.2,,
-function,PySequence_Index,3.2,,
-function,PySequence_Length,3.2,,
-function,PySequence_List,3.2,,
-function,PySequence_Repeat,3.2,,
-function,PySequence_SetItem,3.2,,
-function,PySequence_SetSlice,3.2,,
-function,PySequence_Size,3.2,,
-function,PySequence_Tuple,3.2,,
-var,PySetIter_Type,3.2,,
-function,PySet_Add,3.2,,
-function,PySet_Clear,3.2,,
-function,PySet_Contains,3.2,,
-function,PySet_Discard,3.2,,
-function,PySet_New,3.2,,
-function,PySet_Pop,3.2,,
-function,PySet_Size,3.2,,
-var,PySet_Type,3.2,,
-function,PySlice_AdjustIndices,3.7,,
-function,PySlice_GetIndices,3.2,,
-function,PySlice_GetIndicesEx,3.2,,
-function,PySlice_New,3.2,,
-var,PySlice_Type,3.2,,
-function,PySlice_Unpack,3.7,,
-function,PyState_AddModule,3.3,,
-function,PyState_FindModule,3.2,,
-function,PyState_RemoveModule,3.3,,
+func,PyObject_ASCII,3.2,,
+func,PyObject_AsFileDescriptor,3.2,,
+func,PyObject_Bytes,3.2,,
+func,PyObject_Call,3.2,,
+func,PyObject_CallFunction,3.2,,
+func,PyObject_CallFunctionObjArgs,3.2,,
+func,PyObject_CallMethod,3.2,,
+func,PyObject_CallMethodObjArgs,3.2,,
+func,PyObject_CallNoArgs,3.10,,
+func,PyObject_CallObject,3.2,,
+func,PyObject_Calloc,3.7,,
+func,PyObject_CheckBuffer,3.11,,
+func,PyObject_ClearWeakRefs,3.2,,
+func,PyObject_CopyData,3.11,,
+func,PyObject_DelAttr,3.13,,
+func,PyObject_DelAttrString,3.13,,
+func,PyObject_DelItem,3.2,,
+func,PyObject_DelItemString,3.2,,
+func,PyObject_Dir,3.2,,
+func,PyObject_Format,3.2,,
+func,PyObject_Free,3.2,,
+func,PyObject_GC_Del,3.2,,
+func,PyObject_GC_IsFinalized,3.9,,
+func,PyObject_GC_IsTracked,3.9,,
+func,PyObject_GC_Track,3.2,,
+func,PyObject_GC_UnTrack,3.2,,
+func,PyObject_GenericGetAttr,3.2,,
+func,PyObject_GenericGetDict,3.10,,
+func,PyObject_GenericSetAttr,3.2,,
+func,PyObject_GenericSetDict,3.7,,
+func,PyObject_GetAIter,3.10,,
+func,PyObject_GetAttr,3.2,,
+func,PyObject_GetAttrString,3.2,,
+func,PyObject_GetBuffer,3.11,,
+func,PyObject_GetItem,3.2,,
+func,PyObject_GetIter,3.2,,
+func,PyObject_GetOptionalAttr,3.13,,
+func,PyObject_GetOptionalAttrString,3.13,,
+func,PyObject_GetTypeData,3.12,,
+func,PyObject_HasAttr,3.2,,
+func,PyObject_HasAttrString,3.2,,
+func,PyObject_HasAttrStringWithError,3.13,,
+func,PyObject_HasAttrWithError,3.13,,
+func,PyObject_Hash,3.2,,
+func,PyObject_HashNotImplemented,3.2,,
+func,PyObject_Init,3.2,,
+func,PyObject_InitVar,3.2,,
+func,PyObject_IsInstance,3.2,,
+func,PyObject_IsSubclass,3.2,,
+func,PyObject_IsTrue,3.2,,
+func,PyObject_Length,3.2,,
+func,PyObject_Malloc,3.2,,
+func,PyObject_Not,3.2,,
+func,PyObject_Realloc,3.2,,
+func,PyObject_Repr,3.2,,
+func,PyObject_RichCompare,3.2,,
+func,PyObject_RichCompareBool,3.2,,
+func,PyObject_SelfIter,3.2,,
+func,PyObject_SetAttr,3.2,,
+func,PyObject_SetAttrString,3.2,,
+func,PyObject_SetItem,3.2,,
+func,PyObject_Size,3.2,,
+func,PyObject_Str,3.2,,
+func,PyObject_Type,3.2,,
+func,PyObject_Vectorcall,3.12,,
+func,PyObject_VectorcallMethod,3.12,,
+data,PyProperty_Type,3.2,,
+data,PyRangeIter_Type,3.2,,
+data,PyRange_Type,3.2,,
+data,PyReversed_Type,3.2,,
+func,PySeqIter_New,3.2,,
+data,PySeqIter_Type,3.2,,
+func,PySequence_Check,3.2,,
+func,PySequence_Concat,3.2,,
+func,PySequence_Contains,3.2,,
+func,PySequence_Count,3.2,,
+func,PySequence_DelItem,3.2,,
+func,PySequence_DelSlice,3.2,,
+func,PySequence_Fast,3.2,,
+func,PySequence_GetItem,3.2,,
+func,PySequence_GetSlice,3.2,,
+func,PySequence_In,3.2,,
+func,PySequence_InPlaceConcat,3.2,,
+func,PySequence_InPlaceRepeat,3.2,,
+func,PySequence_Index,3.2,,
+func,PySequence_Length,3.2,,
+func,PySequence_List,3.2,,
+func,PySequence_Repeat,3.2,,
+func,PySequence_SetItem,3.2,,
+func,PySequence_SetSlice,3.2,,
+func,PySequence_Size,3.2,,
+func,PySequence_Tuple,3.2,,
+data,PySetIter_Type,3.2,,
+func,PySet_Add,3.2,,
+func,PySet_Clear,3.2,,
+func,PySet_Contains,3.2,,
+func,PySet_Discard,3.2,,
+func,PySet_New,3.2,,
+func,PySet_Pop,3.2,,
+func,PySet_Size,3.2,,
+data,PySet_Type,3.2,,
+func,PySlice_AdjustIndices,3.7,,
+func,PySlice_GetIndices,3.2,,
+func,PySlice_GetIndicesEx,3.2,,
+func,PySlice_New,3.2,,
+data,PySlice_Type,3.2,,
+func,PySlice_Unpack,3.7,,
+func,PyState_AddModule,3.3,,
+func,PyState_FindModule,3.2,,
+func,PyState_RemoveModule,3.3,,
type,PyStructSequence_Desc,3.2,,full-abi
type,PyStructSequence_Field,3.2,,full-abi
-function,PyStructSequence_GetItem,3.2,,
-function,PyStructSequence_New,3.2,,
-function,PyStructSequence_NewType,3.2,,
-function,PyStructSequence_SetItem,3.2,,
-var,PyStructSequence_UnnamedField,3.11,,
-var,PySuper_Type,3.2,,
-function,PySys_Audit,3.13,,
-function,PySys_AuditTuple,3.13,,
-function,PySys_FormatStderr,3.2,,
-function,PySys_FormatStdout,3.2,,
-function,PySys_GetObject,3.2,,
-function,PySys_GetXOptions,3.7,,
-function,PySys_ResetWarnOptions,3.2,,
-function,PySys_SetArgv,3.2,,
-function,PySys_SetArgvEx,3.2,,
-function,PySys_SetObject,3.2,,
-function,PySys_WriteStderr,3.2,,
-function,PySys_WriteStdout,3.2,,
+func,PyStructSequence_GetItem,3.2,,
+func,PyStructSequence_New,3.2,,
+func,PyStructSequence_NewType,3.2,,
+func,PyStructSequence_SetItem,3.2,,
+data,PyStructSequence_UnnamedField,3.11,,
+data,PySuper_Type,3.2,,
+func,PySys_Audit,3.13,,
+func,PySys_AuditTuple,3.13,,
+func,PySys_FormatStderr,3.2,,
+func,PySys_FormatStdout,3.2,,
+func,PySys_GetObject,3.2,,
+func,PySys_GetXOptions,3.7,,
+func,PySys_ResetWarnOptions,3.2,,
+func,PySys_SetArgv,3.2,,
+func,PySys_SetArgvEx,3.2,,
+func,PySys_SetObject,3.2,,
+func,PySys_WriteStderr,3.2,,
+func,PySys_WriteStdout,3.2,,
type,PyThreadState,3.2,,opaque
-function,PyThreadState_Clear,3.2,,
-function,PyThreadState_Delete,3.2,,
-function,PyThreadState_Get,3.2,,
-function,PyThreadState_GetDict,3.2,,
-function,PyThreadState_GetFrame,3.10,,
-function,PyThreadState_GetID,3.10,,
-function,PyThreadState_GetInterpreter,3.10,,
-function,PyThreadState_New,3.2,,
-function,PyThreadState_SetAsyncExc,3.2,,
-function,PyThreadState_Swap,3.2,,
-function,PyThread_GetInfo,3.3,,
-function,PyThread_ReInitTLS,3.2,,
-function,PyThread_acquire_lock,3.2,,
-function,PyThread_acquire_lock_timed,3.2,,
-function,PyThread_allocate_lock,3.2,,
-function,PyThread_create_key,3.2,,
-function,PyThread_delete_key,3.2,,
-function,PyThread_delete_key_value,3.2,,
-function,PyThread_exit_thread,3.2,,
-function,PyThread_free_lock,3.2,,
-function,PyThread_get_key_value,3.2,,
-function,PyThread_get_stacksize,3.2,,
-function,PyThread_get_thread_ident,3.2,,
-function,PyThread_get_thread_native_id,3.2,on platforms with native thread IDs,
-function,PyThread_init_thread,3.2,,
-function,PyThread_release_lock,3.2,,
-function,PyThread_set_key_value,3.2,,
-function,PyThread_set_stacksize,3.2,,
-function,PyThread_start_new_thread,3.2,,
-function,PyThread_tss_alloc,3.7,,
-function,PyThread_tss_create,3.7,,
-function,PyThread_tss_delete,3.7,,
-function,PyThread_tss_free,3.7,,
-function,PyThread_tss_get,3.7,,
-function,PyThread_tss_is_created,3.7,,
-function,PyThread_tss_set,3.7,,
-function,PyTraceBack_Here,3.2,,
-function,PyTraceBack_Print,3.2,,
-var,PyTraceBack_Type,3.2,,
-var,PyTupleIter_Type,3.2,,
-function,PyTuple_GetItem,3.2,,
-function,PyTuple_GetSlice,3.2,,
-function,PyTuple_New,3.2,,
-function,PyTuple_Pack,3.2,,
-function,PyTuple_SetItem,3.2,,
-function,PyTuple_Size,3.2,,
-var,PyTuple_Type,3.2,,
+func,PyThreadState_Clear,3.2,,
+func,PyThreadState_Delete,3.2,,
+func,PyThreadState_Get,3.2,,
+func,PyThreadState_GetDict,3.2,,
+func,PyThreadState_GetFrame,3.10,,
+func,PyThreadState_GetID,3.10,,
+func,PyThreadState_GetInterpreter,3.10,,
+func,PyThreadState_New,3.2,,
+func,PyThreadState_SetAsyncExc,3.2,,
+func,PyThreadState_Swap,3.2,,
+func,PyThread_GetInfo,3.3,,
+func,PyThread_ReInitTLS,3.2,,
+func,PyThread_acquire_lock,3.2,,
+func,PyThread_acquire_lock_timed,3.2,,
+func,PyThread_allocate_lock,3.2,,
+func,PyThread_create_key,3.2,,
+func,PyThread_delete_key,3.2,,
+func,PyThread_delete_key_value,3.2,,
+func,PyThread_exit_thread,3.2,,
+func,PyThread_free_lock,3.2,,
+func,PyThread_get_key_value,3.2,,
+func,PyThread_get_stacksize,3.2,,
+func,PyThread_get_thread_ident,3.2,,
+func,PyThread_get_thread_native_id,3.2,on platforms with native thread IDs,
+func,PyThread_init_thread,3.2,,
+func,PyThread_release_lock,3.2,,
+func,PyThread_set_key_value,3.2,,
+func,PyThread_set_stacksize,3.2,,
+func,PyThread_start_new_thread,3.2,,
+func,PyThread_tss_alloc,3.7,,
+func,PyThread_tss_create,3.7,,
+func,PyThread_tss_delete,3.7,,
+func,PyThread_tss_free,3.7,,
+func,PyThread_tss_get,3.7,,
+func,PyThread_tss_is_created,3.7,,
+func,PyThread_tss_set,3.7,,
+func,PyTraceBack_Here,3.2,,
+func,PyTraceBack_Print,3.2,,
+data,PyTraceBack_Type,3.2,,
+data,PyTupleIter_Type,3.2,,
+func,PyTuple_GetItem,3.2,,
+func,PyTuple_GetSlice,3.2,,
+func,PyTuple_New,3.2,,
+func,PyTuple_Pack,3.2,,
+func,PyTuple_SetItem,3.2,,
+func,PyTuple_Size,3.2,,
+data,PyTuple_Type,3.2,,
type,PyTypeObject,3.2,,opaque
-function,PyType_ClearCache,3.2,,
-function,PyType_FromMetaclass,3.12,,
-function,PyType_FromModuleAndSpec,3.10,,
-function,PyType_FromSpec,3.2,,
-function,PyType_FromSpecWithBases,3.3,,
-function,PyType_GenericAlloc,3.2,,
-function,PyType_GenericNew,3.2,,
-function,PyType_GetFlags,3.2,,
-function,PyType_GetFullyQualifiedName,3.13,,
-function,PyType_GetModule,3.10,,
-function,PyType_GetModuleByDef,3.13,,
-function,PyType_GetModuleName,3.13,,
-function,PyType_GetModuleState,3.10,,
-function,PyType_GetName,3.11,,
-function,PyType_GetQualName,3.11,,
-function,PyType_GetSlot,3.4,,
-function,PyType_GetTypeDataSize,3.12,,
-function,PyType_IsSubtype,3.2,,
-function,PyType_Modified,3.2,,
-function,PyType_Ready,3.2,,
+func,PyType_ClearCache,3.2,,
+func,PyType_FromMetaclass,3.12,,
+func,PyType_FromModuleAndSpec,3.10,,
+func,PyType_FromSpec,3.2,,
+func,PyType_FromSpecWithBases,3.3,,
+func,PyType_GenericAlloc,3.2,,
+func,PyType_GenericNew,3.2,,
+func,PyType_GetFlags,3.2,,
+func,PyType_GetFullyQualifiedName,3.13,,
+func,PyType_GetModule,3.10,,
+func,PyType_GetModuleByDef,3.13,,
+func,PyType_GetModuleName,3.13,,
+func,PyType_GetModuleState,3.10,,
+func,PyType_GetName,3.11,,
+func,PyType_GetQualName,3.11,,
+func,PyType_GetSlot,3.4,,
+func,PyType_GetTypeDataSize,3.12,,
+func,PyType_IsSubtype,3.2,,
+func,PyType_Modified,3.2,,
+func,PyType_Ready,3.2,,
type,PyType_Slot,3.2,,full-abi
type,PyType_Spec,3.2,,full-abi
-var,PyType_Type,3.2,,
-function,PyUnicodeDecodeError_Create,3.2,,
-function,PyUnicodeDecodeError_GetEncoding,3.2,,
-function,PyUnicodeDecodeError_GetEnd,3.2,,
-function,PyUnicodeDecodeError_GetObject,3.2,,
-function,PyUnicodeDecodeError_GetReason,3.2,,
-function,PyUnicodeDecodeError_GetStart,3.2,,
-function,PyUnicodeDecodeError_SetEnd,3.2,,
-function,PyUnicodeDecodeError_SetReason,3.2,,
-function,PyUnicodeDecodeError_SetStart,3.2,,
-function,PyUnicodeEncodeError_GetEncoding,3.2,,
-function,PyUnicodeEncodeError_GetEnd,3.2,,
-function,PyUnicodeEncodeError_GetObject,3.2,,
-function,PyUnicodeEncodeError_GetReason,3.2,,
-function,PyUnicodeEncodeError_GetStart,3.2,,
-function,PyUnicodeEncodeError_SetEnd,3.2,,
-function,PyUnicodeEncodeError_SetReason,3.2,,
-function,PyUnicodeEncodeError_SetStart,3.2,,
-var,PyUnicodeIter_Type,3.2,,
-function,PyUnicodeTranslateError_GetEnd,3.2,,
-function,PyUnicodeTranslateError_GetObject,3.2,,
-function,PyUnicodeTranslateError_GetReason,3.2,,
-function,PyUnicodeTranslateError_GetStart,3.2,,
-function,PyUnicodeTranslateError_SetEnd,3.2,,
-function,PyUnicodeTranslateError_SetReason,3.2,,
-function,PyUnicodeTranslateError_SetStart,3.2,,
-function,PyUnicode_Append,3.2,,
-function,PyUnicode_AppendAndDel,3.2,,
-function,PyUnicode_AsASCIIString,3.2,,
-function,PyUnicode_AsCharmapString,3.2,,
-function,PyUnicode_AsDecodedObject,3.2,,
-function,PyUnicode_AsDecodedUnicode,3.2,,
-function,PyUnicode_AsEncodedObject,3.2,,
-function,PyUnicode_AsEncodedString,3.2,,
-function,PyUnicode_AsEncodedUnicode,3.2,,
-function,PyUnicode_AsLatin1String,3.2,,
-function,PyUnicode_AsMBCSString,3.7,on Windows,
-function,PyUnicode_AsRawUnicodeEscapeString,3.2,,
-function,PyUnicode_AsUCS4,3.7,,
-function,PyUnicode_AsUCS4Copy,3.7,,
-function,PyUnicode_AsUTF16String,3.2,,
-function,PyUnicode_AsUTF32String,3.2,,
-function,PyUnicode_AsUTF8AndSize,3.10,,
-function,PyUnicode_AsUTF8String,3.2,,
-function,PyUnicode_AsUnicodeEscapeString,3.2,,
-function,PyUnicode_AsWideChar,3.2,,
-function,PyUnicode_AsWideCharString,3.7,,
-function,PyUnicode_BuildEncodingMap,3.2,,
-function,PyUnicode_Compare,3.2,,
-function,PyUnicode_CompareWithASCIIString,3.2,,
-function,PyUnicode_Concat,3.2,,
-function,PyUnicode_Contains,3.2,,
-function,PyUnicode_Count,3.2,,
-function,PyUnicode_Decode,3.2,,
-function,PyUnicode_DecodeASCII,3.2,,
-function,PyUnicode_DecodeCharmap,3.2,,
-function,PyUnicode_DecodeCodePageStateful,3.7,on Windows,
-function,PyUnicode_DecodeFSDefault,3.2,,
-function,PyUnicode_DecodeFSDefaultAndSize,3.2,,
-function,PyUnicode_DecodeLatin1,3.2,,
-function,PyUnicode_DecodeLocale,3.7,,
-function,PyUnicode_DecodeLocaleAndSize,3.7,,
-function,PyUnicode_DecodeMBCS,3.7,on Windows,
-function,PyUnicode_DecodeMBCSStateful,3.7,on Windows,
-function,PyUnicode_DecodeRawUnicodeEscape,3.2,,
-function,PyUnicode_DecodeUTF16,3.2,,
-function,PyUnicode_DecodeUTF16Stateful,3.2,,
-function,PyUnicode_DecodeUTF32,3.2,,
-function,PyUnicode_DecodeUTF32Stateful,3.2,,
-function,PyUnicode_DecodeUTF7,3.2,,
-function,PyUnicode_DecodeUTF7Stateful,3.2,,
-function,PyUnicode_DecodeUTF8,3.2,,
-function,PyUnicode_DecodeUTF8Stateful,3.2,,
-function,PyUnicode_DecodeUnicodeEscape,3.2,,
-function,PyUnicode_EncodeCodePage,3.7,on Windows,
-function,PyUnicode_EncodeFSDefault,3.2,,
-function,PyUnicode_EncodeLocale,3.7,,
-function,PyUnicode_EqualToUTF8,3.13,,
-function,PyUnicode_EqualToUTF8AndSize,3.13,,
-function,PyUnicode_FSConverter,3.2,,
-function,PyUnicode_FSDecoder,3.2,,
-function,PyUnicode_Find,3.2,,
-function,PyUnicode_FindChar,3.7,,
-function,PyUnicode_Format,3.2,,
-function,PyUnicode_FromEncodedObject,3.2,,
-function,PyUnicode_FromFormat,3.2,,
-function,PyUnicode_FromFormatV,3.2,,
-function,PyUnicode_FromObject,3.2,,
-function,PyUnicode_FromOrdinal,3.2,,
-function,PyUnicode_FromString,3.2,,
-function,PyUnicode_FromStringAndSize,3.2,,
-function,PyUnicode_FromWideChar,3.2,,
-function,PyUnicode_GetDefaultEncoding,3.2,,
-function,PyUnicode_GetLength,3.7,,
-function,PyUnicode_InternFromString,3.2,,
-function,PyUnicode_InternInPlace,3.2,,
-function,PyUnicode_IsIdentifier,3.2,,
-function,PyUnicode_Join,3.2,,
-function,PyUnicode_Partition,3.2,,
-function,PyUnicode_RPartition,3.2,,
-function,PyUnicode_RSplit,3.2,,
-function,PyUnicode_ReadChar,3.7,,
-function,PyUnicode_Replace,3.2,,
-function,PyUnicode_Resize,3.2,,
-function,PyUnicode_RichCompare,3.2,,
-function,PyUnicode_Split,3.2,,
-function,PyUnicode_Splitlines,3.2,,
-function,PyUnicode_Substring,3.7,,
-function,PyUnicode_Tailmatch,3.2,,
-function,PyUnicode_Translate,3.2,,
-var,PyUnicode_Type,3.2,,
-function,PyUnicode_WriteChar,3.7,,
+data,PyType_Type,3.2,,
+func,PyUnicodeDecodeError_Create,3.2,,
+func,PyUnicodeDecodeError_GetEncoding,3.2,,
+func,PyUnicodeDecodeError_GetEnd,3.2,,
+func,PyUnicodeDecodeError_GetObject,3.2,,
+func,PyUnicodeDecodeError_GetReason,3.2,,
+func,PyUnicodeDecodeError_GetStart,3.2,,
+func,PyUnicodeDecodeError_SetEnd,3.2,,
+func,PyUnicodeDecodeError_SetReason,3.2,,
+func,PyUnicodeDecodeError_SetStart,3.2,,
+func,PyUnicodeEncodeError_GetEncoding,3.2,,
+func,PyUnicodeEncodeError_GetEnd,3.2,,
+func,PyUnicodeEncodeError_GetObject,3.2,,
+func,PyUnicodeEncodeError_GetReason,3.2,,
+func,PyUnicodeEncodeError_GetStart,3.2,,
+func,PyUnicodeEncodeError_SetEnd,3.2,,
+func,PyUnicodeEncodeError_SetReason,3.2,,
+func,PyUnicodeEncodeError_SetStart,3.2,,
+data,PyUnicodeIter_Type,3.2,,
+func,PyUnicodeTranslateError_GetEnd,3.2,,
+func,PyUnicodeTranslateError_GetObject,3.2,,
+func,PyUnicodeTranslateError_GetReason,3.2,,
+func,PyUnicodeTranslateError_GetStart,3.2,,
+func,PyUnicodeTranslateError_SetEnd,3.2,,
+func,PyUnicodeTranslateError_SetReason,3.2,,
+func,PyUnicodeTranslateError_SetStart,3.2,,
+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,,
+func,PyUnicode_AsUCS4,3.7,,
+func,PyUnicode_AsUCS4Copy,3.7,,
+func,PyUnicode_AsUTF16String,3.2,,
+func,PyUnicode_AsUTF32String,3.2,,
+func,PyUnicode_AsUTF8AndSize,3.10,,
+func,PyUnicode_AsUTF8String,3.2,,
+func,PyUnicode_AsUnicodeEscapeString,3.2,,
+func,PyUnicode_AsWideChar,3.2,,
+func,PyUnicode_AsWideCharString,3.7,,
+func,PyUnicode_BuildEncodingMap,3.2,,
+func,PyUnicode_Compare,3.2,,
+func,PyUnicode_CompareWithASCIIString,3.2,,
+func,PyUnicode_Concat,3.2,,
+func,PyUnicode_Contains,3.2,,
+func,PyUnicode_Count,3.2,,
+func,PyUnicode_Decode,3.2,,
+func,PyUnicode_DecodeASCII,3.2,,
+func,PyUnicode_DecodeCharmap,3.2,,
+func,PyUnicode_DecodeCodePageStateful,3.7,on Windows,
+func,PyUnicode_DecodeFSDefault,3.2,,
+func,PyUnicode_DecodeFSDefaultAndSize,3.2,,
+func,PyUnicode_DecodeLatin1,3.2,,
+func,PyUnicode_DecodeLocale,3.7,,
+func,PyUnicode_DecodeLocaleAndSize,3.7,,
+func,PyUnicode_DecodeMBCS,3.7,on Windows,
+func,PyUnicode_DecodeMBCSStateful,3.7,on Windows,
+func,PyUnicode_DecodeRawUnicodeEscape,3.2,,
+func,PyUnicode_DecodeUTF16,3.2,,
+func,PyUnicode_DecodeUTF16Stateful,3.2,,
+func,PyUnicode_DecodeUTF32,3.2,,
+func,PyUnicode_DecodeUTF32Stateful,3.2,,
+func,PyUnicode_DecodeUTF7,3.2,,
+func,PyUnicode_DecodeUTF7Stateful,3.2,,
+func,PyUnicode_DecodeUTF8,3.2,,
+func,PyUnicode_DecodeUTF8Stateful,3.2,,
+func,PyUnicode_DecodeUnicodeEscape,3.2,,
+func,PyUnicode_EncodeCodePage,3.7,on Windows,
+func,PyUnicode_EncodeFSDefault,3.2,,
+func,PyUnicode_EncodeLocale,3.7,,
+func,PyUnicode_EqualToUTF8,3.13,,
+func,PyUnicode_EqualToUTF8AndSize,3.13,,
+func,PyUnicode_FSConverter,3.2,,
+func,PyUnicode_FSDecoder,3.2,,
+func,PyUnicode_Find,3.2,,
+func,PyUnicode_FindChar,3.7,,
+func,PyUnicode_Format,3.2,,
+func,PyUnicode_FromEncodedObject,3.2,,
+func,PyUnicode_FromFormat,3.2,,
+func,PyUnicode_FromFormatV,3.2,,
+func,PyUnicode_FromObject,3.2,,
+func,PyUnicode_FromOrdinal,3.2,,
+func,PyUnicode_FromString,3.2,,
+func,PyUnicode_FromStringAndSize,3.2,,
+func,PyUnicode_FromWideChar,3.2,,
+func,PyUnicode_GetDefaultEncoding,3.2,,
+func,PyUnicode_GetLength,3.7,,
+func,PyUnicode_InternFromString,3.2,,
+func,PyUnicode_InternInPlace,3.2,,
+func,PyUnicode_IsIdentifier,3.2,,
+func,PyUnicode_Join,3.2,,
+func,PyUnicode_Partition,3.2,,
+func,PyUnicode_RPartition,3.2,,
+func,PyUnicode_RSplit,3.2,,
+func,PyUnicode_ReadChar,3.7,,
+func,PyUnicode_Replace,3.2,,
+func,PyUnicode_Resize,3.2,,
+func,PyUnicode_RichCompare,3.2,,
+func,PyUnicode_Split,3.2,,
+func,PyUnicode_Splitlines,3.2,,
+func,PyUnicode_Substring,3.7,,
+func,PyUnicode_Tailmatch,3.2,,
+func,PyUnicode_Translate,3.2,,
+data,PyUnicode_Type,3.2,,
+func,PyUnicode_WriteChar,3.7,,
type,PyVarObject,3.2,,members
member,PyVarObject.ob_base,3.2,,
member,PyVarObject.ob_size,3.2,,
-function,PyVectorcall_Call,3.12,,
-function,PyVectorcall_NARGS,3.12,,
+func,PyVectorcall_Call,3.12,,
+func,PyVectorcall_NARGS,3.12,,
type,PyWeakReference,3.2,,opaque
-function,PyWeakref_GetObject,3.2,,
-function,PyWeakref_GetRef,3.13,,
-function,PyWeakref_NewProxy,3.2,,
-function,PyWeakref_NewRef,3.2,,
-var,PyWrapperDescr_Type,3.2,,
-function,PyWrapper_New,3.2,,
-var,PyZip_Type,3.2,,
-function,Py_AddPendingCall,3.2,,
-function,Py_AtExit,3.2,,
+func,PyWeakref_GetObject,3.2,,
+func,PyWeakref_GetRef,3.13,,
+func,PyWeakref_NewProxy,3.2,,
+func,PyWeakref_NewRef,3.2,,
+data,PyWrapperDescr_Type,3.2,,
+func,PyWrapper_New,3.2,,
+data,PyZip_Type,3.2,,
+func,Py_AddPendingCall,3.2,,
+func,Py_AtExit,3.2,,
macro,Py_BEGIN_ALLOW_THREADS,3.2,,
macro,Py_BLOCK_THREADS,3.2,,
-function,Py_BuildValue,3.2,,
-function,Py_BytesMain,3.8,,
-function,Py_CompileString,3.2,,
-function,Py_DecRef,3.2,,
-function,Py_DecodeLocale,3.7,,
+func,Py_BuildValue,3.2,,
+func,Py_BytesMain,3.8,,
+func,Py_CompileString,3.2,,
+func,Py_DecRef,3.2,,
+func,Py_DecodeLocale,3.7,,
macro,Py_END_ALLOW_THREADS,3.2,,
-function,Py_EncodeLocale,3.7,,
-function,Py_EndInterpreter,3.2,,
-function,Py_EnterRecursiveCall,3.9,,
-function,Py_Exit,3.2,,
-function,Py_FatalError,3.2,,
-var,Py_FileSystemDefaultEncodeErrors,3.10,,
-var,Py_FileSystemDefaultEncoding,3.2,,
-function,Py_Finalize,3.2,,
-function,Py_FinalizeEx,3.6,,
-function,Py_GenericAlias,3.9,,
-var,Py_GenericAliasType,3.9,,
-function,Py_GetBuildInfo,3.2,,
-function,Py_GetCompiler,3.2,,
-function,Py_GetConstant,3.13,,
-function,Py_GetConstantBorrowed,3.13,,
-function,Py_GetCopyright,3.2,,
-function,Py_GetExecPrefix,3.2,,
-function,Py_GetPath,3.2,,
-function,Py_GetPlatform,3.2,,
-function,Py_GetPrefix,3.2,,
-function,Py_GetProgramFullPath,3.2,,
-function,Py_GetProgramName,3.2,,
-function,Py_GetPythonHome,3.2,,
-function,Py_GetRecursionLimit,3.2,,
-function,Py_GetVersion,3.2,,
-var,Py_HasFileSystemDefaultEncoding,3.2,,
-function,Py_IncRef,3.2,,
-function,Py_Initialize,3.2,,
-function,Py_InitializeEx,3.2,,
-function,Py_Is,3.10,,
-function,Py_IsFalse,3.10,,
-function,Py_IsFinalizing,3.13,,
-function,Py_IsInitialized,3.2,,
-function,Py_IsNone,3.10,,
-function,Py_IsTrue,3.10,,
-function,Py_LeaveRecursiveCall,3.9,,
-function,Py_Main,3.2,,
-function,Py_MakePendingCalls,3.2,,
-function,Py_NewInterpreter,3.2,,
-function,Py_NewRef,3.10,,
-function,Py_ReprEnter,3.2,,
-function,Py_ReprLeave,3.2,,
-function,Py_SetProgramName,3.2,,
-function,Py_SetPythonHome,3.2,,
-function,Py_SetRecursionLimit,3.2,,
+func,Py_EncodeLocale,3.7,,
+func,Py_EndInterpreter,3.2,,
+func,Py_EnterRecursiveCall,3.9,,
+func,Py_Exit,3.2,,
+func,Py_FatalError,3.2,,
+data,Py_FileSystemDefaultEncodeErrors,3.10,,
+data,Py_FileSystemDefaultEncoding,3.2,,
+func,Py_Finalize,3.2,,
+func,Py_FinalizeEx,3.6,,
+func,Py_GenericAlias,3.9,,
+data,Py_GenericAliasType,3.9,,
+func,Py_GetBuildInfo,3.2,,
+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,,
+func,Py_IncRef,3.2,,
+func,Py_Initialize,3.2,,
+func,Py_InitializeEx,3.2,,
+func,Py_Is,3.10,,
+func,Py_IsFalse,3.10,,
+func,Py_IsFinalizing,3.13,,
+func,Py_IsInitialized,3.2,,
+func,Py_IsNone,3.10,,
+func,Py_IsTrue,3.10,,
+func,Py_LeaveRecursiveCall,3.9,,
+func,Py_Main,3.2,,
+func,Py_MakePendingCalls,3.2,,
+func,Py_NewInterpreter,3.2,,
+func,Py_NewRef,3.10,,
+func,Py_ReprEnter,3.2,,
+func,Py_ReprLeave,3.2,,
+func,Py_SetProgramName,3.2,,
+func,Py_SetPythonHome,3.2,,
+func,Py_SetRecursionLimit,3.2,,
type,Py_UCS4,3.2,,
macro,Py_UNBLOCK_THREADS,3.2,,
-var,Py_UTF8Mode,3.8,,
-function,Py_VaBuildValue,3.2,,
-var,Py_Version,3.11,,
-function,Py_XNewRef,3.10,,
+data,Py_UTF8Mode,3.8,,
+func,Py_VaBuildValue,3.2,,
+data,Py_Version,3.11,,
+func,Py_XNewRef,3.10,,
type,Py_buffer,3.11,,full-abi
type,Py_intptr_t,3.2,,
type,Py_ssize_t,3.2,,
diff --git a/Doc/deprecations/c-api-pending-removal-in-3.14.rst b/Doc/deprecations/c-api-pending-removal-in-3.14.rst
new file mode 100644
index 00000000000..d16da66c29a
--- /dev/null
+++ b/Doc/deprecations/c-api-pending-removal-in-3.14.rst
@@ -0,0 +1,72 @@
+Pending Removal in Python 3.14
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* The ``ma_version_tag`` field in :c:type:`PyDictObject` for extension modules
+ (:pep:`699`; :gh:`101193`).
+
+* Creating :c:data:`immutable types ` with mutable
+ bases (:gh:`95388`).
+
+* Functions to configure Python's initialization, deprecated in Python 3.11:
+
+ * :c:func:`!PySys_SetArgvEx()`:
+ Set :c:member:`PyConfig.argv` instead.
+ * :c:func:`!PySys_SetArgv()`:
+ Set :c:member:`PyConfig.argv` instead.
+ * :c:func:`!Py_SetProgramName()`:
+ Set :c:member:`PyConfig.program_name` instead.
+ * :c:func:`!Py_SetPythonHome()`:
+ Set :c:member:`PyConfig.home` instead.
+
+ The :c:func:`Py_InitializeFromConfig` API should be used with
+ :c:type:`PyConfig` instead.
+
+* Global configuration variables:
+
+ * :c:var:`Py_DebugFlag`:
+ Use :c:member:`PyConfig.parser_debug` instead.
+ * :c:var:`Py_VerboseFlag`:
+ Use :c:member:`PyConfig.verbose` instead.
+ * :c:var:`Py_QuietFlag`:
+ Use :c:member:`PyConfig.quiet` instead.
+ * :c:var:`Py_InteractiveFlag`:
+ Use :c:member:`PyConfig.interactive` instead.
+ * :c:var:`Py_InspectFlag`:
+ Use :c:member:`PyConfig.inspect` instead.
+ * :c:var:`Py_OptimizeFlag`:
+ Use :c:member:`PyConfig.optimization_level` instead.
+ * :c:var:`Py_NoSiteFlag`:
+ Use :c:member:`PyConfig.site_import` instead.
+ * :c:var:`Py_BytesWarningFlag`:
+ Use :c:member:`PyConfig.bytes_warning` instead.
+ * :c:var:`Py_FrozenFlag`:
+ Use :c:member:`PyConfig.pathconfig_warnings` instead.
+ * :c:var:`Py_IgnoreEnvironmentFlag`:
+ Use :c:member:`PyConfig.use_environment` instead.
+ * :c:var:`Py_DontWriteBytecodeFlag`:
+ Use :c:member:`PyConfig.write_bytecode` instead.
+ * :c:var:`Py_NoUserSiteDirectory`:
+ Use :c:member:`PyConfig.user_site_directory` instead.
+ * :c:var:`Py_UnbufferedStdioFlag`:
+ Use :c:member:`PyConfig.buffered_stdio` instead.
+ * :c:var:`Py_HashRandomizationFlag`:
+ Use :c:member:`PyConfig.use_hash_seed`
+ and :c:member:`PyConfig.hash_seed` instead.
+ * :c:var:`Py_IsolatedFlag`:
+ Use :c:member:`PyConfig.isolated` instead.
+ * :c:var:`Py_LegacyWindowsFSEncodingFlag`:
+ Use :c:member:`PyPreConfig.legacy_windows_fs_encoding` instead.
+ * :c:var:`Py_LegacyWindowsStdioFlag`:
+ Use :c:member:`PyConfig.legacy_windows_stdio` instead.
+ * :c:var:`!Py_FileSystemDefaultEncoding`:
+ Use :c:member:`PyConfig.filesystem_encoding` instead.
+ * :c:var:`!Py_HasFileSystemDefaultEncoding`:
+ Use :c:member:`PyConfig.filesystem_encoding` instead.
+ * :c:var:`!Py_FileSystemDefaultEncodeErrors`:
+ Use :c:member:`PyConfig.filesystem_errors` instead.
+ * :c:var:`!Py_UTF8Mode`:
+ Use :c:member:`PyPreConfig.utf8_mode` instead.
+ (see :c:func:`Py_PreInitialize`)
+
+ The :c:func:`Py_InitializeFromConfig` API should be used with
+ :c:type:`PyConfig` instead.
diff --git a/Doc/deprecations/c-api-pending-removal-in-3.15.rst b/Doc/deprecations/c-api-pending-removal-in-3.15.rst
new file mode 100644
index 00000000000..e3974415e0c
--- /dev/null
+++ b/Doc/deprecations/c-api-pending-removal-in-3.15.rst
@@ -0,0 +1,27 @@
+Pending Removal in Python 3.15
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* The bundled copy of ``libmpdecimal``.
+* 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.
+* :c:type:`Py_UNICODE` type and the :c:macro:`!Py_UNICODE_WIDE` macro:
+ Use :c:type:`wchar_t` instead.
+* Python initialization functions:
+
+ * :c:func:`PySys_ResetWarnOptions`:
+ Clear :data:`sys.warnoptions` and :data:`!warnings.filters` instead.
+ * :c:func:`Py_GetExecPrefix`:
+ Get :data:`sys.exec_prefix` instead.
+ * :c:func:`Py_GetPath`:
+ Get :data:`sys.path` instead.
+ * :c:func:`Py_GetPrefix`:
+ Get :data:`sys.prefix` instead.
+ * :c:func:`Py_GetProgramFullPath`:
+ Get :data:`sys.executable` instead.
+ * :c:func:`Py_GetProgramName`:
+ Get :data:`sys.executable` instead.
+ * :c:func:`Py_GetPythonHome`:
+ Get :c:member:`PyConfig.home`
+ or the :envvar:`PYTHONHOME` environment variable instead.
diff --git a/Doc/deprecations/c-api-pending-removal-in-future.rst b/Doc/deprecations/c-api-pending-removal-in-future.rst
new file mode 100644
index 00000000000..0c3ae52b87f
--- /dev/null
+++ b/Doc/deprecations/c-api-pending-removal-in-future.rst
@@ -0,0 +1,51 @@
+Pending Removal in Future Versions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following APIs are deprecated and will be removed,
+although there is currently no date scheduled for their removal.
+
+* :c:macro:`Py_TPFLAGS_HAVE_FINALIZE`:
+ Unneeded since Python 3.8.
+* :c:func:`PyErr_Fetch`:
+ Use :c:func:`PyErr_GetRaisedException` instead.
+* :c:func:`PyErr_NormalizeException`:
+ Use :c:func:`PyErr_GetRaisedException` instead.
+* :c:func:`PyErr_Restore`:
+ Use :c:func:`PyErr_SetRaisedException` instead.
+* :c:func:`PyModule_GetFilename`:
+ Use :c:func:`PyModule_GetFilenameObject` instead.
+* :c:func:`PyOS_AfterFork`:
+ Use :c:func:`PyOS_AfterFork_Child` instead.
+* :c:func:`PySlice_GetIndicesEx`:
+ Use :c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices` instead.
+* :c:func:`!PyUnicode_AsDecodedObject`:
+ Use :c:func:`PyCodec_Decode` instead.
+* :c:func:`!PyUnicode_AsDecodedUnicode`:
+ Use :c:func:`PyCodec_Decode` instead.
+* :c:func:`!PyUnicode_AsEncodedObject`:
+ Use :c:func:`PyCodec_Encode` instead.
+* :c:func:`!PyUnicode_AsEncodedUnicode`:
+ Use :c:func:`PyCodec_Encode` instead.
+* :c:func:`PyUnicode_READY`:
+ Unneeded since Python 3.12
+* :c:func:`!PyErr_Display`:
+ Use :c:func:`PyErr_DisplayException` instead.
+* :c:func:`!_PyErr_ChainExceptions`:
+ Use :c:func:`!_PyErr_ChainExceptions1` instead.
+* :c:member:`!PyBytesObject.ob_shash` member:
+ call :c:func:`PyObject_Hash` instead.
+* :c:member:`!PyDictObject.ma_version_tag` member.
+* Thread Local Storage (TLS) API:
+
+ * :c:func:`PyThread_create_key`:
+ Use :c:func:`PyThread_tss_alloc` instead.
+ * :c:func:`PyThread_delete_key`:
+ Use :c:func:`PyThread_tss_free` instead.
+ * :c:func:`PyThread_set_key_value`:
+ Use :c:func:`PyThread_tss_set` instead.
+ * :c:func:`PyThread_get_key_value`:
+ Use :c:func:`PyThread_tss_get` instead.
+ * :c:func:`PyThread_delete_key_value`:
+ Use :c:func:`PyThread_tss_delete` instead.
+ * :c:func:`PyThread_ReInitTLS`:
+ Unneeded since Python 3.7.
diff --git a/Doc/deprecations/index.rst b/Doc/deprecations/index.rst
new file mode 100644
index 00000000000..5aa7062aca2
--- /dev/null
+++ b/Doc/deprecations/index.rst
@@ -0,0 +1,19 @@
+Deprecations
+============
+
+.. include:: pending-removal-in-3.14.rst
+
+.. include:: pending-removal-in-3.15.rst
+
+.. include:: pending-removal-in-3.16.rst
+
+.. include:: pending-removal-in-future.rst
+
+C API Deprecations
+------------------
+
+.. include:: c-api-pending-removal-in-3.14.rst
+
+.. include:: c-api-pending-removal-in-3.15.rst
+
+.. include:: c-api-pending-removal-in-future.rst
diff --git a/Doc/deprecations/pending-removal-in-3.13.rst b/Doc/deprecations/pending-removal-in-3.13.rst
new file mode 100644
index 00000000000..89790497816
--- /dev/null
+++ b/Doc/deprecations/pending-removal-in-3.13.rst
@@ -0,0 +1,52 @@
+Pending Removal in Python 3.13
+------------------------------
+
+Modules (see :pep:`594`):
+
+* :mod:`!aifc`
+* :mod:`!audioop`
+* :mod:`!cgi`
+* :mod:`!cgitb`
+* :mod:`!chunk`
+* :mod:`!crypt`
+* :mod:`!imghdr`
+* :mod:`!mailcap`
+* :mod:`!msilib`
+* :mod:`!nis`
+* :mod:`!nntplib`
+* :mod:`!ossaudiodev`
+* :mod:`!pipes`
+* :mod:`!sndhdr`
+* :mod:`!spwd`
+* :mod:`!sunau`
+* :mod:`!telnetlib`
+* :mod:`!uu`
+* :mod:`!xdrlib`
+
+Other modules:
+
+* :mod:`!lib2to3`, and the :program:`2to3` program (:gh:`84540`)
+
+APIs:
+
+* :class:`!configparser.LegacyInterpolation` (:gh:`90765`)
+* ``locale.resetlocale()`` (:gh:`90817`)
+* :meth:`!turtle.RawTurtle.settiltangle` (:gh:`50096`)
+* :func:`!unittest.findTestCases` (:gh:`50096`)
+* :func:`!unittest.getTestCaseNames` (:gh:`50096`)
+* :func:`!unittest.makeSuite` (:gh:`50096`)
+* :meth:`!unittest.TestProgram.usageExit` (:gh:`67048`)
+* :class:`!webbrowser.MacOSX` (:gh:`86421`)
+* :class:`classmethod` descriptor chaining (:gh:`89519`)
+* :mod:`importlib.resources` deprecated methods:
+
+ * ``contents()``
+ * ``is_resource()``
+ * ``open_binary()``
+ * ``open_text()``
+ * ``path()``
+ * ``read_binary()``
+ * ``read_text()``
+
+ Use :func:`importlib.resources.files` instead. Refer to `importlib-resources: Migrating from Legacy
+ `_ (:gh:`106531`)
diff --git a/Doc/deprecations/pending-removal-in-3.14.rst b/Doc/deprecations/pending-removal-in-3.14.rst
new file mode 100644
index 00000000000..330b426deac
--- /dev/null
+++ b/Doc/deprecations/pending-removal-in-3.14.rst
@@ -0,0 +1,115 @@
+Pending Removal in Python 3.14
+------------------------------
+
+* :mod:`argparse`: The *type*, *choices*, and *metavar* parameters
+ of :class:`!argparse.BooleanOptionalAction` are deprecated
+ and will be removed in 3.14.
+ (Contributed by Nikita Sobolev in :gh:`92248`.)
+
+* :mod:`ast`: The following features have been deprecated in documentation
+ since Python 3.8, now cause a :exc:`DeprecationWarning` to be emitted at
+ runtime when they are accessed or used, and will be removed in Python 3.14:
+
+ * :class:`!ast.Num`
+ * :class:`!ast.Str`
+ * :class:`!ast.Bytes`
+ * :class:`!ast.NameConstant`
+ * :class:`!ast.Ellipsis`
+
+ Use :class:`ast.Constant` instead.
+ (Contributed by Serhiy Storchaka in :gh:`90953`.)
+
+* :mod:`asyncio`:
+
+ * The child watcher classes :class:`~asyncio.MultiLoopChildWatcher`,
+ :class:`~asyncio.FastChildWatcher`, :class:`~asyncio.AbstractChildWatcher`
+ and :class:`~asyncio.SafeChildWatcher` are deprecated and
+ will be removed in Python 3.14.
+ (Contributed by Kumar Aditya in :gh:`94597`.)
+
+ * :func:`asyncio.set_child_watcher`, :func:`asyncio.get_child_watcher`,
+ :meth:`asyncio.AbstractEventLoopPolicy.set_child_watcher` and
+ :meth:`asyncio.AbstractEventLoopPolicy.get_child_watcher` are deprecated
+ and will be removed in Python 3.14.
+ (Contributed by Kumar Aditya in :gh:`94597`.)
+
+ * The :meth:`~asyncio.get_event_loop` method of the
+ default event loop policy now emits a :exc:`DeprecationWarning` if there
+ is no current event loop set and it decides to create one.
+ (Contributed by Serhiy Storchaka and Guido van Rossum in :gh:`100160`.)
+
+* :mod:`collections.abc`: Deprecated :class:`~collections.abc.ByteString`.
+ Prefer :class:`!Sequence` or :class:`~collections.abc.Buffer`.
+ For use in typing, prefer a union, like ``bytes | bytearray``,
+ or :class:`collections.abc.Buffer`.
+ (Contributed by Shantanu Jain in :gh:`91896`.)
+
+* :mod:`email`: Deprecated the *isdst* parameter in :func:`email.utils.localtime`.
+ (Contributed by Alan Williams in :gh:`72346`.)
+
+* :mod:`importlib.abc` deprecated classes:
+
+ * :class:`!importlib.abc.ResourceReader`
+ * :class:`!importlib.abc.Traversable`
+ * :class:`!importlib.abc.TraversableResources`
+
+ Use :mod:`importlib.resources.abc` classes instead:
+
+ * :class:`importlib.resources.abc.Traversable`
+ * :class:`importlib.resources.abc.TraversableResources`
+
+ (Contributed by Jason R. Coombs and Hugo van Kemenade in :gh:`93963`.)
+
+* :mod:`itertools` had undocumented, inefficient, historically buggy,
+ and inconsistent support for copy, deepcopy, and pickle operations.
+ This will be removed in 3.14 for a significant reduction in code
+ volume and maintenance burden.
+ (Contributed by Raymond Hettinger in :gh:`101588`.)
+
+* :mod:`multiprocessing`: The default start method will change to a safer one on
+ Linux, BSDs, and other non-macOS POSIX platforms where ``'fork'`` is currently
+ the default (:gh:`84559`). Adding a runtime warning about this was deemed too
+ disruptive as the majority of code is not expected to care. Use the
+ :func:`~multiprocessing.get_context` or
+ :func:`~multiprocessing.set_start_method` APIs to explicitly specify when
+ your code *requires* ``'fork'``. See :ref:`multiprocessing-start-methods`.
+
+* :mod:`pathlib`: :meth:`~pathlib.PurePath.is_relative_to` and
+ :meth:`~pathlib.PurePath.relative_to`: passing additional arguments is
+ deprecated.
+
+* :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`.)
+
+* :mod:`pty`:
+
+ * ``master_open()``: use :func:`pty.openpty`.
+ * ``slave_open()``: use :func:`pty.openpty`.
+
+* :mod:`sqlite3`:
+
+ * :data:`~sqlite3.version` and :data:`~sqlite3.version_info`.
+
+ * :meth:`~sqlite3.Cursor.execute` and :meth:`~sqlite3.Cursor.executemany`
+ if :ref:`named placeholders ` are used and
+ *parameters* is a sequence instead of a :class:`dict`.
+
+ * date and datetime adapter, date and timestamp converter:
+ see the :mod:`sqlite3` documentation for suggested replacement recipes.
+
+* :class:`types.CodeType`: Accessing :attr:`~codeobject.co_lnotab` was
+ deprecated in :pep:`626`
+ since 3.10 and was planned to be removed in 3.12,
+ but it only got a proper :exc:`DeprecationWarning` in 3.12.
+ May be removed in 3.14.
+ (Contributed by Nikita Sobolev in :gh:`101866`.)
+
+* :mod:`typing`: :class:`~typing.ByteString`, deprecated since Python 3.9,
+ now causes a :exc:`DeprecationWarning` to be emitted when it is used.
+
+* :mod:`urllib`:
+ :class:`!urllib.parse.Quoter` is deprecated: it was not intended to be a
+ public API.
+ (Contributed by Gregory P. Smith in :gh:`88168`.)
diff --git a/Doc/deprecations/pending-removal-in-3.15.rst b/Doc/deprecations/pending-removal-in-3.15.rst
new file mode 100644
index 00000000000..b921b4f97d5
--- /dev/null
+++ b/Doc/deprecations/pending-removal-in-3.15.rst
@@ -0,0 +1,71 @@
+Pending Removal in Python 3.15
+------------------------------
+
+* :mod:`ctypes`:
+
+ * The undocumented :func:`!ctypes.SetPointerType` function
+ has been deprecated since Python 3.13.
+
+* :mod:`http.server`:
+
+ * The obsolete and rarely used :class:`~http.server.CGIHTTPRequestHandler`
+ has been deprecated since Python 3.13.
+ No direct replacement exists.
+ *Anything* is better than CGI to interface
+ a web server with a request handler.
+
+ * The :option:`!--cgi` flag to the :program:`python -m http.server`
+ command-line interface has been deprecated since Python 3.13.
+
+* :mod:`importlib`: ``__package__`` and ``__cached__`` will cease to be set or
+ taken into consideration by the import system (:gh:`97879`).
+
+* :class:`locale`:
+
+ * The :func:`~locale.getdefaultlocale` function
+ has been deprecated since Python 3.11.
+ Its removal was originally planned for Python 3.13 (:gh:`90817`),
+ but has been postponed to Python 3.15.
+ Use :func:`~locale.getlocale`, :func:`~locale.setlocale`,
+ and :func:`~locale.getencoding` instead.
+ (Contributed by Hugo van Kemenade in :gh:`111187`.)
+
+* :mod:`pathlib`:
+
+ * :meth:`.PurePath.is_reserved`
+ has been deprecated since Python 3.13.
+ Use :func:`os.path.isreserved` to detect reserved paths on Windows.
+
+* :mod:`platform`:
+
+ * :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.
+
+* :mod:`threading`:
+
+ * :func:`~threading.RLock` will take no arguments in Python 3.15.
+ Passing any arguments has been deprecated since Python 3.14,
+ as the Python version does not permit any arguments,
+ but the C version allows any number of positional or keyword arguments,
+ ignoring every argument.
+
+* :mod:`typing`:
+
+ * The undocumented keyword argument syntax for creating
+ :class:`~typing.NamedTuple` classes
+ (e.g. ``Point = NamedTuple("Point", x=int, y=int)``)
+ has been deprecated since Python 3.13.
+ Use the class-based syntax or the functional syntax instead.
+
+ * The :func:`typing.no_type_check_decorator` decorator function
+ has been deprecated since Python 3.13.
+ After eight years in the :mod:`typing` module,
+ it has yet to be supported by any major type checker.
+
+* :mod:`wave`:
+
+ * The :meth:`~wave.Wave_read.getmark`, :meth:`!setmark`,
+ and :meth:`~wave.Wave_read.getmarkers` methods of
+ the :class:`~wave.Wave_read` and :class:`~wave.Wave_write` classes
+ have been deprecated since Python 3.13.
diff --git a/Doc/deprecations/pending-removal-in-3.16.rst b/Doc/deprecations/pending-removal-in-3.16.rst
new file mode 100644
index 00000000000..446cc63cb34
--- /dev/null
+++ b/Doc/deprecations/pending-removal-in-3.16.rst
@@ -0,0 +1,42 @@
+Pending Removal in Python 3.16
+------------------------------
+
+* :mod:`builtins`:
+
+ * Bitwise inversion on boolean types, ``~True`` or ``~False``
+ has been deprecated since Python 3.12,
+ as it produces surprising and unintuitive results (``-2`` and ``-1``).
+ Use ``not x`` instead for the logical negation of a Boolean.
+ In the rare case that you need the bitwise inversion of
+ the underlying integer, convert to ``int`` explicitly (``~int(x)``).
+
+* :mod:`array`:
+
+ * The ``'u'`` format code (:c:type:`wchar_t`)
+ has been deprecated in documentation since Python 3.3
+ and at runtime since Python 3.13.
+ Use the ``'w'`` format code (:c:type:`Py_UCS4`)
+ for Unicode characters instead.
+
+* :mod:`shutil`:
+
+ * The :class:`!ExecError` exception
+ has been deprecated since Python 3.14.
+ It has not been used by any function in :mod:`!shutil` since Python 3.4,
+ and is now an alias of :exc:`RuntimeError`.
+
+* :mod:`symtable`:
+
+ * The :meth:`Class.get_methods ` method
+ has been deprecated since Python 3.14.
+
+* :mod:`sys`:
+
+ * The :func:`~sys._enablelegacywindowsfsencoding` function
+ has been deprecated since Python 3.13.
+ Use the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment variable instead.
+
+* :mod:`tarfile`:
+
+ * The undocumented and unused :attr:`!TarFile.tarfile` attribute
+ has been deprecated since Python 3.13.
diff --git a/Doc/deprecations/pending-removal-in-future.rst b/Doc/deprecations/pending-removal-in-future.rst
new file mode 100644
index 00000000000..3f9cf6f2082
--- /dev/null
+++ b/Doc/deprecations/pending-removal-in-future.rst
@@ -0,0 +1,155 @@
+Pending Removal in Future Versions
+----------------------------------
+
+The following APIs will be removed in the future,
+although there is currently no date scheduled for their removal.
+
+* :mod:`argparse`: Nesting argument groups and nesting mutually exclusive
+ groups are deprecated.
+
+* :mod:`array`'s ``'u'`` format code (:gh:`57281`)
+
+* :mod:`builtins`:
+
+ * ``bool(NotImplemented)``.
+ * Generators: ``throw(type, exc, tb)`` and ``athrow(type, exc, tb)``
+ signature is deprecated: use ``throw(exc)`` and ``athrow(exc)`` instead,
+ the single argument signature.
+ * Currently Python accepts numeric literals immediately followed by keywords,
+ for example ``0in x``, ``1or x``, ``0if 1else 2``. It allows confusing and
+ ambiguous expressions like ``[0x1for x in y]`` (which can be interpreted as
+ ``[0x1 for x in y]`` or ``[0x1f or x in y]``). A syntax warning is raised
+ if the numeric literal is immediately followed by one of keywords
+ :keyword:`and`, :keyword:`else`, :keyword:`for`, :keyword:`if`,
+ :keyword:`in`, :keyword:`is` and :keyword:`or`. In a future release it
+ will be changed to a syntax error. (:gh:`87999`)
+ * Support for ``__index__()`` and ``__int__()`` method returning non-int type:
+ these methods will be required to return an instance of a strict subclass of
+ :class:`int`.
+ * Support for ``__float__()`` method returning a strict subclass of
+ :class:`float`: these methods will be required to return an instance of
+ :class:`float`.
+ * Support for ``__complex__()`` method returning a strict subclass of
+ :class:`complex`: these methods will be required to return an instance of
+ :class:`complex`.
+ * Delegation of ``int()`` to ``__trunc__()`` method.
+ * Passing a complex number as the *real* or *imag* argument in the
+ :func:`complex` constructor is now deprecated; it should only be passed
+ as a single positional argument.
+ (Contributed by Serhiy Storchaka in :gh:`109218`.)
+
+* :mod:`calendar`: ``calendar.January`` and ``calendar.February`` constants are
+ deprecated and replaced by :data:`calendar.JANUARY` and
+ :data:`calendar.FEBRUARY`.
+ (Contributed by Prince Roshan in :gh:`103636`.)
+
+* :attr:`codeobject.co_lnotab`: use the :meth:`codeobject.co_lines` method
+ instead.
+
+* :mod:`datetime`:
+
+ * :meth:`~datetime.datetime.utcnow`:
+ use ``datetime.datetime.now(tz=datetime.UTC)``.
+ * :meth:`~datetime.datetime.utcfromtimestamp`:
+ use ``datetime.datetime.fromtimestamp(timestamp, tz=datetime.UTC)``.
+
+* :mod:`gettext`: Plural value must be an integer.
+
+* :mod:`importlib`:
+
+ * ``load_module()`` method: use ``exec_module()`` instead.
+ * :func:`~importlib.util.cache_from_source` *debug_override* parameter is
+ deprecated: use the *optimization* parameter instead.
+
+* :mod:`importlib.metadata`:
+
+ * ``EntryPoints`` tuple interface.
+ * Implicit ``None`` on return values.
+
+* :mod:`logging`: the ``warn()`` method has been deprecated
+ since Python 3.3, use :meth:`~logging.warning` instead.
+
+* :mod:`mailbox`: Use of StringIO input and text mode is deprecated, use
+ BytesIO and binary mode instead.
+
+* :mod:`os`: Calling :func:`os.register_at_fork` in multi-threaded process.
+
+* :class:`!pydoc.ErrorDuringImport`: A tuple value for *exc_info* parameter is
+ deprecated, use an exception instance.
+
+* :mod:`re`: More strict rules are now applied for numerical group references
+ and group names in regular expressions. Only sequence of ASCII digits is now
+ accepted as a numerical reference. The group name in bytes patterns and
+ replacement strings can now only contain ASCII letters and digits and
+ underscore.
+ (Contributed by Serhiy Storchaka in :gh:`91760`.)
+
+* :mod:`!sre_compile`, :mod:`!sre_constants` and :mod:`!sre_parse` modules.
+
+* :mod:`shutil`: :func:`~shutil.rmtree`'s *onerror* parameter is deprecated in
+ Python 3.12; use the *onexc* parameter instead.
+
+* :mod:`ssl` options and protocols:
+
+ * :class:`ssl.SSLContext` without protocol argument is deprecated.
+ * :class:`ssl.SSLContext`: :meth:`~ssl.SSLContext.set_npn_protocols` and
+ :meth:`!selected_npn_protocol` are deprecated: use ALPN
+ instead.
+ * ``ssl.OP_NO_SSL*`` options
+ * ``ssl.OP_NO_TLS*`` options
+ * ``ssl.PROTOCOL_SSLv3``
+ * ``ssl.PROTOCOL_TLS``
+ * ``ssl.PROTOCOL_TLSv1``
+ * ``ssl.PROTOCOL_TLSv1_1``
+ * ``ssl.PROTOCOL_TLSv1_2``
+ * ``ssl.TLSVersion.SSLv3``
+ * ``ssl.TLSVersion.TLSv1``
+ * ``ssl.TLSVersion.TLSv1_1``
+
+* :func:`sysconfig.is_python_build` *check_home* parameter is deprecated and
+ ignored.
+
+* :mod:`threading` methods:
+
+ * :meth:`!threading.Condition.notifyAll`: use :meth:`~threading.Condition.notify_all`.
+ * :meth:`!threading.Event.isSet`: use :meth:`~threading.Event.is_set`.
+ * :meth:`!threading.Thread.isDaemon`, :meth:`threading.Thread.setDaemon`:
+ use :attr:`threading.Thread.daemon` attribute.
+ * :meth:`!threading.Thread.getName`, :meth:`threading.Thread.setName`:
+ use :attr:`threading.Thread.name` attribute.
+ * :meth:`!threading.currentThread`: use :meth:`threading.current_thread`.
+ * :meth:`!threading.activeCount`: use :meth:`threading.active_count`.
+
+* :class:`typing.Text` (:gh:`92332`).
+
+* :class:`unittest.IsolatedAsyncioTestCase`: it is deprecated to return a value
+ that is not ``None`` from a test case.
+
+* :mod:`urllib.parse` deprecated functions: :func:`~urllib.parse.urlparse` instead
+
+ * ``splitattr()``
+ * ``splithost()``
+ * ``splitnport()``
+ * ``splitpasswd()``
+ * ``splitport()``
+ * ``splitquery()``
+ * ``splittag()``
+ * ``splittype()``
+ * ``splituser()``
+ * ``splitvalue()``
+ * ``to_bytes()``
+
+* :mod:`urllib.request`: :class:`~urllib.request.URLopener` and
+ :class:`~urllib.request.FancyURLopener` style of invoking requests is
+ deprecated. Use newer :func:`~urllib.request.urlopen` functions and methods.
+
+* :mod:`wsgiref`: ``SimpleHandler.stdout.write()`` should not do partial
+ writes.
+
+* :mod:`xml.etree.ElementTree`: Testing the truth value of an
+ :class:`~xml.etree.ElementTree.Element` is deprecated. In a future release it
+ will always return ``True``. Prefer explicit ``len(elem)`` or
+ ``elem is not None`` tests instead.
+
+* :meth:`zipimport.zipimporter.load_module` is deprecated:
+ use :meth:`~zipimport.zipimporter.exec_module` instead.
diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst
index fd05c82b416..7f57a3a6aac 100644
--- a/Doc/extending/newtypes.rst
+++ b/Doc/extending/newtypes.rst
@@ -296,7 +296,7 @@ An interesting advantage of using the :c:member:`~PyTypeObject.tp_members` table
descriptors that are used at runtime is that any attribute defined this way can
have an associated doc string simply by providing the text in the table. An
application can use the introspection API to retrieve the descriptor from the
-class object, and get the doc string using its :attr:`!__doc__` attribute.
+class object, and get the doc string using its :attr:`~type.__doc__` attribute.
As with the :c:member:`~PyTypeObject.tp_methods` table, a sentinel entry with a :c:member:`~PyMethodDef.ml_name` value
of ``NULL`` is required.
diff --git a/Doc/extending/newtypes_tutorial.rst b/Doc/extending/newtypes_tutorial.rst
index 7eba9759119..bcf938f117d 100644
--- a/Doc/extending/newtypes_tutorial.rst
+++ b/Doc/extending/newtypes_tutorial.rst
@@ -144,7 +144,7 @@ only used for variable-sized objects and should otherwise be zero.
If you want your type to be subclassable from Python, and your type has the same
:c:member:`~PyTypeObject.tp_basicsize` as its base type, you may have problems with multiple
inheritance. A Python subclass of your type will have to list your type first
- in its :attr:`~class.__bases__`, or else it will not be able to call your type's
+ in its :attr:`~type.__bases__`, or else it will not be able to call your type's
:meth:`~object.__new__` method without getting an error. You can avoid this problem by
ensuring that your type has a larger value for :c:member:`~PyTypeObject.tp_basicsize` than its
base type does. Most of the time, this will be true anyway, because either your
@@ -447,7 +447,7 @@ Further, the attributes can be deleted, setting the C pointers to ``NULL``. Eve
though we can make sure the members are initialized to non-``NULL`` values, the
members can be set to ``NULL`` if the attributes are deleted.
-We define a single method, :meth:`!Custom.name()`, that outputs the objects name as the
+We define a single method, :meth:`!Custom.name`, that outputs the objects name as the
concatenation of the first and last names. ::
static PyObject *
diff --git a/Doc/faq/design.rst b/Doc/faq/design.rst
index c8beb64e39b..e2710fab9cf 100644
--- a/Doc/faq/design.rst
+++ b/Doc/faq/design.rst
@@ -70,7 +70,7 @@ operations. This means that as far as floating-point operations are concerned,
Python behaves like many popular languages including C and Java.
Many numbers that can be written easily in decimal notation cannot be expressed
-exactly in binary floating-point. For example, after::
+exactly in binary floating point. For example, after::
>>> x = 1.2
@@ -87,7 +87,7 @@ which is exactly::
The typical precision of 53 bits provides Python floats with 15--16
decimal digits of accuracy.
-For a fuller explanation, please see the :ref:`floating point arithmetic
+For a fuller explanation, please see the :ref:`floating-point arithmetic
` chapter in the Python tutorial.
@@ -328,7 +328,7 @@ Can Python be compiled to machine code, C or some other language?
-----------------------------------------------------------------
`Cython `_ compiles a modified version of Python with
-optional annotations into C extensions. `Nuitka `_ is
+optional annotations into C extensions. `Nuitka `_ is
an up-and-coming compiler of Python into C++ code, aiming to support the full
Python language.
@@ -345,7 +345,7 @@ to perform a garbage collection, obtain debugging statistics, and tune the
collector's parameters.
Other implementations (such as `Jython `_ or
-`PyPy `_), however, can rely on a different mechanism
+`PyPy `_), however, can rely on a different mechanism
such as a full-blown garbage collector. This difference can cause some
subtle porting problems if your Python code depends on the behavior of the
reference counting implementation.
diff --git a/Doc/faq/extending.rst b/Doc/faq/extending.rst
index 1cff2c4091d..3147fda7c37 100644
--- a/Doc/faq/extending.rst
+++ b/Doc/faq/extending.rst
@@ -246,13 +246,12 @@ Then, when you run GDB:
I want to compile a Python module on my Linux system, but some files are missing. Why?
--------------------------------------------------------------------------------------
-Most packaged versions of Python don't include the
-:file:`/usr/lib/python2.{x}/config/` directory, which contains various files
+Most packaged versions of Python omit some files
required for compiling Python extensions.
-For Red Hat, install the python-devel RPM to get the necessary files.
+For Red Hat, install the python3-devel RPM to get the necessary files.
-For Debian, run ``apt-get install python-dev``.
+For Debian, run ``apt-get install python3-dev``.
How do I tell "incomplete input" from "invalid input"?
------------------------------------------------------
diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst
index eb859c5d599..2a55f6b6fb6 100644
--- a/Doc/faq/general.rst
+++ b/Doc/faq/general.rst
@@ -309,10 +309,10 @@ guaranteed that interfaces will remain the same throughout a series of bugfix
releases.
The latest stable releases can always be found on the `Python download page
-`_. There are two production-ready versions
-of Python: 2.x and 3.x. The recommended version is 3.x, which is supported by
-most widely used libraries. Although 2.x is still widely used, `it is not
-maintained anymore `_.
+`_.
+Python 3.x is the recommended version and supported by most widely used libraries.
+Python 2.x :pep:`is not maintained anymore <373>`.
+
How many people are using Python?
---------------------------------
diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst
index b959cd73921..522923572bf 100644
--- a/Doc/faq/library.rst
+++ b/Doc/faq/library.rst
@@ -796,12 +796,12 @@ is simple::
import random
random.random()
-This returns a random floating point number in the range [0, 1).
+This returns a random floating-point number in the range [0, 1).
There are also many other specialized generators in this module, such as:
* ``randrange(a, b)`` chooses an integer in the range [a, b).
-* ``uniform(a, b)`` chooses a floating point number in the range [a, b).
+* ``uniform(a, b)`` chooses a floating-point number in the range [a, b).
* ``normalvariate(mean, sdev)`` samples the normal (Gaussian) distribution.
Some higher-level functions operate on sequences directly, such as:
diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst
index 0a88c5f6384..fa7b22bde1d 100644
--- a/Doc/faq/programming.rst
+++ b/Doc/faq/programming.rst
@@ -869,7 +869,7 @@ How do I convert a string to a number?
--------------------------------------
For integers, use the built-in :func:`int` type constructor, e.g. ``int('144')
-== 144``. Similarly, :func:`float` converts to floating-point,
+== 144``. Similarly, :func:`float` converts to a floating-point number,
e.g. ``float('144') == 144.0``.
By default, these interpret the number as decimal, so that ``int('0144') ==
@@ -1013,7 +1013,7 @@ Not as such.
For simple input parsing, the easiest approach is usually to split the line into
whitespace-delimited words using the :meth:`~str.split` method of string objects
and then convert decimal strings to numeric values using :func:`int` or
-:func:`float`. :meth:`!split()` supports an optional "sep" parameter which is useful
+:func:`float`. :meth:`!split` supports an optional "sep" parameter which is useful
if the line uses something other than whitespace as a separator.
For more complicated input parsing, regular expressions are more powerful
@@ -1613,9 +1613,16 @@ method too, and it must do so carefully. The basic implementation of
self.__dict__[name] = value
...
-Most :meth:`!__setattr__` implementations must modify
-:meth:`self.__dict__ ` to store
-local state for self without causing an infinite recursion.
+Many :meth:`~object.__setattr__` implementations call :meth:`!object.__setattr__` to set
+an attribute on self without causing infinite recursion::
+
+ class X:
+ def __setattr__(self, name, value):
+ # Custom logic here...
+ object.__setattr__(self, name, value)
+
+Alternatively, it is possible to set attributes by inserting
+entries into :attr:`self.__dict__ ` directly.
How do I call a method defined in a base class from a derived class that extends it?
@@ -1741,11 +1748,31 @@ but effective way to define class private variables. Any identifier of the form
is textually replaced with ``_classname__spam``, where ``classname`` is the
current class name with any leading underscores stripped.
-This doesn't guarantee privacy: an outside user can still deliberately access
-the "_classname__spam" attribute, and private values are visible in the object's
-``__dict__``. Many Python programmers never bother to use private variable
-names at all.
+The identifier can be used unchanged within the class, but to access it outside
+the class, the mangled name must be used:
+
+.. code-block:: python
+
+ class A:
+ def __one(self):
+ return 1
+ def two(self):
+ return 2 * self.__one()
+
+ class B(A):
+ def three(self):
+ return 3 * self._A__one()
+
+ four = 4 * A()._A__one()
+
+In particular, this does not guarantee privacy since an outside user can still
+deliberately access the private attribute; many Python programmers never bother
+to use private variable names at all.
+
+.. seealso::
+ The :ref:`private name mangling specifications `
+ for details and special cases.
My class defines __del__ but it is not called when I delete the object.
-----------------------------------------------------------------------
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index bacbf66b433..17461e23e71 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -342,7 +342,7 @@ Glossary
docstring
A string literal which appears as the first expression in a class,
function or module. While ignored when the suite is executed, it is
- recognized by the compiler and put into the :attr:`!__doc__` attribute
+ recognized by the compiler and put into the :attr:`~definition.__doc__` attribute
of the enclosing class, function or module. Since it is available via
introspection, it is the canonical place for documentation of the
object.
@@ -590,14 +590,12 @@ Glossary
which ships with the standard distribution of Python.
immortal
- If an object is immortal, its reference count is never modified, and
- therefore it is never deallocated.
+ *Immortal objects* are a CPython implementation detail introduced
+ in :pep:`683`.
- Built-in strings and singletons are immortal objects. For example,
- :const:`True` and :const:`None` singletons are immmortal.
-
- See `PEP 683 – Immortal Objects, Using a Fixed Refcount
- `_ for more information.
+ If an object is immortal, its :term:`reference count` is never modified,
+ and therefore it is never deallocated while the interpreter is running.
+ For example, :const:`True` and :const:`None` are immortal in CPython.
immutable
An object with a fixed value. Immutable objects include numbers, strings and
@@ -1123,7 +1121,7 @@ Glossary
:class:`tuple`, and :class:`bytes`. Note that :class:`dict` also
supports :meth:`~object.__getitem__` and :meth:`!__len__`, but is considered a
mapping rather than a sequence because the lookups use arbitrary
- :term:`immutable` keys rather than integers.
+ :term:`hashable` keys rather than integers.
The :class:`collections.abc.Sequence` abstract base class
defines a much richer interface that goes beyond just
@@ -1152,16 +1150,12 @@ Glossary
(subscript) notation uses :class:`slice` objects internally.
soft deprecated
- A soft deprecation can be used when using an API which should no longer
- be used to write new code, but it remains safe to continue using it in
- existing code. The API remains documented and tested, but will not be
- developed further (no enhancement).
-
- The main difference between a "soft" and a (regular) "hard" deprecation
- is that the soft deprecation does not imply scheduling the removal of the
- deprecated API.
+ A soft deprecated API should not be used in new code,
+ but it is safe for already existing code to use it.
+ The API remains documented and tested, but will not be enhanced further.
- Another difference is that a soft deprecation does not issue a warning.
+ Soft deprecation, unlike normal deprecation, does not plan on removing the API
+ and will not emit warnings.
See `PEP 387: Soft Deprecation
`_.
@@ -1233,7 +1227,7 @@ Glossary
type
The type of a Python object determines what kind of object it is; every
object has a type. An object's type is accessible as its
- :attr:`~instance.__class__` attribute or can be retrieved with
+ :attr:`~object.__class__` attribute or can be retrieved with
``type(obj)``.
type alias
diff --git a/Doc/howto/annotations.rst b/Doc/howto/annotations.rst
index be8c7e6c827..174078b84aa 100644
--- a/Doc/howto/annotations.rst
+++ b/Doc/howto/annotations.rst
@@ -102,9 +102,9 @@ Your code will have to have a separate code path if the object
you're examining is a class (``isinstance(o, type)``).
In that case, best practice relies on an implementation detail
of Python 3.9 and before: if a class has annotations defined,
-they are stored in the class's ``__dict__`` dictionary. Since
+they are stored in the class's :attr:`~type.__dict__` dictionary. Since
the class may or may not have annotations defined, best practice
-is to call the ``get`` method on the class dict.
+is to call the :meth:`~dict.get` method on the class dict.
To put it all together, here is some sample code that safely
accesses the ``__annotations__`` attribute on an arbitrary
@@ -121,8 +121,8 @@ the type of ``ann`` using :func:`isinstance` before further
examination.
Note that some exotic or malformed type objects may not have
-a ``__dict__`` attribute, so for extra safety you may also wish
-to use :func:`getattr` to access ``__dict__``.
+a :attr:`~type.__dict__` attribute, so for extra safety you may also wish
+to use :func:`getattr` to access :attr:`!__dict__`.
Manually Un-Stringizing Stringized Annotations
diff --git a/Doc/howto/argparse.rst b/Doc/howto/argparse.rst
index ae5bab90bf8..30d9ac70037 100644
--- a/Doc/howto/argparse.rst
+++ b/Doc/howto/argparse.rst
@@ -444,7 +444,7 @@ And the output:
options:
-h, --help show this help message and exit
- -v {0,1,2}, --verbosity {0,1,2}
+ -v, --verbosity {0,1,2}
increase output verbosity
Note that the change also reflects both in the error message as well as the
diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst
index b29488be39a..c60cd638229 100644
--- a/Doc/howto/descriptor.rst
+++ b/Doc/howto/descriptor.rst
@@ -389,7 +389,9 @@ Here are three practical data validation utilities:
def validate(self, value):
if value not in self.options:
- raise ValueError(f'Expected {value!r} to be one of {self.options!r}')
+ raise ValueError(
+ f'Expected {value!r} to be one of {self.options!r}'
+ )
class Number(Validator):
@@ -469,6 +471,7 @@ The descriptors prevent invalid instances from being created:
Traceback (most recent call last):
...
ValueError: Expected -5 to be at least 0
+
>>> Component('WIDGET', 'metal', 'V') # Blocked: 'V' isn't a number
Traceback (most recent call last):
...
@@ -513,7 +516,7 @@ were defined.
Descriptors are a powerful, general purpose protocol. They are the mechanism
behind properties, methods, static methods, class methods, and
-:func:`super()`. They are used throughout Python itself. Descriptors
+:func:`super`. They are used throughout Python itself. Descriptors
simplify the underlying C code and offer a flexible set of new tools for
everyday Python programs.
@@ -559,8 +562,8 @@ attribute access.
The expression ``obj.x`` looks up the attribute ``x`` in the chain of
namespaces for ``obj``. If the search finds a descriptor outside of the
-instance ``__dict__``, its :meth:`__get__` method is invoked according to the
-precedence rules listed below.
+instance :attr:`~object.__dict__`, its :meth:`~object.__get__` method is
+invoked according to the precedence rules listed below.
The details of invocation depend on whether ``obj`` is an object, class, or
instance of super.
@@ -803,7 +806,7 @@ The full C implementation can be found in :c:func:`!super_getattro` in
Summary of invocation logic
---------------------------
-The mechanism for descriptors is embedded in the :meth:`__getattribute__()`
+The mechanism for descriptors is embedded in the :meth:`__getattribute__`
methods for :class:`object`, :class:`type`, and :func:`super`.
The important points to remember are:
@@ -990,7 +993,7 @@ The documentation shows a typical use to define a managed attribute ``x``:
AttributeError: 'C' object has no attribute '_C__x'
To see how :func:`property` is implemented in terms of the descriptor protocol,
-here is a pure Python equivalent:
+here is a pure Python equivalent that implements most of the core functionality:
.. testcode::
@@ -1004,59 +1007,35 @@ here is a pure Python equivalent:
if doc is None and fget is not None:
doc = fget.__doc__
self.__doc__ = doc
- self._name = None
def __set_name__(self, owner, name):
- self._name = name
-
- @property
- def __name__(self):
- return self._name if self._name is not None else self.fget.__name__
-
- @__name__.setter
- def __name__(self, value):
- self._name = value
+ self.__name__ = name
def __get__(self, obj, objtype=None):
if obj is None:
return self
if self.fget is None:
- raise AttributeError(
- f'property {self.__name__!r} of {type(obj).__name__!r} '
- 'object has no getter'
- )
+ raise AttributeError
return self.fget(obj)
def __set__(self, obj, value):
if self.fset is None:
- raise AttributeError(
- f'property {self.__name__!r} of {type(obj).__name__!r} '
- 'object has no setter'
- )
+ raise AttributeError
self.fset(obj, value)
def __delete__(self, obj):
if self.fdel is None:
- raise AttributeError(
- f'property {self.__name__!r} of {type(obj).__name__!r} '
- 'object has no deleter'
- )
+ raise AttributeError
self.fdel(obj)
def getter(self, fget):
- prop = type(self)(fget, self.fset, self.fdel, self.__doc__)
- prop._name = self._name
- return prop
+ return type(self)(fget, self.fset, self.fdel, self.__doc__)
def setter(self, fset):
- prop = type(self)(self.fget, fset, self.fdel, self.__doc__)
- prop._name = self._name
- return prop
+ return type(self)(self.fget, fset, self.fdel, self.__doc__)
def deleter(self, fdel):
- prop = type(self)(self.fget, self.fset, fdel, self.__doc__)
- prop._name = self._name
- return prop
+ return type(self)(self.fget, self.fset, fdel, self.__doc__)
.. testcode::
:hide:
@@ -1119,23 +1098,23 @@ here is a pure Python equivalent:
>>> try:
... cc.no_getter
... except AttributeError as e:
- ... e.args[0]
+ ... type(e).__name__
...
- "property 'no_getter' of 'CC' object has no getter"
+ 'AttributeError'
>>> try:
... cc.no_setter = 33
... except AttributeError as e:
- ... e.args[0]
+ ... type(e).__name__
...
- "property 'no_setter' of 'CC' object has no setter"
+ 'AttributeError'
>>> try:
... del cc.no_deleter
... except AttributeError as e:
- ... e.args[0]
+ ... type(e).__name__
...
- "property 'no_deleter' of 'CC' object has no deleter"
+ 'AttributeError'
>>> CC.no_doc.__doc__ is None
True
@@ -1326,8 +1305,8 @@ mean, median, and other descriptive statistics that depend on the data. However,
there may be useful functions which are conceptually related but do not depend
on the data. For instance, ``erf(x)`` is handy conversion routine that comes up
in statistical work but does not directly depend on a particular dataset.
-It can be called either from an object or the class: ``s.erf(1.5) --> .9332`` or
-``Sample.erf(1.5) --> .9332``.
+It can be called either from an object or the class: ``s.erf(1.5) --> 0.9332``
+or ``Sample.erf(1.5) --> 0.9332``.
Since static methods return the underlying function with no changes, the
example calls are unexciting:
diff --git a/Doc/howto/enum.rst b/Doc/howto/enum.rst
index 18e13fcf9f5..66929b4104d 100644
--- a/Doc/howto/enum.rst
+++ b/Doc/howto/enum.rst
@@ -9,7 +9,7 @@ Enum HOWTO
.. currentmodule:: enum
An :class:`Enum` is a set of symbolic names bound to unique values. They are
-similar to global variables, but they offer a more useful :func:`repr()`,
+similar to global variables, but they offer a more useful :func:`repr`,
grouping, type-safety, and a few other features.
They are most useful when you have a variable that can take one of a limited
@@ -167,7 +167,7 @@ And a function to display the chores for a given day::
answer SO questions
In cases where the actual values of the members do not matter, you can save
-yourself some work and use :func:`auto()` for the values::
+yourself some work and use :func:`auto` for the values::
>>> from enum import auto
>>> class Weekday(Flag):
@@ -608,7 +608,7 @@ The solution is to specify the module name explicitly as follows::
the source, pickling will be disabled.
The new pickle protocol 4 also, in some circumstances, relies on
-:attr:`~definition.__qualname__` being set to the location where pickle will be able
+:attr:`~type.__qualname__` being set to the location where pickle will be able
to find the class. For example, if the class was made available in class
SomeData in the global scope::
diff --git a/Doc/howto/free-threading-extensions.rst b/Doc/howto/free-threading-extensions.rst
index 1ba91b09516..6abe93d71ad 100644
--- a/Doc/howto/free-threading-extensions.rst
+++ b/Doc/howto/free-threading-extensions.rst
@@ -181,6 +181,8 @@ Some of these functions were added in Python 3.13. You can use the
to provide implementations of these functions for older Python versions.
+.. _free-threaded-memory-allocation:
+
Memory Allocation APIs
======================
@@ -188,7 +190,7 @@ Python's memory management C API provides functions in three different
:ref:`allocation domains `: "raw", "mem", and "object".
For thread-safety, the free-threaded build requires that only Python objects
are allocated using the object domain, and that all Python object are
-allocated using that domain. This differes from the prior Python versions,
+allocated using that domain. This differs from the prior Python versions,
where this was only a best practice and not a hard requirement.
.. note::
@@ -270,3 +272,9 @@ Windows
Due to a limitation of the official Windows installer, you will need to
manually define ``Py_GIL_DISABLED=1`` when building extensions from source.
+
+.. seealso::
+
+ `Porting Extension Modules to Support Free-Threading
+ `_:
+ A community-maintained porting guide for extension authors.
diff --git a/Doc/howto/free-threading-python.rst b/Doc/howto/free-threading-python.rst
new file mode 100644
index 00000000000..b21e3287eca
--- /dev/null
+++ b/Doc/howto/free-threading-python.rst
@@ -0,0 +1,154 @@
+.. _freethreading-python-howto:
+
+**********************************************
+Python experimental support for free threading
+**********************************************
+
+Starting with the 3.13 release, CPython has experimental support for a build of
+Python called :term:`free threading` where the :term:`global interpreter lock`
+(GIL) is disabled. Free-threaded execution allows for full utilization of the
+available processing power by running threads in parallel on available CPU cores.
+While not all software will benefit from this automatically, programs
+designed with threading in mind will run faster on multi-core hardware.
+
+**The free-threaded mode is experimental** and work is ongoing to improve it:
+expect some bugs and a substantial single-threaded performance hit.
+
+This document describes the implications of free threading
+for Python code. See :ref:`freethreading-extensions-howto` for information on
+how to write C extensions that support the free-threaded build.
+
+.. seealso::
+
+ :pep:`703` – Making the Global Interpreter Lock Optional in CPython for an
+ overall description of free-threaded Python.
+
+
+Installation
+============
+
+Starting with Python 3.13, the official macOS and Windows installers
+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
+`_, a
+community-maintained installation guide for installing free-threaded Python.
+
+When building CPython from source, the :option:`--disable-gil` configure option
+should be used to build a free-threaded Python interpreter.
+
+
+Identifying free-threaded Python
+================================
+
+To check if the current interpreter supports free-threading, :option:`python -VV <-V>`
+and :attr:`sys.version` contain "experimental free-threading build".
+The new :func:`sys._is_gil_enabled` function can be used to check whether
+the GIL is actually disabled in the running process.
+
+The ``sysconfig.get_config_var("Py_GIL_DISABLED")`` configuration variable can
+be used to determine whether the build supports free threading. If the variable
+is set to ``1``, then the build supports free threading. This is the recommended
+mechanism for decisions related to the build configuration.
+
+
+The global interpreter lock in free-threaded Python
+===================================================
+
+Free-threaded builds of CPython support optionally running with the GIL enabled
+at runtime using the environment variable :envvar:`PYTHON_GIL` or
+the command-line option :option:`-X gil`.
+
+The GIL may also automatically be enabled when importing a C-API extension
+module that is not explicitly marked as supporting free threading. A warning
+will be printed in this case.
+
+In addition to individual package documentation, the following websites track
+the status of popular packages support for free threading:
+
+* https://py-free-threading.github.io/tracking/
+* https://hugovk.github.io/free-threaded-wheels/
+
+
+Thread safety
+=============
+
+The free-threaded build of CPython aims to provide similar thread-safety
+behavior at the Python level to the default GIL-enabled build. Built-in
+types like :class:`dict`, :class:`list`, and :class:`set` use internal locks
+to protect against concurrent modifications in ways that behave similarly to
+the GIL. However, Python has not historically guaranteed specific behavior for
+concurrent modifications to these built-in types, so this should be treated
+as a description of the current implementation, not a guarantee of current or
+future behavior.
+
+.. note::
+
+ It's recommended to use the :class:`threading.Lock` or other synchronization
+ primitives instead of relying on the internal locks of built-in types, when
+ possible.
+
+
+Known limitations
+=================
+
+This section describes known limitations of the free-threaded CPython build.
+
+Immortalization
+---------------
+
+The free-threaded build of the 3.13 release makes some objects :term:`immortal`.
+Immortal objects are not deallocated and have reference counts that are
+never modified. This is done to avoid reference count contention that would
+prevent efficient multi-threaded scaling.
+
+An object will be made immortal when a new thread is started for the first time
+after the main thread is running. The following objects are immortalized:
+
+* :ref:`function ` objects declared at the module level
+* :ref:`method ` descriptors
+* :ref:`code ` objects
+* :term:`module` objects and their dictionaries
+* :ref:`classes ` (type objects)
+
+Because immortal objects are never deallocated, applications that create many
+objects of these types may see increased memory usage. This is expected to be
+addressed in the 3.14 release.
+
+Additionally, numeric and string literals in the code as well as strings
+returned by :func:`sys.intern` are also immortalized. This behavior is
+expected to remain in the 3.14 free-threaded build.
+
+
+Frame objects
+-------------
+
+It is not safe to access :ref:`frame ` objects from other
+threads and doing so may cause your program to crash . This means that
+:func:`sys._current_frames` is generally not safe to use in a free-threaded
+build. Functions like :func:`inspect.currentframe` and :func:`sys._getframe`
+are generally safe as long as the resulting frame object is not passed to
+another thread.
+
+Iterators
+---------
+
+Sharing the same iterator object between multiple threads is generally not
+safe and threads may see duplicate or missing elements when iterating or crash
+the interpreter.
+
+
+Single-threaded performance
+---------------------------
+
+The free-threaded build has additional overhead when executing Python code
+compared to the default GIL-enabled build. In 3.13, this overhead is about
+40% on the `pyperformance `_ suite.
+Programs that spend most of their time in C extensions or I/O will see
+less of an impact. The largest impact is because the specializing adaptive
+interpreter (:pep:`659`) is disabled in the free-threaded build. We expect
+to re-enable it in a thread-safe way in the 3.14 release. This overhead is
+expected to be reduced in upcoming Python release. We are aiming for an
+overhead of 10% or less on the pyperformance suite compared to the default
+GIL-enabled build.
diff --git a/Doc/howto/index.rst b/Doc/howto/index.rst
index a882f174708..c09f92c9528 100644
--- a/Doc/howto/index.rst
+++ b/Doc/howto/index.rst
@@ -32,6 +32,7 @@ Python Library Reference.
isolating-extensions.rst
timerfd.rst
mro.rst
+ free-threading-python.rst
free-threading-extensions.rst
General:
@@ -52,6 +53,7 @@ General:
Advanced development:
* :ref:`curses-howto`
+* :ref:`freethreading-python-howto`
* :ref:`freethreading-extensions-howto`
* :ref:`isolating-extensions-howto`
* :ref:`python_2.3_mro`
diff --git a/Doc/howto/instrumentation.rst b/Doc/howto/instrumentation.rst
index 9c99fcecce1..6e03ef20a21 100644
--- a/Doc/howto/instrumentation.rst
+++ b/Doc/howto/instrumentation.rst
@@ -307,7 +307,7 @@ Available static markers
.. object:: gc__start(int generation)
Fires when the Python interpreter starts a garbage collection cycle.
- ``arg0`` is the generation to scan, like :func:`gc.collect()`.
+ ``arg0`` is the generation to scan, like :func:`gc.collect`.
.. object:: gc__done(long collected)
diff --git a/Doc/howto/isolating-extensions.rst b/Doc/howto/isolating-extensions.rst
index e35855deedb..a636e06bda8 100644
--- a/Doc/howto/isolating-extensions.rst
+++ b/Doc/howto/isolating-extensions.rst
@@ -339,7 +339,7 @@ That is, heap types should:
- Define a traverse function using ``Py_tp_traverse``, which
visits the type (e.g. using ``Py_VISIT(Py_TYPE(self))``).
-Please refer to the the documentation of
+Please refer to the documentation of
:c:macro:`Py_TPFLAGS_HAVE_GC` and :c:member:`~PyTypeObject.tp_traverse`
for additional considerations.
diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst
index 60d88204b79..96768ec4ae3 100644
--- a/Doc/howto/logging-cookbook.rst
+++ b/Doc/howto/logging-cookbook.rst
@@ -4022,7 +4022,7 @@ As you can see, this output isn't ideal. That's because the underlying code
which writes to ``sys.stderr`` makes multiple writes, each of which results in a
separate logged line (for example, the last three lines above). To get around
this problem, you need to buffer things and only output log lines when newlines
-are seen. Let's use a slghtly better implementation of ``LoggerWriter``:
+are seen. Let's use a slightly better implementation of ``LoggerWriter``:
.. code-block:: python
diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst
index 316b16aa796..3182d5664ab 100644
--- a/Doc/howto/logging.rst
+++ b/Doc/howto/logging.rst
@@ -382,9 +382,53 @@ Logging Flow
The flow of log event information in loggers and handlers is illustrated in the
following diagram.
+.. only:: not html
+
+ .. image:: logging_flow.*
+
.. raw:: html
:file: logging_flow.svg
+.. raw:: html
+
+
+
Loggers
^^^^^^^
diff --git a/Doc/howto/logging_flow.png b/Doc/howto/logging_flow.png
index c2d0befe273..d60ed7c0315 100644
Binary files a/Doc/howto/logging_flow.png and b/Doc/howto/logging_flow.png differ
diff --git a/Doc/howto/logging_flow.svg b/Doc/howto/logging_flow.svg
index 52206bdbcf5..4974994ac6b 100644
--- a/Doc/howto/logging_flow.svg
+++ b/Doc/howto/logging_flow.svg
@@ -1,281 +1,327 @@
-
-
diff --git a/Doc/howto/mro.rst b/Doc/howto/mro.rst
index f44b4f98e57..46db516e16d 100644
--- a/Doc/howto/mro.rst
+++ b/Doc/howto/mro.rst
@@ -335,7 +335,7 @@ E is more specialized than C, even if it is in a higher level.
A lazy programmer can obtain the MRO directly from Python 2.2, since in
this case it coincides with the Python 2.3 linearization. It is enough
-to invoke the .mro() method of class A:
+to invoke the :meth:`~type.mro` method of class A:
>>> A.mro() # doctest: +NORMALIZE_WHITESPACE
[, , ,
diff --git a/Doc/includes/wasm-ios-notavail.rst b/Doc/includes/wasm-ios-notavail.rst
deleted file mode 100644
index c820665f5e4..00000000000
--- a/Doc/includes/wasm-ios-notavail.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-.. include for modules that don't work on WASM or iOS
-
-.. availability:: not WASI, not iOS.
-
- This module does not work or is not available on WebAssembly platforms, or
- on iOS. See :ref:`wasm-availability` for more information on WASM
- availability; see :ref:`iOS-availability` for more information on iOS
- availability.
diff --git a/Doc/includes/wasm-mobile-notavail.rst b/Doc/includes/wasm-mobile-notavail.rst
new file mode 100644
index 00000000000..725b0f7a86d
--- /dev/null
+++ b/Doc/includes/wasm-mobile-notavail.rst
@@ -0,0 +1,6 @@
+.. include for modules that don't work on WASM or mobile platforms
+
+.. availability:: not Android, not iOS, not WASI.
+
+ This module is not supported on :ref:`mobile platforms `
+ or :ref:`WebAssembly platforms `.
diff --git a/Doc/library/__main__.rst b/Doc/library/__main__.rst
index 6232e173d95..647ff9da04d 100644
--- a/Doc/library/__main__.rst
+++ b/Doc/library/__main__.rst
@@ -251,9 +251,9 @@ attribute will include the package's path if imported::
>>> asyncio.__main__.__name__
'asyncio.__main__'
-This won't work for ``__main__.py`` files in the root directory of a .zip file
-though. Hence, for consistency, minimal ``__main__.py`` like the :mod:`venv`
-one mentioned below are preferred.
+This won't work for ``__main__.py`` files in the root directory of a
+``.zip`` file though. Hence, for consistency, a minimal ``__main__.py``
+without a ``__name__`` check is preferred.
.. seealso::
diff --git a/Doc/library/_thread.rst b/Doc/library/_thread.rst
index 81f0cac947f..5fd604c0538 100644
--- a/Doc/library/_thread.rst
+++ b/Doc/library/_thread.rst
@@ -213,9 +213,8 @@ In addition to these methods, lock objects can also be used via the
.. index:: pair: module; signal
-* Threads interact strangely with interrupts: the :exc:`KeyboardInterrupt`
- exception will be received by an arbitrary thread. (When the :mod:`signal`
- module is available, interrupts always go to the main thread.)
+* Interrupts always go to the main thread (the :exc:`KeyboardInterrupt`
+ exception will be received by that thread.)
* Calling :func:`sys.exit` or raising the :exc:`SystemExit` exception is
equivalent to calling :func:`_thread.exit`.
@@ -229,7 +228,3 @@ In addition to these methods, lock objects can also be used via the
:keyword:`try` ... :keyword:`finally` clauses or executing object
destructors.
-* When the main thread exits, it does not do any of its usual cleanup (except
- that :keyword:`try` ... :keyword:`finally` clauses are honored), and the
- standard I/O files are not flushed.
-
diff --git a/Doc/library/abc.rst b/Doc/library/abc.rst
index 168ef3ec00d..38d744e97d0 100644
--- a/Doc/library/abc.rst
+++ b/Doc/library/abc.rst
@@ -99,7 +99,7 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance:
that you can customize the behavior of :func:`issubclass` further without the
need to call :meth:`register` on every class you want to consider a
subclass of the ABC. (This class method is called from the
- :meth:`~class.__subclasscheck__` method of the ABC.)
+ :meth:`~type.__subclasscheck__` method of the ABC.)
This method should return ``True``, ``False`` or :data:`NotImplemented`. If
it returns ``True``, the *subclass* is considered a subclass of this ABC.
@@ -149,7 +149,7 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance:
The :meth:`__subclasshook__` class method defined here says that any class
that has an :meth:`~iterator.__iter__` method in its
:attr:`~object.__dict__` (or in that of one of its base classes, accessed
- via the :attr:`~class.__mro__` list) is considered a ``MyIterable`` too.
+ via the :attr:`~type.__mro__` list) is considered a ``MyIterable`` too.
Finally, the last line makes ``Foo`` a virtual subclass of ``MyIterable``,
even though it does not define an :meth:`~iterator.__iter__` method (it uses
diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst
index 0367c83d936..53ecc97d565 100644
--- a/Doc/library/argparse.rst
+++ b/Doc/library/argparse.rst
@@ -249,11 +249,12 @@ The following sections describe how each of these are used.
prog
^^^^
-By default, :class:`ArgumentParser` objects use ``sys.argv[0]`` to determine
+By default, :class:`ArgumentParser` objects use the base name
+(see :func:`os.path.basename`) of ``sys.argv[0]`` to determine
how to display the name of the program in help messages. This default is almost
-always desirable because it will make the help messages match how the program was
-invoked on the command line. For example, consider a file named
-``myprogram.py`` with the following code::
+always desirable because it will make the help messages match the name that was
+used to invoke the program on the command line. For example, consider a file
+named ``myprogram.py`` with the following code::
import argparse
parser = argparse.ArgumentParser()
@@ -1122,6 +1123,9 @@ is used when no command-line argument was present::
>>> parser.parse_args([])
Namespace(foo=42)
+For required_ arguments, the ``default`` value is ignored. For example, this
+applies to positional arguments with nargs_ values other than ``?`` or ``*``,
+or optional arguments marked as ``required=True``.
Providing ``default=argparse.SUPPRESS`` causes no attribute to be added if the
command-line argument was not present::
@@ -1455,7 +1459,7 @@ The ``deprecated`` keyword argument of
specifies if the argument is deprecated and will be removed
in the future.
For arguments, if ``deprecated`` is ``True``, then a warning will be
-printed to standard error when the argument is used::
+printed to :data:`sys.stderr` when the argument is used::
>>> import argparse
>>> parser = argparse.ArgumentParser(prog='snake.py')
@@ -1466,7 +1470,7 @@ printed to standard error when the argument is used::
snake.py: warning: option '--legs' is deprecated
Namespace(legs=4)
-.. versionchanged:: 3.13
+.. versionadded:: 3.13
Action classes
@@ -2235,8 +2239,8 @@ Exiting methods
.. method:: ArgumentParser.exit(status=0, message=None)
This method terminates the program, exiting with the specified *status*
- and, if given, it prints a *message* before that. The user can override
- this method to handle these steps differently::
+ and, if given, it prints a *message* to :data:`sys.stderr` before that.
+ The user can override this method to handle these steps differently::
class ErrorCatchingArgumentParser(argparse.ArgumentParser):
def exit(self, status=0, message=None):
@@ -2246,8 +2250,8 @@ Exiting methods
.. method:: ArgumentParser.error(message)
- This method prints a usage message including the *message* to the
- standard error and terminates the program with a status code of 2.
+ This method prints a usage message, including the *message*, to
+ :data:`sys.stderr` and terminates the program with a status code of 2.
Intermixed parsing
diff --git a/Doc/library/array.rst b/Doc/library/array.rst
index d34a1888342..e0b1eb89cf6 100644
--- a/Doc/library/array.rst
+++ b/Doc/library/array.rst
@@ -9,7 +9,7 @@
--------------
This module defines an object type which can compactly represent an array of
-basic values: characters, integers, floating point numbers. Arrays are sequence
+basic values: characters, integers, floating-point numbers. Arrays are sequence
types and behave very much like lists, except that the type of objects stored in
them is constrained. The type is specified at object creation time by using a
:dfn:`type code`, which is a single character. The following type codes are
@@ -263,7 +263,7 @@ The string representation is guaranteed to be able to be converted back to an
array with the same type and value using :func:`eval`, so long as the
:class:`~array.array` class has been imported using ``from array import array``.
Variables ``inf`` and ``nan`` must also be defined if it contains
-corresponding floating point values.
+corresponding floating-point values.
Examples::
array('l')
diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst
index c5daa6e2439..0b7d56286b2 100644
--- a/Doc/library/ast.rst
+++ b/Doc/library/ast.rst
@@ -173,9 +173,9 @@ Root nodes
A Python module, as with :ref:`file input `.
Node type generated by :func:`ast.parse` in the default ``"exec"`` *mode*.
- *body* is a :class:`list` of the module's :ref:`ast-statements`.
+ ``body`` is a :class:`list` of the module's :ref:`ast-statements`.
- *type_ignores* is a :class:`list` of the module's type ignore comments;
+ ``type_ignores`` is a :class:`list` of the module's type ignore comments;
see :func:`ast.parse` for more details.
.. doctest::
@@ -194,7 +194,7 @@ Root nodes
A single Python :ref:`expression input `.
Node type generated by :func:`ast.parse` when *mode* is ``"eval"``.
- *body* is a single node,
+ ``body`` is a single node,
one of the :ref:`expression types `.
.. doctest::
@@ -209,7 +209,7 @@ Root nodes
A single :ref:`interactive input `, like in :ref:`tut-interac`.
Node type generated by :func:`ast.parse` when *mode* is ``"single"``.
- *body* is a :class:`list` of :ref:`statement nodes `.
+ ``body`` is a :class:`list` of :ref:`statement nodes `.
.. doctest::
@@ -238,9 +238,9 @@ Root nodes
# type: (int, int) -> int
return a + b
- *argtypes* is a :class:`list` of :ref:`expression nodes `.
+ ``argtypes`` is a :class:`list` of :ref:`expression nodes `.
- *returns* is a single :ref:`expression node `.
+ ``returns`` is a single :ref:`expression node `.
.. doctest::
@@ -889,7 +889,7 @@ Statements
.. class:: AnnAssign(target, annotation, value, simple)
An assignment with a type annotation. ``target`` is a single node and can
- be a :class:`Name`, a :class:`Attribute` or a :class:`Subscript`.
+ be a :class:`Name`, an :class:`Attribute` or a :class:`Subscript`.
``annotation`` is the annotation, such as a :class:`Constant` or :class:`Name`
node. ``value`` is a single optional node.
@@ -1766,9 +1766,9 @@ aliases.
.. class:: TypeVar(name, bound, default_value)
- A :class:`typing.TypeVar`. *name* is the name of the type variable.
- *bound* is the bound or constraints, if any. If *bound* is a :class:`Tuple`,
- it represents constraints; otherwise it represents the bound. *default_value*
+ A :class:`typing.TypeVar`. ``name`` is the name of the type variable.
+ ``bound`` is the bound or constraints, if any. If ``bound`` is a :class:`Tuple`,
+ it represents constraints; otherwise it represents the bound. ``default_value``
is the default value; if the :class:`!TypeVar` has no default, this
attribute will be set to ``None``.
@@ -1796,8 +1796,8 @@ aliases.
.. class:: ParamSpec(name, default_value)
- A :class:`typing.ParamSpec`. *name* is the name of the parameter specification.
- *default_value* is the default value; if the :class:`!ParamSpec` has no default,
+ A :class:`typing.ParamSpec`. ``name`` is the name of the parameter specification.
+ ``default_value`` is the default value; if the :class:`!ParamSpec` has no default,
this attribute will be set to ``None``.
.. doctest::
@@ -1831,8 +1831,8 @@ aliases.
.. class:: TypeVarTuple(name, default_value)
- A :class:`typing.TypeVarTuple`. *name* is the name of the type variable tuple.
- *default_value* is the default value; if the :class:`!TypeVarTuple` has no
+ A :class:`typing.TypeVarTuple`. ``name`` is the name of the type variable tuple.
+ ``default_value`` is the default value; if the :class:`!TypeVarTuple` has no
default, this attribute will be set to ``None``.
.. doctest::
@@ -1981,7 +1981,7 @@ Function and class definitions
YieldFrom(value)
A ``yield`` or ``yield from`` expression. Because these are expressions, they
- must be wrapped in a :class:`Expr` node if the value sent back is not used.
+ must be wrapped in an :class:`Expr` node if the value sent back is not used.
.. doctest::
@@ -2033,8 +2033,7 @@ Function and class definitions
* ``name`` is a raw string for the class name
* ``bases`` is a list of nodes for explicitly specified base classes.
* ``keywords`` is a list of :class:`.keyword` nodes, principally for 'metaclass'.
- Other keywords will be passed to the metaclass, as per `PEP-3115
- `_.
+ Other keywords will be passed to the metaclass, as per :pep:`3115`.
* ``body`` is a list of nodes representing the code within the class
definition.
* ``decorator_list`` is a list of nodes, as in :class:`FunctionDef`.
@@ -2134,7 +2133,7 @@ and classes for traversing abstract syntax trees:
If ``type_comments=True`` is given, the parser is modified to check
and return type comments as specified by :pep:`484` and :pep:`526`.
This is equivalent to adding :data:`ast.PyCF_TYPE_COMMENTS` to the
- flags passed to :func:`compile()`. This will report syntax errors
+ flags passed to :func:`compile`. This will report syntax errors
for misplaced type comments. Without this flag, type comments will
be ignored, and the ``type_comment`` field on selected AST nodes
will always be ``None``. In addition, the locations of ``# type:
diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst
index 1d79f78e8e1..943683f6b8a 100644
--- a/Doc/library/asyncio-eventloop.rst
+++ b/Doc/library/asyncio-eventloop.rst
@@ -126,7 +126,7 @@ Running and stopping the loop
Run the event loop until :meth:`stop` is called.
- If :meth:`stop` is called before :meth:`run_forever()` is called,
+ If :meth:`stop` is called before :meth:`run_forever` is called,
the loop will poll the I/O selector once with a timeout of zero,
run all callbacks scheduled in response to I/O events (and
those that were already scheduled), and then exit.
@@ -165,7 +165,7 @@ Running and stopping the loop
.. coroutinemethod:: loop.shutdown_asyncgens()
Schedule all currently open :term:`asynchronous generator` objects to
- close with an :meth:`~agen.aclose()` call. After calling this method,
+ close with an :meth:`~agen.aclose` call. After calling this method,
the event loop will issue a warning if a new asynchronous generator
is iterated. This should be used to reliably finalize all scheduled
asynchronous generators.
@@ -1262,6 +1262,9 @@ Executing code in thread or process pools
The *executor* argument should be an :class:`concurrent.futures.Executor`
instance. The default executor is used if *executor* is ``None``.
+ The default executor can be set by :meth:`loop.set_default_executor`,
+ otherwise, a :class:`concurrent.futures.ThreadPoolExecutor` will be
+ lazy-initialized and used by :func:`run_in_executor` if needed.
Example::
@@ -1399,7 +1402,7 @@ Allows customizing how exceptions are handled in the event loop.
This method should not be overloaded in subclassed
event loops. For custom exception handling, use
- the :meth:`set_exception_handler()` method.
+ the :meth:`set_exception_handler` method.
Enabling debug mode
^^^^^^^^^^^^^^^^^^^
@@ -1482,7 +1485,7 @@ async/await code consider using the high-level
* *stdin* can be any of these:
* a file-like object
- * an existing file descriptor (a positive integer), for example those created with :meth:`os.pipe()`
+ * an existing file descriptor (a positive integer), for example those created with :meth:`os.pipe`
* the :const:`subprocess.PIPE` constant (default) which will create a new
pipe and connect it,
* the value ``None`` which will make the subprocess inherit the file
diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst
index 893ae5518f7..9dce0731411 100644
--- a/Doc/library/asyncio-future.rst
+++ b/Doc/library/asyncio-future.rst
@@ -120,20 +120,20 @@ Future Object
a :exc:`CancelledError` exception.
If the Future's result isn't yet available, this method raises
- a :exc:`InvalidStateError` exception.
+ an :exc:`InvalidStateError` exception.
.. method:: set_result(result)
Mark the Future as *done* and set its result.
- Raises a :exc:`InvalidStateError` error if the Future is
+ Raises an :exc:`InvalidStateError` error if the Future is
already *done*.
.. method:: set_exception(exception)
Mark the Future as *done* and set an exception.
- Raises a :exc:`InvalidStateError` error if the Future is
+ Raises an :exc:`InvalidStateError` error if the Future is
already *done*.
.. method:: done()
diff --git a/Doc/library/asyncio-llapi-index.rst b/Doc/library/asyncio-llapi-index.rst
index 67136ba69ec..3e21054aa4f 100644
--- a/Doc/library/asyncio-llapi-index.rst
+++ b/Doc/library/asyncio-llapi-index.rst
@@ -56,10 +56,10 @@ See also the main documentation section about the
* - :meth:`loop.close`
- Close the event loop.
- * - :meth:`loop.is_running()`
+ * - :meth:`loop.is_running`
- Return ``True`` if the event loop is running.
- * - :meth:`loop.is_closed()`
+ * - :meth:`loop.is_closed`
- Return ``True`` if the event loop is closed.
* - ``await`` :meth:`loop.shutdown_asyncgens`
diff --git a/Doc/library/asyncio-queue.rst b/Doc/library/asyncio-queue.rst
index 9b579cc1d5f..61991bf2f4e 100644
--- a/Doc/library/asyncio-queue.rst
+++ b/Doc/library/asyncio-queue.rst
@@ -55,7 +55,7 @@ Queue
Return ``True`` if there are :attr:`maxsize` items in the queue.
If the queue was initialized with ``maxsize=0`` (the default),
- then :meth:`full()` never returns ``True``.
+ then :meth:`full` never returns ``True``.
.. coroutinemethod:: get()
diff --git a/Doc/library/asyncio-runner.rst b/Doc/library/asyncio-runner.rst
index ec170dfde9e..8312e55126a 100644
--- a/Doc/library/asyncio-runner.rst
+++ b/Doc/library/asyncio-runner.rst
@@ -91,7 +91,7 @@ Runner context manager
current one. By default :func:`asyncio.new_event_loop` is used and set as
current event loop with :func:`asyncio.set_event_loop` if *loop_factory* is ``None``.
- Basically, :func:`asyncio.run()` example can be rewritten with the runner usage::
+ Basically, :func:`asyncio.run` example can be rewritten with the runner usage::
async def main():
await asyncio.sleep(1)
diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst
index c5deac7e274..4716a3f9c8a 100644
--- a/Doc/library/asyncio-task.rst
+++ b/Doc/library/asyncio-task.rst
@@ -414,6 +414,53 @@ reported by :meth:`asyncio.Task.cancelling`.
Improved handling of simultaneous internal and external cancellations
and correct preservation of cancellation counts.
+Terminating a Task Group
+------------------------
+
+While terminating a task group is not natively supported by the standard
+library, termination can be achieved by adding an exception-raising task
+to the task group and ignoring the raised exception:
+
+.. code-block:: python
+
+ import asyncio
+ from asyncio import TaskGroup
+
+ class TerminateTaskGroup(Exception):
+ """Exception raised to terminate a task group."""
+
+ async def force_terminate_task_group():
+ """Used to force termination of a task group."""
+ raise TerminateTaskGroup()
+
+ async def job(task_id, sleep_time):
+ print(f'Task {task_id}: start')
+ await asyncio.sleep(sleep_time)
+ print(f'Task {task_id}: done')
+
+ async def main():
+ try:
+ async with TaskGroup() as group:
+ # spawn some tasks
+ group.create_task(job(1, 0.5))
+ group.create_task(job(2, 1.5))
+ # sleep for 1 second
+ await asyncio.sleep(1)
+ # add an exception-raising task to force the group to terminate
+ group.create_task(force_terminate_task_group())
+ except* TerminateTaskGroup:
+ pass
+
+ asyncio.run(main())
+
+Expected output:
+
+.. code-block:: text
+
+ Task 1: start
+ Task 2: start
+ Task 1: done
+
Sleeping
========
@@ -1170,7 +1217,7 @@ Task Object
a :exc:`CancelledError` exception.
If the Task's result isn't yet available, this method raises
- a :exc:`InvalidStateError` exception.
+ an :exc:`InvalidStateError` exception.
.. method:: exception()
diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst
index 184f981c102..5f83b3a2658 100644
--- a/Doc/library/asyncio.rst
+++ b/Doc/library/asyncio.rst
@@ -56,9 +56,13 @@ Additionally, there are **low-level** APIs for
* :ref:`bridge ` callback-based libraries and code
with async/await syntax.
+.. include:: ../includes/wasm-notavail.rst
+
.. _asyncio-cli:
-You can experiment with an ``asyncio`` concurrent context in the REPL:
+.. rubric:: asyncio REPL
+
+You can experiment with an ``asyncio`` concurrent context in the :term:`REPL`:
.. code-block:: pycon
@@ -70,7 +74,14 @@ You can experiment with an ``asyncio`` concurrent context in the REPL:
>>> await asyncio.sleep(10, result='hello')
'hello'
-.. include:: ../includes/wasm-notavail.rst
+.. audit-event:: cpython.run_stdin "" ""
+
+.. versionchanged:: 3.12.5 (also 3.11.10, 3.10.15, 3.9.20, and 3.8.20)
+ Emits audit events.
+
+.. versionchanged:: 3.13
+ Uses PyREPL if possible, in which case :envvar:`PYTHONSTARTUP` is
+ also executed. Emits audit events.
.. We use the "rubric" directive here to avoid creating
the "Reference" subsection in the TOC.
diff --git a/Doc/library/calendar.rst b/Doc/library/calendar.rst
index d5876054da3..eafc038d6cb 100644
--- a/Doc/library/calendar.rst
+++ b/Doc/library/calendar.rst
@@ -393,13 +393,22 @@ The :mod:`calendar` module exports the following data attributes:
.. data:: day_name
- An array that represents the days of the week in the current locale.
+ A sequence that represents the days of the week in the current locale,
+ where Monday is day number 0.
+
+ >>> import calendar
+ >>> list(calendar.day_name)
+ ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
.. data:: day_abbr
- An array that represents the abbreviated days of the week in the current locale.
+ A sequence that represents the abbreviated days of the week in the current locale,
+ where Mon is day number 0.
+ >>> import calendar
+ >>> list(calendar.day_abbr)
+ ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
.. data:: MONDAY
TUESDAY
@@ -426,17 +435,24 @@ The :mod:`calendar` module exports the following data attributes:
.. data:: month_name
- An array that represents the months of the year in the current locale. This
+ A sequence that represents the months of the year in the current locale. This
follows normal convention of January being month number 1, so it has a length of
13 and ``month_name[0]`` is the empty string.
+ >>> import calendar
+ >>> list(calendar.month_name)
+ ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
+
.. data:: month_abbr
- An array that represents the abbreviated months of the year in the current
+ A sequence that represents the abbreviated months of the year in the current
locale. This follows normal convention of January being month number 1, so it
has a length of 13 and ``month_abbr[0]`` is the empty string.
+ >>> import calendar
+ >>> list(calendar.month_abbr)
+ ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
.. data:: JANUARY
FEBRUARY
diff --git a/Doc/library/cmdline.rst b/Doc/library/cmdline.rst
index 5174515ffc2..487fd775337 100644
--- a/Doc/library/cmdline.rst
+++ b/Doc/library/cmdline.rst
@@ -40,6 +40,7 @@ The following modules have a command-line interface.
* :mod:`runpy`
* :ref:`site `
* :ref:`sqlite3 `
+* :ref:`symtable `
* :ref:`sysconfig `
* :mod:`tabnanny`
* :ref:`tarfile `
diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst
index ea27436f67f..0adbd305b46 100644
--- a/Doc/library/collections.abc.rst
+++ b/Doc/library/collections.abc.rst
@@ -216,6 +216,9 @@ Collections Abstract Base Classes -- Detailed Descriptions
ABC for classes that provide the :meth:`~object.__call__` method.
+ See :ref:`annotating-callables` for details on how to use
+ :class:`!Callable` in type annotations.
+
.. class:: Iterable
ABC for classes that provide the :meth:`~container.__iter__` method.
@@ -253,6 +256,9 @@ Collections Abstract Base Classes -- Detailed Descriptions
:meth:`~generator.send`,
:meth:`~generator.throw` and :meth:`~generator.close` methods.
+ See :ref:`annotating-generators-and-coroutines`
+ for details on using :class:`!Generator` in type annotations.
+
.. versionadded:: 3.5
.. class:: Sequence
@@ -331,6 +337,11 @@ Collections Abstract Base Classes -- Detailed Descriptions
Using ``isinstance(gencoro, Coroutine)`` for them will return ``False``.
Use :func:`inspect.isawaitable` to detect them.
+ See :ref:`annotating-generators-and-coroutines`
+ for details on using :class:`!Coroutine` in type annotations.
+ The variance and order of type parameters correspond to those of
+ :class:`Generator`.
+
.. versionadded:: 3.5
.. class:: AsyncIterable
@@ -352,6 +363,9 @@ Collections Abstract Base Classes -- Detailed Descriptions
ABC for :term:`asynchronous generator` classes that implement the protocol
defined in :pep:`525` and :pep:`492`.
+ See :ref:`annotating-generators-and-coroutines`
+ for details on using :class:`!AsyncGenerator` in type annotations.
+
.. versionadded:: 3.6
.. class:: Buffer
diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst
index ce89101d6b6..0cc9063f153 100644
--- a/Doc/library/collections.rst
+++ b/Doc/library/collections.rst
@@ -874,8 +874,8 @@ they add the ability to access fields by name instead of position index.
``(1, 2)``, then ``x`` will be a required argument, ``y`` will default to
``1``, and ``z`` will default to ``2``.
- If *module* is defined, the ``__module__`` attribute of the named tuple is
- set to that value.
+ If *module* is defined, the :attr:`~type.__module__` attribute of the
+ named tuple is set to that value.
Named tuple instances do not have per-instance dictionaries, so they are
lightweight and require no more memory than regular tuples.
@@ -1169,8 +1169,11 @@ Some differences from :class:`dict` still remain:
In addition to the usual mapping methods, ordered dictionaries also support
reverse iteration using :func:`reversed`.
+.. _collections_OrderedDict__eq__:
+
Equality tests between :class:`OrderedDict` objects are order-sensitive
-and are implemented as ``list(od1.items())==list(od2.items())``.
+and are roughly equivalent to ``list(od1.items())==list(od2.items())``.
+
Equality tests between :class:`OrderedDict` objects and other
:class:`~collections.abc.Mapping` objects are order-insensitive like regular
dictionaries. This allows :class:`OrderedDict` objects to be substituted
@@ -1186,7 +1189,7 @@ anywhere a regular dictionary is used.
method.
.. versionchanged:: 3.9
- Added merge (``|``) and update (``|=``) operators, specified in :pep:`584`.
+ Added merge (``|``) and update (``|=``) operators, specified in :pep:`584`.
:class:`OrderedDict` Examples and Recipes
diff --git a/Doc/library/colorsys.rst b/Doc/library/colorsys.rst
index 125d62b1740..ffebf4e40dd 100644
--- a/Doc/library/colorsys.rst
+++ b/Doc/library/colorsys.rst
@@ -14,7 +14,7 @@ The :mod:`colorsys` module defines bidirectional conversions of color values
between colors expressed in the RGB (Red Green Blue) color space used in
computer monitors and three other coordinate systems: YIQ, HLS (Hue Lightness
Saturation) and HSV (Hue Saturation Value). Coordinates in all of these color
-spaces are floating point values. In the YIQ space, the Y coordinate is between
+spaces are floating-point values. In the YIQ space, the Y coordinate is between
0 and 1, but the I and Q coordinates can be positive or negative. In all other
spaces, the coordinates are all between 0 and 1.
diff --git a/Doc/library/compileall.rst b/Doc/library/compileall.rst
index d9c0cb67a92..c42288419c4 100644
--- a/Doc/library/compileall.rst
+++ b/Doc/library/compileall.rst
@@ -90,7 +90,7 @@ compile Python sources.
.. option:: -j N
Use *N* workers to compile the files within the given directory.
- If ``0`` is used, then the result of :func:`os.process_cpu_count()`
+ If ``0`` is used, then the result of :func:`os.process_cpu_count`
will be used.
.. option:: --invalidation-mode [timestamp|checked-hash|unchecked-hash]
diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst
index e84fb513e45..cf13de4116f 100644
--- a/Doc/library/configparser.rst
+++ b/Doc/library/configparser.rst
@@ -147,23 +147,28 @@ case-insensitive and stored in lowercase [1]_.
It is possible to read several configurations into a single
:class:`ConfigParser`, where the most recently added configuration has the
highest priority. Any conflicting keys are taken from the more recent
-configuration while the previously existing keys are retained.
+configuration while the previously existing keys are retained. The example
+below reads in an ``override.ini`` file, which will override any conflicting
+keys from the ``example.ini`` file.
+
+.. code-block:: ini
+
+ [DEFAULT]
+ ServerAliveInterval = -1
.. doctest::
- >>> another_config = configparser.ConfigParser()
- >>> another_config.read('example.ini')
- ['example.ini']
- >>> another_config['topsecret.server.example']['Port']
- '50022'
- >>> another_config.read_string("[topsecret.server.example]\nPort=48484")
- >>> another_config['topsecret.server.example']['Port']
- '48484'
- >>> another_config.read_dict({"topsecret.server.example": {"Port": 21212}})
- >>> another_config['topsecret.server.example']['Port']
- '21212'
- >>> another_config['topsecret.server.example']['ForwardX11']
- 'no'
+ >>> config_override = configparser.ConfigParser()
+ >>> config_override['DEFAULT'] = {'ServerAliveInterval': '-1'}
+ >>> with open('override.ini', 'w') as configfile:
+ ... config_override.write(configfile)
+ ...
+ >>> config_override = configparser.ConfigParser()
+ >>> config_override.read(['example.ini', 'override.ini'])
+ ['example.ini', 'override.ini']
+ >>> print(config_override.get('DEFAULT', 'ServerAliveInterval'))
+ -1
+
This behaviour is equivalent to a :meth:`ConfigParser.read` call with several
files passed to the *filenames* parameter.
@@ -981,9 +986,34 @@ ConfigParser Objects
When *converters* is given, it should be a dictionary where each key
represents the name of a type converter and each value is a callable
implementing the conversion from string to the desired datatype. Every
- converter gets its own corresponding :meth:`!get*()` method on the parser
+ converter gets its own corresponding :meth:`!get*` method on the parser
object and section proxies.
+ It is possible to read several configurations into a single
+ :class:`ConfigParser`, where the most recently added configuration has the
+ highest priority. Any conflicting keys are taken from the more recent
+ configuration while the previously existing keys are retained. The example
+ below reads in an ``override.ini`` file, which will override any conflicting
+ keys from the ``example.ini`` file.
+
+ .. code-block:: ini
+
+ [DEFAULT]
+ ServerAliveInterval = -1
+
+ .. doctest::
+
+ >>> config_override = configparser.ConfigParser()
+ >>> config_override['DEFAULT'] = {'ServerAliveInterval': '-1'}
+ >>> with open('override.ini', 'w') as configfile:
+ ... config_override.write(configfile)
+ ...
+ >>> config_override = configparser.ConfigParser()
+ >>> config_override.read(['example.ini', 'override.ini'])
+ ['example.ini', 'override.ini']
+ >>> print(config_override.get('DEFAULT', 'ServerAliveInterval'))
+ -1
+
.. versionchanged:: 3.1
The default *dict_type* is :class:`collections.OrderedDict`.
@@ -996,7 +1026,7 @@ ConfigParser Objects
The *converters* argument was added.
.. versionchanged:: 3.7
- The *defaults* argument is read with :meth:`read_dict()`,
+ The *defaults* argument is read with :meth:`read_dict`,
providing consistent behavior across the parser: non-string
keys and values are implicitly converted to strings.
@@ -1153,7 +1183,7 @@ ConfigParser Objects
.. method:: getfloat(section, option, *, raw=False, vars=None[, fallback])
A convenience method which coerces the *option* in the specified *section*
- to a floating point number. See :meth:`get` for explanation of *raw*,
+ to a floating-point number. See :meth:`get` for explanation of *raw*,
*vars* and *fallback*.
diff --git a/Doc/library/constants.rst b/Doc/library/constants.rst
index 93a7244f87d..3eceecc4e0a 100644
--- a/Doc/library/constants.rst
+++ b/Doc/library/constants.rst
@@ -79,6 +79,8 @@ A small number of constants live in the built-in namespace. They are:
:exc:`SyntaxError`), so they can be considered "true" constants.
+.. _site-consts:
+
Constants added by the :mod:`site` module
-----------------------------------------
@@ -94,6 +96,13 @@ should not be used in programs.
(i.e. EOF) to exit", and when called, raise :exc:`SystemExit` with the
specified exit code.
+.. data:: help
+ :noindex:
+
+ Object that when printed, prints the message "Type help() for interactive
+ help, or help(object) for help about object.", and when called,
+ acts as described :func:`elsewhere `.
+
.. data:: copyright
credits
diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst
index 27cf99446e5..f5b349441bc 100644
--- a/Doc/library/contextlib.rst
+++ b/Doc/library/contextlib.rst
@@ -322,7 +322,7 @@ Functions and classes provided:
.. versionchanged:: 3.12
``suppress`` now supports suppressing exceptions raised as
- part of an :exc:`BaseExceptionGroup`.
+ part of a :exc:`BaseExceptionGroup`.
.. function:: redirect_stdout(new_target)
diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst
index 8ae386b489f..2a79dfe8f81 100644
--- a/Doc/library/contextvars.rst
+++ b/Doc/library/contextvars.rst
@@ -15,7 +15,7 @@ function and the :class:`~contextvars.Context` class should be used to
manage the current context in asynchronous frameworks.
Context managers that have state should use Context Variables
-instead of :func:`threading.local()` to prevent their state from
+instead of :func:`threading.local` to prevent their state from
bleeding to other code unexpectedly, when used in concurrent code.
See also :pep:`567` for additional details.
@@ -146,7 +146,7 @@ Manual Context Management
Every thread will have a different top-level :class:`~contextvars.Context`
object. This means that a :class:`ContextVar` object behaves in a similar
- fashion to :func:`threading.local()` when values are assigned in different
+ fashion to :func:`threading.local` when values are assigned in different
threads.
Context implements the :class:`collections.abc.Mapping` interface.
@@ -254,7 +254,7 @@ client::
# without passing it explicitly to this function.
client_addr = client_addr_var.get()
- return f'Good bye, client @ {client_addr}\n'.encode()
+ return f'Good bye, client @ {client_addr}\r\n'.encode()
async def handle_request(reader, writer):
addr = writer.transport.get_extra_info('socket').getpeername()
@@ -268,9 +268,10 @@ client::
print(line)
if not line.strip():
break
- writer.write(line)
- writer.write(render_goodbye())
+ writer.write(b'HTTP/1.1 200 OK\r\n') # status line
+ writer.write(b'\r\n') # headers
+ writer.write(render_goodbye()) # body
writer.close()
async def main():
@@ -282,5 +283,6 @@ client::
asyncio.run(main())
- # To test it you can use telnet:
+ # To test it you can use telnet or curl:
# telnet 127.0.0.1 8081
+ # curl 127.0.0.1:8081
diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst
index 820535e3cba..12b44569271 100644
--- a/Doc/library/ctypes.rst
+++ b/Doc/library/ctypes.rst
@@ -51,7 +51,7 @@ function call fails.
Here are some examples for Windows. Note that ``msvcrt`` is the MS standard C
-library containing most standard C functions, and uses the cdecl calling
+library containing most standard C functions, and uses the ``cdecl`` calling
convention::
>>> from ctypes import *
@@ -107,7 +107,7 @@ Functions are accessed as attributes of dll objects::
Note that win32 system dlls like ``kernel32`` and ``user32`` often export ANSI
as well as UNICODE versions of a function. The UNICODE version is exported with
-an ``W`` appended to the name, while the ANSI version is exported with an ``A``
+a ``W`` appended to the name, while the ANSI version is exported with an ``A``
appended to the name. The win32 ``GetModuleHandle`` function, which returns a
*module handle* for a given module name, has the following C prototype, and a
macro is used to expose one of them as ``GetModuleHandle`` depending on whether
@@ -2621,6 +2621,15 @@ Arrays and pointers
Array subclass constructors accept positional arguments, used to
initialize the elements in order.
+.. function:: ARRAY(type, length)
+
+ Create an array.
+ Equivalent to ``type * length``, where *type* is a
+ :mod:`ctypes` data type and *length* an integer.
+
+ This function is :term:`soft deprecated` in favor of multiplication.
+ There are no plans to remove it.
+
.. class:: _Pointer
diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst
index 91ea6150fb1..6c7fc721a3e 100644
--- a/Doc/library/curses.rst
+++ b/Doc/library/curses.rst
@@ -21,7 +21,7 @@ for Windows, DOS, and possibly other systems as well. This extension module is
designed to match the API of ncurses, an open-source curses library hosted on
Linux and the BSD variants of Unix.
-.. include:: ../includes/wasm-ios-notavail.rst
+.. include:: ../includes/wasm-mobile-notavail.rst
.. note::
diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst
index fcb5e8bad29..cfca11afbd2 100644
--- a/Doc/library/dataclasses.rst
+++ b/Doc/library/dataclasses.rst
@@ -124,7 +124,7 @@ Module contents
- *unsafe_hash*: If ``False`` (the default), a :meth:`~object.__hash__` method
is generated according to how *eq* and *frozen* are set.
- :meth:`!__hash__` is used by built-in :meth:`hash()`, and when objects are
+ :meth:`!__hash__` is used by built-in :meth:`hash`, and when objects are
added to hashed collections such as dictionaries and sets. Having a
:meth:`!__hash__` implies that instances of the class are immutable.
Mutability is a complicated property that depends on the programmer's
@@ -185,10 +185,21 @@ Module contents
- *slots*: If true (the default is ``False``), :attr:`~object.__slots__` attribute
will be generated and new class will be returned instead of the original one.
If :attr:`!__slots__` is already defined in the class, then :exc:`TypeError`
- is raised. Calling no-arg :func:`super` in dataclasses using ``slots=True`` will result in
- the following exception being raised:
- ``TypeError: super(type, obj): obj must be an instance or subtype of type``.
- The two-arg :func:`super` is a valid workaround. See :gh:`90562` for full details.
+ is raised.
+
+ .. warning::
+ Calling no-arg :func:`super` in dataclasses using ``slots=True``
+ will result in the following exception being raised:
+ ``TypeError: super(type, obj): obj must be an instance or subtype of type``.
+ The two-arg :func:`super` is a valid workaround.
+ See :gh:`90562` for full details.
+
+ .. warning::
+ Passing parameters to a base class :meth:`~object.__init_subclass__`
+ when using ``slots=True`` will result in a :exc:`TypeError`.
+ Either use ``__init_subclass__`` with no parameters
+ or use default values as a workaround.
+ See :gh:`91126` for full details.
.. versionadded:: 3.10
@@ -204,7 +215,8 @@ Module contents
- *weakref_slot*: If true (the default is ``False``), add a slot
named "__weakref__", which is required to make an instance
- weakref-able. It is an error to specify ``weakref_slot=True``
+ :func:`weakref-able `.
+ It is an error to specify ``weakref_slot=True``
without also specifying ``slots=True``.
.. versionadded:: 3.11
diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst
index b6d8e6e6df0..9246aff12a6 100644
--- a/Doc/library/datetime.rst
+++ b/Doc/library/datetime.rst
@@ -48,7 +48,7 @@ Aware and Naive Objects
-----------------------
Date and time objects may be categorized as "aware" or "naive" depending on
-whether or not they include timezone information.
+whether or not they include time zone information.
With sufficient knowledge of applicable algorithmic and political time
adjustments, such as time zone and daylight saving time information,
@@ -58,7 +58,7 @@ interpretation. [#]_
A **naive** object does not contain enough information to unambiguously locate
itself relative to other date/time objects. Whether a naive object represents
-Coordinated Universal Time (UTC), local time, or time in some other timezone is
+Coordinated Universal Time (UTC), local time, or time in some other time zone is
purely up to the program, just like it is up to the program whether a
particular number represents metres, miles, or mass. Naive objects are easy to
understand and to work with, at the cost of ignoring some aspects of reality.
@@ -70,9 +70,9 @@ These :class:`tzinfo` objects capture information about the offset from UTC
time, the time zone name, and whether daylight saving time is in effect.
Only one concrete :class:`tzinfo` class, the :class:`timezone` class, is
-supplied by the :mod:`!datetime` module. The :class:`timezone` class can
-represent simple timezones with fixed offsets from UTC, such as UTC itself or
-North American EST and EDT timezones. Supporting timezones at deeper levels of
+supplied by the :mod:`!datetime` module. The :class:`!timezone` class can
+represent simple time zones with fixed offsets from UTC, such as UTC itself or
+North American EST and EDT time zones. Supporting time zones at deeper levels of
detail is up to the application. The rules for time adjustment across the
world are more political than rational, change frequently, and there is no
standard suitable for every application aside from UTC.
@@ -95,7 +95,7 @@ The :mod:`!datetime` module exports the following constants:
.. attribute:: UTC
- Alias for the UTC timezone singleton :attr:`datetime.timezone.utc`.
+ Alias for the UTC time zone singleton :attr:`datetime.timezone.utc`.
.. versionadded:: 3.11
@@ -283,17 +283,37 @@ Class attributes:
Note that, because of normalization, ``timedelta.max`` is greater than ``-timedelta.min``.
``-timedelta.max`` is not representable as a :class:`timedelta` object.
+
Instance attributes (read-only):
-+------------------+--------------------------------------------+
-| Attribute | Value |
-+==================+============================================+
-| ``days`` | Between -999999999 and 999999999 inclusive |
-+------------------+--------------------------------------------+
-| ``seconds`` | Between 0 and 86399 inclusive |
-+------------------+--------------------------------------------+
-| ``microseconds`` | Between 0 and 999999 inclusive |
-+------------------+--------------------------------------------+
+.. attribute:: timedelta.days
+
+ Between -999,999,999 and 999,999,999 inclusive.
+
+
+.. attribute:: timedelta.seconds
+
+ Between 0 and 86,399 inclusive.
+
+ .. caution::
+
+ It is a somewhat common bug for code to unintentionally use this attribute
+ when it is actually intended to get a :meth:`~timedelta.total_seconds`
+ value instead:
+
+ .. doctest::
+
+ >>> from datetime import timedelta
+ >>> duration = timedelta(seconds=11235813)
+ >>> duration.days, duration.seconds
+ (130, 3813)
+ >>> duration.total_seconds()
+ 11235813.0
+
+.. attribute:: timedelta.microseconds
+
+ Between 0 and 999,999 inclusive.
+
Supported operations:
@@ -345,7 +365,7 @@ Supported operations:
| | same value. (2) |
+--------------------------------+-----------------------------------------------+
| ``-t1`` | Equivalent to ``timedelta(-t1.days, |
-| | -t1.seconds*, -t1.microseconds)``, |
+| | -t1.seconds, -t1.microseconds)``, |
| | and to ``t1 * -1``. (1)(4) |
+--------------------------------+-----------------------------------------------+
| ``abs(t)`` | Equivalent to ``+t`` when ``t.days >= 0``, |
@@ -869,7 +889,7 @@ Other constructors, all class methods:
.. classmethod:: datetime.today()
- Return the current local datetime, with :attr:`.tzinfo` ``None``.
+ Return the current local date and time, with :attr:`.tzinfo` ``None``.
Equivalent to::
@@ -1053,7 +1073,7 @@ Other constructors, all class methods:
.. versionadded:: 3.7
.. versionchanged:: 3.11
Previously, this method only supported formats that could be emitted by
- :meth:`date.isoformat()` or :meth:`datetime.isoformat()`.
+ :meth:`date.isoformat` or :meth:`datetime.isoformat`.
.. classmethod:: datetime.fromisocalendar(year, week, day)
@@ -1070,7 +1090,7 @@ Other constructors, all class methods:
Return a :class:`.datetime` corresponding to *date_string*, parsed according to
*format*.
- If *format* does not contain microseconds or timezone information, this is equivalent to::
+ If *format* does not contain microseconds or time zone information, this is equivalent to::
datetime(*(time.strptime(date_string, format)[0:6]))
@@ -1311,22 +1331,22 @@ Instance methods:
If provided, *tz* must be an instance of a :class:`tzinfo` subclass, and its
:meth:`utcoffset` and :meth:`dst` methods must not return ``None``. If *self*
- is naive, it is presumed to represent time in the system timezone.
+ is naive, it is presumed to represent time in the system time zone.
If called without arguments (or with ``tz=None``) the system local
- timezone is assumed for the target timezone. The ``.tzinfo`` attribute of the converted
+ time zone is assumed for the target time zone. The ``.tzinfo`` attribute of the converted
datetime instance will be set to an instance of :class:`timezone`
with the zone name and offset obtained from the OS.
If ``self.tzinfo`` is *tz*, ``self.astimezone(tz)`` is equal to *self*: no
adjustment of date or time data is performed. Else the result is local
- time in the timezone *tz*, representing the same UTC time as *self*: after
+ time in the time zone *tz*, representing the same UTC time as *self*: after
``astz = dt.astimezone(tz)``, ``astz - astz.utcoffset()`` will have
the same date and time data as ``dt - dt.utcoffset()``.
- If you merely want to attach a time zone object *tz* to a datetime *dt* without
+ If you merely want to attach a :class:`timezone` object *tz* to a datetime *dt* without
adjustment of date and time data, use ``dt.replace(tzinfo=tz)``. If you
- merely want to remove the time zone object from an aware datetime *dt* without
+ merely want to remove the :class:`!timezone` object from an aware datetime *dt* without
conversion of date and time data, use ``dt.replace(tzinfo=None)``.
Note that the default :meth:`tzinfo.fromutc` method can be overridden in a
@@ -1336,7 +1356,7 @@ Instance methods:
def astimezone(self, tz):
if self.tzinfo is tz:
return self
- # Convert self to UTC, and attach the new time zone object.
+ # Convert self to UTC, and attach the new timezone object.
utc = (self - self.utcoffset()).replace(tzinfo=tz)
# Convert from UTC to tz's local time.
return tz.fromutc(utc)
@@ -1450,7 +1470,7 @@ Instance methods:
There is no method to obtain the POSIX timestamp directly from a
naive :class:`.datetime` instance representing UTC time. If your
- application uses this convention and your system timezone is not
+ application uses this convention and your system time zone is not
set to UTC, you can obtain the POSIX timestamp by supplying
``tzinfo=timezone.utc``::
@@ -1861,7 +1881,7 @@ Other constructor:
.. versionadded:: 3.7
.. versionchanged:: 3.11
Previously, this method only supported formats that could be emitted by
- :meth:`time.isoformat()`.
+ :meth:`time.isoformat`.
Instance methods:
@@ -2021,7 +2041,7 @@ Examples of working with a :class:`.time` object::
supply implementations of the standard :class:`tzinfo` methods needed by the
:class:`.datetime` methods you use. The :mod:`!datetime` module provides
:class:`timezone`, a simple concrete subclass of :class:`tzinfo` which can
- represent timezones with fixed offset from UTC such as UTC itself or North
+ represent time zones with fixed offset from UTC such as UTC itself or North
American EST and EDT.
Special requirement for pickling: A :class:`tzinfo` subclass must have an
@@ -2146,7 +2166,7 @@ When a :class:`.datetime` object is passed in response to a :class:`.datetime`
method, ``dt.tzinfo`` is the same object as *self*. :class:`tzinfo` methods can
rely on this, unless user code calls :class:`tzinfo` methods directly. The
intent is that the :class:`tzinfo` methods interpret *dt* as being in local
-time, and not need worry about objects in other timezones.
+time, and not need worry about objects in other time zones.
There is one more :class:`tzinfo` method that a subclass may wish to override:
@@ -2263,12 +2283,12 @@ only EST (fixed offset -5 hours), or only EDT (fixed offset -4 hours)).
:mod:`zoneinfo`
The :mod:`!datetime` module has a basic :class:`timezone` class (for
handling arbitrary fixed offsets from UTC) and its :attr:`timezone.utc`
- attribute (a UTC timezone instance).
+ attribute (a UTC :class:`!timezone` instance).
- ``zoneinfo`` brings the *IANA timezone database* (also known as the Olson
+ ``zoneinfo`` brings the *IANA time zone database* (also known as the Olson
database) to Python, and its usage is recommended.
- `IANA timezone database `_
+ `IANA time zone database `_
The Time Zone Database (often called tz, tzdata or zoneinfo) contains code
and data that represent the history of local time for many representative
locations around the globe. It is updated periodically to reflect changes
@@ -2282,10 +2302,10 @@ only EST (fixed offset -5 hours), or only EDT (fixed offset -4 hours)).
-------------------------
The :class:`timezone` class is a subclass of :class:`tzinfo`, each
-instance of which represents a timezone defined by a fixed offset from
+instance of which represents a time zone defined by a fixed offset from
UTC.
-Objects of this class cannot be used to represent timezone information in the
+Objects of this class cannot be used to represent time zone information in the
locations where different offsets are used in different days of the year or
where historical changes have been made to civil time.
@@ -2346,7 +2366,7 @@ Class attributes:
.. attribute:: timezone.utc
- The UTC timezone, ``timezone(timedelta(0))``.
+ The UTC time zone, ``timezone(timedelta(0))``.
.. index::
@@ -2555,7 +2575,7 @@ Using ``datetime.strptime(date_string, format)`` is equivalent to::
datetime(*(time.strptime(date_string, format)[0:6]))
-except when the format includes sub-second components or timezone offset
+except when the format includes sub-second components or time zone offset
information, which are supported in ``datetime.strptime`` but are discarded by
``time.strptime``.
diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst
index 77148a558d1..6c659ea52ad 100644
--- a/Doc/library/dbm.rst
+++ b/Doc/library/dbm.rst
@@ -19,8 +19,6 @@ slow-but-simple implementation in module :mod:`dbm.dumb` will be used. There
is a `third party interface `_ to
the Oracle Berkeley DB.
-.. include:: ../includes/wasm-ios-notavail.rst
-
.. exception:: error
A tuple containing the exceptions that can be raised by each of the supported
@@ -164,6 +162,8 @@ SQLite backend for the :mod:`dbm` module.
The files created by :mod:`dbm.sqlite3` can thus be opened by :mod:`sqlite3`,
or any other SQLite browser, including the SQLite CLI.
+.. include:: ../includes/wasm-notavail.rst
+
.. function:: open(filename, /, flag="r", mode=0o666)
Open an SQLite database.
@@ -207,6 +207,8 @@ functionality like crash tolerance.
The file formats created by :mod:`dbm.gnu` and :mod:`dbm.ndbm` are incompatible
and can not be used interchangeably.
+.. include:: ../includes/wasm-mobile-notavail.rst
+
.. exception:: error
Raised on :mod:`dbm.gnu`-specific errors, such as I/O errors. :exc:`KeyError` is
@@ -326,6 +328,8 @@ This module can be used with the "classic" NDBM interface or the
when storing values larger than this limit. Reading such corrupted files can
result in a hard crash (segmentation fault).
+.. include:: ../includes/wasm-mobile-notavail.rst
+
.. exception:: error
Raised on :mod:`dbm.ndbm`-specific errors, such as I/O errors. :exc:`KeyError` is raised
diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst
index db323802a6f..916f17cadfa 100644
--- a/Doc/library/decimal.rst
+++ b/Doc/library/decimal.rst
@@ -1,4 +1,4 @@
-:mod:`!decimal` --- Decimal fixed point and floating point arithmetic
+:mod:`!decimal` --- Decimal fixed-point and floating-point arithmetic
=====================================================================
.. module:: decimal
@@ -31,7 +31,7 @@
--------------
The :mod:`decimal` module provides support for fast correctly rounded
-decimal floating point arithmetic. It offers several advantages over the
+decimal floating-point arithmetic. It offers several advantages over the
:class:`float` datatype:
* Decimal "is based on a floating-point model which was designed with people
@@ -207,7 +207,7 @@ a decimal raises :class:`InvalidOperation`::
.. versionchanged:: 3.3
Decimals interact well with much of the rest of Python. Here is a small decimal
-floating point flying circus:
+floating-point flying circus:
.. doctest::
:options: +NORMALIZE_WHITESPACE
@@ -373,7 +373,7 @@ Decimal objects
digits, and an integer exponent. For example, ``Decimal((0, (1, 4, 1, 4), -3))``
returns ``Decimal('1.414')``.
- If *value* is a :class:`float`, the binary floating point value is losslessly
+ If *value* is a :class:`float`, the binary floating-point value is losslessly
converted to its exact decimal equivalent. This conversion can often require
53 or more digits of precision. For example, ``Decimal(float('1.1'))``
converts to
@@ -403,7 +403,7 @@ Decimal objects
Underscores are allowed for grouping, as with integral and floating-point
literals in code.
- Decimal floating point objects share many properties with the other built-in
+ Decimal floating-point objects share many properties with the other built-in
numeric types such as :class:`float` and :class:`int`. All of the usual math
operations and special methods apply. Likewise, decimal objects can be
copied, pickled, printed, used as dictionary keys, used as set elements,
@@ -445,7 +445,7 @@ Decimal objects
Mixed-type comparisons between :class:`Decimal` instances and other
numeric types are now fully supported.
- In addition to the standard numeric properties, decimal floating point
+ In addition to the standard numeric properties, decimal floating-point
objects also have a number of specialized methods:
@@ -1741,7 +1741,7 @@ The following table summarizes the hierarchy of signals::
.. _decimal-notes:
-Floating Point Notes
+Floating-Point Notes
--------------------
@@ -1754,7 +1754,7 @@ can still incur round-off error when non-zero digits exceed the fixed precision.
The effects of round-off error can be amplified by the addition or subtraction
of nearly offsetting quantities resulting in loss of significance. Knuth
-provides two instructive examples where rounded floating point arithmetic with
+provides two instructive examples where rounded floating-point arithmetic with
insufficient precision causes the breakdown of the associative and distributive
properties of addition:
@@ -1844,7 +1844,7 @@ treated as equal and their sign is informational.
In addition to the two signed zeros which are distinct yet equal, there are
various representations of zero with differing precisions yet equivalent in
value. This takes a bit of getting used to. For an eye accustomed to
-normalized floating point representations, it is not immediately obvious that
+normalized floating-point representations, it is not immediately obvious that
the following calculation returns a value equal to zero:
>>> 1 / Decimal('Infinity')
@@ -2171,7 +2171,7 @@ value unchanged:
Q. Is there a way to convert a regular float to a :class:`Decimal`?
-A. Yes, any binary floating point number can be exactly expressed as a
+A. Yes, any binary floating-point number can be exactly expressed as a
Decimal though an exact conversion may take more precision than intuition would
suggest:
@@ -2225,7 +2225,7 @@ Q. Is the CPython implementation fast for large numbers?
A. Yes. In the CPython and PyPy3 implementations, the C/CFFI versions of
the decimal module integrate the high speed `libmpdec
`_ library for
-arbitrary precision correctly rounded decimal floating point arithmetic [#]_.
+arbitrary precision correctly rounded decimal floating-point arithmetic [#]_.
``libmpdec`` uses `Karatsuba multiplication
`_
for medium-sized numbers and the `Number Theoretic Transform
diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst
index ca215888f09..c5507e89a52 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -1102,11 +1102,15 @@ iterations of the loop.
.. opcode:: BUILD_TUPLE (count)
Creates a tuple consuming *count* items from the stack, and pushes the
- resulting tuple onto the stack.::
+ resulting tuple onto the stack::
- assert count > 0
- STACK, values = STACK[:-count], STACK[-count:]
- STACK.append(tuple(values))
+ if count == 0:
+ value = ()
+ else:
+ value = tuple(STACK[-count:])
+ STACK = STACK[:-count]
+
+ STACK.append(value)
.. opcode:: BUILD_LIST (count)
@@ -1581,7 +1585,7 @@ iterations of the loop.
end = STACK.pop()
start = STACK.pop()
- STACK.append(slice(start, stop))
+ STACK.append(slice(start, end))
if it is 3, implements::
@@ -1748,7 +1752,7 @@ iterations of the loop.
| ``INTRINSIC_STOPITERATION_ERROR`` | Extracts the return value from a |
| | ``StopIteration`` exception. |
+-----------------------------------+-----------------------------------+
- | ``INTRINSIC_ASYNC_GEN_WRAP`` | Wraps an aync generator value |
+ | ``INTRINSIC_ASYNC_GEN_WRAP`` | Wraps an async generator value |
+-----------------------------------+-----------------------------------+
| ``INTRINSIC_UNARY_POSITIVE`` | Performs the unary ``+`` |
| | operation |
diff --git a/Doc/library/email.compat32-message.rst b/Doc/library/email.compat32-message.rst
index c4c322a82e1..4285c436e8d 100644
--- a/Doc/library/email.compat32-message.rst
+++ b/Doc/library/email.compat32-message.rst
@@ -7,6 +7,7 @@
:synopsis: The base class representing email messages in a fashion
backward compatible with Python 3.2
:noindex:
+ :no-index:
The :class:`Message` class is very similar to the
@@ -104,7 +105,7 @@ Here are the methods of the :class:`Message` class:
.. method:: __str__()
- Equivalent to :meth:`.as_string()`. Allows ``str(msg)`` to produce a
+ Equivalent to :meth:`.as_string`. Allows ``str(msg)`` to produce a
string containing the formatted message.
@@ -142,7 +143,7 @@ Here are the methods of the :class:`Message` class:
.. method:: __bytes__()
- Equivalent to :meth:`.as_bytes()`. Allows ``bytes(msg)`` to produce a
+ Equivalent to :meth:`.as_bytes`. Allows ``bytes(msg)`` to produce a
bytes object containing the formatted message.
.. versionadded:: 3.4
diff --git a/Doc/library/email.contentmanager.rst b/Doc/library/email.contentmanager.rst
index 34121f8c0a7..a86e227429b 100644
--- a/Doc/library/email.contentmanager.rst
+++ b/Doc/library/email.contentmanager.rst
@@ -58,11 +58,12 @@
* the type itself (``typ``)
* the type's fully qualified name (``typ.__module__ + '.' +
typ.__qualname__``).
- * the type's qualname (``typ.__qualname__``)
- * the type's name (``typ.__name__``).
+ * the type's :attr:`qualname ` (``typ.__qualname__``)
+ * the type's :attr:`name ` (``typ.__name__``).
If none of the above match, repeat all of the checks above for each of
- the types in the :term:`MRO` (``typ.__mro__``). Finally, if no other key
+ the types in the :term:`MRO` (:attr:`typ.__mro__ `).
+ Finally, if no other key
yields a handler, check for a handler for the key ``None``. If there is
no handler for ``None``, raise a :exc:`KeyError` for the fully
qualified name of the type.
diff --git a/Doc/library/email.errors.rst b/Doc/library/email.errors.rst
index 33ab4265116..f8f43d82a3d 100644
--- a/Doc/library/email.errors.rst
+++ b/Doc/library/email.errors.rst
@@ -58,6 +58,13 @@ The following exception classes are defined in the :mod:`email.errors` module:
:class:`~email.mime.nonmultipart.MIMENonMultipart` (e.g.
:class:`~email.mime.image.MIMEImage`).
+
+.. exception:: HeaderWriteError()
+
+ Raised when an error occurs when the :mod:`~email.generator` outputs
+ headers.
+
+
.. exception:: MessageDefect()
This is the base class for all defects found when parsing email messages.
diff --git a/Doc/library/email.headerregistry.rst b/Doc/library/email.headerregistry.rst
index bcbd00c833e..7f8044932fa 100644
--- a/Doc/library/email.headerregistry.rst
+++ b/Doc/library/email.headerregistry.rst
@@ -317,7 +317,7 @@ variant, :attr:`~.BaseHeader.max_count` is set to 1.
class. When *use_default_map* is ``True`` (the default), the standard
mapping of header names to classes is copied in to the registry during
initialization. *base_class* is always the last class in the generated
- class's ``__bases__`` list.
+ class's :class:`~type.__bases__` list.
The default mappings are:
diff --git a/Doc/library/email.message.rst b/Doc/library/email.message.rst
index e9cce1af186..71d6e321f38 100644
--- a/Doc/library/email.message.rst
+++ b/Doc/library/email.message.rst
@@ -124,7 +124,7 @@ message objects.
.. method:: __bytes__()
- Equivalent to :meth:`.as_bytes()`. Allows ``bytes(msg)`` to produce a
+ Equivalent to :meth:`.as_bytes`. Allows ``bytes(msg)`` to produce a
bytes object containing the serialized message.
diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst
index 83feedf7283..314767d0802 100644
--- a/Doc/library/email.policy.rst
+++ b/Doc/library/email.policy.rst
@@ -229,6 +229,24 @@ added matters. To illustrate::
.. versionadded:: 3.6
+
+ .. attribute:: verify_generated_headers
+
+ If ``True`` (the default), the generator will raise
+ :exc:`~email.errors.HeaderWriteError` instead of writing a header
+ that is improperly folded or delimited, such that it would
+ be parsed as multiple headers or joined with adjacent data.
+ Such headers can be generated by custom header classes or bugs
+ in the ``email`` module.
+
+ As it's a security feature, this defaults to ``True`` even in the
+ :class:`~email.policy.Compat32` policy.
+ For backwards compatible, but unsafe, behavior, it must be set to
+ ``False`` explicitly.
+
+ .. versionadded:: 3.13
+
+
The following :class:`Policy` method is intended to be called by code using
the email library to create policy instances with custom settings:
diff --git a/Doc/library/email.utils.rst b/Doc/library/email.utils.rst
index 6f0bed130bc..6bd45200d86 100644
--- a/Doc/library/email.utils.rst
+++ b/Doc/library/email.utils.rst
@@ -159,7 +159,7 @@ of the new API.
Fri, 09 Nov 2001 01:08:47 -0000
- Optional *timeval* if given is a floating point time value as accepted by
+ Optional *timeval* if given is a floating-point time value as accepted by
:func:`time.gmtime` and :func:`time.localtime`, otherwise the current time is
used.
diff --git a/Doc/library/ensurepip.rst b/Doc/library/ensurepip.rst
index 518a2940edc..8dfb7ad9c95 100644
--- a/Doc/library/ensurepip.rst
+++ b/Doc/library/ensurepip.rst
@@ -38,7 +38,7 @@ when creating a virtual environment) or after explicitly uninstalling
:pep:`453`: Explicit bootstrapping of pip in Python installations
The original rationale and specification for this module.
-.. include:: ../includes/wasm-ios-notavail.rst
+.. include:: ../includes/wasm-mobile-notavail.rst
Command line interface
----------------------
diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst
index 9cf94e342da..a724fe4bcdc 100644
--- a/Doc/library/enum.rst
+++ b/Doc/library/enum.rst
@@ -570,6 +570,8 @@ Data Types
>>> len(white)
3
+ .. versionadded:: 3.11
+
.. method:: __bool__(self):
Returns *True* if any members in flag, *False* otherwise::
@@ -661,7 +663,7 @@ Data Types
* the result is a valid *IntFlag*: an *IntFlag* is returned
* the result is not a valid *IntFlag*: the result depends on the :class:`FlagBoundary` setting
- The :func:`repr()` of unnamed zero-valued flags has changed. It is now:
+ The :func:`repr` of unnamed zero-valued flags has changed. It is now:
>>> Color(0)
diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst
index 7910b306f14..b5ba86f1b19 100644
--- a/Doc/library/exceptions.rst
+++ b/Doc/library/exceptions.rst
@@ -412,8 +412,8 @@ The following exceptions are the exceptions that are usually raised.
represented. This cannot occur for integers (which would rather raise
:exc:`MemoryError` than give up). However, for historical reasons,
OverflowError is sometimes raised for integers that are outside a required
- range. Because of the lack of standardization of floating point exception
- handling in C, most floating point operations are not checked.
+ range. Because of the lack of standardization of floating-point exception
+ handling in C, most floating-point operations are not checked.
.. exception:: PythonFinalizationError
diff --git a/Doc/library/filecmp.rst b/Doc/library/filecmp.rst
index 2a0670ffcc2..282d0e0d8db 100644
--- a/Doc/library/filecmp.rst
+++ b/Doc/library/filecmp.rst
@@ -70,7 +70,7 @@ The :mod:`filecmp` module defines the following functions:
The :class:`dircmp` class
-------------------------
-.. class:: dircmp(a, b, ignore=None, hide=None, shallow=True)
+.. class:: dircmp(a, b, ignore=None, hide=None, *, shallow=True)
Construct a new directory comparison object, to compare the directories *a*
and *b*. *ignore* is a list of names to ignore, and defaults to
diff --git a/Doc/library/fractions.rst b/Doc/library/fractions.rst
index 552d6030b1c..7e615ed230a 100644
--- a/Doc/library/fractions.rst
+++ b/Doc/library/fractions.rst
@@ -31,7 +31,7 @@ another rational number, or from a string.
:class:`Fraction` instance with the same value. The next two versions accept
either a :class:`float` or a :class:`decimal.Decimal` instance, and return a
:class:`Fraction` instance with exactly the same value. Note that due to the
- usual issues with binary floating-point (see :ref:`tut-fp-issues`), the
+ usual issues with binary floating point (see :ref:`tut-fp-issues`), the
argument to ``Fraction(1.1)`` is not exactly equal to 11/10, and so
``Fraction(1.1)`` does *not* return ``Fraction(11, 10)`` as one might expect.
(But see the documentation for the :meth:`limit_denominator` method below.)
@@ -87,7 +87,7 @@ another rational number, or from a string.
.. versionchanged:: 3.9
The :func:`math.gcd` function is now used to normalize the *numerator*
- and *denominator*. :func:`math.gcd` always return a :class:`int` type.
+ and *denominator*. :func:`math.gcd` always returns an :class:`int` type.
Previously, the GCD type depended on *numerator* and *denominator*.
.. versionchanged:: 3.11
diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst
index 8c39dc00f5d..bb153220672 100644
--- a/Doc/library/ftplib.rst
+++ b/Doc/library/ftplib.rst
@@ -243,7 +243,7 @@ FTP objects
Retrieve a file in binary transfer mode.
:param str cmd:
- An appropriate ``STOR`` command: :samp:`"STOR {filename}"`.
+ An appropriate ``RETR`` command: :samp:`"RETR {filename}"`.
:param callback:
A single parameter callable that is called
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index b75b6dfc315..8d023ebf48a 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -57,7 +57,7 @@ are always available. They are listed here in alphabetical order.
.. function:: abs(x)
Return the absolute value of a number. The argument may be an
- integer, a floating point number, or an object implementing
+ integer, a floating-point number, or an object implementing
:meth:`~object.__abs__`.
If the argument is a complex number, its magnitude is returned.
@@ -161,7 +161,7 @@ are always available. They are listed here in alphabetical order.
This function drops you into the debugger at the call site. Specifically,
it calls :func:`sys.breakpointhook`, passing ``args`` and ``kws`` straight
through. By default, ``sys.breakpointhook()`` calls
- :func:`pdb.set_trace()` expecting no arguments. In this case, it is
+ :func:`pdb.set_trace` expecting no arguments. In this case, it is
purely a convenience function so you don't have to explicitly import
:mod:`pdb` or type as much code to enter the debugger. However,
:func:`sys.breakpointhook` can be set to some other function and
@@ -283,9 +283,11 @@ are always available. They are listed here in alphabetical order.
:func:`property`.
.. versionchanged:: 3.10
- Class methods now inherit the method attributes (``__module__``,
- ``__name__``, ``__qualname__``, ``__doc__`` and ``__annotations__``) and
- have a new ``__wrapped__`` attribute.
+ Class methods now inherit the method attributes
+ (:attr:`~function.__module__`, :attr:`~function.__name__`,
+ :attr:`~function.__qualname__`, :attr:`~function.__doc__` and
+ :attr:`~function.__annotations__`) and have a new ``__wrapped__``
+ attribute.
.. deprecated-removed:: 3.11 3.13
Class methods can no longer wrap other :term:`descriptors ` such as
@@ -538,7 +540,7 @@ are always available. They are listed here in alphabetical order.
Take two (non-complex) numbers as arguments and return a pair of numbers
consisting of their quotient and remainder when using integer division. With
mixed operand types, the rules for binary arithmetic operators apply. For
- integers, the result is the same as ``(a // b, a % b)``. For floating point
+ integers, the result is the same as ``(a // b, a % b)``. For floating-point
numbers the result is ``(q, a % b)``, where *q* is usually ``math.floor(a /
b)`` but may be 1 less than that. In any case ``q * b + a % b`` is very
close to *a*, if ``a % b`` is non-zero it has the same sign as *b*, and ``0
@@ -734,7 +736,7 @@ are always available. They are listed here in alphabetical order.
single: NaN
single: Infinity
- Return a floating point number constructed from a number or a string.
+ Return a floating-point number constructed from a number or a string.
Examples:
@@ -775,8 +777,8 @@ are always available. They are listed here in alphabetical order.
Case is not significant, so, for example, "inf", "Inf", "INFINITY", and
"iNfINity" are all acceptable spellings for positive infinity.
- Otherwise, if the argument is an integer or a floating point number, a
- floating point number with the same value (within Python's floating point
+ Otherwise, if the argument is an integer or a floating-point number, a
+ floating-point number with the same value (within Python's floating-point
precision) is returned. If the argument is outside the range of a Python
float, an :exc:`OverflowError` will be raised.
@@ -1003,7 +1005,7 @@ are always available. They are listed here in alphabetical order.
``int(x)`` returns ``x.__int__()``. If the argument defines :meth:`~object.__index__`,
it returns ``x.__index__()``. If the argument defines :meth:`~object.__trunc__`,
it returns ``x.__trunc__()``.
- For floating point numbers, this truncates towards zero.
+ For floating-point numbers, this truncates towards zero.
If the argument is not a number or if *base* is given, then it must be a string,
:class:`bytes`, or :class:`bytearray` instance representing an integer
@@ -1279,8 +1281,9 @@ are always available. They are listed here in alphabetical order.
.. note::
- :class:`object` does *not* have a :attr:`~object.__dict__`, so you can't
- assign arbitrary attributes to an instance of the :class:`object` class.
+ :class:`object` instances do *not* have :attr:`~object.__dict__`
+ attributes, so you can't assign arbitrary attributes to an instance of
+ :class:`object`.
.. function:: oct(x)
@@ -1329,7 +1332,7 @@ are always available. They are listed here in alphabetical order.
(which on *some* Unix systems, means that *all* writes append to the end of
the file regardless of the current seek position). In text mode, if
*encoding* is not specified the encoding used is platform-dependent:
- :func:`locale.getencoding()` is called to get the current locale encoding.
+ :func:`locale.getencoding` is called to get the current locale encoding.
(For reading and writing raw bytes use binary mode and leave
*encoding* unspecified.) The available modes are:
@@ -1502,7 +1505,7 @@ are always available. They are listed here in alphabetical order.
(where :func:`open` is declared), :mod:`os`, :mod:`os.path`, :mod:`tempfile`,
and :mod:`shutil`.
- .. audit-event:: open file,mode,flags open
+ .. audit-event:: open path,mode,flags open
The ``mode`` and ``flags`` arguments may have been modified or inferred from
the original call.
@@ -1693,6 +1696,13 @@ are always available. They are listed here in alphabetical order.
.. versionchanged:: 3.5
The docstrings of property objects are now writeable.
+ .. attribute:: __name__
+
+ Attribute holding the name of the property. The name of the property
+ can be changed at runtime.
+
+ .. versionadded:: 3.13
+
.. _func-range:
.. class:: range(stop)
@@ -1893,10 +1903,11 @@ are always available. They are listed here in alphabetical order.
For more information on static methods, see :ref:`types`.
.. versionchanged:: 3.10
- Static methods now inherit the method attributes (``__module__``,
- ``__name__``, ``__qualname__``, ``__doc__`` and ``__annotations__``),
- have a new ``__wrapped__`` attribute, and are now callable as regular
- functions.
+ Static methods now inherit the method attributes
+ (:attr:`~function.__module__`, :attr:`~function.__name__`,
+ :attr:`~function.__qualname__`, :attr:`~function.__doc__` and
+ :attr:`~function.__annotations__`), have a new ``__wrapped__`` attribute,
+ and are now callable as regular functions.
.. index::
@@ -1921,7 +1932,7 @@ are always available. They are listed here in alphabetical order.
For some use cases, there are good alternatives to :func:`sum`.
The preferred, fast way to concatenate a sequence of strings is by calling
- ``''.join(sequence)``. To add floating point values with extended precision,
+ ``''.join(sequence)``. To add floating-point values with extended precision,
see :func:`math.fsum`\. To concatenate a series of iterables, consider using
:func:`itertools.chain`.
@@ -1943,14 +1954,14 @@ are always available. They are listed here in alphabetical order.
to be searched. The search starts from the class right after the
*type*.
- For example, if :attr:`~class.__mro__` of *object_or_type* is
+ For example, if :attr:`~type.__mro__` of *object_or_type* is
``D -> B -> C -> A -> object`` and the value of *type* is ``B``,
then :func:`super` searches ``C -> A -> object``.
- The :attr:`~class.__mro__` attribute of the *object_or_type* lists the method
- resolution search order used by both :func:`getattr` and :func:`super`. The
- attribute is dynamic and can change whenever the inheritance hierarchy is
- updated.
+ The :attr:`~type.__mro__` attribute of the class corresponding to
+ *object_or_type* lists the method resolution search order used by both
+ :func:`getattr` and :func:`super`. The attribute is dynamic and can change
+ whenever the inheritance hierarchy is updated.
If the second argument is omitted, the super object returned is unbound. If
the second argument is an object, ``isinstance(obj, type)`` must be true. If
@@ -2026,28 +2037,30 @@ are always available. They are listed here in alphabetical order.
With one argument, return the type of an *object*. The return value is a
type object and generally the same object as returned by
- :attr:`object.__class__ `.
+ :attr:`object.__class__`.
The :func:`isinstance` built-in function is recommended for testing the type
of an object, because it takes subclasses into account.
-
With three arguments, return a new type object. This is essentially a
dynamic form of the :keyword:`class` statement. The *name* string is
- the class name and becomes the :attr:`~definition.__name__` attribute.
+ the class name and becomes the :attr:`~type.__name__` attribute.
The *bases* tuple contains the base classes and becomes the
- :attr:`~class.__bases__` attribute; if empty, :class:`object`, the
+ :attr:`~type.__bases__` attribute; if empty, :class:`object`, the
ultimate base of all classes, is added. The *dict* dictionary contains
attribute and method definitions for the class body; it may be copied
- or wrapped before becoming the :attr:`~object.__dict__` attribute.
- The following two statements create identical :class:`type` objects:
+ or wrapped before becoming the :attr:`~type.__dict__` attribute.
+ The following two statements create identical :class:`!type` objects:
>>> class X:
... a = 1
...
>>> X = type('X', (), dict(a=1))
- See also :ref:`bltin-type-objects`.
+ See also:
+
+ * :ref:`Documentation on attributes and methods on classes `.
+ * :ref:`bltin-type-objects`
Keyword arguments provided to the three argument form are passed to the
appropriate metaclass machinery (usually :meth:`~object.__init_subclass__`)
@@ -2057,18 +2070,18 @@ are always available. They are listed here in alphabetical order.
See also :ref:`class-customization`.
.. versionchanged:: 3.6
- Subclasses of :class:`type` which don't override ``type.__new__`` may no
+ Subclasses of :class:`!type` which don't override ``type.__new__`` may no
longer use the one-argument form to get the type of an object.
.. function:: vars()
vars(object)
Return the :attr:`~object.__dict__` attribute for a module, class, instance,
- or any other object with a :attr:`~object.__dict__` attribute.
+ or any other object with a :attr:`!__dict__` attribute.
Objects such as modules and instances have an updateable :attr:`~object.__dict__`
attribute; however, other objects may have write restrictions on their
- :attr:`~object.__dict__` attributes (for example, classes use a
+ :attr:`!__dict__` attributes (for example, classes use a
:class:`types.MappingProxyType` to prevent direct dictionary updates).
Without an argument, :func:`vars` acts like :func:`locals`.
diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst
index 9d5c72802a2..3540a1e8f49 100644
--- a/Doc/library/functools.rst
+++ b/Doc/library/functools.rst
@@ -34,7 +34,7 @@ The :mod:`functools` module defines the following functions:
Returns the same as ``lru_cache(maxsize=None)``, creating a thin
wrapper around a dictionary lookup for the function arguments. Because it
never needs to evict old values, this is smaller and faster than
- :func:`lru_cache()` with a size limit.
+ :func:`lru_cache` with a size limit.
For example::
@@ -218,7 +218,7 @@ The :mod:`functools` module defines the following functions:
cache. See :ref:`faq-cache-method-calls`
An `LRU (least recently used) cache
- `_
+ `_
works best when the most recent calls are the best predictors of upcoming
calls (for example, the most popular articles on a news server tend to
change each day). The cache's size limit assures that the cache does not
@@ -492,6 +492,25 @@ The :mod:`functools` module defines the following functions:
... print(arg.real, arg.imag)
...
+ For code that dispatches on a collections type (e.g., ``list``), but wants
+ to typehint the items of the collection (e.g., ``list[int]``), the
+ dispatch type should be passed explicitly to the decorator itself with the
+ typehint going into the function definition::
+
+ >>> @fun.register(list)
+ ... def _(arg: list[int], verbose=False):
+ ... if verbose:
+ ... print("Enumerate this:")
+ ... for i, elem in enumerate(arg):
+ ... print(i, elem)
+
+ .. note::
+
+ At runtime the function will dispatch on an instance of a list regardless
+ of the type contained within the list i.e. ``[1,2,3]`` will be
+ dispatched the same as ``["foo", "bar", "baz"]``. The annotation
+ provided in this example is for static type checkers only and has no
+ runtime impact.
To enable registering :term:`lambdas` and pre-existing functions,
the :func:`register` attribute can also be used in a functional form::
@@ -646,10 +665,11 @@ The :mod:`functools` module defines the following functions:
attributes of the wrapper function are updated with the corresponding attributes
from the original function. The default values for these arguments are the
module level constants ``WRAPPER_ASSIGNMENTS`` (which assigns to the wrapper
- function's ``__module__``, ``__name__``, ``__qualname__``, ``__annotations__``,
- ``__type_params__``, and ``__doc__``, the documentation string)
- and ``WRAPPER_UPDATES`` (which
- updates the wrapper function's ``__dict__``, i.e. the instance dictionary).
+ function's :attr:`~function.__module__`, :attr:`~function.__name__`,
+ :attr:`~function.__qualname__`, :attr:`~function.__annotations__`,
+ :attr:`~function.__type_params__`, and :attr:`~function.__doc__`, the
+ documentation string) and ``WRAPPER_UPDATES`` (which updates the wrapper
+ function's :attr:`~function.__dict__`, i.e. the instance dictionary).
To allow access to the original function for introspection and other purposes
(e.g. bypassing a caching decorator such as :func:`lru_cache`), this function
@@ -670,7 +690,7 @@ The :mod:`functools` module defines the following functions:
.. versionchanged:: 3.2
The ``__wrapped__`` attribute is now automatically added.
- The ``__annotations__`` attribute is now copied by default.
+ The :attr:`~function.__annotations__` attribute is now copied by default.
Missing attributes no longer trigger an :exc:`AttributeError`.
.. versionchanged:: 3.4
@@ -679,7 +699,7 @@ The :mod:`functools` module defines the following functions:
(see :issue:`17482`)
.. versionchanged:: 3.12
- The ``__type_params__`` attribute is now copied by default.
+ The :attr:`~function.__type_params__` attribute is now copied by default.
.. decorator:: wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
@@ -741,9 +761,10 @@ have three read-only attributes:
The keyword arguments that will be supplied when the :class:`partial` object is
called.
-:class:`partial` objects are like :class:`function` objects in that they are
-callable, weak referenceable, and can have attributes. There are some important
-differences. For instance, the :attr:`~definition.__name__` and :attr:`__doc__` attributes
+:class:`partial` objects are like :ref:`function objects `
+in that they are callable, weak referenceable, and can have attributes.
+There are some important differences. For instance, the
+:attr:`~function.__name__` and :attr:`function.__doc__` attributes
are not created automatically. Also, :class:`partial` objects defined in
classes behave like static methods and do not transform into bound methods
during instance attribute look-up.
diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst
index 790dfdfd00b..8ce850ba777 100644
--- a/Doc/library/gc.rst
+++ b/Doc/library/gc.rst
@@ -42,7 +42,7 @@ The :mod:`gc` module provides the following functions:
With no arguments, run a full collection. The optional argument *generation*
may be an integer specifying which generation to collect (from 0 to 2). A
- :exc:`ValueError` is raised if the generation number is invalid. The sum of
+ :exc:`ValueError` is raised if the generation number is invalid. The sum of
collected objects and uncollectable objects is returned.
The free lists maintained for a number of built-in types are cleared
diff --git a/Doc/library/getpass.rst b/Doc/library/getpass.rst
index 9d67250033d..3b5296f9ec6 100644
--- a/Doc/library/getpass.rst
+++ b/Doc/library/getpass.rst
@@ -49,7 +49,7 @@ The :mod:`getpass` module provides two functions:
systems which support the :mod:`pwd` module, otherwise, an :exc:`OSError`
is raised.
- In general, this function should be preferred over :func:`os.getlogin()`.
+ In general, this function should be preferred over :func:`os.getlogin`.
.. versionchanged:: 3.13
Previously, various exceptions beyond just :exc:`OSError` were raised.
diff --git a/Doc/library/grp.rst b/Doc/library/grp.rst
index 30caea328ba..d1c7f22a209 100644
--- a/Doc/library/grp.rst
+++ b/Doc/library/grp.rst
@@ -10,7 +10,7 @@
This module provides access to the Unix group database. It is available on all
Unix versions.
-.. availability:: Unix, not WASI, not iOS.
+.. availability:: Unix, not WASI, not Android, not iOS.
Group database entries are reported as a tuple-like object, whose attributes
correspond to the members of the ``group`` structure (Attribute field below, see
diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst
index 5d24b77e13b..dffb167c747 100644
--- a/Doc/library/hashlib.rst
+++ b/Doc/library/hashlib.rst
@@ -655,7 +655,7 @@ on the hash function used in digital signatures.
by the signer.
(`NIST SP-800-106 "Randomized Hashing for Digital Signatures"
- `_)
+ `_)
In BLAKE2 the salt is processed as a one-time input to the hash function during
initialization, rather than as an input to each compression function.
@@ -809,8 +809,8 @@ Domain Dedication 1.0 Universal:
.. _NIST-SP-800-132: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf
.. _stackexchange pbkdf2 iterations question: https://security.stackexchange.com/questions/3959/recommended-of-iterations-when-using-pbkdf2-sha256/
.. _Attacks on cryptographic hash algorithms: https://en.wikipedia.org/wiki/Cryptographic_hash_function#Attacks_on_cryptographic_hash_algorithms
-.. _the FIPS 180-4 standard: https://csrc.nist.gov/publications/detail/fips/180/4/final
-.. _the FIPS 202 standard: https://csrc.nist.gov/publications/detail/fips/202/final
+.. _the FIPS 180-4 standard: https://csrc.nist.gov/pubs/fips/180-4/upd1/final
+.. _the FIPS 202 standard: https://csrc.nist.gov/pubs/fips/202/final
.. _HACL\* project: https://github.com/hacl-star/hacl-star
@@ -827,7 +827,7 @@ Domain Dedication 1.0 Universal:
https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.180-4.pdf
The FIPS 180-4 publication on Secure Hash Algorithms.
- https://csrc.nist.gov/publications/detail/fips/202/final
+ https://csrc.nist.gov/pubs/fips/202/final
The FIPS 202 publication on the SHA-3 Standard.
https://www.blake2.net/
diff --git a/Doc/library/http.cookiejar.rst b/Doc/library/http.cookiejar.rst
index 31ac8bafb6a..23ddecf8738 100644
--- a/Doc/library/http.cookiejar.rst
+++ b/Doc/library/http.cookiejar.rst
@@ -137,7 +137,7 @@ The following classes are provided:
The Netscape protocol with the bugs fixed. Uses :mailheader:`Set-Cookie2` in
place of :mailheader:`Set-Cookie`. Not widely used.
- http://kristol.org/cookie/errata.html
+ https://kristol.org/cookie/errata.html
Unfinished errata to :rfc:`2965`.
:rfc:`2964` - Use of HTTP State Management
diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst
index 3c80fa747d5..1197b575c00 100644
--- a/Doc/library/http.server.rst
+++ b/Doc/library/http.server.rst
@@ -263,7 +263,7 @@ provides three different variants:
Adds a blank line
(indicating the end of the HTTP headers in the response)
- to the headers buffer and calls :meth:`flush_headers()`.
+ to the headers buffer and calls :meth:`flush_headers`.
.. versionchanged:: 3.2
The buffered headers are written to the output stream.
@@ -378,7 +378,7 @@ provides three different variants:
If the request was mapped to a file, it is opened. Any :exc:`OSError`
exception in opening the requested file is mapped to a ``404``,
- ``'File not found'`` error. If there was a ``'If-Modified-Since'``
+ ``'File not found'`` error. If there was an ``'If-Modified-Since'``
header in the request, and the file was not modified after this time,
a ``304``, ``'Not Modified'`` response is sent. Otherwise, the content
type is guessed by calling the :meth:`guess_type` method, which in turn
diff --git a/Doc/library/importlib.resources.abc.rst b/Doc/library/importlib.resources.abc.rst
index 5ea8044e1ec..54995ddbfbc 100644
--- a/Doc/library/importlib.resources.abc.rst
+++ b/Doc/library/importlib.resources.abc.rst
@@ -22,7 +22,7 @@
something like a data file that lives next to the ``__init__.py``
file of the package. The purpose of this class is to help abstract
out the accessing of such data files so that it does not matter if
- the package and its data file(s) are stored in a e.g. zip file
+ the package and its data file(s) are stored e.g. in a zip file
versus on the file system.
For any of methods of this class, a *resource* argument is
diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst
index b58ef359378..1b798568646 100644
--- a/Doc/library/importlib.rst
+++ b/Doc/library/importlib.rst
@@ -657,7 +657,7 @@ ABC hierarchy::
something like a data file that lives next to the ``__init__.py``
file of the package. The purpose of this class is to help abstract
out the accessing of such data files so that it does not matter if
- the package and its data file(s) are stored in a e.g. zip file
+ the package and its data file(s) are stored e.g. in a zip file
versus on the file system.
For any of methods of this class, a *resource* argument is
@@ -1166,10 +1166,9 @@ find and load modules.
.. class:: ModuleSpec(name, loader, *, origin=None, loader_state=None, is_package=None)
A specification for a module's import-system-related state. This is
- typically exposed as the module's :attr:`__spec__` attribute. In the
- descriptions below, the names in parentheses give the corresponding
- attribute available directly on the module object,
- e.g. ``module.__spec__.origin == module.__file__``. Note, however, that
+ typically exposed as the module's :attr:`__spec__` attribute. Many
+ of these attributes are also available directly on a module: for example,
+ ``module.__spec__.origin == module.__file__``. Note, however, that
while the *values* are usually equivalent, they can differ since there is
no synchronization between the two objects. For example, it is possible to update
the module's :attr:`__file__` at runtime and this will not be automatically
@@ -1179,66 +1178,60 @@ find and load modules.
.. attribute:: name
- (:attr:`__name__`)
-
- The module's fully qualified name.
- The :term:`finder` should always set this attribute to a non-empty string.
+ The module's fully qualified name
+ (see :attr:`__name__` attributes on modules).
+ The :term:`finder` should always set this attribute to a non-empty string.
.. attribute:: loader
- (:attr:`__loader__`)
-
- The :term:`loader` used to load the module.
- The :term:`finder` should always set this attribute.
+ The :term:`loader` used to load the module
+ (see :attr:`__loader__` attributes on modules).
+ The :term:`finder` should always set this attribute.
.. attribute:: origin
- (:attr:`__file__`)
-
- The location the :term:`loader` should use to load the module.
- For example, for modules loaded from a .py file this is the filename.
- The :term:`finder` should always set this attribute to a meaningful value
- for the :term:`loader` to use. In the uncommon case that there is not one
- (like for namespace packages), it should be set to ``None``.
+ The location the :term:`loader` should use to load the module
+ (see :attr:`__file__` attributes on modules).
+ For example, for modules loaded from a .py file this is the filename.
+ The :term:`finder` should always set this attribute to a meaningful value
+ for the :term:`loader` to use. In the uncommon case that there is not one
+ (like for namespace packages), it should be set to ``None``.
.. attribute:: submodule_search_locations
- (:attr:`__path__`)
-
- The list of locations where the package's submodules will be found.
- Most of the time this is a single directory.
- The :term:`finder` should set this attribute to a list, even an empty one, to indicate
- to the import system that the module is a package. It should be set to ``None`` for
- non-package modules. It is set automatically later to a special object for
- namespace packages.
+ The list of locations where the package's submodules will be found
+ (see :attr:`__path__` attributes on modules).
+ Most of the time this is a single directory.
+ The :term:`finder` should set this attribute to a list, even an empty one, to indicate
+ to the import system that the module is a package. It should be set to ``None`` for
+ non-package modules. It is set automatically later to a special object for
+ namespace packages.
.. attribute:: loader_state
- The :term:`finder` may set this attribute to an object containing additional,
- module-specific data to use when loading the module. Otherwise it should be
- set to ``None``.
+ The :term:`finder` may set this attribute to an object containing additional,
+ module-specific data to use when loading the module. Otherwise it should be
+ set to ``None``.
.. attribute:: cached
- (:attr:`__cached__`)
-
- The filename of a compiled version of the module's code.
- The :term:`finder` should always set this attribute but it may be ``None``
- for modules that do not need compiled code stored.
+ The filename of a compiled version of the module's code
+ (see :attr:`__cached__` attributes on modules).
+ The :term:`finder` should always set this attribute but it may be ``None``
+ for modules that do not need compiled code stored.
.. attribute:: parent
- (:attr:`__package__`)
-
- (Read-only) The fully qualified name of the package the module is in (or the
- empty string for a top-level module).
- If the module is a package then this is the same as :attr:`name`.
+ (Read-only) The fully qualified name of the package the module is in (or the
+ empty string for a top-level module).
+ See :attr:`__package__` attributes on modules.
+ If the module is a package then this is the same as :attr:`name`.
.. attribute:: has_location
- ``True`` if the spec's :attr:`origin` refers to a loadable location,
- ``False`` otherwise. This value impacts how :attr:`origin` is interpreted
- and how the module's :attr:`__file__` is populated.
+ ``True`` if the spec's :attr:`origin` refers to a loadable location,
+ ``False`` otherwise. This value impacts how :attr:`origin` is interpreted
+ and how the module's :attr:`__file__` is populated.
.. class:: AppleFrameworkLoader(name, path)
@@ -1252,7 +1245,7 @@ find and load modules.
be only a single binary per framework, and there can be no executable binary
material outside the Frameworks folder.
- To accomodate this requirement, when running on iOS, extension module
+ To accommodate this requirement, when running on iOS, extension module
binaries are *not* packaged as ``.so`` files on ``sys.path``, but as
individual standalone frameworks. To discover those frameworks, this loader
is be registered against the ``.fwork`` file extension, with a ``.fwork``
@@ -1584,20 +1577,34 @@ Note that if ``name`` is a submodule (contains a dot),
Importing a source file directly
''''''''''''''''''''''''''''''''
-To import a Python source file directly, use the following recipe::
+This recipe should be used with caution: it is an approximation of an import
+statement where the file path is specified directly, rather than
+:data:`sys.path` being searched. Alternatives should first be considered first,
+such as modifying :data:`sys.path` when a proper module is required, or using
+:func:`runpy.run_path` when the global namespace resulting from running a Python
+file is appropriate.
- import importlib.util
- import sys
+To import a Python source file directly from a path, use the following recipe::
- # For illustrative purposes.
- import tokenize
- file_path = tokenize.__file__
- module_name = tokenize.__name__
+ import importlib.util
+ import sys
+
+
+ def import_from_path(module_name, file_path):
+ spec = importlib.util.spec_from_file_location(module_name, file_path)
+ module = importlib.util.module_from_spec(spec)
+ sys.modules[module_name] = module
+ spec.loader.exec_module(module)
+ return module
- spec = importlib.util.spec_from_file_location(module_name, file_path)
- module = importlib.util.module_from_spec(spec)
- sys.modules[module_name] = module
- spec.loader.exec_module(module)
+
+ # For illustrative purposes only (use of `json` is arbitrary).
+ import json
+ file_path = json.__file__
+ module_name = json.__name__
+
+ # Similar outcome as `import json`.
+ json = import_from_path(module_name, file_path)
Implementing lazy imports
@@ -1623,7 +1630,6 @@ The example below shows how to implement lazy imports::
False
-
Setting up an importer
''''''''''''''''''''''
diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst
index 7838eeed284..7ed39ae2fec 100644
--- a/Doc/library/inspect.rst
+++ b/Doc/library/inspect.rst
@@ -457,7 +457,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes):
.. versionchanged:: 3.8
Functions wrapped in :func:`functools.partial` now return ``True`` if the
- wrapped function is a :term:`asynchronous generator` function.
+ wrapped function is an :term:`asynchronous generator` function.
.. versionchanged:: 3.13
Functions wrapped in :func:`functools.partialmethod` now return ``True``
@@ -520,7 +520,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes):
has a :meth:`~object.__get__` method, but not a :meth:`~object.__set__`
method or a :meth:`~object.__delete__` method. Beyond that, the set of
attributes varies. A :attr:`~definition.__name__` attribute is usually
- sensible, and :attr:`!__doc__` often is.
+ sensible, and :attr:`~definition.__doc__` often is.
Methods implemented via descriptors that also pass one of the other tests
return ``False`` from the :func:`ismethoddescriptor` test, simply because the
@@ -938,7 +938,7 @@ function.
.. attribute:: Parameter.kind.description
- Describes a enum value of :attr:`Parameter.kind`.
+ Describes an enum value of :attr:`Parameter.kind`.
.. versionadded:: 3.8
@@ -1018,7 +1018,8 @@ function.
.. attribute:: BoundArguments.kwargs
A dict of keyword arguments values. Dynamically computed from the
- :attr:`arguments` attribute.
+ :attr:`arguments` attribute. Arguments that can be passed positionally
+ are included in :attr:`args` instead.
.. attribute:: BoundArguments.signature
@@ -1236,7 +1237,7 @@ Classes and functions
This function handles several details for you:
* If ``eval_str`` is true, values of type ``str`` will
- be un-stringized using :func:`eval()`. This is intended
+ be un-stringized using :func:`eval`. This is intended
for use with stringized annotations
(``from __future__ import annotations``).
* If ``obj`` doesn't have an annotations dict, returns an
@@ -1250,16 +1251,16 @@ Classes and functions
* Always, always, always returns a freshly created dict.
``eval_str`` controls whether or not values of type ``str`` are replaced
- with the result of calling :func:`eval()` on those values:
+ with the result of calling :func:`eval` on those values:
- * If eval_str is true, :func:`eval()` is called on values of type ``str``.
- (Note that ``get_annotations`` doesn't catch exceptions; if :func:`eval()`
+ * If eval_str is true, :func:`eval` is called on values of type ``str``.
+ (Note that ``get_annotations`` doesn't catch exceptions; if :func:`eval`
raises an exception, it will unwind the stack past the ``get_annotations``
call.)
* If eval_str is false (the default), values of type ``str`` are unchanged.
- ``globals`` and ``locals`` are passed in to :func:`eval()`; see the documentation
- for :func:`eval()` for more information. If ``globals`` or ``locals``
+ ``globals`` and ``locals`` are passed in to :func:`eval`; see the documentation
+ for :func:`eval` for more information. If ``globals`` or ``locals``
is ``None``, this function may replace that value with a context-specific
default, contingent on ``type(obj)``:
diff --git a/Doc/library/intro.rst b/Doc/library/intro.rst
index ffc8939d211..8f76044be48 100644
--- a/Doc/library/intro.rst
+++ b/Doc/library/intro.rst
@@ -58,7 +58,7 @@ Notes on availability
operating system.
* If not separately noted, all functions that claim "Availability: Unix" are
- supported on macOS and iOS, both of which build on a Unix core.
+ supported on macOS, iOS and Android, all of which build on a Unix core.
* If an availability note contains both a minimum Kernel version and a minimum
libc version, then both conditions must hold. For example a feature with note
@@ -120,43 +120,57 @@ DOM APIs as well as limited networking capabilities with JavaScript's
.. _Pyodide: https://pyodide.org/
.. _PyScript: https://pyscript.net/
+.. _mobile-availability:
.. _iOS-availability:
-iOS
----
+Mobile platforms
+----------------
-iOS is, in most respects, a POSIX operating system. File I/O, socket handling,
+Android and iOS are, in most respects, POSIX operating systems. File I/O, socket handling,
and threading all behave as they would on any POSIX operating system. However,
-there are several major differences between iOS and other POSIX systems.
-
-* iOS can only use Python in "embedded" mode. There is no Python REPL, and no
- ability to execute binaries that are part of the normal Python developer
- experience, such as :program:`pip`. To add Python code to your iOS app, you must use
- the :ref:`Python embedding API ` to add a Python interpreter to an
- iOS app created with Xcode. See the :ref:`iOS usage guide ` for
- more details.
-
-* An iOS app cannot use any form of subprocessing, background processing, or
- inter-process communication. If an iOS app attempts to create a subprocess,
- the process creating the subprocess will either lock up, or crash. An iOS app
- has no visibility of other applications that are running, nor any ability to
- communicate with other running applications, outside of the iOS-specific APIs
- that exist for this purpose.
-
-* iOS apps have limited access to modify system resources (such as the system
+there are several major differences:
+
+* Mobile platforms can only use Python in "embedded" mode. There is no Python
+ REPL, and no ability to use separate executables such as :program:`python` or
+ :program:`pip`. To add Python code to your mobile app, you must use
+ the :ref:`Python embedding API `. For more details, see
+ :ref:`using-android` and :ref:`using-ios`.
+
+* Subprocesses:
+
+ * On Android, creating subprocesses is possible but `officially unsupported
+ `__.
+ In particular, Android does not support any part of the System V IPC API,
+ so :mod:`multiprocessing` is not available.
+
+ * An iOS app cannot use any form of subprocessing, multiprocessing, or
+ inter-process communication. If an iOS app attempts to create a subprocess,
+ the process creating the subprocess will either lock up, or crash. An iOS app
+ has no visibility of other applications that are running, nor any ability to
+ communicate with other running applications, outside of the iOS-specific APIs
+ that exist for this purpose.
+
+* Mobile apps have limited access to modify system resources (such as the system
clock). These resources will often be *readable*, but attempts to modify
those resources will usually fail.
-* iOS apps have a limited concept of console input and output. ``stdout`` and
- ``stderr`` *exist*, and content written to ``stdout`` and ``stderr`` will be
- visible in logs when running in Xcode, but this content *won't* be recorded
- in the system log. If a user who has installed your app provides their app
- logs as a diagnostic aid, they will not include any detail written to
- ``stdout`` or ``stderr``.
+* Console input and output:
+
+ * On Android, the native ``stdout`` and ``stderr`` are not connected to
+ anything, so Python installs its own streams which redirect messages to the
+ system log. These can be seen under the tags ``python.stdout`` and
+ ``python.stderr`` respectively.
+
+ * iOS apps have a limited concept of console output. ``stdout`` and
+ ``stderr`` *exist*, and content written to ``stdout`` and ``stderr`` will be
+ visible in logs when running in Xcode, but this content *won't* be recorded
+ in the system log. If a user who has installed your app provides their app
+ logs as a diagnostic aid, they will not include any detail written to
+ ``stdout`` or ``stderr``.
- iOS apps have no concept of ``stdin`` at all. While iOS apps can have a
- keyboard, this is a software feature, not something that is attached to
- ``stdin``.
+ * Mobile apps have no usable ``stdin`` at all. While apps can display an on-screen
+ keyboard, this is a software feature, not something that is attached to
+ ``stdin``.
- As a result, Python library that involve console manipulation (such as
- :mod:`curses` and :mod:`readline`) are not available on iOS.
+ As a result, Python modules that involve console manipulation (such as
+ :mod:`curses` and :mod:`readline`) are not available on mobile platforms.
diff --git a/Doc/library/io.rst b/Doc/library/io.rst
index 748c49968f5..f793d7a7ef9 100644
--- a/Doc/library/io.rst
+++ b/Doc/library/io.rst
@@ -55,7 +55,7 @@ the backing store is natively made of bytes (such as in the case of a file),
encoding and decoding of data is made transparently as well as optional
translation of platform-specific newline characters.
-The easiest way to create a text stream is with :meth:`open()`, optionally
+The easiest way to create a text stream is with :meth:`open`, optionally
specifying an encoding::
f = open("myfile.txt", "r", encoding="utf-8")
@@ -77,7 +77,7 @@ objects. No encoding, decoding, or newline translation is performed. This
category of streams can be used for all kinds of non-text data, and also when
manual control over the handling of text data is desired.
-The easiest way to create a binary stream is with :meth:`open()` with ``'b'`` in
+The easiest way to create a binary stream is with :meth:`open` with ``'b'`` in
the mode string::
f = open("myfile.jpg", "rb")
@@ -950,7 +950,7 @@ Text I/O
:class:`TextIOBase`.
*encoding* gives the name of the encoding that the stream will be decoded or
- encoded with. It defaults to :func:`locale.getencoding()`.
+ encoded with. It defaults to :func:`locale.getencoding`.
``encoding="locale"`` can be used to specify the current locale's encoding
explicitly. See :ref:`io-text-encoding` for more information.
@@ -1182,7 +1182,7 @@ re-enter a buffered object which it is already accessing, a :exc:`RuntimeError`
is raised. Note this doesn't prohibit a different thread from entering the
buffered object.
-The above implicitly extends to text files, since the :func:`open()` function
+The above implicitly extends to text files, since the :func:`open` function
will wrap a buffered object inside a :class:`TextIOWrapper`. This includes
-standard streams and therefore affects the built-in :func:`print()` function as
+standard streams and therefore affects the built-in :func:`print` function as
well.
diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst
index 0441a7d47b5..be5794588b1 100644
--- a/Doc/library/ipaddress.rst
+++ b/Doc/library/ipaddress.rst
@@ -1010,7 +1010,7 @@ The module also provides the following module level functions:
doesn't make sense. There are some times however, where you may wish to
have :mod:`ipaddress` sort these anyway. If you need to do this, you can use
- this function as the *key* argument to :func:`sorted()`.
+ this function as the *key* argument to :func:`sorted`.
*obj* is either a network or address object.
diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst
index 3dc3f60923a..43e665c3f0d 100644
--- a/Doc/library/itertools.rst
+++ b/Doc/library/itertools.rst
@@ -337,7 +337,7 @@ loops that truncate the stream.
yield n
n += step
- When counting with floating point numbers, better accuracy can sometimes be
+ When counting with floating-point numbers, better accuracy can sometimes be
achieved by substituting multiplicative code such as: ``(start + step * i
for i in count())``.
diff --git a/Doc/library/json.rst b/Doc/library/json.rst
index 42cb1f850fe..bb7b1852e80 100644
--- a/Doc/library/json.rst
+++ b/Doc/library/json.rst
@@ -13,7 +13,7 @@
`JSON (JavaScript Object Notation) `_, specified by
:rfc:`7159` (which obsoletes :rfc:`4627`) and by
-`ECMA-404 `_,
+`ECMA-404 `_,
is a lightweight data interchange format inspired by
`JavaScript `_ object literal syntax
(although it is not a strict subset of JavaScript [#rfc-errata]_ ).
@@ -241,28 +241,28 @@ Basic Usage
*object_hook* is an optional function that will be called with the result of
any object literal decoded (a :class:`dict`). The return value of
- *object_hook* will be used instead of the :class:`dict`. This feature can be used
- to implement custom decoders (e.g. `JSON-RPC `_
- class hinting).
+ *object_hook* will be used instead of the :class:`dict`. This feature can
+ be used to implement custom decoders (e.g. `JSON-RPC
+ `_ class hinting).
*object_pairs_hook* is an optional function that will be called with the
result of any object literal decoded with an ordered list of pairs. The
return value of *object_pairs_hook* will be used instead of the
- :class:`dict`. This feature can be used to implement custom decoders.
- If *object_hook* is also defined, the *object_pairs_hook* takes priority.
+ :class:`dict`. This feature can be used to implement custom decoders. If
+ *object_hook* is also defined, the *object_pairs_hook* takes priority.
.. versionchanged:: 3.1
Added support for *object_pairs_hook*.
- *parse_float*, if specified, will be called with the string of every JSON
- float to be decoded. By default, this is equivalent to ``float(num_str)``.
- This can be used to use another datatype or parser for JSON floats
- (e.g. :class:`decimal.Decimal`).
+ *parse_float* is an optional function that will be called with the string of
+ every JSON float to be decoded. By default, this is equivalent to
+ ``float(num_str)``. This can be used to use another datatype or parser for
+ JSON floats (e.g. :class:`decimal.Decimal`).
- *parse_int*, if specified, will be called with the string of every JSON int
- to be decoded. By default, this is equivalent to ``int(num_str)``. This can
- be used to use another datatype or parser for JSON integers
- (e.g. :class:`float`).
+ *parse_int* is an optional function that will be called with the string of
+ every JSON int to be decoded. By default, this is equivalent to
+ ``int(num_str)``. This can be used to use another datatype or parser for
+ JSON integers (e.g. :class:`float`).
.. versionchanged:: 3.11
The default *parse_int* of :func:`int` now limits the maximum length of
@@ -270,10 +270,9 @@ Basic Usage
conversion length limitation ` to help avoid denial
of service attacks.
- *parse_constant*, if specified, will be called with one of the following
- strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``.
- This can be used to raise an exception if invalid JSON numbers
- are encountered.
+ *parse_constant* is an optional function that will be called with one of the
+ following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This can be
+ used to raise an exception if invalid JSON numbers are encountered.
.. versionchanged:: 3.1
*parse_constant* doesn't get called on 'null', 'true', 'false' anymore.
@@ -345,34 +344,33 @@ Encoders and Decoders
It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as their
corresponding ``float`` values, which is outside the JSON spec.
- *object_hook*, if specified, will be called with the result of every JSON
- object decoded and its return value will be used in place of the given
- :class:`dict`. This can be used to provide custom deserializations (e.g. to
- support `JSON-RPC `_ class hinting).
+ *object_hook* is an optional function that will be called with the result of
+ every JSON object decoded and its return value will be used in place of the
+ given :class:`dict`. This can be used to provide custom deserializations
+ (e.g. to support `JSON-RPC `_ class hinting).
- *object_pairs_hook*, if specified will be called with the result of every
- JSON object decoded with an ordered list of pairs. The return value of
- *object_pairs_hook* will be used instead of the :class:`dict`. This
- feature can be used to implement custom decoders. If *object_hook* is also
- defined, the *object_pairs_hook* takes priority.
+ *object_pairs_hook* is an optional function that will be called with the
+ result of every JSON object decoded with an ordered list of pairs. The
+ return value of *object_pairs_hook* will be used instead of the
+ :class:`dict`. This feature can be used to implement custom decoders. If
+ *object_hook* is also defined, the *object_pairs_hook* takes priority.
.. versionchanged:: 3.1
Added support for *object_pairs_hook*.
- *parse_float*, if specified, will be called with the string of every JSON
- float to be decoded. By default, this is equivalent to ``float(num_str)``.
- This can be used to use another datatype or parser for JSON floats
- (e.g. :class:`decimal.Decimal`).
+ *parse_float* is an optional function that will be called with the string of
+ every JSON float to be decoded. By default, this is equivalent to
+ ``float(num_str)``. This can be used to use another datatype or parser for
+ JSON floats (e.g. :class:`decimal.Decimal`).
- *parse_int*, if specified, will be called with the string of every JSON int
- to be decoded. By default, this is equivalent to ``int(num_str)``. This can
- be used to use another datatype or parser for JSON integers
- (e.g. :class:`float`).
+ *parse_int* is an optional function that will be called with the string of
+ every JSON int to be decoded. By default, this is equivalent to
+ ``int(num_str)``. This can be used to use another datatype or parser for
+ JSON integers (e.g. :class:`float`).
- *parse_constant*, if specified, will be called with one of the following
- strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``.
- This can be used to raise an exception if invalid JSON numbers
- are encountered.
+ *parse_constant* is an optional function that will be called with one of the
+ following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This can be
+ used to raise an exception if invalid JSON numbers are encountered.
If *strict* is false (``True`` is the default), then control characters
will be allowed inside strings. Control characters in this context are
@@ -559,7 +557,7 @@ Standard Compliance and Interoperability
----------------------------------------
The JSON format is specified by :rfc:`7159` and by
-`ECMA-404 `_.
+`ECMA-404 `_.
This section details this module's level of compliance with the RFC.
For simplicity, :class:`JSONEncoder` and :class:`JSONDecoder` subclasses, and
parameters other than those explicitly mentioned, are not considered.
diff --git a/Doc/library/locale.rst b/Doc/library/locale.rst
index 0a8cbd4f95f..0246f991570 100644
--- a/Doc/library/locale.rst
+++ b/Doc/library/locale.rst
@@ -424,7 +424,7 @@ The :mod:`locale` module defines the following exception and functions:
.. function:: format_string(format, val, grouping=False, monetary=False)
Formats a number *val* according to the current :const:`LC_NUMERIC` setting.
- The format follows the conventions of the ``%`` operator. For floating point
+ The format follows the conventions of the ``%`` operator. For floating-point
values, the decimal point is modified if appropriate. If *grouping* is ``True``,
also takes the grouping into account.
@@ -455,7 +455,7 @@ The :mod:`locale` module defines the following exception and functions:
.. function:: str(float)
- Formats a floating point number using the same format as the built-in function
+ Formats a floating-point number using the same format as the built-in function
``str(float)``, but takes the decimal point into account.
diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst
index dfbf0b1cf2f..317ca872824 100644
--- a/Doc/library/logging.config.rst
+++ b/Doc/library/logging.config.rst
@@ -69,7 +69,7 @@ in :mod:`logging` itself) and defining handlers which are declared either in
dictConfigClass(config).configure()
For example, a subclass of :class:`DictConfigurator` could call
- ``DictConfigurator.__init__()`` in its own :meth:`__init__()`, then
+ ``DictConfigurator.__init__()`` in its own :meth:`__init__`, then
set up custom prefixes which would be usable in the subsequent
:meth:`configure` call. :attr:`dictConfigClass` would be bound to
this new subclass, and then :func:`dictConfig` could be called exactly as
@@ -753,9 +753,12 @@ The ``queue`` and ``listener`` keys are optional.
If the ``queue`` key is present, the corresponding value can be one of the following:
-* An actual instance of :class:`queue.Queue` or a subclass thereof. This is of course
- only possible if you are constructing or modifying the configuration dictionary in
- code.
+* An object implementing the :class:`queue.Queue` public API. For instance,
+ this may be an actual instance of :class:`queue.Queue` or a subclass thereof,
+ or a proxy obtained by :meth:`multiprocessing.managers.SyncManager.Queue`.
+
+ This is of course only possible if you are constructing or modifying
+ the configuration dictionary in code.
* A string that resolves to a callable which, when called with no arguments, returns
the :class:`queue.Queue` instance to use. That callable could be a
diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst
index 0624423c950..8ab107d2a33 100644
--- a/Doc/library/logging.rst
+++ b/Doc/library/logging.rst
@@ -304,7 +304,8 @@ in a module, ``__name__`` is the module's name in the Python package namespace.
parameter mirrors the equivalent one in the :mod:`warnings` module.
The fourth keyword argument is *extra* which can be used to pass a
- dictionary which is used to populate the __dict__ of the :class:`LogRecord`
+ dictionary which is used to populate the :attr:`~object.__dict__` of the
+ :class:`LogRecord`
created for the logging event with user-defined attributes. These custom
attributes can then be used as you like. For example, they could be
incorporated into logged messages. For example::
@@ -352,10 +353,6 @@ in a module, ``__name__`` is the module's name in the Python package namespace.
.. versionchanged:: 3.8
The *stacklevel* parameter was added.
- .. versionchanged:: 3.13
- Remove the undocumented ``warn()`` method which was an alias to the
- :meth:`warning` method.
-
.. method:: Logger.info(msg, *args, **kwargs)
@@ -368,6 +365,10 @@ in a module, ``__name__`` is the module's name in the Python package namespace.
Logs a message with level :const:`WARNING` on this logger. The arguments are
interpreted as for :meth:`debug`.
+ .. note:: There is an obsolete method ``warn`` which is functionally
+ identical to ``warning``. As ``warn`` is deprecated, please do not use
+ it - use ``warning`` instead.
+
.. method:: Logger.error(msg, *args, **kwargs)
Logs a message with level :const:`ERROR` on this logger. The arguments are
@@ -1098,11 +1099,11 @@ information into logging calls. For a usage example, see the section on
.. attribute:: manager
- Delegates to the underlying :attr:`!manager`` on *logger*.
+ Delegates to the underlying :attr:`!manager` on *logger*.
.. attribute:: _log
- Delegates to the underlying :meth:`!_log`` method on *logger*.
+ Delegates to the underlying :meth:`!_log` method on *logger*.
In addition to the above, :class:`LoggerAdapter` supports the following
methods of :class:`Logger`: :meth:`~Logger.debug`, :meth:`~Logger.info`,
@@ -1124,11 +1125,6 @@ information into logging calls. For a usage example, see the section on
Attribute :attr:`!manager` and method :meth:`!_log` were added, which
delegate to the underlying logger and allow adapters to be nested.
- .. versionchanged:: 3.13
-
- Remove the undocumented :meth:`!warn`` method which was an alias to the
- :meth:`!warning` method.
-
.. versionchanged:: 3.13
The *merge_extra* argument was added.
@@ -1224,10 +1220,6 @@ functions.
identical to ``warning``. As ``warn`` is deprecated, please do not use
it - use ``warning`` instead.
- .. versionchanged:: 3.13
- Remove the undocumented ``warn()`` function which was an alias to the
- :func:`warning` function.
-
.. function:: error(msg, *args, **kwargs)
diff --git a/Doc/library/mailbox.rst b/Doc/library/mailbox.rst
index 40ea71cd342..abb32f9bf34 100644
--- a/Doc/library/mailbox.rst
+++ b/Doc/library/mailbox.rst
@@ -1387,7 +1387,7 @@ When an :class:`!MHMessage` instance is created based upon a
.. method:: get_visible()
- Return an :class:`Message` instance whose headers are the message's
+ Return a :class:`Message` instance whose headers are the message's
visible headers and whose body is empty.
diff --git a/Doc/library/marshal.rst b/Doc/library/marshal.rst
index f9ba4d554b0..9e4606df0f7 100644
--- a/Doc/library/marshal.rst
+++ b/Doc/library/marshal.rst
@@ -42,8 +42,8 @@ supports a substantially wider range of objects than marshal.
Not all Python object types are supported; in general, only objects whose value
is independent from a particular invocation of Python can be written and read by
-this module. The following types are supported: booleans, integers, floating
-point numbers, complex numbers, strings, bytes, bytearrays, tuples, lists, sets,
+this module. The following types are supported: booleans, integers, floating-point
+numbers, complex numbers, strings, bytes, bytearrays, tuples, lists, sets,
frozensets, dictionaries, and code objects (if *allow_code* is true),
where it should be understood that
tuples, lists, sets, frozensets and dictionaries are only supported as long as
@@ -142,7 +142,7 @@ In addition, the following constants are defined:
Indicates the format that the module uses. Version 0 is the historical
format, version 1 shares interned strings and version 2 uses a binary format
- for floating point numbers.
+ for floating-point numbers.
Version 3 adds support for object instancing and recursion.
The current version is 4.
diff --git a/Doc/library/math.rst b/Doc/library/math.rst
index 316144992d6..dd2ba419b5b 100644
--- a/Doc/library/math.rst
+++ b/Doc/library/math.rst
@@ -123,7 +123,7 @@ Number-theoretic and representation functions
.. function:: fsum(iterable)
- Return an accurate floating point sum of values in the iterable. Avoids
+ Return an accurate floating-point sum of values in the iterable. Avoids
loss of precision by tracking multiple intermediate partial sums.
The algorithm's accuracy depends on IEEE-754 arithmetic guarantees and the
@@ -133,7 +133,7 @@ Number-theoretic and representation functions
least significant bit.
For further discussion and two alternative approaches, see the `ASPN cookbook
- recipes for accurate floating point summation
+ recipes for accurate floating-point summation
`_\.
@@ -304,7 +304,7 @@ Number-theoretic and representation functions
If the result of the remainder operation is zero, that zero will have
the same sign as *x*.
- On platforms using IEEE 754 binary floating-point, the result of this
+ On platforms using IEEE 754 binary floating point, the result of this
operation is always exactly representable: no rounding error is introduced.
.. versionadded:: 3.7
diff --git a/Doc/library/mimetypes.rst b/Doc/library/mimetypes.rst
index 91e8c30f860..8ad4850584a 100644
--- a/Doc/library/mimetypes.rst
+++ b/Doc/library/mimetypes.rst
@@ -295,3 +295,13 @@ than one MIME-type database; it provides an interface similar to the one of the
types, else to the list of non-standard types.
.. versionadded:: 3.2
+
+
+ .. method:: MimeTypes.add_type(type, ext, strict=True)
+
+ Add a mapping from the MIME type *type* to the extension *ext*. When the
+ extension is already known, the new type will replace the old one. When the type
+ is already known the extension will be added to the list of known extensions.
+
+ When *strict* is ``True`` (the default), the mapping will be added to the
+ official MIME types, otherwise to the non-standard ones.
diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst
index 49762491bae..80d6e4dae24 100644
--- a/Doc/library/multiprocessing.rst
+++ b/Doc/library/multiprocessing.rst
@@ -8,7 +8,7 @@
--------------
-.. include:: ../includes/wasm-ios-notavail.rst
+.. include:: ../includes/wasm-mobile-notavail.rst
Introduction
------------
@@ -254,6 +254,7 @@ processes:
p.join()
Queues are thread and process safe.
+ Any object put into a :mod:`~multiprocessing` queue will be serialized.
**Pipes**
@@ -281,6 +282,8 @@ processes:
of corruption from processes using different ends of the pipe at the same
time.
+ The :meth:`~Connection.send` method serializes the the object and
+ :meth:`~Connection.recv` re-creates the object.
Synchronization between processes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -502,7 +505,7 @@ The :mod:`multiprocessing` package mostly replicates the API of the
The constructor should always be called with keyword arguments. *group*
should always be ``None``; it exists solely for compatibility with
:class:`threading.Thread`. *target* is the callable object to be invoked by
- the :meth:`run()` method. It defaults to ``None``, meaning nothing is
+ the :meth:`run` method. It defaults to ``None``, meaning nothing is
called. *name* is the process name (see :attr:`name` for more details).
*args* is the argument tuple for the target invocation. *kwargs* is a
dictionary of keyword arguments for the target invocation. If provided,
@@ -639,7 +642,7 @@ The :mod:`multiprocessing` package mostly replicates the API of the
You can use this value if you want to wait on several events at
once using :func:`multiprocessing.connection.wait`. Otherwise
- calling :meth:`join()` is simpler.
+ calling :meth:`join` is simpler.
On Windows, this is an OS handle usable with the ``WaitForSingleObject``
and ``WaitForMultipleObjects`` family of API calls. On POSIX, this is
@@ -666,7 +669,7 @@ The :mod:`multiprocessing` package mostly replicates the API of the
.. method:: kill()
- Same as :meth:`terminate()` but using the ``SIGKILL`` signal on POSIX.
+ Same as :meth:`terminate` but using the ``SIGKILL`` signal on POSIX.
.. versionadded:: 3.7
@@ -709,7 +712,7 @@ The :mod:`multiprocessing` package mostly replicates the API of the
.. exception:: BufferTooShort
- Exception raised by :meth:`Connection.recv_bytes_into()` when the supplied
+ Exception raised by :meth:`Connection.recv_bytes_into` when the supplied
buffer object is too small for the message read.
If ``e`` is an instance of :exc:`BufferTooShort` then ``e.args[0]`` will give
@@ -745,6 +748,11 @@ If you use :class:`JoinableQueue` then you **must** call
semaphore used to count the number of unfinished tasks may eventually overflow,
raising an exception.
+One difference from other Python queue implementations, is that :mod:`multiprocessing`
+queues serializes all objects that are put into them using :mod:`pickle`.
+The object return by the get method is a re-created object that does not share memory
+with the original object.
+
Note that one can also create a shared queue by using a manager object -- see
:ref:`multiprocessing-managers`.
@@ -811,6 +819,8 @@ For an example of the usage of queues for interprocess communication see
used for receiving messages and ``conn2`` can only be used for sending
messages.
+ The :meth:`~multiprocessing.Connection.send` method serializes the the object using
+ :mod:`pickle` and the :meth:`~multiprocessing.Connection.recv` re-creates the object.
.. class:: Queue([maxsize])
@@ -837,6 +847,8 @@ For an example of the usage of queues for interprocess communication see
Return ``True`` if the queue is empty, ``False`` otherwise. Because of
multithreading/multiprocessing semantics, this is not reliable.
+ May raise an :exc:`OSError` on closed queues. (not guaranteed)
+
.. method:: full()
Return ``True`` if the queue is full, ``False`` otherwise. Because of
@@ -940,6 +952,8 @@ For an example of the usage of queues for interprocess communication see
Return ``True`` if the queue is empty, ``False`` otherwise.
+ Always raises an :exc:`OSError` if the SimpleQueue is closed.
+
.. method:: get()
Remove and return an item from the queue.
@@ -1459,17 +1473,6 @@ object -- see :ref:`multiprocessing-managers`.
On macOS, ``sem_timedwait`` is unsupported, so calling ``acquire()`` with
a timeout will emulate that function's behavior using a sleeping loop.
-.. note::
-
- If the SIGINT signal generated by :kbd:`Ctrl-C` arrives while the main thread is
- blocked by a call to :meth:`BoundedSemaphore.acquire`, :meth:`Lock.acquire`,
- :meth:`RLock.acquire`, :meth:`Semaphore.acquire`, :meth:`Condition.acquire`
- or :meth:`Condition.wait` then the call will be immediately interrupted and
- :exc:`KeyboardInterrupt` will be raised.
-
- This differs from the behaviour of :mod:`threading` where SIGINT will be
- ignored while the equivalent blocking calls are in progress.
-
.. note::
Some of this package's functionality requires a functioning shared semaphore
@@ -2958,7 +2961,7 @@ Beware of replacing :data:`sys.stdin` with a "file like object"
resulting in a bad file descriptor error, but introduces a potential danger
to applications which replace :func:`sys.stdin` with a "file-like object"
with output buffering. This danger is that if multiple processes call
- :meth:`~io.IOBase.close()` on this file-like object, it could result in the same
+ :meth:`~io.IOBase.close` on this file-like object, it could result in the same
data being flushed to the object multiple times, resulting in corruption.
If you write a file-like object and implement your own caching, you can
diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst
index 3e96259f94d..74a49a8fb33 100644
--- a/Doc/library/optparse.rst
+++ b/Doc/library/optparse.rst
@@ -1352,7 +1352,7 @@ The whole point of creating and populating an OptionParser is to call its
the list of arguments to process (default: ``sys.argv[1:]``)
``values``
- an :class:`Values` object to store option arguments in (default: a
+ a :class:`Values` object to store option arguments in (default: a
new instance of :class:`Values`) -- if you give an existing object, the
option defaults will not be initialized on it
diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst
index b582321515d..ecbbc1d7605 100644
--- a/Doc/library/os.path.rst
+++ b/Doc/library/os.path.rst
@@ -81,7 +81,7 @@ the :mod:`glob` module.)
Return the longest common sub-path of each pathname in the iterable
*paths*. Raise :exc:`ValueError` if *paths* contain both absolute
- and relative pathnames, the *paths* are on the different drives or
+ and relative pathnames, if *paths* are on different drives, or
if *paths* is empty. Unlike :func:`commonprefix`, this returns a
valid path.
@@ -201,14 +201,14 @@ the :mod:`glob` module.)
.. function:: getatime(path)
- Return the time of last access of *path*. The return value is a floating point number giving
+ Return the time of last access of *path*. The return value is a floating-point number giving
the number of seconds since the epoch (see the :mod:`time` module). Raise
:exc:`OSError` if the file does not exist or is inaccessible.
.. function:: getmtime(path)
- Return the time of last modification of *path*. The return value is a floating point number
+ Return the time of last modification of *path*. The return value is a floating-point number
giving the number of seconds since the epoch (see the :mod:`time` module).
Raise :exc:`OSError` if the file does not exist or is inaccessible.
@@ -389,7 +389,7 @@ the :mod:`glob` module.)
that contains symbolic links. On Windows, it converts forward slashes to
backward slashes. To normalize case, use :func:`normcase`.
- .. note::
+ .. note::
On POSIX systems, in accordance with `IEEE Std 1003.1 2013 Edition; 4.13
Pathname Resolution `_,
if a pathname begins with exactly two slashes, the first component
diff --git a/Doc/library/os.rst b/Doc/library/os.rst
index b93b06d4e72..b93e01e9986 100644
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -34,8 +34,8 @@ Notes on the availability of these functions:
* On VxWorks, os.popen, os.fork, os.execv and os.spawn*p* are not supported.
-* On WebAssembly platforms, and on iOS, large parts of the :mod:`os` module are
- not available or behave differently. API related to processes (e.g.
+* On WebAssembly platforms, Android and iOS, large parts of the :mod:`os` module are
+ not available or behave differently. APIs related to processes (e.g.
:func:`~os.fork`, :func:`~os.execve`) and resources (e.g. :func:`~os.nice`)
are not available. Others like :func:`~os.getuid` and :func:`~os.getpid` are
emulated or stubs. WebAssembly platforms also lack support for signals (e.g.
@@ -113,8 +113,8 @@ of the UTF-8 encoding:
* Use UTF-8 as the :term:`filesystem encoding `.
-* :func:`sys.getfilesystemencoding()` returns ``'utf-8'``.
-* :func:`locale.getpreferredencoding()` returns ``'utf-8'`` (the *do_setlocale*
+* :func:`sys.getfilesystemencoding` returns ``'utf-8'``.
+* :func:`locale.getpreferredencoding` returns ``'utf-8'`` (the *do_setlocale*
argument has no effect).
* :data:`sys.stdin`, :data:`sys.stdout`, and :data:`sys.stderr` all use
UTF-8 as their text encoding, with the ``surrogateescape``
@@ -133,8 +133,8 @@ level APIs also exhibit different default behaviours:
* Command line arguments, environment variables and filenames are decoded
to text using the UTF-8 encoding.
-* :func:`os.fsdecode()` and :func:`os.fsencode()` use the UTF-8 encoding.
-* :func:`open()`, :func:`io.open()`, and :func:`codecs.open()` use the UTF-8
+* :func:`os.fsdecode` and :func:`os.fsencode` use the UTF-8 encoding.
+* :func:`open`, :func:`io.open`, and :func:`codecs.open` use the UTF-8
encoding by default. However, they still use the strict error handler by
default so that attempting to open a binary file in text mode is likely
to raise an exception rather than producing nonsense data.
@@ -542,7 +542,7 @@ process and user.
the groups of which the specified username is a member, plus the specified
group id.
- .. availability:: Unix, not WASI.
+ .. availability:: Unix, not WASI, not Android.
.. versionadded:: 3.2
@@ -576,21 +576,21 @@ process and user.
Set the current process's effective group id.
- .. availability:: Unix, not WASI.
+ .. availability:: Unix, not WASI, not Android.
.. function:: seteuid(euid, /)
Set the current process's effective user id.
- .. availability:: Unix, not WASI.
+ .. availability:: Unix, not WASI, not Android.
.. function:: setgid(gid, /)
Set the current process' group id.
- .. availability:: Unix, not WASI.
+ .. availability:: Unix, not WASI, not Android.
.. function:: setgroups(groups, /)
@@ -684,14 +684,14 @@ process and user.
Set the current process's real and effective group ids.
- .. availability:: Unix, not WASI.
+ .. availability:: Unix, not WASI, not Android.
.. function:: setresgid(rgid, egid, sgid, /)
Set the current process's real, effective, and saved group ids.
- .. availability:: Unix, not WASI.
+ .. availability:: Unix, not WASI, not Android.
.. versionadded:: 3.2
@@ -700,7 +700,7 @@ process and user.
Set the current process's real, effective, and saved user ids.
- .. availability:: Unix, not WASI.
+ .. availability:: Unix, not WASI, not Android.
.. versionadded:: 3.2
@@ -709,7 +709,7 @@ process and user.
Set the current process's real and effective user ids.
- .. availability:: Unix, not WASI.
+ .. availability:: Unix, not WASI, not Android.
.. function:: getsid(pid, /)
@@ -732,7 +732,7 @@ process and user.
Set the current process's user id.
- .. availability:: Unix, not WASI.
+ .. availability:: Unix, not WASI, not Android.
.. placed in this section since it relates to errno.... a little weak
@@ -785,7 +785,7 @@ process and user.
``socket.gethostbyaddr(socket.gethostname())``.
On macOS, iOS and Android, this returns the *kernel* name and version (i.e.,
- ``'Darwin'`` on macOS and iOS; ``'Linux'`` on Android). :func:`platform.uname()`
+ ``'Darwin'`` on macOS and iOS; ``'Linux'`` on Android). :func:`platform.uname`
can be used to get the user-facing operating system name and version on iOS and
Android.
@@ -1551,7 +1551,7 @@ or `the MSDN `_ on Windo
.. function:: pwritev(fd, buffers, offset, flags=0, /)
- Write the *buffers* contents to file descriptor *fd* at a offset *offset*,
+ Write the *buffers* contents to file descriptor *fd* at an offset *offset*,
leaving the file offset unchanged. *buffers* must be a sequence of
:term:`bytes-like objects `. Buffers are processed in
array order. Entire contents of the first buffer is written before
@@ -2178,7 +2178,7 @@ features:
Change the root directory of the current process to *path*.
- .. availability:: Unix, not WASI.
+ .. availability:: Unix, not WASI, not Android.
.. versionchanged:: 3.6
Accepts a :term:`path-like object`.
@@ -2830,7 +2830,7 @@ features:
.. versionchanged:: 3.6
Added support for the :term:`context manager` protocol and the
- :func:`~scandir.close()` method. If a :func:`scandir` iterator is neither
+ :func:`~scandir.close` method. If a :func:`scandir` iterator is neither
exhausted nor explicitly closed a :exc:`ResourceWarning` will be emitted
in its destructor.
@@ -3775,7 +3775,7 @@ features:
new file descriptor is :ref:`non-inheritable `.
*initval* is the initial value of the event counter. The initial value
- must be an 32 bit unsigned integer. Please note that the initial value is
+ must be a 32 bit unsigned integer. Please note that the initial value is
limited to a 32 bit unsigned int although the event counter is an unsigned
64 bit integer with a maximum value of 2\ :sup:`64`\ -\ 2.
@@ -3854,7 +3854,7 @@ features:
.. data:: EFD_SEMAPHORE
- Provide semaphore-like semantics for reads from a :func:`eventfd` file
+ Provide semaphore-like semantics for reads from an :func:`eventfd` file
descriptor. On read the internal counter is decremented by one.
.. availability:: Linux >= 2.6.30
@@ -3862,6 +3862,8 @@ features:
.. versionadded:: 3.10
+.. _os-timerfd:
+
Timer File Descriptors
~~~~~~~~~~~~~~~~~~~~~~
@@ -4282,7 +4284,7 @@ to be ignored.
.. audit-event:: os.exec path,args,env os.execl
- .. availability:: Unix, Windows, not WASI, not iOS.
+ .. availability:: Unix, Windows, not WASI, not Android, not iOS.
.. versionchanged:: 3.3
Added support for specifying *path* as an open file descriptor
@@ -4485,7 +4487,7 @@ written in Python, such as a mail server's external command delivery program.
for technical details of why we're surfacing this longstanding
platform compatibility problem to developers.
- .. availability:: POSIX, not WASI, not iOS.
+ .. availability:: POSIX, not WASI, not Android, not iOS.
.. function:: forkpty()
@@ -4512,7 +4514,7 @@ written in Python, such as a mail server's external command delivery program.
threads, this now raises a :exc:`DeprecationWarning`. See the
longer explanation on :func:`os.fork`.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. function:: kill(pid, sig, /)
@@ -4570,7 +4572,7 @@ written in Python, such as a mail server's external command delivery program.
See the :manpage:`pidfd_open(2)` man page for more details.
- .. availability:: Linux >= 5.3
+ .. availability:: Linux >= 5.3, Android >= :func:`build-time ` API level 31
.. versionadded:: 3.9
.. data:: PIDFD_NONBLOCK
@@ -4621,7 +4623,7 @@ written in Python, such as a mail server's external command delivery program.
documentation for more powerful ways to manage and communicate with
subprocesses.
- .. availability:: not WASI, not iOS.
+ .. availability:: not WASI, not Android, not iOS.
.. note::
The :ref:`Python UTF-8 Mode ` affects encodings used
@@ -4729,7 +4731,7 @@ written in Python, such as a mail server's external command delivery program.
``os.POSIX_SPAWN_CLOSEFROM`` is available on platforms where
:c:func:`!posix_spawn_file_actions_addclosefrom_np` exists.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. function:: posix_spawnp(path, argv, env, *, file_actions=None, \
setpgroup=None, resetids=False, setsid=False, setsigmask=(), \
@@ -4745,7 +4747,7 @@ written in Python, such as a mail server's external command delivery program.
.. versionadded:: 3.8
- .. availability:: POSIX, not WASI, not iOS.
+ .. availability:: POSIX, not WASI, not Android, not iOS.
See :func:`posix_spawn` documentation.
@@ -4778,7 +4780,7 @@ written in Python, such as a mail server's external command delivery program.
There is no way to unregister a function.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. versionadded:: 3.7
@@ -4847,7 +4849,7 @@ written in Python, such as a mail server's external command delivery program.
.. audit-event:: os.spawn mode,path,args,env os.spawnl
- .. availability:: Unix, Windows, not WASI, not iOS.
+ .. availability:: Unix, Windows, not WASI, not Android, not iOS.
:func:`spawnlp`, :func:`spawnlpe`, :func:`spawnvp`
and :func:`spawnvpe` are not available on Windows. :func:`spawnle` and
@@ -4971,7 +4973,7 @@ written in Python, such as a mail server's external command delivery program.
.. audit-event:: os.system command os.system
- .. availability:: Unix, Windows, not WASI, not iOS.
+ .. availability:: Unix, Windows, not WASI, not Android, not iOS.
.. function:: times()
@@ -5015,7 +5017,7 @@ written in Python, such as a mail server's external command delivery program.
:func:`waitstatus_to_exitcode` can be used to convert the exit status into an
exit code.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. seealso::
@@ -5049,7 +5051,7 @@ written in Python, such as a mail server's external command delivery program.
Otherwise, if there are no matching children
that could be waited for, :exc:`ChildProcessError` is raised.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. versionadded:: 3.3
@@ -5090,7 +5092,7 @@ written in Python, such as a mail server's external command delivery program.
:func:`waitstatus_to_exitcode` can be used to convert the exit status into an
exit code.
- .. availability:: Unix, Windows, not WASI, not iOS.
+ .. availability:: Unix, Windows, not WASI, not Android, not iOS.
.. versionchanged:: 3.5
If the system call is interrupted and the signal handler does not raise an
@@ -5110,7 +5112,7 @@ written in Python, such as a mail server's external command delivery program.
:func:`waitstatus_to_exitcode` can be used to convert the exit status into an
exitcode.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. function:: wait4(pid, options)
@@ -5124,7 +5126,7 @@ written in Python, such as a mail server's external command delivery program.
:func:`waitstatus_to_exitcode` can be used to convert the exit status into an
exitcode.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. data:: P_PID
@@ -5141,7 +5143,7 @@ written in Python, such as a mail server's external command delivery program.
* :data:`!P_PIDFD` - wait for the child identified by the file descriptor
*id* (a process file descriptor created with :func:`pidfd_open`).
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. note:: :data:`!P_PIDFD` is only available on Linux >= 5.4.
@@ -5156,7 +5158,7 @@ written in Python, such as a mail server's external command delivery program.
:func:`waitid` causes child processes to be reported if they have been
continued from a job control stop since they were last reported.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. data:: WEXITED
@@ -5167,7 +5169,7 @@ written in Python, such as a mail server's external command delivery program.
The other ``wait*`` functions always report children that have terminated,
so this option is not available for them.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. versionadded:: 3.3
@@ -5179,7 +5181,7 @@ written in Python, such as a mail server's external command delivery program.
This option is not available for the other ``wait*`` functions.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. versionadded:: 3.3
@@ -5192,7 +5194,7 @@ written in Python, such as a mail server's external command delivery program.
This option is not available for :func:`waitid`.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. data:: WNOHANG
@@ -5201,7 +5203,7 @@ written in Python, such as a mail server's external command delivery program.
:func:`waitid` to return right away if no child process status is available
immediately.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. data:: WNOWAIT
@@ -5211,7 +5213,7 @@ written in Python, such as a mail server's external command delivery program.
This option is not available for the other ``wait*`` functions.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. data:: CLD_EXITED
@@ -5224,7 +5226,7 @@ written in Python, such as a mail server's external command delivery program.
These are the possible values for :attr:`!si_code` in the result returned by
:func:`waitid`.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. versionadded:: 3.3
@@ -5259,7 +5261,7 @@ written in Python, such as a mail server's external command delivery program.
:func:`WIFEXITED`, :func:`WEXITSTATUS`, :func:`WIFSIGNALED`,
:func:`WTERMSIG`, :func:`WIFSTOPPED`, :func:`WSTOPSIG` functions.
- .. availability:: Unix, Windows, not WASI, not iOS.
+ .. availability:: Unix, Windows, not WASI, not Android, not iOS.
.. versionadded:: 3.9
@@ -5275,7 +5277,7 @@ used to determine the disposition of a process.
This function should be employed only if :func:`WIFSIGNALED` is true.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. function:: WIFCONTINUED(status)
@@ -5286,7 +5288,7 @@ used to determine the disposition of a process.
See :data:`WCONTINUED` option.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. function:: WIFSTOPPED(status)
@@ -5298,14 +5300,14 @@ used to determine the disposition of a process.
done using :data:`WUNTRACED` option or when the process is being traced (see
:manpage:`ptrace(2)`).
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. function:: WIFSIGNALED(status)
Return ``True`` if the process was terminated by a signal, otherwise return
``False``.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. function:: WIFEXITED(status)
@@ -5314,7 +5316,7 @@ used to determine the disposition of a process.
by calling ``exit()`` or ``_exit()``, or by returning from ``main()``;
otherwise return ``False``.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. function:: WEXITSTATUS(status)
@@ -5323,7 +5325,7 @@ used to determine the disposition of a process.
This function should be employed only if :func:`WIFEXITED` is true.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. function:: WSTOPSIG(status)
@@ -5332,7 +5334,7 @@ used to determine the disposition of a process.
This function should be employed only if :func:`WIFSTOPPED` is true.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
.. function:: WTERMSIG(status)
@@ -5341,7 +5343,7 @@ used to determine the disposition of a process.
This function should be employed only if :func:`WIFSIGNALED` is true.
- .. availability:: Unix, not WASI, not iOS.
+ .. availability:: Unix, not WASI, not Android, not iOS.
Interface to the scheduler
diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst
index 3b48d25f96d..ee8a9086d5e 100644
--- a/Doc/library/pathlib.rst
+++ b/Doc/library/pathlib.rst
@@ -21,6 +21,12 @@ inherit from pure paths but also provide I/O operations.
.. image:: pathlib-inheritance.png
:align: center
:class: invert-in-dark-mode
+ :alt: Inheritance diagram showing the classes available in pathlib. The
+ most basic class is PurePath, which has three direct subclasses:
+ PurePosixPath, PureWindowsPath, and Path. Further to these four
+ classes, there are two classes that use multiple inheritance:
+ PosixPath subclasses PurePosixPath and Path, and WindowsPath
+ subclasses PureWindowsPath and Path.
If you've never used this module before or just aren't sure which class is
right for your task, :class:`Path` is most likely what you need. It instantiates
@@ -172,8 +178,8 @@ we also call *flavours*:
A subclass of :class:`PurePath`, this path flavour represents non-Windows
filesystem paths::
- >>> PurePosixPath('/etc')
- PurePosixPath('/etc')
+ >>> PurePosixPath('/etc/hosts')
+ PurePosixPath('/etc/hosts')
*pathsegments* is specified similarly to :class:`PurePath`.
@@ -182,8 +188,8 @@ we also call *flavours*:
A subclass of :class:`PurePath`, this path flavour represents Windows
filesystem paths, including `UNC paths`_::
- >>> PureWindowsPath('c:/Program Files/')
- PureWindowsPath('c:/Program Files')
+ >>> PureWindowsPath('c:/', 'Users', 'Ximénez')
+ PureWindowsPath('c:/Users/Ximénez')
>>> PureWindowsPath('//server/share/file')
PureWindowsPath('//server/share/file')
@@ -764,8 +770,8 @@ calls on path objects. There are three ways to instantiate concrete paths:
A subclass of :class:`Path` and :class:`PurePosixPath`, this class
represents concrete non-Windows filesystem paths::
- >>> PosixPath('/etc')
- PosixPath('/etc')
+ >>> PosixPath('/etc/hosts')
+ PosixPath('/etc/hosts')
*pathsegments* is specified similarly to :class:`PurePath`.
@@ -779,8 +785,8 @@ calls on path objects. There are three ways to instantiate concrete paths:
A subclass of :class:`Path` and :class:`PureWindowsPath`, this class
represents concrete Windows filesystem paths::
- >>> WindowsPath('c:/Program Files/')
- WindowsPath('c:/Program Files')
+ >>> WindowsPath('c:/', 'Users', 'Ximénez')
+ WindowsPath('c:/Users/Ximénez')
*pathsegments* is specified similarly to :class:`PurePath`.
@@ -872,22 +878,123 @@ conforming to :rfc:`8089`.
it strictly impure.
+Expanding and resolving paths
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. classmethod:: Path.home()
+
+ Return a new path object representing the user's home directory (as
+ returned by :func:`os.path.expanduser` with ``~`` construct). If the home
+ directory can't be resolved, :exc:`RuntimeError` is raised.
+
+ ::
+
+ >>> Path.home()
+ PosixPath('/home/antoine')
+
+ .. versionadded:: 3.5
+
+
+.. method:: Path.expanduser()
+
+ Return a new path with expanded ``~`` and ``~user`` constructs,
+ as returned by :meth:`os.path.expanduser`. If a home directory can't be
+ resolved, :exc:`RuntimeError` is raised.
+
+ ::
+
+ >>> p = PosixPath('~/films/Monty Python')
+ >>> p.expanduser()
+ PosixPath('/home/eric/films/Monty Python')
+
+ .. versionadded:: 3.5
+
+
+.. classmethod:: Path.cwd()
+
+ Return a new path object representing the current directory (as returned
+ by :func:`os.getcwd`)::
+
+ >>> Path.cwd()
+ PosixPath('/home/antoine/pathlib')
+
+
+.. method:: Path.absolute()
+
+ Make the path absolute, without normalization or resolving symlinks.
+ Returns a new path object::
+
+ >>> p = Path('tests')
+ >>> p
+ PosixPath('tests')
+ >>> p.absolute()
+ PosixPath('/home/antoine/pathlib/tests')
+
+
+.. method:: Path.resolve(strict=False)
+
+ Make the path absolute, resolving any symlinks. A new path object is
+ returned::
+
+ >>> p = Path()
+ >>> p
+ PosixPath('.')
+ >>> p.resolve()
+ PosixPath('/home/antoine/pathlib')
+
+ "``..``" components are also eliminated (this is the only method to do so)::
+
+ >>> p = Path('docs/../setup.py')
+ >>> p.resolve()
+ PosixPath('/home/antoine/pathlib/setup.py')
+
+ If a path doesn't exist or a symlink loop is encountered, and *strict* is
+ ``True``, :exc:`OSError` is raised. If *strict* is ``False``, the path is
+ resolved as far as possible and any remainder is appended without checking
+ whether it exists.
+
+ .. versionchanged:: 3.6
+ The *strict* parameter was added (pre-3.6 behavior is strict).
+
+ .. versionchanged:: 3.13
+ Symlink loops are treated like other errors: :exc:`OSError` is raised in
+ strict mode, and no exception is raised in non-strict mode. In previous
+ versions, :exc:`RuntimeError` is raised no matter the value of *strict*.
+
+
+.. method:: Path.readlink()
+
+ Return the path to which the symbolic link points (as returned by
+ :func:`os.readlink`)::
+
+ >>> p = Path('mylink')
+ >>> p.symlink_to('setup.py')
+ >>> p.readlink()
+ PosixPath('setup.py')
+
+ .. versionadded:: 3.9
+
+ .. versionchanged:: 3.13
+ Raises :exc:`UnsupportedOperation` if :func:`os.readlink` is not
+ available. In previous versions, :exc:`NotImplementedError` was raised.
+
+
Querying file type and status
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. versionchanged:: 3.8
- :meth:`~Path.exists()`, :meth:`~Path.is_dir()`, :meth:`~Path.is_file()`,
- :meth:`~Path.is_mount()`, :meth:`~Path.is_symlink()`,
- :meth:`~Path.is_block_device()`, :meth:`~Path.is_char_device()`,
- :meth:`~Path.is_fifo()`, :meth:`~Path.is_socket()` now return ``False``
+ :meth:`~Path.exists`, :meth:`~Path.is_dir`, :meth:`~Path.is_file`,
+ :meth:`~Path.is_mount`, :meth:`~Path.is_symlink`,
+ :meth:`~Path.is_block_device`, :meth:`~Path.is_char_device`,
+ :meth:`~Path.is_fifo`, :meth:`~Path.is_socket` now return ``False``
instead of raising an exception for paths that contain characters
unrepresentable at the OS level.
.. method:: Path.stat(*, follow_symlinks=True)
- Return a :class:`os.stat_result` object containing information about this path, like :func:`os.stat`.
+ Return an :class:`os.stat_result` object containing information about this path, like :func:`os.stat`.
The result is looked up at each call to this method.
This method normally follows symlinks; to stat a symlink add the argument
@@ -1260,7 +1367,7 @@ Reading directories
This can be used to prune the search, or to impose a specific order of visiting,
or even to inform :meth:`Path.walk` about directories the caller creates or
renames before it resumes :meth:`Path.walk` again. Modifying *dirnames* when
- *top_down* is false has no effect on the behavior of :meth:`Path.walk()` since the
+ *top_down* is false has no effect on the behavior of :meth:`Path.walk` since the
directories in *dirnames* have already been generated by the time *dirnames*
is yielded to the caller.
@@ -1537,107 +1644,6 @@ Permissions and ownership
symbolic link's mode is changed rather than its target's.
-Other methods
-^^^^^^^^^^^^^
-
-.. classmethod:: Path.cwd()
-
- Return a new path object representing the current directory (as returned
- by :func:`os.getcwd`)::
-
- >>> Path.cwd()
- PosixPath('/home/antoine/pathlib')
-
-
-.. classmethod:: Path.home()
-
- Return a new path object representing the user's home directory (as
- returned by :func:`os.path.expanduser` with ``~`` construct). If the home
- directory can't be resolved, :exc:`RuntimeError` is raised.
-
- ::
-
- >>> Path.home()
- PosixPath('/home/antoine')
-
- .. versionadded:: 3.5
-
-
-.. method:: Path.expanduser()
-
- Return a new path with expanded ``~`` and ``~user`` constructs,
- as returned by :meth:`os.path.expanduser`. If a home directory can't be
- resolved, :exc:`RuntimeError` is raised.
-
- ::
-
- >>> p = PosixPath('~/films/Monty Python')
- >>> p.expanduser()
- PosixPath('/home/eric/films/Monty Python')
-
- .. versionadded:: 3.5
-
-
-.. method:: Path.readlink()
-
- Return the path to which the symbolic link points (as returned by
- :func:`os.readlink`)::
-
- >>> p = Path('mylink')
- >>> p.symlink_to('setup.py')
- >>> p.readlink()
- PosixPath('setup.py')
-
- .. versionadded:: 3.9
-
- .. versionchanged:: 3.13
- Raises :exc:`UnsupportedOperation` if :func:`os.readlink` is not
- available. In previous versions, :exc:`NotImplementedError` was raised.
-
-
-.. method:: Path.absolute()
-
- Make the path absolute, without normalization or resolving symlinks.
- Returns a new path object::
-
- >>> p = Path('tests')
- >>> p
- PosixPath('tests')
- >>> p.absolute()
- PosixPath('/home/antoine/pathlib/tests')
-
-
-.. method:: Path.resolve(strict=False)
-
- Make the path absolute, resolving any symlinks. A new path object is
- returned::
-
- >>> p = Path()
- >>> p
- PosixPath('.')
- >>> p.resolve()
- PosixPath('/home/antoine/pathlib')
-
- "``..``" components are also eliminated (this is the only method to do so)::
-
- >>> p = Path('docs/../setup.py')
- >>> p.resolve()
- PosixPath('/home/antoine/pathlib/setup.py')
-
- If a path doesn't exist or a symlink loop is encountered, and *strict* is
- ``True``, :exc:`OSError` is raised. If *strict* is ``False``, the path is
- resolved as far as possible and any remainder is appended without checking
- whether it exists.
-
- .. versionchanged:: 3.6
- The *strict* parameter was added (pre-3.6 behavior is strict).
-
- .. versionchanged:: 3.13
- Symlink loops are treated like other errors: :exc:`OSError` is raised in
- strict mode, and no exception is raised in non-strict mode. In previous
- versions, :exc:`RuntimeError` is raised no matter the value of *strict*.
-
-
.. _pathlib-pattern-language:
Pattern language
@@ -1759,39 +1765,54 @@ Corresponding tools
Below is a table mapping various :mod:`os` functions to their corresponding
:class:`PurePath`/:class:`Path` equivalent.
-==================================== ==============================
-:mod:`os` and :mod:`os.path` :mod:`pathlib`
-==================================== ==============================
-:func:`os.path.abspath` :meth:`Path.absolute`
-:func:`os.path.realpath` :meth:`Path.resolve`
-:func:`os.chmod` :meth:`Path.chmod`
-:func:`os.mkdir` :meth:`Path.mkdir`
-:func:`os.makedirs` :meth:`Path.mkdir`
-:func:`os.rename` :meth:`Path.rename`
-:func:`os.replace` :meth:`Path.replace`
-:func:`os.rmdir` :meth:`Path.rmdir`
-:func:`os.remove`, :func:`os.unlink` :meth:`Path.unlink`
-:func:`os.getcwd` :func:`Path.cwd`
-:func:`os.path.exists` :meth:`Path.exists`
-:func:`os.path.expanduser` :meth:`Path.expanduser` and
- :meth:`Path.home`
-:func:`os.listdir` :meth:`Path.iterdir`
-:func:`os.walk` :meth:`Path.walk`
-:func:`os.path.isdir` :meth:`Path.is_dir`
-:func:`os.path.isfile` :meth:`Path.is_file`
-:func:`os.path.islink` :meth:`Path.is_symlink`
-:func:`os.link` :meth:`Path.hardlink_to`
-:func:`os.symlink` :meth:`Path.symlink_to`
-:func:`os.readlink` :meth:`Path.readlink`
-:func:`os.path.relpath` :meth:`PurePath.relative_to`
-:func:`os.stat` :meth:`Path.stat`,
- :meth:`Path.owner`,
- :meth:`Path.group`
-:func:`os.path.isabs` :meth:`PurePath.is_absolute`
-:func:`os.path.join` :func:`PurePath.joinpath`
-:func:`os.path.basename` :attr:`PurePath.name`
-:func:`os.path.dirname` :attr:`PurePath.parent`
-:func:`os.path.samefile` :meth:`Path.samefile`
-:func:`os.path.splitext` :attr:`PurePath.stem` and
- :attr:`PurePath.suffix`
-==================================== ==============================
+===================================== ==============================================
+:mod:`os` and :mod:`os.path` :mod:`pathlib`
+===================================== ==============================================
+:func:`os.path.dirname` :attr:`PurePath.parent`
+:func:`os.path.basename` :attr:`PurePath.name`
+:func:`os.path.splitext` :attr:`PurePath.stem`, :attr:`PurePath.suffix`
+:func:`os.path.join` :meth:`PurePath.joinpath`
+:func:`os.path.isabs` :meth:`PurePath.is_absolute`
+:func:`os.path.relpath` :meth:`PurePath.relative_to` [1]_
+:func:`os.path.expanduser` :meth:`Path.expanduser` [2]_
+:func:`os.path.realpath` :meth:`Path.resolve`
+:func:`os.path.abspath` :meth:`Path.absolute` [3]_
+:func:`os.path.exists` :meth:`Path.exists`
+:func:`os.path.isfile` :meth:`Path.is_file`
+:func:`os.path.isdir` :meth:`Path.is_dir`
+:func:`os.path.islink` :meth:`Path.is_symlink`
+:func:`os.path.isjunction` :meth:`Path.is_junction`
+:func:`os.path.ismount` :meth:`Path.is_mount`
+:func:`os.path.samefile` :meth:`Path.samefile`
+:func:`os.getcwd` :meth:`Path.cwd`
+:func:`os.stat` :meth:`Path.stat`
+:func:`os.lstat` :meth:`Path.lstat`
+:func:`os.listdir` :meth:`Path.iterdir`
+:func:`os.walk` :meth:`Path.walk` [4]_
+:func:`os.mkdir`, :func:`os.makedirs` :meth:`Path.mkdir`
+:func:`os.link` :meth:`Path.hardlink_to`
+:func:`os.symlink` :meth:`Path.symlink_to`
+:func:`os.readlink` :meth:`Path.readlink`
+:func:`os.rename` :meth:`Path.rename`
+:func:`os.replace` :meth:`Path.replace`
+:func:`os.remove`, :func:`os.unlink` :meth:`Path.unlink`
+:func:`os.rmdir` :meth:`Path.rmdir`
+:func:`os.chmod` :meth:`Path.chmod`
+:func:`os.lchmod` :meth:`Path.lchmod`
+===================================== ==============================================
+
+.. rubric:: Footnotes
+
+.. [1] :func:`os.path.relpath` calls :func:`~os.path.abspath` to make paths
+ absolute and remove "``..``" parts, whereas :meth:`PurePath.relative_to`
+ is a lexical operation that raises :exc:`ValueError` when its inputs'
+ anchors differ (e.g. if one path is absolute and the other relative.)
+.. [2] :func:`os.path.expanduser` returns the path unchanged if the home
+ directory can't be resolved, whereas :meth:`Path.expanduser` raises
+ :exc:`RuntimeError`.
+.. [3] :func:`os.path.abspath` removes "``..``" components without resolving
+ symlinks, which may change the meaning of the path, whereas
+ :meth:`Path.absolute` leaves any "``..``" components in the path.
+.. [4] :func:`os.walk` always follows symlinks when categorizing paths into
+ *dirnames* and *filenames*, whereas :meth:`Path.walk` categorizes all
+ symlinks into *filenames* when *follow_symlinks* is false (the default.)
diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst
index cd649620394..9478d7b7d55 100644
--- a/Doc/library/pdb.rst
+++ b/Doc/library/pdb.rst
@@ -49,7 +49,7 @@ You can then step through the code following this statement, and continue
running without the debugger using the :pdbcmd:`continue` command.
.. versionchanged:: 3.7
- The built-in :func:`breakpoint()`, when called with defaults, can be used
+ The built-in :func:`breakpoint`, when called with defaults, can be used
instead of ``import pdb; pdb.set_trace()``.
::
diff --git a/Doc/library/pkgutil.rst b/Doc/library/pkgutil.rst
index 5d4ff34ba02..f095cc84173 100644
--- a/Doc/library/pkgutil.rst
+++ b/Doc/library/pkgutil.rst
@@ -34,9 +34,9 @@ support.
*name* argument. This feature is similar to :file:`\*.pth` files (see the
:mod:`site` module for more information), except that it doesn't special-case
lines starting with ``import``. A :file:`\*.pkg` file is trusted at face
- value: apart from checking for duplicates, all entries found in a
- :file:`\*.pkg` file are added to the path, regardless of whether they exist
- on the filesystem. (This is a feature.)
+ value: apart from skipping blank lines and ignoring comments, all entries
+ found in a :file:`\*.pkg` file are added to the path, regardless of whether
+ they exist on the filesystem (this is a feature).
If the input path is not a list (as is the case for frozen packages) it is
returned unchanged. The input path is not modified; an extended copy is
diff --git a/Doc/library/platform.rst b/Doc/library/platform.rst
index f082393ef93..1beb3b9eb89 100644
--- a/Doc/library/platform.rst
+++ b/Doc/library/platform.rst
@@ -150,7 +150,7 @@ Cross Platform
On iOS and Android, this returns the user-facing OS name (i.e, ``'iOS``,
``'iPadOS'`` or ``'Android'``). To obtain the kernel name (``'Darwin'`` or
- ``'Linux'``), use :func:`os.uname()`.
+ ``'Linux'``), use :func:`os.uname`.
.. function:: system_alias(system, release, version)
@@ -165,7 +165,7 @@ Cross Platform
returned if the value cannot be determined.
On iOS and Android, this is the user-facing OS version. To obtain the
- Darwin or Linux kernel version, use :func:`os.uname()`.
+ Darwin or Linux kernel version, use :func:`os.uname`.
.. function:: uname()
diff --git a/Doc/library/plistlib.rst b/Doc/library/plistlib.rst
index 78b3c2697bd..2906ebe7822 100644
--- a/Doc/library/plistlib.rst
+++ b/Doc/library/plistlib.rst
@@ -117,7 +117,7 @@ This module defines the following functions:
when a key of a dictionary is not a string, otherwise such keys are skipped.
When *aware_datetime* is true and any field with type ``datetime.datetime``
- is set as a :ref:`aware object `, it will convert to
+ is set as an :ref:`aware object `, it will convert to
UTC timezone before writing it.
A :exc:`TypeError` will be raised if the object is of an unsupported type or
diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst
index 9721da7220d..3334833eba6 100644
--- a/Doc/library/profile.rst
+++ b/Doc/library/profile.rst
@@ -682,7 +682,7 @@ you are using :class:`profile.Profile` or :class:`cProfile.Profile`,
that you choose (see :ref:`profile-calibration`). For most machines, a timer
that returns a lone integer value will provide the best results in terms of
low overhead during profiling. (:func:`os.times` is *pretty* bad, as it
- returns a tuple of floating point values). If you want to substitute a
+ returns a tuple of floating-point values). If you want to substitute a
better timer in the cleanest fashion, derive a class and hardwire a
replacement dispatch method that best handles your timer call, along with the
appropriate calibration constant.
@@ -699,7 +699,7 @@ you are using :class:`profile.Profile` or :class:`cProfile.Profile`,
As the :class:`cProfile.Profile` class cannot be calibrated, custom timer
functions should be used with care and should be as fast as possible. For
the best results with a custom timer, it might be necessary to hard-code it
- in the C source of the internal :mod:`_lsprof` module.
+ in the C source of the internal :mod:`!_lsprof` module.
Python 3.3 adds several new functions in :mod:`time` that can be used to make
precise measurements of process or wall-clock time. For example, see
diff --git a/Doc/library/pydoc.rst b/Doc/library/pydoc.rst
index f7ca1e04569..70e9c604eba 100644
--- a/Doc/library/pydoc.rst
+++ b/Doc/library/pydoc.rst
@@ -21,7 +21,7 @@ modules. The documentation can be presented as pages of text on the console,
served to a web browser, or saved to HTML files.
For modules, classes, functions and methods, the displayed documentation is
-derived from the docstring (i.e. the :attr:`!__doc__` attribute) of the object,
+derived from the docstring (i.e. the :attr:`~definition.__doc__` attribute) of the object,
and recursively of its documentable members. If there is no docstring,
:mod:`!pydoc` tries to obtain a description from the block of comment lines just
above the definition of the class, function or method in the source file, or at
diff --git a/Doc/library/random.rst b/Doc/library/random.rst
index 755d1c8908c..ef0cfb0e76c 100644
--- a/Doc/library/random.rst
+++ b/Doc/library/random.rst
@@ -200,8 +200,8 @@ Functions for sequences
For a given seed, the :func:`choices` function with equal weighting
typically produces a different sequence than repeated calls to
- :func:`choice`. The algorithm used by :func:`choices` uses floating
- point arithmetic for internal consistency and speed. The algorithm used
+ :func:`choice`. The algorithm used by :func:`choices` uses floating-point
+ arithmetic for internal consistency and speed. The algorithm used
by :func:`choice` defaults to integer arithmetic with repeated selections
to avoid small biases from round-off error.
@@ -298,12 +298,12 @@ be found in any statistics text.
.. function:: random()
- Return the next random floating point number in the range ``0.0 <= X < 1.0``
+ Return the next random floating-point number in the range ``0.0 <= X < 1.0``
.. function:: uniform(a, b)
- Return a random floating point number *N* such that ``a <= N <= b`` for
+ Return a random floating-point number *N* such that ``a <= N <= b`` for
``a <= b`` and ``b <= N <= a`` for ``b < a``.
The end-point value ``b`` may or may not be included in the range
@@ -313,7 +313,7 @@ be found in any statistics text.
.. function:: triangular(low, high, mode)
- Return a random floating point number *N* such that ``low <= N <= high`` and
+ Return a random floating-point number *N* such that ``low <= N <= high`` and
with the specified *mode* between those bounds. The *low* and *high* bounds
default to zero and one. The *mode* argument defaults to the midpoint
between the bounds, giving a symmetric distribution.
@@ -741,7 +741,7 @@ The following options are accepted:
.. option:: -f
--float
- Print a random floating point number between 1 and N inclusive,
+ Print a random floating-point number between 0 and N inclusive,
using :meth:`uniform`.
If no options are given, the output depends on the input:
diff --git a/Doc/library/re.rst b/Doc/library/re.rst
index cc979fe66f7..9db6f1da3be 100644
--- a/Doc/library/re.rst
+++ b/Doc/library/re.rst
@@ -572,6 +572,12 @@ character ``'$'``.
Word boundaries are determined by the current locale
if the :py:const:`~re.LOCALE` flag is used.
+ .. note::
+
+ Note that ``\B`` does not match an empty string, which differs from
+ RE implementations in other programming languages such as Perl.
+ This behavior is kept for compatibility reasons.
+
.. index:: single: \d; in regular expressions
``\d``
@@ -600,10 +606,9 @@ character ``'$'``.
``\s``
For Unicode (str) patterns:
- Matches Unicode whitespace characters (which includes
- ``[ \t\n\r\f\v]``, and also many other characters, for example the
- non-breaking spaces mandated by typography rules in many
- languages).
+ Matches Unicode whitespace characters (as defined by :py:meth:`str.isspace`).
+ This includes ``[ \t\n\r\f\v]``, and also many other characters, for example the
+ non-breaking spaces mandated by typography rules in many languages.
Matches ``[ \t\n\r\f\v]`` if the :py:const:`~re.ASCII` flag is used.
diff --git a/Doc/library/readline.rst b/Doc/library/readline.rst
index 5658b93c81d..4a042056632 100644
--- a/Doc/library/readline.rst
+++ b/Doc/library/readline.rst
@@ -24,7 +24,7 @@ in the GNU Readline manual for information about the format and
allowable constructs of that file, and the capabilities of the
Readline library in general.
-.. include:: ../includes/wasm-ios-notavail.rst
+.. include:: ../includes/wasm-mobile-notavail.rst
.. note::
@@ -45,6 +45,10 @@ Readline library in general.
python:bind -v
python:bind ^I rl_complete
+ Also note that different libraries may use different history file formats.
+ When switching the underlying library, existing history files may become
+ unusable.
+
.. data:: backend
The name of the underlying Readline library being used, either
diff --git a/Doc/library/resource.rst b/Doc/library/resource.rst
index dd80b1e6670..0515d205bbc 100644
--- a/Doc/library/resource.rst
+++ b/Doc/library/resource.rst
@@ -305,7 +305,7 @@ These functions are used to retrieve resource usage information:
elements.
The fields :attr:`ru_utime` and :attr:`ru_stime` of the return value are
- floating point values representing the amount of time spent executing in user
+ floating-point values representing the amount of time spent executing in user
mode and the amount of time spent executing in system mode, respectively. The
remaining values are integers. Consult the :manpage:`getrusage(2)` man page for
detailed information about these values. A brief summary is presented here:
diff --git a/Doc/library/secrets.rst b/Doc/library/secrets.rst
index 1401a925103..75dafc54d40 100644
--- a/Doc/library/secrets.rst
+++ b/Doc/library/secrets.rst
@@ -52,7 +52,7 @@ randomness that your operating system provides.
.. function:: randbits(k)
- Return an int with *k* random bits.
+ Return a non-negative int with *k* random bits.
Generating tokens
diff --git a/Doc/library/select.rst b/Doc/library/select.rst
index 06ebaf0201e..f23a249f44b 100644
--- a/Doc/library/select.rst
+++ b/Doc/library/select.rst
@@ -129,7 +129,7 @@ The module defines the following:
Empty iterables are allowed, but acceptance of three empty iterables is
platform-dependent. (It is known to work on Unix but not on Windows.) The
- optional *timeout* argument specifies a time-out as a floating point number
+ optional *timeout* argument specifies a time-out as a floating-point number
in seconds. When the *timeout* argument is omitted the function blocks until
at least one file descriptor is ready. A time-out value of zero specifies a
poll and never blocks.
diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst
index fd32479195e..af7e35f5fb2 100644
--- a/Doc/library/shutil.rst
+++ b/Doc/library/shutil.rst
@@ -449,9 +449,10 @@ Directory and files operations
*mode* is a permission mask passed to :func:`os.access`, by default
determining if the file exists and is executable.
- *path* is a "``PATH`` string" specifying the lookup directory list. When no
- *path* is specified, the results of :func:`os.environ` are used, returning
- either the "PATH" value or a fallback of :data:`os.defpath`.
+ *path* is a "``PATH`` string" specifying the directories to look in,
+ delimited by :data:`os.pathsep`. When no *path* is specified, the
+ :envvar:`PATH` environment variable is read from :data:`os.environ`,
+ falling back to :data:`os.defpath` if it is not set.
On Windows, the current directory is prepended to the *path* if *mode* does
not include ``os.X_OK``. When the *mode* does include ``os.X_OK``, the
@@ -460,9 +461,9 @@ Directory and files operations
consulting the current working directory for executables: set the environment
variable ``NoDefaultCurrentDirectoryInExePath``.
- Also on Windows, the ``PATHEXT`` variable is used to resolve commands
- that may not already include an extension. For example, if you call
- ``shutil.which("python")``, :func:`which` will search ``PATHEXT``
+ Also on Windows, the :envvar:`PATHEXT` environment variable is used to
+ resolve commands that may not already include an extension. For example,
+ if you call ``shutil.which("python")``, :func:`which` will search ``PATHEXT``
to know that it should look for ``python.exe`` within the *path*
directories. For example, on Windows::
diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst
index 48c6841c648..17fcb2b3707 100644
--- a/Doc/library/signal.rst
+++ b/Doc/library/signal.rst
@@ -411,7 +411,7 @@ The :mod:`signal` module defines the following functions:
See the :manpage:`pidfd_send_signal(2)` man page for more information.
- .. availability:: Linux >= 5.1
+ .. availability:: Linux >= 5.1, Android >= :func:`build-time ` API level 31
.. versionadded:: 3.9
@@ -425,7 +425,7 @@ The :mod:`signal` module defines the following functions:
signal to a particular Python thread would be to force a running system call
to fail with :exc:`InterruptedError`.
- Use :func:`threading.get_ident()` or the :attr:`~threading.Thread.ident`
+ Use :func:`threading.get_ident` or the :attr:`~threading.Thread.ident`
attribute of :class:`threading.Thread` objects to get a suitable value
for *thread_id*.
diff --git a/Doc/library/site.rst b/Doc/library/site.rst
index 1c420419568..4508091f679 100644
--- a/Doc/library/site.rst
+++ b/Doc/library/site.rst
@@ -15,8 +15,9 @@ import can be suppressed using the interpreter's :option:`-S` option.
.. index:: triple: module; search; path
-Importing this module will append site-specific paths to the module search path
-and add a few builtins, unless :option:`-S` was used. In that case, this module
+Importing this module normally appends site-specific paths to the module search path
+and adds :ref:`callables `, including :func:`help` to the built-in
+namespace. However, Python startup option :option:`-S` blocks this and this module
can be safely imported with no automatic modifications to the module search path
or additions to the builtins. To explicitly trigger the usual site-specific
additions, call the :func:`main` function.
@@ -32,7 +33,10 @@ It starts by constructing up to four directories from a head and a tail part.
For the head part, it uses ``sys.prefix`` and ``sys.exec_prefix``; empty heads
are skipped. For the tail part, it uses the empty string and then
:file:`lib/site-packages` (on Windows) or
-:file:`lib/python{X.Y}/site-packages` (on Unix and macOS). For each
+:file:`lib/python{X.Y[t]}/site-packages` (on Unix and macOS). (The
+optional suffix "t" indicates the :term:`free threading` build, and is
+appended if ``"t"`` is present in the :attr:`sys.abiflags` constant.)
+For each
of the distinct head-tail combinations, it sees if it refers to an existing
directory, and if so, adds it to ``sys.path`` and also inspects the newly
added path for configuration files.
@@ -40,6 +44,11 @@ added path for configuration files.
.. versionchanged:: 3.5
Support for the "site-python" directory has been removed.
+.. versionchanged:: 3.13
+ On Unix, :term:`Free threading ` Python installations are
+ identified by the "t" suffix in the version-specific directory name, such as
+ :file:`lib/python3.13t/`.
+
If a file named "pyvenv.cfg" exists one directory above sys.executable,
sys.prefix and sys.exec_prefix are set to that directory and
it is also checked for site-packages (sys.base_prefix and
@@ -188,11 +197,12 @@ Module contents
Path to the user site-packages for the running Python. Can be ``None`` if
:func:`getusersitepackages` hasn't been called yet. Default value is
- :file:`~/.local/lib/python{X.Y}/site-packages` for UNIX and non-framework
+ :file:`~/.local/lib/python{X.Y}[t]/site-packages` for UNIX and non-framework
macOS builds, :file:`~/Library/Python/{X.Y}/lib/python/site-packages` for macOS
framework builds, and :file:`{%APPDATA%}\\Python\\Python{XY}\\site-packages`
- on Windows. This directory is a site directory, which means that
- :file:`.pth` files in it will be processed.
+ on Windows. The optional "t" indicates the free-threaded build. This
+ directory is a site directory, which means that :file:`.pth` files in it
+ will be processed.
.. data:: USER_BASE
diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
index 2df0257d1f2..dc1baa28e1c 100644
--- a/Doc/library/socket.rst
+++ b/Doc/library/socket.rst
@@ -700,6 +700,13 @@ Constants
.. versionadded:: 3.12
+.. data:: SHUT_RD
+ SHUT_WR
+ SHUT_RDWR
+
+ These constants are used by the :meth:`~socket.socket.shutdown` method of socket objects.
+
+ .. availability:: not WASI.
Functions
^^^^^^^^^
@@ -729,7 +736,7 @@ The following functions all create :ref:`socket objects `.
of :meth:`socket.getpeername` but not the actual OS resource. Unlike
:func:`socket.fromfd`, *fileno* will return the same socket and not a
duplicate. This may help close a detached socket using
- :meth:`socket.close()`.
+ :meth:`socket.close`.
The newly created socket is :ref:`non-inheritable `.
@@ -1265,7 +1272,7 @@ The :mod:`socket` module also offers various network-related services:
.. audit-event:: socket.sethostname name socket.sethostname
- .. availability:: Unix.
+ .. availability:: Unix, not Android.
.. versionadded:: 3.3
@@ -1408,7 +1415,7 @@ to sockets.
.. method:: socket.close()
Mark the socket closed. The underlying system resource (e.g. a file
- descriptor) is also closed when all file objects from :meth:`makefile()`
+ descriptor) is also closed when all file objects from :meth:`makefile`
are closed. Once that happens, all future operations on the socket
object will fail. The remote end will receive no more data (after
queued data is flushed).
@@ -1423,10 +1430,10 @@ to sockets.
.. note::
- :meth:`close()` releases the resource associated with a connection but
+ :meth:`close` releases the resource associated with a connection but
does not necessarily close the connection immediately. If you want
- to close the connection in a timely fashion, call :meth:`shutdown()`
- before :meth:`close()`.
+ to close the connection in a timely fashion, call :meth:`shutdown`
+ before :meth:`close`.
.. method:: socket.connect(address)
@@ -1922,7 +1929,7 @@ to sockets.
.. method:: socket.settimeout(value)
Set a timeout on blocking socket operations. The *value* argument can be a
- nonnegative floating point number expressing seconds, or ``None``.
+ nonnegative floating-point number expressing seconds, or ``None``.
If a non-zero value is given, subsequent socket operations will raise a
:exc:`timeout` exception if the timeout period *value* has elapsed before
the operation has completed. If zero is given, the socket is put in
@@ -2035,7 +2042,7 @@ can be changed by calling :func:`setdefaulttimeout`.
in non-blocking mode. Also, the blocking and timeout modes are shared between
file descriptors and socket objects that refer to the same network endpoint.
This implementation detail can have visible consequences if e.g. you decide
- to use the :meth:`~socket.fileno()` of a socket.
+ to use the :meth:`~socket.fileno` of a socket.
Timeouts and the ``connect`` method
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst
index 6da8798ddfe..91250c45410 100644
--- a/Doc/library/sqlite3.rst
+++ b/Doc/library/sqlite3.rst
@@ -127,7 +127,7 @@ and call :meth:`res.fetchone() ` to fetch the resulting row:
We can see that the table has been created,
as the query returns a :class:`tuple` containing the table's name.
If we query ``sqlite_master`` for a non-existent table ``spam``,
-:meth:`!res.fetchone()` will return ``None``:
+:meth:`!res.fetchone` will return ``None``:
.. doctest::
@@ -525,21 +525,20 @@ Module constants
The mappings from SQLite threading modes to DB-API 2.0 threadsafety levels
are as follows:
- +------------------+-----------------+----------------------+-------------------------------+
- | SQLite threading | `threadsafety`_ | `SQLITE_THREADSAFE`_ | DB-API 2.0 meaning |
- | mode | | | |
- +==================+=================+======================+===============================+
- | single-thread | 0 | 0 | Threads may not share the |
- | | | | module |
- +------------------+-----------------+----------------------+-------------------------------+
- | multi-thread | 1 | 2 | Threads may share the module, |
- | | | | but not connections |
- +------------------+-----------------+----------------------+-------------------------------+
- | serialized | 3 | 1 | Threads may share the module, |
- | | | | connections and cursors |
- +------------------+-----------------+----------------------+-------------------------------+
-
- .. _threadsafety: https://peps.python.org/pep-0249/#threadsafety
+ +------------------+----------------------+----------------------+-------------------------------+
+ | SQLite threading | :pep:`threadsafety | `SQLITE_THREADSAFE`_ | DB-API 2.0 meaning |
+ | mode | <0249#threadsafety>` | | |
+ +==================+======================+======================+===============================+
+ | single-thread | 0 | 0 | Threads may not share the |
+ | | | | module |
+ +------------------+----------------------+----------------------+-------------------------------+
+ | multi-thread | 1 | 2 | Threads may share the module, |
+ | | | | but not connections |
+ +------------------+----------------------+----------------------+-------------------------------+
+ | serialized | 3 | 1 | Threads may share the module, |
+ | | | | connections and cursors |
+ +------------------+----------------------+----------------------+-------------------------------+
+
.. _SQLITE_THREADSAFE: https://sqlite.org/compile.html#threadsafe
.. versionchanged:: 3.11
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
index dc72f67c636..b7fb1fc07d1 100644
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -1049,25 +1049,25 @@ SSL Sockets
SSL sockets provide the following methods of :ref:`socket-objects`:
- - :meth:`~socket.socket.accept()`
- - :meth:`~socket.socket.bind()`
- - :meth:`~socket.socket.close()`
- - :meth:`~socket.socket.connect()`
- - :meth:`~socket.socket.detach()`
- - :meth:`~socket.socket.fileno()`
- - :meth:`~socket.socket.getpeername()`, :meth:`~socket.socket.getsockname()`
- - :meth:`~socket.socket.getsockopt()`, :meth:`~socket.socket.setsockopt()`
- - :meth:`~socket.socket.gettimeout()`, :meth:`~socket.socket.settimeout()`,
- :meth:`~socket.socket.setblocking()`
- - :meth:`~socket.socket.listen()`
- - :meth:`~socket.socket.makefile()`
- - :meth:`~socket.socket.recv()`, :meth:`~socket.socket.recv_into()`
+ - :meth:`~socket.socket.accept`
+ - :meth:`~socket.socket.bind`
+ - :meth:`~socket.socket.close`
+ - :meth:`~socket.socket.connect`
+ - :meth:`~socket.socket.detach`
+ - :meth:`~socket.socket.fileno`
+ - :meth:`~socket.socket.getpeername`, :meth:`~socket.socket.getsockname`
+ - :meth:`~socket.socket.getsockopt`, :meth:`~socket.socket.setsockopt`
+ - :meth:`~socket.socket.gettimeout`, :meth:`~socket.socket.settimeout`,
+ :meth:`~socket.socket.setblocking`
+ - :meth:`~socket.socket.listen`
+ - :meth:`~socket.socket.makefile`
+ - :meth:`~socket.socket.recv`, :meth:`~socket.socket.recv_into`
(but passing a non-zero ``flags`` argument is not allowed)
- - :meth:`~socket.socket.send()`, :meth:`~socket.socket.sendall()` (with
+ - :meth:`~socket.socket.send`, :meth:`~socket.socket.sendall` (with
the same limitation)
- - :meth:`~socket.socket.sendfile()` (but :mod:`os.sendfile` will be used
- for plain-text sockets only, else :meth:`~socket.socket.send()` will be used)
- - :meth:`~socket.socket.shutdown()`
+ - :meth:`~socket.socket.sendfile` (but :mod:`os.sendfile` will be used
+ for plain-text sockets only, else :meth:`~socket.socket.send` will be used)
+ - :meth:`~socket.socket.shutdown`
However, since the SSL (and TLS) protocol has its own framing atop
of TCP, the SSL sockets abstraction can, in certain respects, diverge from
@@ -1566,7 +1566,7 @@ to speed up repeated connections from the same clients.
The *capath* string, if present, is
the path to a directory containing several CA certificates in PEM format,
following an `OpenSSL specific layout
- `_.
+ `_.
The *cadata* object, if present, is either an ASCII string of one or more
PEM-encoded certificates or a :term:`bytes-like object` of DER-encoded
@@ -1641,7 +1641,7 @@ to speed up repeated connections from the same clients.
Set the available ciphers for sockets created with this context.
It should be a string in the `OpenSSL cipher list format
- `_.
+ `_.
If no cipher can be selected (because compile-time options or other
configuration forbids use of all the specified ciphers), an
:class:`SSLError` will be raised.
@@ -1742,7 +1742,7 @@ to speed up repeated connections from the same clients.
IDN-encoded internationalized domain name, the *server_name_callback*
receives a decoded U-label (``"pythön.org"``).
- If there is an decoding error on the server name, the TLS connection will
+ If there is a decoding error on the server name, the TLS connection will
terminate with an :const:`ALERT_DESCRIPTION_INTERNAL_ERROR` fatal TLS
alert message to the client.
@@ -1874,7 +1874,7 @@ to speed up repeated connections from the same clients.
.. method:: SSLContext.session_stats()
Get statistics about the SSL sessions created or managed by this context.
- A dictionary is returned which maps the names of each `piece of information `_ to their
+ A dictionary is returned which maps the names of each `piece of information `_ to their
numeric values. For example, here is the total number of hits and misses
in the session cache since the context was created::
@@ -2017,7 +2017,7 @@ to speed up repeated connections from the same clients.
.. attribute:: SSLContext.security_level
An integer representing the `security level
- `_
+ `_
for the context. This attribute is read-only.
.. versionadded:: 3.10
@@ -2710,7 +2710,7 @@ Verifying certificates
When calling the :class:`SSLContext` constructor directly,
:const:`CERT_NONE` is the default. Since it does not authenticate the other
-peer, it can be insecure, especially in client mode where most of time you
+peer, it can be insecure, especially in client mode where most of the time you
would like to ensure the authenticity of the server you're talking to.
Therefore, when in client mode, it is highly recommended to use
:const:`CERT_REQUIRED`. However, it is in itself not sufficient; you also
@@ -2759,7 +2759,7 @@ enabled when negotiating a SSL session is possible through the
:meth:`SSLContext.set_ciphers` method. Starting from Python 3.2.3, the
ssl module disables certain weak ciphers by default, but you may want
to further restrict the cipher choice. Be sure to read OpenSSL's documentation
-about the `cipher list format `_.
+about the `cipher list format `_.
If you want to check which ciphers are enabled by a given cipher list, use
:meth:`SSLContext.get_ciphers` or the ``openssl ciphers`` command on your
system.
diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst
index 8453135d2e1..614f5b905a4 100644
--- a/Doc/library/statistics.rst
+++ b/Doc/library/statistics.rst
@@ -73,7 +73,7 @@ or sample.
======================= ===============================================================
:func:`mean` Arithmetic mean ("average") of data.
-:func:`fmean` Fast, floating point arithmetic mean, with optional weighting.
+:func:`fmean` Fast, floating-point arithmetic mean, with optional weighting.
:func:`geometric_mean` Geometric mean of data.
:func:`harmonic_mean` Harmonic mean of data.
:func:`kde` Estimate the probability density distribution of the data.
@@ -485,6 +485,12 @@ However, for reading convenience, most of the examples show sorted sequences.
>>> mode(["red", "blue", "blue", "red", "green", "red", "red"])
'red'
+ Only hashable inputs are supported. To handle type :class:`set`,
+ consider casting to :class:`frozenset`. To handle type :class:`list`,
+ consider casting to :class:`tuple`. For mixed or nested inputs, consider
+ using this slower quadratic algorithm that only depends on equality tests:
+ ``max(data, key=data.count)``.
+
.. versionchanged:: 3.8
Now handles multimodal datasets by returning the first mode encountered.
Formerly, it raised :exc:`StatisticsError` when more than one mode was
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
index 79687b94f0a..8b9d29545e3 100644
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -209,18 +209,18 @@ Numeric Types --- :class:`int`, :class:`float`, :class:`complex`
pair: object; numeric
pair: object; Boolean
pair: object; integer
- pair: object; floating point
+ pair: object; floating-point
pair: object; complex number
pair: C; language
-There are three distinct numeric types: :dfn:`integers`, :dfn:`floating
-point numbers`, and :dfn:`complex numbers`. In addition, Booleans are a
-subtype of integers. Integers have unlimited precision. Floating point
+There are three distinct numeric types: :dfn:`integers`, :dfn:`floating-point
+numbers`, and :dfn:`complex numbers`. In addition, Booleans are a
+subtype of integers. Integers have unlimited precision. Floating-point
numbers are usually implemented using :c:expr:`double` in C; information
-about the precision and internal representation of floating point
+about the precision and internal representation of floating-point
numbers for the machine on which your program is running is available
in :data:`sys.float_info`. Complex numbers have a real and imaginary
-part, which are each a floating point number. To extract these parts
+part, which are each a floating-point number. To extract these parts
from a complex number *z*, use ``z.real`` and ``z.imag``. (The standard
library includes the additional numeric types :mod:`fractions.Fraction`, for
rationals, and :mod:`decimal.Decimal`, for floating-point numbers with
@@ -229,7 +229,7 @@ user-definable precision.)
.. index::
pair: numeric; literals
pair: integer; literals
- pair: floating point; literals
+ pair: floating-point; literals
pair: complex number; literals
pair: hexadecimal; literals
pair: octal; literals
@@ -238,7 +238,7 @@ user-definable precision.)
Numbers are created by numeric literals or as the result of built-in functions
and operators. Unadorned integer literals (including hex, octal and binary
numbers) yield integers. Numeric literals containing a decimal point or an
-exponent sign yield floating point numbers. Appending ``'j'`` or ``'J'`` to a
+exponent sign yield floating-point numbers. Appending ``'j'`` or ``'J'`` to a
numeric literal yields an imaginary number (a complex number with a zero real
part) which you can add to an integer or float to get a complex number with real
and imaginary parts.
@@ -832,7 +832,7 @@ over ``&``, ``|`` and ``^``.
.. deprecated:: 3.12
The use of the bitwise inversion operator ``~`` is deprecated and will
- raise an error in Python 3.14.
+ raise an error in Python 3.16.
:class:`bool` is a subclass of :class:`int` (see :ref:`typesnumeric`). In
many numeric contexts, ``False`` and ``True`` behave like the integers 0 and 1, respectively.
@@ -1209,8 +1209,9 @@ accepts integers that meet the value restriction ``0 <= x <= 255``).
| ``s.pop()`` or ``s.pop(i)`` | retrieves the item at *i* and | \(2) |
| | also removes it from *s* | |
+------------------------------+--------------------------------+---------------------+
-| ``s.remove(x)`` | remove the first item from *s* | \(3) |
-| | where ``s[i]`` is equal to *x* | |
+| ``s.remove(x)`` | removes the first item from | \(3) |
+| | *s* where ``s[i]`` is equal to | |
+| | *x* | |
+------------------------------+--------------------------------+---------------------+
| ``s.reverse()`` | reverses the items of *s* in | \(4) |
| | place | |
@@ -1497,8 +1498,8 @@ objects that compare equal might have different :attr:`~range.start`,
.. seealso::
* The `linspace recipe `_
- shows how to implement a lazy version of range suitable for floating
- point applications.
+ shows how to implement a lazy version of range suitable for floating-point
+ applications.
.. index::
single: string; text sequence type
@@ -2095,8 +2096,9 @@ expression support in the :mod:`re` module).
If *sep* is given, consecutive delimiters are not grouped together and are
deemed to delimit empty strings (for example, ``'1,,2'.split(',')`` returns
``['1', '', '2']``). The *sep* argument may consist of multiple characters
- (for example, ``'1<>2<>3'.split('<>')`` returns ``['1', '2', '3']``).
- Splitting an empty string with a specified separator returns ``['']``.
+ as a single delimiter (to split with multiple delimiters, use
+ :func:`re.split`). Splitting an empty string with a specified separator
+ returns ``['']``.
For example::
@@ -2106,6 +2108,8 @@ expression support in the :mod:`re` module).
['1', '2,3']
>>> '1,2,,3,'.split(',')
['1', '2', '', '3', '']
+ >>> '1<>2<>3<4'.split('<>')
+ ['1', '2', '3<4']
If *sep* is not specified or is ``None``, a different splitting algorithm is
applied: runs of consecutive whitespace are regarded as a single separator,
@@ -2439,19 +2443,19 @@ The conversion types are:
+------------+-----------------------------------------------------+-------+
| ``'X'`` | Signed hexadecimal (uppercase). | \(2) |
+------------+-----------------------------------------------------+-------+
-| ``'e'`` | Floating point exponential format (lowercase). | \(3) |
+| ``'e'`` | Floating-point exponential format (lowercase). | \(3) |
+------------+-----------------------------------------------------+-------+
-| ``'E'`` | Floating point exponential format (uppercase). | \(3) |
+| ``'E'`` | Floating-point exponential format (uppercase). | \(3) |
+------------+-----------------------------------------------------+-------+
-| ``'f'`` | Floating point decimal format. | \(3) |
+| ``'f'`` | Floating-point decimal format. | \(3) |
+------------+-----------------------------------------------------+-------+
-| ``'F'`` | Floating point decimal format. | \(3) |
+| ``'F'`` | Floating-point decimal format. | \(3) |
+------------+-----------------------------------------------------+-------+
-| ``'g'`` | Floating point format. Uses lowercase exponential | \(4) |
+| ``'g'`` | Floating-point format. Uses lowercase exponential | \(4) |
| | format if exponent is less than -4 or not less than | |
| | precision, decimal format otherwise. | |
+------------+-----------------------------------------------------+-------+
-| ``'G'`` | Floating point format. Uses uppercase exponential | \(4) |
+| ``'G'`` | Floating-point format. Uses uppercase exponential | \(4) |
| | format if exponent is less than -4 or not less than | |
| | precision, decimal format otherwise. | |
+------------+-----------------------------------------------------+-------+
@@ -3149,10 +3153,9 @@ produce new objects.
If *sep* is given, consecutive delimiters are not grouped together and are
deemed to delimit empty subsequences (for example, ``b'1,,2'.split(b',')``
returns ``[b'1', b'', b'2']``). The *sep* argument may consist of a
- multibyte sequence (for example, ``b'1<>2<>3'.split(b'<>')`` returns
- ``[b'1', b'2', b'3']``). Splitting an empty sequence with a specified
- separator returns ``[b'']`` or ``[bytearray(b'')]`` depending on the type
- of object being split. The *sep* argument may be any
+ multibyte sequence as a single delimiter. Splitting an empty sequence with
+ a specified separator returns ``[b'']`` or ``[bytearray(b'')]`` depending
+ on the type of object being split. The *sep* argument may be any
:term:`bytes-like object`.
For example::
@@ -3163,6 +3166,8 @@ produce new objects.
[b'1', b'2,3']
>>> b'1,2,,3,'.split(b',')
[b'1', b'2', b'', b'3', b'']
+ >>> b'1<>2<>3<4'.split(b'<>')
+ [b'1', b'2', b'3<4']
If *sep* is not specified or is ``None``, a different splitting algorithm
is applied: runs of consecutive ASCII whitespace are regarded as a single
@@ -3436,7 +3441,7 @@ place, and instead produce new objects.
``b'abcdefghijklmnopqrstuvwxyz'``. Uppercase ASCII characters
are those byte values in the sequence ``b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'``.
- Unlike :func:`str.swapcase()`, it is always the case that
+ Unlike :func:`str.swapcase`, it is always the case that
``bin.swapcase().swapcase() == bin`` for the binary versions. Case
conversions are symmetrical in ASCII, even though that is not generally
true for arbitrary Unicode code points.
@@ -3657,19 +3662,19 @@ The conversion types are:
+------------+-----------------------------------------------------+-------+
| ``'X'`` | Signed hexadecimal (uppercase). | \(2) |
+------------+-----------------------------------------------------+-------+
-| ``'e'`` | Floating point exponential format (lowercase). | \(3) |
+| ``'e'`` | Floating-point exponential format (lowercase). | \(3) |
+------------+-----------------------------------------------------+-------+
-| ``'E'`` | Floating point exponential format (uppercase). | \(3) |
+| ``'E'`` | Floating-point exponential format (uppercase). | \(3) |
+------------+-----------------------------------------------------+-------+
-| ``'f'`` | Floating point decimal format. | \(3) |
+| ``'f'`` | Floating-point decimal format. | \(3) |
+------------+-----------------------------------------------------+-------+
-| ``'F'`` | Floating point decimal format. | \(3) |
+| ``'F'`` | Floating-point decimal format. | \(3) |
+------------+-----------------------------------------------------+-------+
-| ``'g'`` | Floating point format. Uses lowercase exponential | \(4) |
+| ``'g'`` | Floating-point format. Uses lowercase exponential | \(4) |
| | format if exponent is less than -4 or not less than | |
| | precision, decimal format otherwise. | |
+------------+-----------------------------------------------------+-------+
-| ``'G'`` | Floating point format. Uses uppercase exponential | \(4) |
+| ``'G'`` | Floating-point format. Uses uppercase exponential | \(4) |
| | format if exponent is less than -4 or not less than | |
| | precision, decimal format otherwise. | |
+------------+-----------------------------------------------------+-------+
@@ -3891,7 +3896,7 @@ copying.
>>> a == b
False
- Note that, as with floating point numbers, ``v is w`` does *not* imply
+ Note that, as with floating-point numbers, ``v is w`` does *not* imply
``v == w`` for memoryview objects.
.. versionchanged:: 3.3
@@ -3982,7 +3987,7 @@ copying.
dangling resources) as soon as possible.
After this method has been called, any further operation on the view
- raises a :class:`ValueError` (except :meth:`release()` itself which can
+ raises a :class:`ValueError` (except :meth:`release` itself which can
be called multiple times)::
>>> m = memoryview(b'abc')
@@ -4565,7 +4570,7 @@ can be used interchangeably to index the same dictionary entry.
Return a shallow copy of the dictionary.
- .. classmethod:: fromkeys(iterable, value=None)
+ .. classmethod:: fromkeys(iterable, value=None, /)
Create a new dictionary with keys from *iterable* and values set to *value*.
@@ -5481,22 +5486,6 @@ types, where they are relevant. Some of these are not reported by the
:func:`dir` built-in function.
-.. attribute:: object.__dict__
-
- A dictionary or other mapping object used to store an object's (writable)
- attributes.
-
-
-.. attribute:: instance.__class__
-
- The class to which a class instance belongs.
-
-
-.. attribute:: class.__bases__
-
- The tuple of base classes of a class object.
-
-
.. attribute:: definition.__name__
The name of the class, function, method, descriptor, or
@@ -5511,43 +5500,24 @@ types, where they are relevant. Some of these are not reported by the
.. versionadded:: 3.3
-.. attribute:: definition.__type_params__
-
- The :ref:`type parameters ` of generic classes, functions,
- and :ref:`type aliases `.
-
- .. versionadded:: 3.12
-
-
-.. attribute:: class.__mro__
+.. attribute:: definition.__module__
- This attribute is a tuple of classes that are considered when looking for
- base classes during method resolution.
+ The name of the module in which a class or function was defined.
-.. method:: class.mro()
+.. attribute:: definition.__doc__
- This method can be overridden by a metaclass to customize the method
- resolution order for its instances. It is called at class instantiation, and
- its result is stored in :attr:`~class.__mro__`.
+ The documentation string of a class or function, or ``None`` if undefined.
-.. method:: class.__subclasses__
-
- Each class keeps a list of weak references to its immediate subclasses. This
- method returns a list of all those references still alive. The list is in
- definition order. Example::
-
- >>> int.__subclasses__()
- [, , , ]
-
+.. attribute:: definition.__type_params__
-.. attribute:: class.__static_attributes__
+ The :ref:`type parameters ` of generic classes, functions,
+ and :ref:`type aliases `. For classes and functions that
+ are not generic, this will be an empty tuple.
- A tuple containing names of attributes of this class which are accessed
- through ``self.X`` from any function in its body.
+ .. versionadded:: 3.12
- .. versionadded:: 3.13
.. _int_max_str_digits:
diff --git a/Doc/library/string.rst b/Doc/library/string.rst
index c3c0d732cf1..57a1f920523 100644
--- a/Doc/library/string.rst
+++ b/Doc/library/string.rst
@@ -418,7 +418,7 @@ instead.
.. index:: single: _ (underscore); in string formatting
The ``'_'`` option signals the use of an underscore for a thousands
-separator for floating point presentation types and for integer
+separator for floating-point presentation types and for integer
presentation type ``'d'``. For integer presentation types ``'b'``,
``'o'``, ``'x'``, and ``'X'``, underscores will be inserted every 4
digits. For other presentation types, specifying this option is an
@@ -491,9 +491,9 @@ The available integer presentation types are:
+---------+----------------------------------------------------------+
In addition to the above presentation types, integers can be formatted
-with the floating point presentation types listed below (except
+with the floating-point presentation types listed below (except
``'n'`` and ``None``). When doing so, :func:`float` is used to convert the
-integer to a floating point number before formatting.
+integer to a floating-point number before formatting.
The available presentation types for :class:`float` and
:class:`~decimal.Decimal` values are:
@@ -574,11 +574,13 @@ The available presentation types for :class:`float` and
| ``'%'`` | Percentage. Multiplies the number by 100 and displays |
| | in fixed (``'f'``) format, followed by a percent sign. |
+---------+----------------------------------------------------------+
- | None | For :class:`float` this is the same as ``'g'``, except |
+ | None | For :class:`float` this is like the ``'g'`` type, except |
| | that when fixed-point notation is used to format the |
| | result, it always includes at least one digit past the |
- | | decimal point. The precision used is as large as needed |
- | | to represent the given value faithfully. |
+ | | decimal point, and switches to the scientific notation |
+ | | when ``exp >= p - 1``. When the precision is not |
+ | | specified, the latter will be as large as needed to |
+ | | represent the given value faithfully. |
| | |
| | For :class:`~decimal.Decimal`, this is the same as |
| | either ``'g'`` or ``'G'`` depending on the value of |
diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst
index a2c293443e2..4769affdf1d 100644
--- a/Doc/library/struct.rst
+++ b/Doc/library/struct.rst
@@ -279,9 +279,9 @@ Notes:
(1)
.. index:: single: ? (question mark); in struct format strings
- The ``'?'`` conversion code corresponds to the :c:expr:`_Bool` type defined by
- C99. If this type is not available, it is simulated using a :c:expr:`char`. In
- standard mode, it is always represented by one byte.
+ The ``'?'`` conversion code corresponds to the :c:expr:`_Bool` type
+ defined by C standards since C99. In standard mode, it is
+ represented by one byte.
(2)
When attempting to pack a non-integer using any of the integer conversion
diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst
index 3a2178e2b7b..59c98e867ff 100644
--- a/Doc/library/subprocess.rst
+++ b/Doc/library/subprocess.rst
@@ -25,7 +25,7 @@ modules and functions can be found in the following sections.
:pep:`324` -- PEP proposing the subprocess module
-.. include:: ../includes/wasm-ios-notavail.rst
+.. include:: ../includes/wasm-mobile-notavail.rst
Using the :mod:`subprocess` Module
----------------------------------
@@ -608,7 +608,7 @@ functions.
If *group* is not ``None``, the setregid() system call will be made in the
child process prior to the execution of the subprocess. If the provided
- value is a string, it will be looked up via :func:`grp.getgrnam()` and
+ value is a string, it will be looked up via :func:`grp.getgrnam` and
the value in ``gr_gid`` will be used. If the value is an integer, it
will be passed verbatim. (POSIX only)
@@ -618,7 +618,7 @@ functions.
If *extra_groups* is not ``None``, the setgroups() system call will be
made in the child process prior to the execution of the subprocess.
Strings provided in *extra_groups* will be looked up via
- :func:`grp.getgrnam()` and the values in ``gr_gid`` will be used.
+ :func:`grp.getgrnam` and the values in ``gr_gid`` will be used.
Integer values will be passed verbatim. (POSIX only)
.. availability:: POSIX
@@ -626,7 +626,7 @@ functions.
If *user* is not ``None``, the setreuid() system call will be made in the
child process prior to the execution of the subprocess. If the provided
- value is a string, it will be looked up via :func:`pwd.getpwnam()` and
+ value is a string, it will be looked up via :func:`pwd.getpwnam` and
the value in ``pw_uid`` will be used. If the value is an integer, it will
be passed verbatim. (POSIX only)
@@ -1126,7 +1126,7 @@ The :mod:`subprocess` module exposes the following constants.
.. data:: NORMAL_PRIORITY_CLASS
A :class:`Popen` ``creationflags`` parameter to specify that a new process
- will have an normal priority. (default)
+ will have a normal priority. (default)
.. versionadded:: 3.7
diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst
index 0fa06da5220..5f08deba332 100644
--- a/Doc/library/sys.monitoring.rst
+++ b/Doc/library/sys.monitoring.rst
@@ -258,7 +258,7 @@ Per code object events
Events can also be controlled on a per code object basis. The functions
defined below which accept a :class:`types.CodeType` should be prepared
to accept a look-alike object from functions which are not defined
-in Python (see :ref:`monitoring`).
+in Python (see :ref:`c-api-monitoring`).
.. function:: get_local_events(tool_id: int, code: CodeType, /) -> int
diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst
index ed809d04167..1e1f65851fd 100644
--- a/Doc/library/sys.rst
+++ b/Doc/library/sys.rst
@@ -735,11 +735,11 @@ always available.
regardless of their size. This function is mainly useful for tracking
and debugging memory leaks. Because of the interpreter's internal
caches, the result can vary from call to call; you may have to call
- :func:`_clear_internal_caches()` and :func:`gc.collect()` to get more
+ :func:`_clear_internal_caches` and :func:`gc.collect` to get more
predictable results.
If a Python build or implementation cannot reasonably compute this
- information, :func:`getallocatedblocks()` is allowed to return 0 instead.
+ information, :func:`getallocatedblocks` is allowed to return 0 instead.
.. versionadded:: 3.4
diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst
index 9556da808f8..3921908b7c7 100644
--- a/Doc/library/sysconfig.rst
+++ b/Doc/library/sysconfig.rst
@@ -305,7 +305,7 @@ Installation path functions
mix with those by the other.
End users should not use this function, but :func:`get_default_scheme` and
- :func:`get_preferred_scheme()` instead.
+ :func:`get_preferred_scheme` instead.
.. versionadded:: 3.10
@@ -376,7 +376,7 @@ Other functions
This is used mainly to distinguish platform-specific build directories and
platform-specific built distributions. Typically includes the OS name and
- version and the architecture (as supplied by 'os.uname()'), although the
+ version and the architecture (as supplied by :func:`os.uname`), although the
exact information included depends on the OS; e.g., on Linux, the kernel
version isn't particularly important.
diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst
index 5b624f35331..08a2951bc42 100644
--- a/Doc/library/tarfile.rst
+++ b/Doc/library/tarfile.rst
@@ -617,7 +617,7 @@ be finalized; only the internally used file object will be closed. See the
it is best practice to only do so in top-level applications or
:mod:`site configuration `.
To set a global default this way, a filter function needs to be wrapped in
- :func:`staticmethod()` to prevent injection of a ``self`` argument.
+ :func:`staticmethod` to prevent injection of a ``self`` argument.
.. method:: TarFile.add(name, arcname=None, recursive=True, *, filter=None)
diff --git a/Doc/library/test.rst b/Doc/library/test.rst
index 2a61f0aaef2..04d28aee0f8 100644
--- a/Doc/library/test.rst
+++ b/Doc/library/test.rst
@@ -946,7 +946,7 @@ The :mod:`test.support` module defines the following functions:
other modules, possibly a C backend (like ``csv`` and its ``_csv``).
The *extra* argument can be a set of names that wouldn't otherwise be automatically
- detected as "public", like objects without a proper ``__module__``
+ detected as "public", like objects without a proper :attr:`~definition.__module__`
attribute. If provided, it will be added to the automatically detected ones.
The *not_exported* argument can be a set of names that must not be treated
@@ -1701,7 +1701,7 @@ The :mod:`test.support.warnings_helper` module provides support for warnings tes
.. function:: check_warnings(*filters, quiet=True)
- A convenience wrapper for :func:`warnings.catch_warnings()` that makes it
+ A convenience wrapper for :func:`warnings.catch_warnings` that makes it
easier to test that a warning was correctly raised. It is approximately
equivalent to calling ``warnings.catch_warnings(record=True)`` with
:meth:`warnings.simplefilter` set to ``always`` and with the option to
diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst
index 7b259e22dc7..cb82fea3776 100644
--- a/Doc/library/threading.rst
+++ b/Doc/library/threading.rst
@@ -412,7 +412,7 @@ since it is impossible to detect the termination of alien threads.
timeout occurs.
When the *timeout* argument is present and not ``None``, it should be a
- floating point number specifying a timeout for the operation in seconds
+ floating-point number specifying a timeout for the operation in seconds
(or fractions thereof). As :meth:`~Thread.join` always returns ``None``,
you must call :meth:`~Thread.is_alive` after :meth:`~Thread.join` to
decide whether a timeout happened -- if the thread is still alive, the
@@ -794,7 +794,7 @@ item to the buffer only needs to wake up one consumer thread.
occurs. Once awakened or timed out, it re-acquires the lock and returns.
When the *timeout* argument is present and not ``None``, it should be a
- floating point number specifying a timeout for the operation in seconds
+ floating-point number specifying a timeout for the operation in seconds
(or fractions thereof).
When the underlying lock is an :class:`RLock`, it is not released using
@@ -1018,10 +1018,10 @@ method. The :meth:`~Event.wait` method blocks until the flag is true.
has not expired. The return value represents the
reason that this blocking method returned; ``True`` if returning because
the internal flag is set to true, or ``False`` if a timeout is given and
- the the internal flag did not become true within the given wait time.
+ the internal flag did not become true within the given wait time.
When the timeout argument is present and not ``None``, it should be a
- floating point number specifying a timeout for the operation in seconds,
+ floating-point number specifying a timeout for the operation in seconds,
or fractions thereof.
.. versionchanged:: 3.1
diff --git a/Doc/library/time.rst b/Doc/library/time.rst
index 4d7661715aa..a0bf13fc0a3 100644
--- a/Doc/library/time.rst
+++ b/Doc/library/time.rst
@@ -69,7 +69,7 @@ An explanation of some terminology and conventions is in order.
systems, the clock "ticks" only 50 or 100 times a second.
* On the other hand, the precision of :func:`.time` and :func:`sleep` is better
- than their Unix equivalents: times are expressed as floating point numbers,
+ than their Unix equivalents: times are expressed as floating-point numbers,
:func:`.time` returns the most accurate time available (using Unix
:c:func:`!gettimeofday` where available), and :func:`sleep` will accept a time
with a nonzero fraction (Unix :c:func:`!select` is used to implement this, where
@@ -193,7 +193,7 @@ Functions
Use :func:`clock_settime_ns` to avoid the precision loss caused by the
:class:`float` type.
- .. availability:: Unix.
+ .. availability:: Unix, not Android, not iOS.
.. versionadded:: 3.3
@@ -202,7 +202,7 @@ Functions
Similar to :func:`clock_settime` but set time with nanoseconds.
- .. availability:: Unix.
+ .. availability:: Unix, not Android, not iOS.
.. versionadded:: 3.7
@@ -273,7 +273,7 @@ Functions
This is the inverse function of :func:`localtime`. Its argument is the
:class:`struct_time` or full 9-tuple (since the dst flag is needed; use ``-1``
as the dst flag if it is unknown) which expresses the time in *local* time, not
- UTC. It returns a floating point number, for compatibility with :func:`.time`.
+ UTC. It returns a floating-point number, for compatibility with :func:`.time`.
If the input value cannot be represented as a valid time, either
:exc:`OverflowError` or :exc:`ValueError` will be raised (which depends on
whether the invalid value is caught by Python or the underlying C libraries).
@@ -327,7 +327,7 @@ Functions
.. impl-detail::
- On CPython, use the same clock than :func:`time.monotonic()` and is a
+ On CPython, use the same clock than :func:`time.monotonic` and is a
monotonic clock, i.e. a clock that cannot go backwards.
Use :func:`perf_counter_ns` to avoid the precision loss caused by the
@@ -339,7 +339,7 @@ Functions
On Windows, the function is now system-wide.
.. versionchanged:: 3.13
- Use the same clock than :func:`time.monotonic()`.
+ Use the same clock than :func:`time.monotonic`.
.. function:: perf_counter_ns() -> int
@@ -376,7 +376,7 @@ Functions
.. function:: sleep(secs)
Suspend execution of the calling thread for the given number of seconds.
- The argument may be a floating point number to indicate a more precise sleep
+ The argument may be a floating-point number to indicate a more precise sleep
time.
If the sleep is interrupted by a signal and no exception is raised by the
@@ -665,13 +665,13 @@ Functions
.. function:: time() -> float
- Return the time in seconds since the epoch_ as a floating point
+ Return the time in seconds since the epoch_ as a floating-point
number. The handling of `leap seconds`_ is platform dependent.
On Windows and most Unix systems, the leap seconds are not counted towards
the time in seconds since the epoch_. This is commonly referred to as `Unix
time `_.
- Note that even though the time is always returned as a floating point
+ Note that even though the time is always returned as a floating-point
number, not all systems provide time with a better precision than 1 second.
While this function normally returns non-decreasing values, it can return a
lower value than a previous call if the system clock has been set back
diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst
index f40790c1175..f284988daf2 100644
--- a/Doc/library/tkinter.rst
+++ b/Doc/library/tkinter.rst
@@ -58,7 +58,7 @@ details that are unchanged.
* `Modern Tkinter for Busy Python Developers `_
By Mark Roseman. (ISBN 978-1999149567)
- * `Python GUI programming with Tkinter `_
+ * `Python GUI programming with Tkinter `_
By Alan D. Moore. (ISBN 978-1788835886)
* `Programming Python `_
@@ -983,10 +983,10 @@ option (other options are available as well).
Added the :class:`!PhotoImage` method :meth:`!copy_replace` to copy a region
from one image to other image, possibly with pixel zooming and/or
subsampling.
- Add *from_coords* parameter to :class:`!PhotoImage` methods :meth:`!copy()`,
- :meth:`!zoom()` and :meth:`!subsample()`.
+ Add *from_coords* parameter to :class:`!PhotoImage` methods :meth:`!copy`,
+ :meth:`!zoom` and :meth:`!subsample`.
Add *zoom* and *subsample* parameters to :class:`!PhotoImage` method
- :meth:`!copy()`.
+ :meth:`!copy`.
The image object can then be used wherever an ``image`` option is supported by
some widget (e.g. labels, buttons, menus). In these cases, Tk will not keep a
diff --git a/Doc/library/token.rst b/Doc/library/token.rst
index 919ff590b72..0cc9dddd91e 100644
--- a/Doc/library/token.rst
+++ b/Doc/library/token.rst
@@ -75,7 +75,7 @@ the :mod:`tokenize` module.
:noindex:
Token value indicating that a type comment was recognized. Such
- tokens are only produced when :func:`ast.parse()` is invoked with
+ tokens are only produced when :func:`ast.parse` is invoked with
``type_comments=True``.
diff --git a/Doc/library/tomllib.rst b/Doc/library/tomllib.rst
index b523ad93b35..521a7a17fb3 100644
--- a/Doc/library/tomllib.rst
+++ b/Doc/library/tomllib.rst
@@ -13,7 +13,7 @@
--------------
-This module provides an interface for parsing TOML (Tom's Obvious Minimal
+This module provides an interface for parsing TOML 1.0.0 (Tom's Obvious Minimal
Language, `https://toml.io `_). This module does not
support writing TOML.
diff --git a/Doc/library/traceback.rst b/Doc/library/traceback.rst
index bfd2c3efc4b..401e12be45f 100644
--- a/Doc/library/traceback.rst
+++ b/Doc/library/traceback.rst
@@ -42,6 +42,14 @@ The module defines the following functions:
:term:`file ` or :term:`file-like object` to
receive the output.
+ .. note::
+
+ The meaning of the *limit* parameter is different than the meaning
+ of :const:`sys.tracebacklimit`. A negative *limit* value corresponds to
+ a positive value of :const:`!sys.tracebacklimit`, whereas the behaviour of
+ a positive *limit* value cannot be achieved with
+ :const:`!sys.tracebacklimit`.
+
.. versionchanged:: 3.5
Added negative *limit* support.
diff --git a/Doc/library/types.rst b/Doc/library/types.rst
index 116868c24be..3c3c760c206 100644
--- a/Doc/library/types.rst
+++ b/Doc/library/types.rst
@@ -91,8 +91,8 @@ Dynamic Type Creation
For classes that have an ``__orig_bases__`` attribute, this
function returns the value of ``cls.__orig_bases__``.
- For classes without the ``__orig_bases__`` attribute, ``cls.__bases__`` is
- returned.
+ For classes without the ``__orig_bases__`` attribute,
+ :attr:`cls.__bases__ ` is returned.
Examples::
@@ -392,7 +392,7 @@ Standard names are defined for the following types:
In addition, when a class is defined with a :attr:`~object.__slots__` attribute, then for
each slot, an instance of :class:`!MemberDescriptorType` will be added as an attribute
- on the class. This allows the slot to appear in the class's :attr:`~object.__dict__`.
+ on the class. This allows the slot to appear in the class's :attr:`~type.__dict__`.
.. impl-detail::
diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst
index 53fe6ddf9b2..40df38c5503 100644
--- a/Doc/library/typing.rst
+++ b/Doc/library/typing.rst
@@ -208,7 +208,7 @@ Annotating callable objects
===========================
Functions -- or other :term:`callable` objects -- can be annotated using
-:class:`collections.abc.Callable` or :data:`typing.Callable`.
+:class:`collections.abc.Callable` or deprecated :data:`typing.Callable`.
``Callable[[int], str]`` signifies a function that takes a single parameter
of type :class:`int` and returns a :class:`str`.
@@ -401,7 +401,7 @@ The type of class objects
=========================
A variable annotated with ``C`` may accept a value of type ``C``. In
-contrast, a variable annotated with ``type[C]`` (or
+contrast, a variable annotated with ``type[C]`` (or deprecated
:class:`typing.Type[C] `) may accept values that are classes
themselves -- specifically, it will accept the *class object* of ``C``. For
example::
@@ -441,6 +441,87 @@ For example::
``type[Any]`` is equivalent to :class:`type`, which is the root of Python's
:ref:`metaclass hierarchy `.
+
+.. _annotating-generators-and-coroutines:
+
+Annotating generators and coroutines
+====================================
+
+A generator can be annotated using the generic type
+:class:`Generator[YieldType, SendType, ReturnType] `.
+For example::
+
+ def echo_round() -> Generator[int, float, str]:
+ sent = yield 0
+ while sent >= 0:
+ sent = yield round(sent)
+ return 'Done'
+
+Note that unlike many other generic classes in the standard library,
+the ``SendType`` of :class:`~collections.abc.Generator` behaves
+contravariantly, not covariantly or invariantly.
+
+The ``SendType`` and ``ReturnType`` parameters default to :const:`!None`::
+
+ def infinite_stream(start: int) -> Generator[int]:
+ while True:
+ yield start
+ start += 1
+
+It is also possible to set these types explicitly::
+
+ def infinite_stream(start: int) -> Generator[int, None, None]:
+ while True:
+ yield start
+ start += 1
+
+Simple generators that only ever yield values can also be annotated
+as having a return type of either
+:class:`Iterable[YieldType] `
+or :class:`Iterator[YieldType] `::
+
+ def infinite_stream(start: int) -> Iterator[int]:
+ while True:
+ yield start
+ start += 1
+
+Async generators are handled in a similar fashion, but don't
+expect a ``ReturnType`` type argument
+(:class:`AsyncGenerator[YieldType, SendType] `).
+The ``SendType`` argument defaults to :const:`!None`, so the following definitions
+are equivalent::
+
+ async def infinite_stream(start: int) -> AsyncGenerator[int]:
+ while True:
+ yield start
+ start = await increment(start)
+
+ async def infinite_stream(start: int) -> AsyncGenerator[int, None]:
+ while True:
+ yield start
+ start = await increment(start)
+
+As in the synchronous case,
+:class:`AsyncIterable[YieldType] `
+and :class:`AsyncIterator[YieldType] ` are
+available as well::
+
+ async def infinite_stream(start: int) -> AsyncIterator[int]:
+ while True:
+ yield start
+ start = await increment(start)
+
+Coroutines can be annotated using
+:class:`Coroutine[YieldType, SendType, ReturnType] `.
+Generic arguments correspond to those of :class:`~collections.abc.Generator`,
+for example::
+
+ from collections.abc import Coroutine
+ c: Coroutine[list[str], str, int] # Some coroutine defined elsewhere
+ x = c.send('hi') # Inferred type of 'x' is list[str]
+ async def bar() -> None:
+ y = await c # Inferred type of 'y' is int
+
.. _user-defined-generics:
User-defined generic types
@@ -1235,7 +1316,7 @@ These can be used as types in annotations. They all support subscription using
year: int
def mutate_movie(m: Movie) -> None:
- m["year"] = 1992 # allowed
+ m["year"] = 1999 # allowed
m["title"] = "The Matrix" # typechecker error
There is no runtime checking for this property.
@@ -1377,6 +1458,23 @@ These can be used as types in annotations. They all support subscription using
>>> X.__metadata__
('very', 'important', 'metadata')
+ * At runtime, if you want to retrieve the original
+ type wrapped by ``Annotated``, use the :attr:`!__origin__` attribute:
+
+ .. doctest::
+
+ >>> from typing import Annotated, get_origin
+ >>> Password = Annotated[str, "secret"]
+ >>> Password.__origin__
+
+
+ Note that using :func:`get_origin` will return ``Annotated`` itself:
+
+ .. doctest::
+
+ >>> get_origin(Password)
+ typing.Annotated
+
.. seealso::
:pep:`593` - Flexible function and variable annotations
@@ -2175,7 +2273,9 @@ types.
Backward-compatible usage::
- # For creating a generic NamedTuple on Python 3.11 or lower
+ # For creating a generic NamedTuple on Python 3.11
+ T = TypeVar("T")
+
class Group(NamedTuple, Generic[T]):
key: T
group: list[T]
@@ -2709,7 +2809,7 @@ Functions and decorators
.. seealso::
`Unreachable Code and Exhaustiveness Checking
- `__ has more
+ `__ has more
information about exhaustiveness checking with static typing.
.. versionadded:: 3.11
@@ -3095,7 +3195,8 @@ Introspection helpers
empty dictionary is returned.
* If *obj* is a class ``C``, the function returns a dictionary that merges
annotations from ``C``'s base classes with those on ``C`` directly. This
- is done by traversing ``C.__mro__`` and iteratively combining
+ is done by traversing :attr:`C.__mro__ ` and iteratively
+ combining
``__annotations__`` dictionaries. Annotations on classes appearing
earlier in the :term:`method resolution order` always take precedence over
annotations on classes appearing later in the method resolution order.
@@ -3141,6 +3242,7 @@ Introspection helpers
assert get_origin(str) is None
assert get_origin(Dict[str, int]) is dict
assert get_origin(Union[int, str]) is Union
+ assert get_origin(Annotated[str, "metadata"]) is Annotated
P = ParamSpec('P')
assert get_origin(P.args) is P
assert get_origin(P.kwargs) is P
@@ -3318,14 +3420,9 @@ Aliases to built-in types
Deprecated alias to :class:`dict`.
Note that to annotate arguments, it is preferred
- to use an abstract collection type such as :class:`Mapping`
+ to use an abstract collection type such as :class:`~collections.abc.Mapping`
rather than to use :class:`dict` or :class:`!typing.Dict`.
- This type can be used as follows::
-
- def count_words(text: str) -> Dict[str, int]:
- ...
-
.. deprecated:: 3.9
:class:`builtins.dict ` now supports subscripting (``[]``).
See :pep:`585` and :ref:`types-genericalias`.
@@ -3335,16 +3432,9 @@ Aliases to built-in types
Deprecated alias to :class:`list`.
Note that to annotate arguments, it is preferred
- to use an abstract collection type such as :class:`Sequence` or
- :class:`Iterable` rather than to use :class:`list` or :class:`!typing.List`.
-
- This type may be used as follows::
-
- def vec2[T: (int, float)](x: T, y: T) -> List[T]:
- return [x, y]
-
- def keep_positives[T: (int, float)](vector: Sequence[T]) -> List[T]:
- return [item for item in vector if item > 0]
+ to use an abstract collection type such as
+ :class:`~collections.abc.Sequence` or :class:`~collections.abc.Iterable`
+ rather than to use :class:`list` or :class:`!typing.List`.
.. deprecated:: 3.9
:class:`builtins.list ` now supports subscripting (``[]``).
@@ -3355,8 +3445,8 @@ Aliases to built-in types
Deprecated alias to :class:`builtins.set `.
Note that to annotate arguments, it is preferred
- to use an abstract collection type such as :class:`AbstractSet`
- rather than to use :class:`set` or :class:`!typing.Set`.
+ to use an abstract collection type such as :class:`collections.abc.Set`
+ rather than to use :class:`set` or :class:`typing.Set`.
.. deprecated:: 3.9
:class:`builtins.set ` now supports subscripting (``[]``).
@@ -3552,11 +3642,6 @@ Aliases to container ABCs in :mod:`collections.abc`
Deprecated alias to :class:`collections.abc.Mapping`.
- This type can be used as follows::
-
- def get_position_in_index(word_list: Mapping[str, int], word: str) -> int:
- return word_list[word]
-
.. deprecated:: 3.9
:class:`collections.abc.Mapping` now supports subscripting (``[]``).
See :pep:`585` and :ref:`types-genericalias`.
@@ -3620,14 +3705,9 @@ Aliases to asynchronous ABCs in :mod:`collections.abc`
Deprecated alias to :class:`collections.abc.Coroutine`.
- The variance and order of type variables
- correspond to those of :class:`Generator`, for example::
-
- from collections.abc import Coroutine
- c: Coroutine[list[str], str, int] # Some coroutine defined elsewhere
- x = c.send('hi') # Inferred type of 'x' is list[str]
- async def bar() -> None:
- y = await c # Inferred type of 'y' is int
+ See :ref:`annotating-generators-and-coroutines`
+ for details on using :class:`collections.abc.Coroutine`
+ and ``typing.Coroutine`` in type annotations.
.. versionadded:: 3.5.3
@@ -3639,40 +3719,9 @@ Aliases to asynchronous ABCs in :mod:`collections.abc`
Deprecated alias to :class:`collections.abc.AsyncGenerator`.
- An async generator can be annotated by the generic type
- ``AsyncGenerator[YieldType, SendType]``. For example::
-
- async def echo_round() -> AsyncGenerator[int, float]:
- sent = yield 0
- while sent >= 0.0:
- rounded = await round(sent)
- sent = yield rounded
-
- Unlike normal generators, async generators cannot return a value, so there
- is no ``ReturnType`` type parameter. As with :class:`Generator`, the
- ``SendType`` behaves contravariantly.
-
- The ``SendType`` defaults to :const:`!None`::
-
- async def infinite_stream(start: int) -> AsyncGenerator[int]:
- while True:
- yield start
- start = await increment(start)
-
- It is also possible to set this type explicitly::
-
- async def infinite_stream(start: int) -> AsyncGenerator[int, None]:
- while True:
- yield start
- start = await increment(start)
-
- Alternatively, annotate your generator as having a return type of
- either ``AsyncIterable[YieldType]`` or ``AsyncIterator[YieldType]``::
-
- async def infinite_stream(start: int) -> AsyncIterator[int]:
- while True:
- yield start
- start = await increment(start)
+ See :ref:`annotating-generators-and-coroutines`
+ for details on using :class:`collections.abc.AsyncGenerator`
+ and ``typing.AsyncGenerator`` in type annotations.
.. versionadded:: 3.6.1
@@ -3754,40 +3803,9 @@ Aliases to other ABCs in :mod:`collections.abc`
Deprecated alias to :class:`collections.abc.Generator`.
- A generator can be annotated by the generic type
- ``Generator[YieldType, SendType, ReturnType]``. For example::
-
- def echo_round() -> Generator[int, float, str]:
- sent = yield 0
- while sent >= 0:
- sent = yield round(sent)
- return 'Done'
-
- Note that unlike many other generics in the typing module, the ``SendType``
- of :class:`Generator` behaves contravariantly, not covariantly or
- invariantly.
-
- The ``SendType`` and ``ReturnType`` parameters default to :const:`!None`::
-
- def infinite_stream(start: int) -> Generator[int]:
- while True:
- yield start
- start += 1
-
- It is also possible to set these types explicitly::
-
- def infinite_stream(start: int) -> Generator[int, None, None]:
- while True:
- yield start
- start += 1
-
- Alternatively, annotate your generator as having a return type of
- either ``Iterable[YieldType]`` or ``Iterator[YieldType]``::
-
- def infinite_stream(start: int) -> Iterator[int]:
- while True:
- yield start
- start += 1
+ See :ref:`annotating-generators-and-coroutines`
+ for details on using :class:`collections.abc.Generator`
+ and ``typing.Generator`` in type annotations.
.. deprecated:: 3.9
:class:`collections.abc.Generator` now supports subscripting (``[]``).
diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst
index d8ba24c3146..55ebf1acdb7 100644
--- a/Doc/library/unittest.mock.rst
+++ b/Doc/library/unittest.mock.rst
@@ -239,7 +239,7 @@ the *new_callable* argument to :func:`patch`.
Accessing any attribute not in this list will raise an :exc:`AttributeError`.
If *spec* is an object (rather than a list of strings) then
- :attr:`~instance.__class__` returns the class of the spec object. This
+ :attr:`~object.__class__` returns the class of the spec object. This
allows mocks to pass :func:`isinstance` tests.
* *spec_set*: A stricter variant of *spec*. If used, attempting to *set*
@@ -860,6 +860,20 @@ object::
3
>>> p.assert_called_once_with()
+.. caution::
+
+ If an :exc:`AttributeError` is raised by :class:`PropertyMock`,
+ it will be interpreted as a missing descriptor and
+ :meth:`~object.__getattr__` will be called on the parent mock::
+
+ >>> m = MagicMock()
+ >>> no_attribute = PropertyMock(side_effect=AttributeError)
+ >>> type(m).my_property = no_attribute
+ >>> m.my_property
+
+
+ See :meth:`~object.__getattr__` for details.
+
.. class:: AsyncMock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, unsafe=False, **kwargs)
diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst
index eb42210e096..c49aba69b12 100644
--- a/Doc/library/unittest.rst
+++ b/Doc/library/unittest.rst
@@ -2316,8 +2316,8 @@ Loading and running tests
(see :ref:`Warning control `),
otherwise it will be set to ``'default'``.
- Calling ``main`` actually returns an instance of the ``TestProgram`` class.
- This stores the result of the tests run as the ``result`` attribute.
+ Calling ``main`` returns an object with the ``result`` attribute that contains
+ the result of the tests run as a :class:`unittest.TestResult`.
.. versionchanged:: 3.1
The *exit* parameter was added.
@@ -2529,7 +2529,7 @@ Signal Handling
.. versionadded:: 3.2
The :option:`-c/--catch ` command-line option to unittest,
-along with the ``catchbreak`` parameter to :func:`unittest.main()`, provide
+along with the ``catchbreak`` parameter to :func:`unittest.main`, provide
more friendly handling of control-C during a test run. With catch break
behavior enabled control-C will allow the currently running test to complete,
and the test run will then end and report all the results so far. A second
diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst
index 27909b763e9..fb5353e1895 100644
--- a/Doc/library/urllib.parse.rst
+++ b/Doc/library/urllib.parse.rst
@@ -22,11 +22,19 @@ to an absolute URL given a "base URL."
The module has been designed to match the internet RFC on Relative Uniform
Resource Locators. It supports the following URL schemes: ``file``, ``ftp``,
-``gopher``, ``hdl``, ``http``, ``https``, ``imap``, ``mailto``, ``mms``,
+``gopher``, ``hdl``, ``http``, ``https``, ``imap``, ``itms-services``, ``mailto``, ``mms``,
``news``, ``nntp``, ``prospero``, ``rsync``, ``rtsp``, ``rtsps``, ``rtspu``,
``sftp``, ``shttp``, ``sip``, ``sips``, ``snews``, ``svn``, ``svn+ssh``,
``telnet``, ``wais``, ``ws``, ``wss``.
+.. impl-detail::
+
+ The inclusion of the ``itms-services`` URL scheme can prevent an app from
+ passing Apple's App Store review process for the macOS and iOS App Stores.
+ Handling for the ``itms-services`` scheme is always removed on iOS; on
+ macOS, it *may* be removed if CPython has been built with the
+ :option:`--with-app-store-compliance` option.
+
The :mod:`urllib.parse` module defines functions that fall into two broad
categories: URL parsing and URL quoting. These are covered in detail in
the following sections.
diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst
index 754405e0fbe..ce82552a3ae 100644
--- a/Doc/library/urllib.request.rst
+++ b/Doc/library/urllib.request.rst
@@ -241,7 +241,7 @@ The following classes are provided:
*method* should be a string that indicates the HTTP request method that
will be used (e.g. ``'HEAD'``). If provided, its value is stored in the
- :attr:`~Request.method` attribute and is used by :meth:`get_method()`.
+ :attr:`~Request.method` attribute and is used by :meth:`get_method`.
The default is ``'GET'`` if *data* is ``None`` or ``'POST'`` otherwise.
Subclasses may indicate a different default method by setting the
:attr:`~Request.method` attribute in the class itself.
@@ -1092,7 +1092,7 @@ FileHandler Objects
.. versionchanged:: 3.2
This method is applicable only for local hostnames. When a remote
- hostname is given, an :exc:`~urllib.error.URLError` is raised.
+ hostname is given, a :exc:`~urllib.error.URLError` is raised.
.. _data-handler-objects:
@@ -1107,7 +1107,7 @@ DataHandler Objects
ignores white spaces in base64 encoded data URLs so the URL may be wrapped
in whatever source file it comes from. But even though some browsers don't
mind about a missing padding at the end of a base64 encoded data URL, this
- implementation will raise an :exc:`ValueError` in that case.
+ implementation will raise a :exc:`ValueError` in that case.
.. _ftp-handler-objects:
diff --git a/Doc/library/venv.rst b/Doc/library/venv.rst
index fff1075c247..e2c77963ff3 100644
--- a/Doc/library/venv.rst
+++ b/Doc/library/venv.rst
@@ -37,14 +37,14 @@ A virtual environment is (amongst other things):
are by default isolated from software in other virtual environments and Python
interpreters and libraries installed in the operating system.
-* Contained in a directory, conventionally either named ``venv`` or ``.venv`` in
+* Contained in a directory, conventionally named ``.venv`` or ``venv`` in
the project directory, or under a container directory for lots of virtual
environments, such as ``~/.virtualenvs``.
* Not checked into source control systems such as Git.
* Considered as disposable -- it should be simple to delete and recreate it from
- scratch. You don't place any project code in the environment
+ scratch. You don't place any project code in the environment.
* Not considered as movable or copyable -- you just recreate the same
environment in the target location.
@@ -56,12 +56,132 @@ See :pep:`405` for more background on Python virtual environments.
`Python Packaging User Guide: Creating and using virtual environments
`__
-.. include:: ../includes/wasm-ios-notavail.rst
+.. include:: ../includes/wasm-mobile-notavail.rst
Creating virtual environments
-----------------------------
-.. include:: /using/venv-create.inc
+:ref:`Virtual environments ` are created by executing the ``venv``
+module:
+
+.. code-block:: shell
+
+ python -m venv /path/to/new/virtual/environment
+
+This creates the target directory (including parent directories as needed)
+and places a :file:`pyvenv.cfg` file in it with a ``home`` key
+pointing to the Python installation from which the command was run.
+It also creates a :file:`bin` (or :file:`Scripts` on Windows) subdirectory
+containing a copy or symlink of the Python executable
+(as appropriate for the platform or arguments used at environment creation time).
+It also creates a :file:`lib/pythonX.Y/site-packages` subdirectory
+(on Windows, this is :file:`Lib\site-packages`).
+If an existing directory is specified, it will be re-used.
+
+.. versionchanged:: 3.5
+ The use of ``venv`` is now recommended for creating virtual environments.
+
+.. deprecated-removed:: 3.6 3.8
+ :program:`pyvenv` was the recommended tool for creating virtual environments
+ for Python 3.3 and 3.4, and replaced in 3.5 by executing ``venv`` directly.
+
+.. highlight:: none
+
+On Windows, invoke the ``venv`` command as follows:
+
+.. code-block:: ps1con
+
+ PS> python -m venv C:\path\to\new\virtual\environment
+
+The command, if run with ``-h``, will show the available options::
+
+ usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear]
+ [--upgrade] [--without-pip] [--prompt PROMPT] [--upgrade-deps]
+ [--without-scm-ignore-files]
+ ENV_DIR [ENV_DIR ...]
+
+ Creates virtual Python environments in one or more target directories.
+
+ positional arguments:
+ ENV_DIR A directory to create the environment in.
+
+ options:
+ -h, --help show this help message and exit
+ --system-site-packages
+ Give the virtual environment access to the system
+ site-packages dir.
+ --symlinks Try to use symlinks rather than copies, when
+ symlinks are not the default for the platform.
+ --copies Try to use copies rather than symlinks, even when
+ symlinks are the default for the platform.
+ --clear Delete the contents of the environment directory
+ if it already exists, before environment creation.
+ --upgrade Upgrade the environment directory to use this
+ version of Python, assuming Python has been
+ upgraded in-place.
+ --without-pip Skips installing or upgrading pip in the virtual
+ environment (pip is bootstrapped by default)
+ --prompt PROMPT Provides an alternative prompt prefix for this
+ environment.
+ --upgrade-deps Upgrade core dependencies (pip) to the latest
+ version in PyPI
+ --without-scm-ignore-files
+ Skips adding SCM ignore files to the environment
+ directory (Git is supported by default).
+
+ Once an environment has been created, you may wish to activate it, e.g. by
+ sourcing an activate script in its bin directory.
+
+
+.. versionchanged:: 3.4
+ Installs pip by default, added the ``--without-pip`` and ``--copies``
+ options.
+
+.. versionchanged:: 3.4
+ In earlier versions, if the target directory already existed, an error was
+ raised, unless the ``--clear`` or ``--upgrade`` option was provided.
+
+.. versionchanged:: 3.9
+ Add ``--upgrade-deps`` option to upgrade pip + setuptools to the latest on PyPI.
+
+.. versionchanged:: 3.12
+
+ ``setuptools`` is no longer a core venv dependency.
+
+.. versionchanged:: 3.13
+
+ Added the ``--without-scm-ignore-files`` option.
+.. versionchanged:: 3.13
+ ``venv`` now creates a :file:`.gitignore` file for Git by default.
+
+.. note::
+ While symlinks are supported on Windows, they are not recommended. Of
+ particular note is that double-clicking ``python.exe`` in File Explorer
+ will resolve the symlink eagerly and ignore the virtual environment.
+
+.. note::
+ On Microsoft Windows, it may be required to enable the ``Activate.ps1``
+ script by setting the execution policy for the user. You can do this by
+ issuing the following PowerShell command:
+
+ .. code-block:: powershell
+
+ PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
+
+ See `About Execution Policies
+ `_
+ for more information.
+
+The created :file:`pyvenv.cfg` file also includes the
+``include-system-site-packages`` key, set to ``true`` if ``venv`` is
+run with the ``--system-site-packages`` option, ``false`` otherwise.
+
+Unless the ``--without-pip`` option is given, :mod:`ensurepip` will be
+invoked to bootstrap ``pip`` into the virtual environment.
+
+Multiple paths can be given to ``venv``, in which case an identical virtual
+environment will be created, according to the given options, at each provided
+path.
.. _venv-explanation:
@@ -117,7 +237,7 @@ should be runnable without activating it.
In order to achieve this, scripts installed into virtual environments have
a "shebang" line which points to the environment's Python interpreter,
-i.e. :samp:`#!/{}/bin/python`.
+:samp:`#!/{}/bin/python`.
This means that the script will run with that interpreter regardless of the
value of :envvar:`PATH`. On Windows, "shebang" line processing is supported if
you have the :ref:`launcher` installed. Thus, double-clicking an installed
@@ -168,31 +288,31 @@ creation according to their needs, the :class:`EnvBuilder` class.
The :class:`EnvBuilder` class accepts the following keyword arguments on
instantiation:
- * ``system_site_packages`` -- a Boolean value indicating that the system Python
+ * *system_site_packages* -- a boolean value indicating that the system Python
site-packages should be available to the environment (defaults to ``False``).
- * ``clear`` -- a Boolean value which, if true, will delete the contents of
+ * *clear* -- a boolean value which, if true, will delete the contents of
any existing target directory, before creating the environment.
- * ``symlinks`` -- a Boolean value indicating whether to attempt to symlink the
+ * *symlinks* -- a boolean value indicating whether to attempt to symlink the
Python binary rather than copying.
- * ``upgrade`` -- a Boolean value which, if true, will upgrade an existing
+ * *upgrade* -- a boolean value which, if true, will upgrade an existing
environment with the running Python - for use when that Python has been
upgraded in-place (defaults to ``False``).
- * ``with_pip`` -- a Boolean value which, if true, ensures pip is
+ * *with_pip* -- a boolean value which, if true, ensures pip is
installed in the virtual environment. This uses :mod:`ensurepip` with
the ``--default-pip`` option.
- * ``prompt`` -- a String to be used after virtual environment is activated
+ * *prompt* -- a string to be used after virtual environment is activated
(defaults to ``None`` which means directory name of the environment would
be used). If the special string ``"."`` is provided, the basename of the
current directory is used as the prompt.
- * ``upgrade_deps`` -- Update the base venv modules to the latest on PyPI
+ * *upgrade_deps* -- Update the base venv modules to the latest on PyPI
- * ``scm_ignore_files`` -- Create ignore files based for the specified source
+ * *scm_ignore_files* -- Create ignore files based for the specified source
control managers (SCM) in the iterable. Support is defined by having a
method named ``create_{scm}_ignore_file``. The only value supported by
default is ``"git"`` via :meth:`create_git_ignore_file`.
@@ -210,10 +330,7 @@ creation according to their needs, the :class:`EnvBuilder` class.
.. versionchanged:: 3.13
Added the ``scm_ignore_files`` parameter
- Creators of third-party virtual environment tools will be free to use the
- provided :class:`EnvBuilder` class as a base class.
-
- The returned env-builder is an object which has a method, ``create``:
+ :class:`EnvBuilder` may be used as a base class.
.. method:: create(env_dir)
@@ -313,14 +430,14 @@ creation according to their needs, the :class:`EnvBuilder` class.
.. method:: upgrade_dependencies(context)
- Upgrades the core venv dependency packages (currently ``pip``)
+ Upgrades the core venv dependency packages (currently :pypi:`pip`)
in the environment. This is done by shelling out to the
``pip`` executable in the environment.
.. versionadded:: 3.9
.. versionchanged:: 3.12
- ``setuptools`` is no longer a core venv dependency.
+ :pypi:`setuptools` is no longer a core venv dependency.
.. method:: post_setup(context)
@@ -328,25 +445,15 @@ creation according to their needs, the :class:`EnvBuilder` class.
implementations to pre-install packages in the virtual environment or
perform other post-creation steps.
- .. versionchanged:: 3.7.2
- Windows now uses redirector scripts for ``python[w].exe`` instead of
- copying the actual binaries. In 3.7.2 only :meth:`setup_python` does
- nothing unless running from a build in the source tree.
-
- .. versionchanged:: 3.7.3
- Windows copies the redirector scripts as part of :meth:`setup_python`
- instead of :meth:`setup_scripts`. This was not the case in 3.7.2.
- When using symlinks, the original executables will be linked.
-
- In addition, :class:`EnvBuilder` provides this utility method that can be
- called from :meth:`setup_scripts` or :meth:`post_setup` in subclasses to
- assist in installing custom scripts into the virtual environment.
-
.. method:: install_scripts(context, path)
+ This method can be
+ called from :meth:`setup_scripts` or :meth:`post_setup` in subclasses to
+ assist in installing custom scripts into the virtual environment.
+
*path* is the path to a directory that should contain subdirectories
- "common", "posix", "nt", each containing scripts destined for the bin
- directory in the environment. The contents of "common" and the
+ ``common``, ``posix``, ``nt``; each containing scripts destined for the
+ ``bin`` directory in the environment. The contents of ``common`` and the
directory corresponding to :data:`os.name` are copied after some text
replacement of placeholders:
@@ -371,10 +478,20 @@ creation according to their needs, the :class:`EnvBuilder` class.
.. method:: create_git_ignore_file(context)
Creates a ``.gitignore`` file within the virtual environment that causes
- the entire directory to be ignored by the ``git`` source control manager.
+ the entire directory to be ignored by the Git source control manager.
.. versionadded:: 3.13
+ .. versionchanged:: 3.7.2
+ Windows now uses redirector scripts for ``python[w].exe`` instead of
+ copying the actual binaries. In 3.7.2 only :meth:`setup_python` does
+ nothing unless running from a build in the source tree.
+
+ .. versionchanged:: 3.7.3
+ Windows copies the redirector scripts as part of :meth:`setup_python`
+ instead of :meth:`setup_scripts`. This was not the case in 3.7.2.
+ When using symlinks, the original executables will be linked.
+
There is also a module-level convenience function:
.. function:: create(env_dir, system_site_packages=False, clear=False, \
@@ -387,16 +504,16 @@ There is also a module-level convenience function:
.. versionadded:: 3.3
.. versionchanged:: 3.4
- Added the ``with_pip`` parameter
+ Added the *with_pip* parameter
.. versionchanged:: 3.6
- Added the ``prompt`` parameter
+ Added the *prompt* parameter
.. versionchanged:: 3.9
- Added the ``upgrade_deps`` parameter
+ Added the *upgrade_deps* parameter
.. versionchanged:: 3.13
- Added the ``scm_ignore_files`` parameter
+ Added the *scm_ignore_files* parameter
An example of extending ``EnvBuilder``
--------------------------------------
diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst
index c66e65abee4..83163cc6882 100644
--- a/Doc/library/warnings.rst
+++ b/Doc/library/warnings.rst
@@ -595,6 +595,9 @@ Available Context Managers
passed to :func:`simplefilter` as if it were called immediately on
entering the context.
+ See :ref:`warning-filter` for the meaning of the *category* and *lineno*
+ parameters.
+
.. note::
The :class:`catch_warnings` manager works by replacing and
diff --git a/Doc/library/wave.rst b/Doc/library/wave.rst
index 89664693cc8..36c2bde87fb 100644
--- a/Doc/library/wave.rst
+++ b/Doc/library/wave.rst
@@ -46,8 +46,8 @@ The :mod:`wave` module defines the following function and exception:
the file object.
The :func:`.open` function may be used in a :keyword:`with` statement. When
- the :keyword:`!with` block completes, the :meth:`Wave_read.close()` or
- :meth:`Wave_write.close()` method is called.
+ the :keyword:`!with` block completes, the :meth:`Wave_read.close` or
+ :meth:`Wave_write.close` method is called.
.. versionchanged:: 3.4
Added support for unseekable files.
diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst
index d6e062df945..2a25ed045c6 100644
--- a/Doc/library/weakref.rst
+++ b/Doc/library/weakref.rst
@@ -197,7 +197,7 @@ See :ref:`__slots__ documentation ` for details.
>>> del k1 # d = {k2: 2}
.. versionchanged:: 3.9
- Added support for ``|`` and ``|=`` operators, specified in :pep:`584`.
+ Added support for ``|`` and ``|=`` operators, as specified in :pep:`584`.
:class:`WeakKeyDictionary` objects have an additional method that
exposes the internal references directly. The references are not guaranteed to
diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst
index 334f21f01c1..2d19c514ce4 100644
--- a/Doc/library/webbrowser.rst
+++ b/Doc/library/webbrowser.rst
@@ -51,7 +51,7 @@ The options are, naturally, mutually exclusive. Usage example::
python -m webbrowser -t "https://www.python.org"
-.. include:: ../includes/wasm-notavail.rst
+.. availability:: not WASI, not Android.
The following exception is defined:
@@ -72,6 +72,8 @@ The following functions are defined:
(note that under many window managers this will occur regardless of the
setting of this variable).
+ Returns ``True`` if a browser was successfully launched, ``False`` otherwise.
+
Note that on some platforms, trying to open a filename using this function,
may work and start the operating system's associated program. However, this
is neither supported nor portable.
@@ -84,11 +86,16 @@ The following functions are defined:
Open *url* in a new window of the default browser, if possible, otherwise, open
*url* in the only browser window.
+ Returns ``True`` if a browser was successfully launched, ``False`` otherwise.
+
+
.. function:: open_new_tab(url)
Open *url* in a new page ("tab") of the default browser, if possible, otherwise
equivalent to :func:`open_new`.
+ Returns ``True`` if a browser was successfully launched, ``False`` otherwise.
+
.. function:: get(using=None)
diff --git a/Doc/library/wsgiref.rst b/Doc/library/wsgiref.rst
index e46730f1716..8d4c5eb6600 100644
--- a/Doc/library/wsgiref.rst
+++ b/Doc/library/wsgiref.rst
@@ -783,8 +783,8 @@ in :pep:`3333`.
.. class:: StartResponse()
- A :class:`typing.Protocol` describing `start_response()
- `_
+ A :class:`typing.Protocol` describing :pep:`start_response()
+ <3333#the-start-response-callable>`
callables (:pep:`3333`).
.. data:: WSGIEnvironment
@@ -797,18 +797,18 @@ in :pep:`3333`.
.. class:: InputStream()
- A :class:`typing.Protocol` describing a `WSGI Input Stream
- `_.
+ A :class:`typing.Protocol` describing a :pep:`WSGI Input Stream
+ <3333#input-and-error-streams>`.
.. class:: ErrorStream()
- A :class:`typing.Protocol` describing a `WSGI Error Stream
- `_.
+ A :class:`typing.Protocol` describing a :pep:`WSGI Error Stream
+ <3333#input-and-error-streams>`.
.. class:: FileWrapper()
- A :class:`typing.Protocol` describing a `file wrapper
- `_.
+ A :class:`typing.Protocol` describing a :pep:`file wrapper
+ <3333#optional-platform-specific-file-handling>`.
See :class:`wsgiref.util.FileWrapper` for a concrete implementation of this
protocol.
diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst
index 4c1e7bd7e67..1daf6628013 100644
--- a/Doc/library/xml.etree.elementtree.rst
+++ b/Doc/library/xml.etree.elementtree.rst
@@ -874,6 +874,7 @@ Element Objects
.. module:: xml.etree.ElementTree
:noindex:
+ :no-index:
.. class:: Element(tag, attrib={}, **extra)
@@ -970,7 +971,7 @@ Element Objects
.. method:: extend(subelements)
- Appends *subelements* from a sequence object with zero or more elements.
+ Appends *subelements* from an iterable of elements.
Raises :exc:`TypeError` if a subelement is not an :class:`Element`.
.. versionadded:: 3.2
@@ -1374,7 +1375,7 @@ XMLParser Objects
.. versionchanged:: 3.8
Parameters are now :ref:`keyword-only `.
- The *html* argument no longer supported.
+ The *html* argument is no longer supported.
.. method:: close()
diff --git a/Doc/library/xmlrpc.client.rst b/Doc/library/xmlrpc.client.rst
index 614fb19d1f5..c57f433e6ef 100644
--- a/Doc/library/xmlrpc.client.rst
+++ b/Doc/library/xmlrpc.client.rst
@@ -165,7 +165,7 @@ between conformable Python objects and XML on the wire.
A good description of XML-RPC operation and client software in several languages.
Contains pretty much everything an XML-RPC client developer needs to know.
- `XML-RPC Introspection `_
+ `XML-RPC Introspection `_
Describes the XML-RPC protocol extension for introspection.
`XML-RPC Specification `_
diff --git a/Doc/library/zipapp.rst b/Doc/library/zipapp.rst
index cf561b454e9..cdaba07ab46 100644
--- a/Doc/library/zipapp.rst
+++ b/Doc/library/zipapp.rst
@@ -332,7 +332,7 @@ Formally, the Python zip application format is therefore:
interpreter name, and then a newline (``b'\n'``) character. The interpreter
name can be anything acceptable to the OS "shebang" processing, or the Python
launcher on Windows. The interpreter should be encoded in UTF-8 on Windows,
- and in :func:`sys.getfilesystemencoding()` on POSIX.
+ and in :func:`sys.getfilesystemencoding` on POSIX.
2. Standard zipfile data, as generated by the :mod:`zipfile` module. The
zipfile content *must* include a file called ``__main__.py`` (which must be
in the "root" of the zipfile - i.e., it cannot be in a subdirectory). The
diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst
index 8181b975951..c7e43ef7739 100644
--- a/Doc/reference/compound_stmts.rst
+++ b/Doc/reference/compound_stmts.rst
@@ -841,7 +841,7 @@ A literal pattern corresponds to most
: | "None"
: | "True"
: | "False"
- : | `signed_number`: NUMBER | "-" NUMBER
+ signed_number: ["-"] NUMBER
The rule ``strings`` and the token ``NUMBER`` are defined in the
:doc:`standard Python grammar <./grammar>`. Triple-quoted strings are
@@ -1217,9 +1217,10 @@ A function definition defines a user-defined function object (see section
: | `parameter_list_no_posonly`
parameter_list_no_posonly: `defparameter` ("," `defparameter`)* ["," [`parameter_list_starargs`]]
: | `parameter_list_starargs`
- parameter_list_starargs: "*" [`parameter`] ("," `defparameter`)* ["," ["**" `parameter` [","]]]
+ parameter_list_starargs: "*" [`star_parameter`] ("," `defparameter`)* ["," ["**" `parameter` [","]]]
: | "**" `parameter` [","]
parameter: `identifier` [":" `expression`]
+ star_parameter: `identifier` [":" ["*"] `expression`]
defparameter: `parameter` ["=" `expression`]
funcname: `identifier`
@@ -1326,7 +1327,8 @@ and may only be passed by positional arguments.
Parameters may have an :term:`annotation ` of the form "``: expression``"
following the parameter name. Any parameter may have an annotation, even those of the form
-``*identifier`` or ``**identifier``. Functions may have "return" annotation of
+``*identifier`` or ``**identifier``. (As a special case, parameters of the form
+``*identifier`` may have an annotation "``: *expression``".) Functions may have "return" annotation of
the form "``-> expression``" after the parameter list. These annotations can be
any valid Python expression. The presence of annotations does not change the
semantics of a function. The annotation values are available as values of
@@ -1337,6 +1339,10 @@ enables postponed evaluation. Otherwise, they are evaluated when the function
definition is executed. In this case annotations may be evaluated in
a different order than they appear in the source code.
+.. versionchanged:: 3.11
+ Parameters of the form "``*identifier``" may have an annotation
+ "``: *expression``". See :pep:`646`.
+
.. index:: pair: lambda; expression
It is also possible to create anonymous functions (functions not bound to a
@@ -1422,7 +1428,7 @@ dictionary. The class name is bound to this class object in the original local
namespace.
The order in which attributes are defined in the class body is preserved
-in the new class's ``__dict__``. Note that this is reliable only right
+in the new class's :attr:`~type.__dict__`. Note that this is reliable only right
after the class is created and only for classes that were defined using
the definition syntax.
@@ -1453,8 +1459,8 @@ decorators. The result is then bound to the class name.
A list of :ref:`type parameters ` may be given in square brackets
immediately after the class's name.
This indicates to static type checkers that the class is generic. At runtime,
-the type parameters can be retrieved from the class's ``__type_params__``
-attribute. See :ref:`generic-classes` for more.
+the type parameters can be retrieved from the class's
+:attr:`~type.__type_params__` attribute. See :ref:`generic-classes` for more.
.. versionchanged:: 3.12
Type parameter lists are new in Python 3.12.
@@ -1667,8 +1673,8 @@ with more precision. The scope of type parameters is modeled with a special
function (technically, an :ref:`annotation scope `) that
wraps the creation of the generic object.
-Generic functions, classes, and type aliases have a :attr:`!__type_params__`
-attribute listing their type parameters.
+Generic functions, classes, and type aliases have a
+:attr:`~definition.__type_params__` attribute listing their type parameters.
Type parameters come in three kinds:
@@ -1892,5 +1898,5 @@ like ``TYPE_PARAMS_OF_ListOrSet`` are not actually bound at runtime.
therefore the function's :term:`docstring`.
.. [#] A string literal appearing as the first statement in the class body is
- transformed into the namespace's ``__doc__`` item and therefore the class's
- :term:`docstring`.
+ transformed into the namespace's :attr:`~type.__doc__` item and therefore
+ the class's :term:`docstring`.
diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst
index 527eac6f62c..57d9b286c6c 100644
--- a/Doc/reference/datamodel.rst
+++ b/Doc/reference/datamodel.rst
@@ -106,12 +106,16 @@ that mutable object is changed.
Types affect almost all aspects of object behavior. Even the importance of
object identity is affected in some sense: for immutable types, operations that
compute new values may actually return a reference to any existing object with
-the same type and value, while for mutable objects this is not allowed. E.g.,
-after ``a = 1; b = 1``, ``a`` and ``b`` may or may not refer to the same object
-with the value one, depending on the implementation, but after ``c = []; d =
-[]``, ``c`` and ``d`` are guaranteed to refer to two different, unique, newly
-created empty lists. (Note that ``c = d = []`` assigns the same object to both
-``c`` and ``d``.)
+the same type and value, while for mutable objects this is not allowed.
+For example, after ``a = 1; b = 1``, *a* and *b* may or may not refer to
+the same object with the value one, depending on the implementation.
+This is because :class:`int` is an immutable type, so the reference to ``1``
+can be reused. This behaviour depends on the implementation used, so should
+not be relied upon, but is something to be aware of when making use of object
+identity tests.
+However, after ``c = []; d = []``, *c* and *d* are guaranteed to refer to two
+different, unique, newly created empty lists. (Note that ``e = f = []`` assigns
+the *same* object to both *e* and *f*.)
.. _types:
@@ -215,7 +219,7 @@ properties:
* A sign is shown only when the number is negative.
-Python distinguishes between integers, floating point numbers, and complex
+Python distinguishes between integers, floating-point numbers, and complex
numbers:
@@ -259,18 +263,18 @@ Booleans (:class:`bool`)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. index::
- pair: object; floating point
- pair: floating point; number
+ pair: object; floating-point
+ pair: floating-point; number
pair: C; language
pair: Java; language
-These represent machine-level double precision floating point numbers. You are
+These represent machine-level double precision floating-point numbers. You are
at the mercy of the underlying machine architecture (and C or Java
implementation) for the accepted range and handling of overflow. Python does not
-support single-precision floating point numbers; the savings in processor and
+support single-precision floating-point numbers; the savings in processor and
memory usage that are usually the reason for using these are dwarfed by the
overhead of using objects in Python, so there is no reason to complicate the
-language with two kinds of floating point numbers.
+language with two kinds of floating-point numbers.
:class:`numbers.Complex` (:class:`complex`)
@@ -281,7 +285,7 @@ language with two kinds of floating point numbers.
pair: complex; number
These represent complex numbers as a pair of machine-level double precision
-floating point numbers. The same caveats apply as for floating point numbers.
+floating-point numbers. The same caveats apply as for floating-point numbers.
The real and imaginary parts of a complex number ``z`` can be retrieved through
the read-only attributes ``z.real`` and ``z.imag``.
@@ -373,7 +377,7 @@ Bytes
A bytes object is an immutable array. The items are 8-bit bytes,
represented by integers in the range 0 <= x < 256. Bytes literals
- (like ``b'abc'``) and the built-in :func:`bytes()` constructor
+ (like ``b'abc'``) and the built-in :func:`bytes` constructor
can be used to create bytes objects. Also, bytes objects can be
decoded to strings via the :meth:`~bytes.decode` method.
@@ -492,7 +496,7 @@ in the same order they were added sequentially over the dictionary.
Replacing an existing key does not change the order, however removing a key
and re-inserting it will add it to the end instead of keeping its old place.
-Dictionaries are mutable; they can be created by the ``{...}`` notation (see
+Dictionaries are mutable; they can be created by the ``{}`` notation (see
section :ref:`dict`).
.. index::
@@ -587,7 +591,6 @@ Most of these attributes check the type of the assigned value:
* - .. attribute:: function.__doc__
- The function's documentation string, or ``None`` if unavailable.
- Not inherited by subclasses.
* - .. attribute:: function.__name__
- The function's name.
@@ -727,14 +730,7 @@ When an instance method object is derived from a :class:`classmethod` object, th
itself, so that calling either ``x.f(1)`` or ``C.f(1)`` is equivalent to
calling ``f(C,1)`` where ``f`` is the underlying function.
-Note that the transformation from :ref:`function object `
-to instance method
-object happens each time the attribute is retrieved from the instance. In
-some cases, a fruitful optimization is to assign the attribute to a local
-variable and call that local variable. Also notice that this
-transformation only happens for user-defined functions; other callable
-objects (and all non-callable objects) are retrieved without
-transformation. It is also important to note that user-defined functions
+It is important to note that user-defined functions
which are attributes of a class instance are not converted to bound
methods; this *only* happens when the function is an attribute of the
class.
@@ -835,6 +831,7 @@ this case, the special read-only attribute :attr:`!__self__` is set to the objec
denoted by *alist*. (The attribute has the same semantics as it does with
:attr:`other instance methods `.)
+.. _classes:
Classes
^^^^^^^
@@ -920,6 +917,8 @@ namespace as a dictionary object.
or keep the module around while using its dictionary directly.
+.. _class-attrs-and-methods:
+
Custom classes
--------------
@@ -962,6 +961,9 @@ of a base class.
A class object can be called (see above) to yield a class instance (see below).
+Special attributes
+^^^^^^^^^^^^^^^^^^
+
.. index::
single: __name__ (class attribute)
single: __module__ (class attribute)
@@ -973,42 +975,100 @@ A class object can be called (see above) to yield a class instance (see below).
single: __static_attributes__ (class attribute)
single: __firstlineno__ (class attribute)
-Special attributes:
+.. list-table::
+ :header-rows: 1
- :attr:`~definition.__name__`
- The class name.
+ * - Attribute
+ - Meaning
- :attr:`__module__`
- The name of the module in which the class was defined.
+ * - .. attribute:: type.__name__
+ - The class's name.
+ See also: :attr:`__name__ attributes `.
- :attr:`~object.__dict__`
- The dictionary containing the class's namespace.
+ * - .. attribute:: type.__qualname__
+ - The class's :term:`qualified name`.
+ See also: :attr:`__qualname__ attributes `.
- :attr:`~class.__bases__`
- A tuple containing the base classes, in the order of
- their occurrence in the base class list.
+ * - .. attribute:: type.__module__
+ - The name of the module in which the class was defined.
- :attr:`__doc__`
- The class's documentation string, or ``None`` if undefined.
+ * - .. attribute:: type.__dict__
+ - A :class:`mapping proxy `
+ providing a read-only view of the class's namespace.
+ See also: :attr:`__dict__ attributes `.
- :attr:`__annotations__`
- A dictionary containing
- :term:`variable annotations `
- collected during class body execution. For best practices on
- working with :attr:`__annotations__`, please see
- :ref:`annotations-howto`.
+ * - .. attribute:: type.__bases__
+ - A :class:`tuple` containing the class's bases.
+ In most cases, for a class defined as ``class X(A, B, C)``,
+ ``X.__bases__`` will be exactly equal to ``(A, B, C)``.
+
+ * - .. attribute:: type.__doc__
+ - The class's documentation string, or ``None`` if undefined.
+ Not inherited by subclasses.
+
+ * - .. attribute:: type.__annotations__
+ - A dictionary containing
+ :term:`variable annotations `
+ collected during class body execution. For best practices on working
+ with :attr:`!__annotations__`, please see :ref:`annotations-howto`.
+
+ .. caution::
+
+ Accessing the :attr:`!__annotations__` attribute of a class
+ object directly may yield incorrect results in the presence of
+ metaclasses. In addition, the attribute may not exist for
+ some classes. Use :func:`inspect.get_annotations` to
+ retrieve class annotations safely.
- :attr:`__type_params__`
- A tuple containing the :ref:`type parameters ` of
- a :ref:`generic class `.
+ * - .. attribute:: type.__type_params__
+ - A :class:`tuple` containing the :ref:`type parameters ` of
+ a :ref:`generic class `.
+
+ .. versionadded:: 3.12
+
+ * - .. attribute:: type.__static_attributes__
+ - A :class:`tuple` containing names of attributes of this class which are
+ assigned through ``self.X`` from any function in its body.
+
+ .. versionadded:: 3.13
+
+ * - .. attribute:: type.__firstlineno__
+ - The line number of the first line of the class definition,
+ including decorators.
+ Setting the :attr:`__module__` attribute removes the
+ :attr:`!__firstlineno__` item from the type's dictionary.
+
+ .. versionadded:: 3.13
+
+ * - .. attribute:: type.__mro__
+ - The :class:`tuple` of classes that are considered when looking for
+ base classes during method resolution.
+
+
+Special methods
+^^^^^^^^^^^^^^^
+
+In addition to the special attributes described above, all Python classes also
+have the following two methods available:
+
+.. method:: type.mro
+
+ This method can be overridden by a metaclass to customize the method
+ resolution order for its instances. It is called at class instantiation,
+ and its result is stored in :attr:`~type.__mro__`.
+
+.. method:: type.__subclasses__
- :attr:`~class.__static_attributes__`
- A tuple containing names of attributes of this class which are accessed
- through ``self.X`` from any function in its body.
+ Each class keeps a list of weak references to its immediate subclasses. This
+ method returns a list of all those references still alive. The list is in
+ definition order. Example:
- :attr:`__firstlineno__`
- The line number of the first line of the class definition, including decorators.
+ .. doctest::
+ >>> class A: pass
+ >>> class B(A): pass
+ >>> A.__subclasses__()
+ []
Class instances
---------------
@@ -1048,12 +1108,22 @@ dictionary directly.
Class instances can pretend to be numbers, sequences, or mappings if they have
methods with certain special names. See section :ref:`specialnames`.
+Special attributes
+^^^^^^^^^^^^^^^^^^
+
.. index::
single: __dict__ (instance attribute)
single: __class__ (instance attribute)
-Special attributes: :attr:`~object.__dict__` is the attribute dictionary;
-:attr:`~instance.__class__` is the instance's class.
+.. attribute:: object.__class__
+
+ The class to which a class instance belongs.
+
+.. attribute:: object.__dict__
+
+ A dictionary or other mapping object used to store an object's (writable)
+ attributes. Not all instances have a :attr:`!__dict__` attribute; see the
+ section on :ref:`slots` for more details.
I/O objects (also known as file objects)
@@ -2283,9 +2353,9 @@ Notes on using *__slots__*:
* The action of a *__slots__* declaration is not limited to the class
where it is defined. *__slots__* declared in parents are available in
- child classes. However, child subclasses will get a :attr:`~object.__dict__` and
- *__weakref__* unless they also define *__slots__* (which should only
- contain names of any *additional* slots).
+ child classes. However, instances of a child subclass will get a
+ :attr:`~object.__dict__` and *__weakref__* unless the subclass also defines
+ *__slots__* (which should only contain names of any *additional* slots).
* If a class defines a slot also defined in a base class, the instance variable
defined by the base class slot is inaccessible (except by retrieving its
@@ -2304,7 +2374,7 @@ Notes on using *__slots__*:
to provide per-attribute docstrings that will be recognised by
:func:`inspect.getdoc` and displayed in the output of :func:`help`.
-* :attr:`~instance.__class__` assignment works only if both classes have the
+* :attr:`~object.__class__` assignment works only if both classes have the
same *__slots__*.
* :ref:`Multiple inheritance ` with multiple slotted parent
@@ -2570,7 +2640,7 @@ in the local namespace as the defined class.
When a new class is created by ``type.__new__``, the object provided as the
namespace parameter is copied to a new ordered mapping and the original
object is discarded. The new copy is wrapped in a read-only proxy, which
-becomes the :attr:`~object.__dict__` attribute of the class object.
+becomes the :attr:`~type.__dict__` attribute of the class object.
.. seealso::
@@ -2598,14 +2668,14 @@ order to allow the addition of Abstract Base Classes (ABCs) as "virtual base
classes" to any class or type (including built-in types), including other
ABCs.
-.. method:: class.__instancecheck__(self, instance)
+.. method:: type.__instancecheck__(self, instance)
Return true if *instance* should be considered a (direct or indirect)
instance of *class*. If defined, called to implement ``isinstance(instance,
class)``.
-.. method:: class.__subclasscheck__(self, subclass)
+.. method:: type.__subclasscheck__(self, subclass)
Return true if *subclass* should be considered a (direct or indirect)
subclass of *class*. If defined, called to implement ``issubclass(subclass,
@@ -2621,8 +2691,8 @@ case the instance is itself a class.
:pep:`3119` - Introducing Abstract Base Classes
Includes the specification for customizing :func:`isinstance` and
- :func:`issubclass` behavior through :meth:`~class.__instancecheck__` and
- :meth:`~class.__subclasscheck__`, with motivation for this functionality
+ :func:`issubclass` behavior through :meth:`~type.__instancecheck__` and
+ :meth:`~type.__subclasscheck__`, with motivation for this functionality
in the context of adding Abstract Base Classes (see the :mod:`abc`
module) to the language.
diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst
index f24e1537af3..c6d98fc2e70 100644
--- a/Doc/reference/executionmodel.rst
+++ b/Doc/reference/executionmodel.rst
@@ -225,8 +225,8 @@ Annotation scopes differ from function scopes in the following ways:
statements in inner scopes. This includes only type parameters, as no other
syntactic elements that can appear within annotation scopes can introduce new names.
* While annotation scopes have an internal name, that name is not reflected in the
- :term:`__qualname__ ` of objects defined within the scope.
- Instead, the :attr:`!__qualname__`
+ :term:`qualified name` of objects defined within the scope.
+ Instead, the :attr:`~definition.__qualname__`
of such objects is as if the object were defined in the enclosing scope.
.. versionadded:: 3.12
diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst
index 00b57effd3e..ab72ad49d04 100644
--- a/Doc/reference/expressions.rst
+++ b/Doc/reference/expressions.rst
@@ -33,7 +33,7 @@ implementation for built-in types works as follows:
* If either argument is a complex number, the other is converted to complex;
-* otherwise, if either argument is a floating point number, the other is
+* otherwise, if either argument is a floating-point number, the other is
converted to floating point;
* otherwise, both must be integers and no conversion is necessary.
@@ -83,18 +83,47 @@ exception.
pair: name; mangling
pair: private; names
-**Private name mangling:** When an identifier that textually occurs in a class
-definition begins with two or more underscore characters and does not end in two
-or more underscores, it is considered a :dfn:`private name` of that class.
-Private names are transformed to a longer form before code is generated for
-them. The transformation inserts the class name, with leading underscores
-removed and a single underscore inserted, in front of the name. For example,
-the identifier ``__spam`` occurring in a class named ``Ham`` will be transformed
-to ``_Ham__spam``. This transformation is independent of the syntactical
-context in which the identifier is used. If the transformed name is extremely
-long (longer than 255 characters), implementation defined truncation may happen.
-If the class name consists only of underscores, no transformation is done.
+Private name mangling
+^^^^^^^^^^^^^^^^^^^^^
+When an identifier that textually occurs in a class definition begins with two
+or more underscore characters and does not end in two or more underscores, it
+is considered a :dfn:`private name` of that class.
+
+.. seealso::
+
+ The :ref:`class specifications `.
+
+More precisely, private names are transformed to a longer form before code is
+generated for them. If the transformed name is longer than 255 characters,
+implementation-defined truncation may happen.
+
+The transformation is independent of the syntactical context in which the
+identifier is used but only the following private identifiers are mangled:
+
+- Any name used as the name of a variable that is assigned or read or any
+ name of an attribute being accessed.
+
+ The :attr:`~definition.__name__` attribute of nested functions, classes, and
+ type aliases is however not mangled.
+
+- The name of imported modules, e.g., ``__spam`` in ``import __spam``.
+ If the module is part of a package (i.e., its name contains a dot),
+ the name is *not* mangled, e.g., the ``__foo`` in ``import __foo.bar``
+ is not mangled.
+
+- The name of an imported member, e.g., ``__f`` in ``from spam import __f``.
+
+The transformation rule is defined as follows:
+
+- The class name, with leading underscores removed and a single leading
+ underscore inserted, is inserted in front of the identifier, e.g., the
+ identifier ``__spam`` occurring in a class named ``Foo``, ``_Foo`` or
+ ``__Foo`` is transformed to ``_Foo__spam``.
+
+- If the class name consists only of underscores, the transformation is the
+ identity, e.g., the identifier ``__spam`` occurring in a class named ``_``
+ or ``__`` is left as is.
.. _atom-literals:
@@ -110,8 +139,8 @@ Python supports string and bytes literals and various numeric literals:
: | `integer` | `floatnumber` | `imagnumber`
Evaluation of a literal yields an object of the given type (string, bytes,
-integer, floating point number, complex number) with the given value. The value
-may be approximated in the case of floating point and imaginary (complex)
+integer, floating-point number, complex number) with the given value. The value
+may be approximated in the case of floating-point and imaginary (complex)
literals. See section :ref:`literals` for details.
.. index::
@@ -218,10 +247,12 @@ A comprehension in an :keyword:`!async def` function may consist of either a
:keyword:`!for` or :keyword:`!async for` clause following the leading
expression, may contain additional :keyword:`!for` or :keyword:`!async for`
clauses, and may also use :keyword:`await` expressions.
-If a comprehension contains either :keyword:`!async for` clauses or
-:keyword:`!await` expressions or other asynchronous comprehensions it is called
-an :dfn:`asynchronous comprehension`. An asynchronous comprehension may
-suspend the execution of the coroutine function in which it appears.
+
+If a comprehension contains :keyword:`!async for` clauses, or if it contains
+:keyword:`!await` expressions or other asynchronous comprehensions anywhere except
+the iterable expression in the leftmost :keyword:`!for` clause, it is called an
+:dfn:`asynchronous comprehension`. An asynchronous comprehension may suspend the
+execution of the coroutine function in which it appears.
See also :pep:`530`.
.. versionadded:: 3.6
@@ -253,7 +284,7 @@ A list display is a possibly empty series of expressions enclosed in square
brackets:
.. productionlist:: python-grammar
- list_display: "[" [`starred_list` | `comprehension`] "]"
+ list_display: "[" [`flexible_expression_list` | `comprehension`] "]"
A list display yields a new list object, the contents being specified by either
a list of expressions or a comprehension. When a comma-separated list of
@@ -278,7 +309,7 @@ A set display is denoted by curly braces and distinguishable from dictionary
displays by the lack of colons separating keys and values:
.. productionlist:: python-grammar
- set_display: "{" (`starred_list` | `comprehension`) "}"
+ set_display: "{" (`flexible_expression_list` | `comprehension`) "}"
A set display yields a new mutable set object, the contents being specified by
either a sequence of expressions or a comprehension. When a comma-separated
@@ -423,7 +454,7 @@ Yield expressions
.. productionlist:: python-grammar
yield_atom: "(" `yield_expression` ")"
yield_from: "yield" "from" `expression`
- yield_expression: "yield" `expression_list` | `yield_from`
+ yield_expression: "yield" `yield_list` | `yield_from`
The yield expression is used when defining a :term:`generator` function
or an :term:`asynchronous generator` function and
@@ -454,9 +485,9 @@ When a generator function is called, it returns an iterator known as a
generator. That generator then controls the execution of the generator
function. The execution starts when one of the generator's methods is called.
At that time, the execution proceeds to the first yield expression, where it is
-suspended again, returning the value of :token:`~python-grammar:expression_list`
+suspended again, returning the value of :token:`~python-grammar:yield_list`
to the generator's caller,
-or ``None`` if :token:`~python-grammar:expression_list` is omitted.
+or ``None`` if :token:`~python-grammar:yield_list` is omitted.
By suspended, we mean that all local state is
retained, including the current bindings of local variables, the instruction
pointer, the internal evaluation stack, and the state of any exception handling.
@@ -545,7 +576,7 @@ is already executing raises a :exc:`ValueError` exception.
:meth:`~generator.__next__` method, the current yield expression always
evaluates to :const:`None`. The execution then continues to the next yield
expression, where the generator is suspended again, and the value of the
- :token:`~python-grammar:expression_list` is returned to :meth:`__next__`'s
+ :token:`~python-grammar:yield_list` is returned to :meth:`__next__`'s
caller. If the generator exits without yielding another value, a
:exc:`StopIteration` exception is raised.
@@ -664,7 +695,7 @@ how a generator object would be used in a :keyword:`for` statement.
Calling one of the asynchronous generator's methods returns an :term:`awaitable`
object, and the execution starts when this object is awaited on. At that time,
the execution proceeds to the first yield expression, where it is suspended
-again, returning the value of :token:`~python-grammar:expression_list` to the
+again, returning the value of :token:`~python-grammar:yield_list` to the
awaiting coroutine. As with a generator, suspension means that all local state
is retained, including the current bindings of local variables, the instruction
pointer, the internal evaluation stack, and the state of any exception handling.
@@ -728,7 +759,7 @@ which are used to control the execution of a generator function.
asynchronous generator function is resumed with an :meth:`~agen.__anext__`
method, the current yield expression always evaluates to :const:`None` in the
returned awaitable, which when run will continue to the next yield
- expression. The value of the :token:`~python-grammar:expression_list` of the
+ expression. The value of the :token:`~python-grammar:yield_list` of the
yield expression is the value of the :exc:`StopIteration` exception raised by
the completing coroutine. If the asynchronous generator exits without
yielding another value, the awaitable instead raises a
@@ -741,7 +772,7 @@ which are used to control the execution of a generator function.
.. coroutinemethod:: agen.asend(value)
Returns an awaitable which when run resumes the execution of the
- asynchronous generator. As with the :meth:`~generator.send()` method for a
+ asynchronous generator. As with the :meth:`~generator.send` method for a
generator, this "sends" a value into the asynchronous generator function,
and the *value* argument becomes the result of the current yield expression.
The awaitable returned by the :meth:`asend` method will return the next
@@ -861,7 +892,7 @@ will generally select an element from the container. The subscription of a
:ref:`GenericAlias ` object.
.. productionlist:: python-grammar
- subscription: `primary` "[" `expression_list` "]"
+ subscription: `primary` "[" `flexible_expression_list` "]"
When an object is subscripted, the interpreter will evaluate the primary and
the expression list.
@@ -873,9 +904,13 @@ primary is subscripted, the evaluated result of the expression list will be
passed to one of these methods. For more details on when ``__class_getitem__``
is called instead of ``__getitem__``, see :ref:`classgetitem-versus-getitem`.
-If the expression list contains at least one comma, it will evaluate to a
-:class:`tuple` containing the items of the expression list. Otherwise, the
-expression list will evaluate to the value of the list's sole member.
+If the expression list contains at least one comma, or if any of the expressions
+are starred, the expression list will evaluate to a :class:`tuple` containing
+the items of the expression list. Otherwise, the expression list will evaluate
+to the value of the list's sole member.
+
+.. versionchanged:: 3.11
+ Expressions in an expression list may be starred. See :pep:`646`.
For built-in objects, there are two types of objects that support subscription
via :meth:`~object.__getitem__`:
@@ -1211,7 +1246,8 @@ Raising ``0.0`` to a negative power results in a :exc:`ZeroDivisionError`.
Raising a negative number to a fractional power results in a :class:`complex`
number. (In earlier versions it raised a :exc:`ValueError`.)
-This operation can be customized using the special :meth:`~object.__pow__` method.
+This operation can be customized using the special :meth:`~object.__pow__` and
+:meth:`~object.__rpow__` methods.
.. _unary:
@@ -1299,6 +1335,9 @@ This operation can be customized using the special :meth:`~object.__mul__` and
The ``@`` (at) operator is intended to be used for matrix multiplication. No
builtin Python types implement this operator.
+This operation can be customized using the special :meth:`~object.__matmul__` and
+:meth:`~object.__rmatmul__` methods.
+
.. versionadded:: 3.5
.. index::
@@ -1314,8 +1353,10 @@ integer; the result is that of mathematical division with the 'floor' function
applied to the result. Division by zero raises the :exc:`ZeroDivisionError`
exception.
-This operation can be customized using the special :meth:`~object.__truediv__` and
-:meth:`~object.__floordiv__` methods.
+The division operation can be customized using the special :meth:`~object.__truediv__`
+and :meth:`~object.__rtruediv__` methods.
+The floor division operation can be customized using the special
+:meth:`~object.__floordiv__` and :meth:`~object.__rfloordiv__` methods.
.. index::
single: modulo
@@ -1324,7 +1365,7 @@ This operation can be customized using the special :meth:`~object.__truediv__` a
The ``%`` (modulo) operator yields the remainder from the division of the first
argument by the second. The numeric arguments are first converted to a common
type. A zero right argument raises the :exc:`ZeroDivisionError` exception. The
-arguments may be floating point numbers, e.g., ``3.14%0.7`` equals ``0.34``
+arguments may be floating-point numbers, e.g., ``3.14%0.7`` equals ``0.34``
(since ``3.14`` equals ``4*0.7 + 0.34``.) The modulo operator always yields a
result with the same sign as its second operand (or zero); the absolute value of
the result is strictly smaller than the absolute value of the second operand
@@ -1340,11 +1381,12 @@ also overloaded by string objects to perform old-style string formatting (also
known as interpolation). The syntax for string formatting is described in the
Python Library Reference, section :ref:`old-string-formatting`.
-The *modulo* operation can be customized using the special :meth:`~object.__mod__` method.
+The *modulo* operation can be customized using the special :meth:`~object.__mod__`
+and :meth:`~object.__rmod__` methods.
The floor division operator, the modulo operator, and the :func:`divmod`
-function are not defined for complex numbers. Instead, convert to a floating
-point number using the :func:`abs` function if appropriate.
+function are not defined for complex numbers. Instead, convert to a
+floating-point number using the :func:`abs` function if appropriate.
.. index::
single: addition
@@ -1367,7 +1409,8 @@ This operation can be customized using the special :meth:`~object.__add__` and
The ``-`` (subtraction) operator yields the difference of its arguments. The
numeric arguments are first converted to a common type.
-This operation can be customized using the special :meth:`~object.__sub__` method.
+This operation can be customized using the special :meth:`~object.__sub__` and
+:meth:`~object.__rsub__` methods.
.. _shifting:
@@ -1388,8 +1431,10 @@ The shifting operations have lower priority than the arithmetic operations:
These operators accept integers as arguments. They shift the first argument to
the left or right by the number of bits given by the second argument.
-This operation can be customized using the special :meth:`~object.__lshift__` and
-:meth:`~object.__rshift__` methods.
+The left shift operation can be customized using the special :meth:`~object.__lshift__`
+and :meth:`~object.__rlshift__` methods.
+The right shift operation can be customized using the special :meth:`~object.__rshift__`
+and :meth:`~object.__rrshift__` methods.
.. index:: pair: exception; ValueError
@@ -1762,6 +1807,7 @@ returns a boolean value regardless of the type of its argument
single: assignment expression
single: walrus operator
single: named expression
+ pair: assignment; expression
Assignment expressions
======================
@@ -1864,10 +1910,12 @@ Expression lists
single: , (comma); expression list
.. productionlist:: python-grammar
+ starred_expression: ["*"] `or_expr`
+ flexible_expression: `assignment_expression` | `starred_expression`
+ flexible_expression_list: `flexible_expression` ("," `flexible_expression`)* [","]
+ starred_expression_list: `starred_expression` ("," `starred_expression`)* [","]
expression_list: `expression` ("," `expression`)* [","]
- starred_list: `starred_item` ("," `starred_item`)* [","]
- starred_expression: `expression` | (`starred_item` ",")* [`starred_item`]
- starred_item: `assignment_expression` | "*" `or_expr`
+ yield_list: `expression_list` | `starred_expression` "," [`starred_expression_list`]
.. index:: pair: object; tuple
@@ -1888,6 +1936,9 @@ the unpacking.
.. versionadded:: 3.5
Iterable unpacking in expression lists, originally proposed by :pep:`448`.
+.. versionadded:: 3.11
+ Any item in an expression list may be starred. See :pep:`646`.
+
.. index:: pair: trailing; comma
A trailing comma is required only to create a one-item tuple,
diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst
index f8c9724114d..19b8aa05072 100644
--- a/Doc/reference/import.rst
+++ b/Doc/reference/import.rst
@@ -281,7 +281,7 @@ When the named module is not found in :data:`sys.modules`, Python next
searches :data:`sys.meta_path`, which contains a list of meta path finder
objects. These finders are queried in order to see if they know how to handle
the named module. Meta path finders must implement a method called
-:meth:`~importlib.abc.MetaPathFinder.find_spec()` which takes three arguments:
+:meth:`~importlib.abc.MetaPathFinder.find_spec` which takes three arguments:
a name, an import path, and (optionally) a target module. The meta path
finder can use any strategy it wants to determine whether it can handle
the named module or not.
@@ -292,7 +292,7 @@ spec object. If it cannot handle the named module, it returns ``None``. If
a spec, then a :exc:`ModuleNotFoundError` is raised. Any other exceptions
raised are simply propagated up, aborting the import process.
-The :meth:`~importlib.abc.MetaPathFinder.find_spec()` method of meta path
+The :meth:`~importlib.abc.MetaPathFinder.find_spec` method of meta path
finders is called with two or three arguments. The first is the fully
qualified name of the module being imported, for example ``foo.bar.baz``.
The second argument is the path entries to use for the module search. For
@@ -596,6 +596,10 @@ listed below.
Raise :exc:`DeprecationWarning` instead of :exc:`ImportWarning`
when falling back to ``__package__``.
+ .. deprecated-removed:: 3.13 3.15
+ ``__package__`` will cease to be set or taken into consideration
+ by the import system or standard library.
+
.. attribute:: __spec__
@@ -653,6 +657,10 @@ listed below.
It is **strongly** recommended that you rely on :attr:`__spec__`
instead of ``__cached__``.
+ .. deprecated-removed:: 3.13 3.15
+ ``__cached__`` will cease to be set or taken into consideration
+ by the import system or standard library.
+
.. _package-path-rules:
module.__path__
diff --git a/Doc/reference/introduction.rst b/Doc/reference/introduction.rst
index cf186705e6e..b7b70e6be5a 100644
--- a/Doc/reference/introduction.rst
+++ b/Doc/reference/introduction.rst
@@ -74,7 +74,7 @@ PyPy
and a Just in Time compiler. One of the goals of the project is to encourage
experimentation with the language itself by making it easier to modify the
interpreter (since it is written in Python). Additional information is
- available on `the PyPy project's home page `_.
+ available on `the PyPy project's home page `_.
Each of these implementations varies in some way from the language as documented
in this manual, or introduces specific information beyond what's covered in the
diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst
index 41ea89fd234..c2f5f145bb2 100644
--- a/Doc/reference/lexical_analysis.rst
+++ b/Doc/reference/lexical_analysis.rst
@@ -503,11 +503,10 @@ must be expressed with escapes.
single: r"; raw string literal
Both string and bytes literals may optionally be prefixed with a letter ``'r'``
-or ``'R'``; such strings are called :dfn:`raw strings` and treat backslashes as
-literal characters. As a result, in string literals, ``'\U'`` and ``'\u'``
-escapes in raw strings are not treated specially. Given that Python 2.x's raw
-unicode literals behave differently than Python 3.x's the ``'ur'`` syntax
-is not supported.
+or ``'R'``; such constructs are called :dfn:`raw string literals`
+and :dfn:`raw bytes literals` respectively and treat backslashes as
+literal characters. As a result, in raw string literals, ``'\U'`` and ``'\u'``
+escapes are not treated specially.
.. versionadded:: 3.3
The ``'rb'`` prefix of raw bytes literals has been added as a synonym
@@ -879,10 +878,10 @@ Numeric literals
----------------
.. index:: number, numeric literal, integer literal
- floating point literal, hexadecimal literal
+ floating-point literal, hexadecimal literal
octal literal, binary literal, decimal literal, imaginary literal, complex literal
-There are three types of numeric literals: integers, floating point numbers, and
+There are three types of numeric literals: integers, floating-point numbers, and
imaginary numbers. There are no complex literals (complex numbers can be formed
by adding a real number and an imaginary number).
@@ -943,10 +942,10 @@ Some examples of integer literals::
single: _ (underscore); in numeric literal
.. _floating:
-Floating point literals
+Floating-point literals
-----------------------
-Floating point literals are described by the following lexical definitions:
+Floating-point literals are described by the following lexical definitions:
.. productionlist:: python-grammar
floatnumber: `pointfloat` | `exponentfloat`
@@ -958,10 +957,10 @@ Floating point literals are described by the following lexical definitions:
Note that the integer and exponent parts are always interpreted using radix 10.
For example, ``077e010`` is legal, and denotes the same number as ``77e10``. The
-allowed range of floating point literals is implementation-dependent. As in
+allowed range of floating-point literals is implementation-dependent. As in
integer literals, underscores are supported for digit grouping.
-Some examples of floating point literals::
+Some examples of floating-point literals::
3.14 10. .001 1e100 3.14e-10 0e0 3.14_15_93
@@ -982,9 +981,9 @@ Imaginary literals are described by the following lexical definitions:
imagnumber: (`floatnumber` | `digitpart`) ("j" | "J")
An imaginary literal yields a complex number with a real part of 0.0. Complex
-numbers are represented as a pair of floating point numbers and have the same
+numbers are represented as a pair of floating-point numbers and have the same
restrictions on their range. To create a complex number with a nonzero real
-part, add a floating point number to it, e.g., ``(3+4j)``. Some examples of
+part, add a floating-point number to it, e.g., ``(3+4j)``. Some examples of
imaginary literals::
3.14j 10.j 10j .001j 1e100j 3.14e-10j 3.14_15_93j
@@ -1019,9 +1018,9 @@ The following tokens serve as delimiters in the grammar:
.. code-block:: none
( ) [ ] { }
- , : . ; @ = ->
- += -= *= /= //= %= @=
- &= |= ^= >>= <<= **=
+ , : ! . ; @ =
+ -> += -= *= /= //= %=
+ @= &= |= ^= >>= <<= **=
The period can also occur in floating-point and imaginary literals. A sequence
of three periods has a special meaning as an ellipsis literal. The second half
diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst
index 4f6c0c63ae4..618664b23f0 100644
--- a/Doc/reference/simple_stmts.rst
+++ b/Doc/reference/simple_stmts.rst
@@ -293,7 +293,7 @@ statements, cannot be an unpacking) and the expression list, performs the binary
operation specific to the type of assignment on the two operands, and assigns
the result to the original target. The target is only evaluated once.
-An augmented assignment expression like ``x += 1`` can be rewritten as ``x = x +
+An augmented assignment statement like ``x += 1`` can be rewritten as ``x = x +
1`` to achieve a similar, but not exactly equal effect. In the augmented
version, ``x`` is only evaluated once. Also, when possible, the actual operation
is performed *in-place*, meaning that rather than creating a new object and
diff --git a/Doc/requirements-oldest-sphinx.txt b/Doc/requirements-oldest-sphinx.txt
index 4e49ba1a8ed..068fe0cb426 100644
--- a/Doc/requirements-oldest-sphinx.txt
+++ b/Doc/requirements-oldest-sphinx.txt
@@ -14,7 +14,7 @@ python-docs-theme>=2022.1
alabaster==0.7.16
Babel==2.15.0
-certifi==2024.6.2
+certifi==2024.7.4
charset-normalizer==3.3.2
docutils==0.19
idna==3.7
diff --git a/Doc/requirements.txt b/Doc/requirements.txt
index b47a9d8a863..bf1028020b7 100644
--- a/Doc/requirements.txt
+++ b/Doc/requirements.txt
@@ -6,12 +6,12 @@
# Sphinx version is pinned so that new versions that introduce new warnings
# won't suddenly cause build failures. Updating the version is fine as long
# as no warnings are raised by doing so.
-sphinx~=7.3.0
+sphinx~=8.0.0
blurb
-sphinxext-opengraph==0.7.5
-sphinx-notfound-page==1.0.0
+sphinxext-opengraph~=0.9.0
+sphinx-notfound-page~=1.0.0
# The theme used by the documentation is stored separately, so we need
# to install that as well.
diff --git a/Doc/tools/check-warnings.py b/Doc/tools/check-warnings.py
index c50b00636c3..d9c4a33b775 100644
--- a/Doc/tools/check-warnings.py
+++ b/Doc/tools/check-warnings.py
@@ -2,6 +2,7 @@
"""
Check the output of running Sphinx in nit-picky mode (missing references).
"""
+
from __future__ import annotations
import argparse
@@ -14,7 +15,7 @@
from typing import TextIO
# Fail if NEWS nit found before this line number
-NEWS_NIT_THRESHOLD = 200
+NEWS_NIT_THRESHOLD = 1400
# Exclude these whether they're dirty or clean,
# because they trigger a rebuild of dirty files.
@@ -206,7 +207,9 @@ def annotate_diff(
def fail_if_regression(
- warnings: list[str], files_with_expected_nits: set[str], files_with_nits: set[str]
+ warnings: list[str],
+ files_with_expected_nits: set[str],
+ files_with_nits: set[str],
) -> int:
"""
Ensure some files always pass Sphinx nit-picky mode (no missing references).
@@ -252,17 +255,11 @@ def fail_if_new_news_nit(warnings: list[str], threshold: int) -> int:
"""
Ensure no warnings are found in the NEWS file before a given line number.
"""
- news_nits = (
- warning
- for warning in warnings
- if "/build/NEWS:" in warning
- )
+ news_nits = (warning for warning in warnings if "/build/NEWS:" in warning)
# Nits found before the threshold line
new_news_nits = [
- nit
- for nit in news_nits
- if int(nit.split(":")[1]) <= threshold
+ nit for nit in news_nits if int(nit.split(":")[1]) <= threshold
]
if new_news_nits:
@@ -311,7 +308,8 @@ def main(argv: list[str] | None = None) -> int:
exit_code = 0
wrong_directory_msg = "Must run this script from the repo root"
- assert Path("Doc").exists() and Path("Doc").is_dir(), wrong_directory_msg
+ if not Path("Doc").exists() or not Path("Doc").is_dir():
+ raise RuntimeError(wrong_directory_msg)
with Path("Doc/sphinx-warnings.txt").open(encoding="UTF-8") as f:
warnings = f.read().splitlines()
@@ -339,7 +337,9 @@ def main(argv: list[str] | None = None) -> int:
)
if args.fail_if_improved:
- exit_code += fail_if_improved(files_with_expected_nits, files_with_nits)
+ exit_code += fail_if_improved(
+ files_with_expected_nits, files_with_nits
+ )
if args.fail_if_new_news_nit:
exit_code += fail_if_new_news_nit(warnings, args.fail_if_new_news_nit)
diff --git a/Doc/tools/extensions/audit_events.py b/Doc/tools/extensions/audit_events.py
new file mode 100644
index 00000000000..23d82c0f441
--- /dev/null
+++ b/Doc/tools/extensions/audit_events.py
@@ -0,0 +1,264 @@
+"""Support for documenting audit events."""
+
+from __future__ import annotations
+
+import re
+from typing import TYPE_CHECKING
+
+from docutils import nodes
+from sphinx.errors import NoUri
+from sphinx.locale import _ as sphinx_gettext
+from sphinx.transforms.post_transforms import SphinxPostTransform
+from sphinx.util import logging
+from sphinx.util.docutils import SphinxDirective
+
+if TYPE_CHECKING:
+ from collections.abc import Iterator
+
+ from sphinx.application import Sphinx
+ from sphinx.builders import Builder
+ from sphinx.environment import BuildEnvironment
+
+logger = logging.getLogger(__name__)
+
+# This list of sets are allowable synonyms for event argument names.
+# If two names are in the same set, they are treated as equal for the
+# purposes of warning. This won't help if the number of arguments is
+# different!
+_SYNONYMS = [
+ frozenset({"file", "path", "fd"}),
+]
+
+
+class AuditEvents:
+ def __init__(self) -> None:
+ self.events: dict[str, list[str]] = {}
+ self.sources: dict[str, list[tuple[str, str]]] = {}
+
+ def __iter__(self) -> Iterator[tuple[str, list[str], tuple[str, str]]]:
+ for name, args in self.events.items():
+ for source in self.sources[name]:
+ yield name, args, source
+
+ def add_event(
+ self, name, args: list[str], source: tuple[str, str]
+ ) -> None:
+ if name in self.events:
+ self._check_args_match(name, args)
+ else:
+ self.events[name] = args
+ self.sources.setdefault(name, []).append(source)
+
+ def _check_args_match(self, name: str, args: list[str]) -> None:
+ current_args = self.events[name]
+ msg = (
+ f"Mismatched arguments for audit-event {name}: "
+ f"{current_args!r} != {args!r}"
+ )
+ if current_args == args:
+ return
+ if len(current_args) != len(args):
+ logger.warning(msg)
+ return
+ for a1, a2 in zip(current_args, args, strict=False):
+ if a1 == a2:
+ continue
+ if any(a1 in s and a2 in s for s in _SYNONYMS):
+ continue
+ logger.warning(msg)
+ return
+
+ def id_for(self, name) -> str:
+ source_count = len(self.sources.get(name, ()))
+ name_clean = re.sub(r"\W", "_", name)
+ return f"audit_event_{name_clean}_{source_count}"
+
+ def rows(self) -> Iterator[tuple[str, list[str], list[tuple[str, str]]]]:
+ for name in sorted(self.events.keys()):
+ yield name, self.events[name], self.sources[name]
+
+
+def initialise_audit_events(app: Sphinx) -> None:
+ """Initialise the audit_events attribute on the environment."""
+ if not hasattr(app.env, "audit_events"):
+ app.env.audit_events = AuditEvents()
+
+
+def audit_events_purge(
+ app: Sphinx, env: BuildEnvironment, docname: str
+) -> None:
+ """This is to remove traces of removed documents from env.audit_events."""
+ fresh_audit_events = AuditEvents()
+ for name, args, (doc, target) in env.audit_events:
+ if doc != docname:
+ fresh_audit_events.add_event(name, args, (doc, target))
+
+
+def audit_events_merge(
+ app: Sphinx,
+ env: BuildEnvironment,
+ docnames: list[str],
+ other: BuildEnvironment,
+) -> None:
+ """In Sphinx parallel builds, this merges audit_events from subprocesses."""
+ for name, args, source in other.audit_events:
+ env.audit_events.add_event(name, args, source)
+
+
+class AuditEvent(SphinxDirective):
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 2
+ final_argument_whitespace = True
+
+ _label = [
+ sphinx_gettext(
+ "Raises an :ref:`auditing event ` "
+ "{name} with no arguments."
+ ),
+ sphinx_gettext(
+ "Raises an :ref:`auditing event ` "
+ "{name} with argument {args}."
+ ),
+ sphinx_gettext(
+ "Raises an :ref:`auditing event ` "
+ "{name} with arguments {args}."
+ ),
+ ]
+
+ def run(self) -> list[nodes.paragraph]:
+ name = self.arguments[0]
+ if len(self.arguments) >= 2 and self.arguments[1]:
+ args = [
+ arg
+ for argument in self.arguments[1].strip("'\"").split(",")
+ if (arg := argument.strip())
+ ]
+ else:
+ args = []
+ ids = []
+ try:
+ target = self.arguments[2].strip("\"'")
+ except (IndexError, TypeError):
+ target = None
+ if not target:
+ target = self.env.audit_events.id_for(name)
+ ids.append(target)
+ self.env.audit_events.add_event(name, args, (self.env.docname, target))
+
+ node = nodes.paragraph("", classes=["audit-hook"], ids=ids)
+ self.set_source_info(node)
+ if self.content:
+ node.rawsource = '\n'.join(self.content) # for gettext
+ self.state.nested_parse(self.content, self.content_offset, node)
+ else:
+ num_args = min(2, len(args))
+ text = self._label[num_args].format(
+ name=f"``{name}``",
+ args=", ".join(f"``{a}``" for a in args),
+ )
+ node.rawsource = text # for gettext
+ parsed, messages = self.state.inline_text(text, self.lineno)
+ node += parsed
+ node += messages
+ return [node]
+
+
+class audit_event_list(nodes.General, nodes.Element): # noqa: N801
+ pass
+
+
+class AuditEventListDirective(SphinxDirective):
+ def run(self) -> list[audit_event_list]:
+ return [audit_event_list()]
+
+
+class AuditEventListTransform(SphinxPostTransform):
+ default_priority = 500
+
+ def run(self) -> None:
+ if self.document.next_node(audit_event_list) is None:
+ return
+
+ table = self._make_table(self.app.builder, self.env.docname)
+ for node in self.document.findall(audit_event_list):
+ node.replace_self(table)
+
+ def _make_table(self, builder: Builder, docname: str) -> nodes.table:
+ table = nodes.table(cols=3)
+ group = nodes.tgroup(
+ "",
+ nodes.colspec(colwidth=30),
+ nodes.colspec(colwidth=55),
+ nodes.colspec(colwidth=15),
+ cols=3,
+ )
+ head = nodes.thead()
+ body = nodes.tbody()
+
+ table += group
+ group += head
+ group += body
+
+ head += nodes.row(
+ "",
+ nodes.entry("", nodes.paragraph("", "Audit event")),
+ nodes.entry("", nodes.paragraph("", "Arguments")),
+ nodes.entry("", nodes.paragraph("", "References")),
+ )
+
+ for name, args, sources in builder.env.audit_events.rows():
+ body += self._make_row(builder, docname, name, args, sources)
+
+ return table
+
+ @staticmethod
+ def _make_row(
+ builder: Builder,
+ docname: str,
+ name: str,
+ args: list[str],
+ sources: list[tuple[str, str]],
+ ) -> nodes.row:
+ row = nodes.row()
+ name_node = nodes.paragraph("", nodes.Text(name))
+ row += nodes.entry("", name_node)
+
+ args_node = nodes.paragraph()
+ for arg in args:
+ args_node += nodes.literal(arg, arg)
+ args_node += nodes.Text(", ")
+ if len(args_node.children) > 0:
+ args_node.children.pop() # remove trailing comma
+ row += nodes.entry("", args_node)
+
+ backlinks_node = nodes.paragraph()
+ backlinks = enumerate(sorted(set(sources)), start=1)
+ for i, (doc, label) in backlinks:
+ if isinstance(label, str):
+ ref = nodes.reference("", f"[{i}]", internal=True)
+ try:
+ target = (
+ f"{builder.get_relative_uri(docname, doc)}#{label}"
+ )
+ except NoUri:
+ continue
+ else:
+ ref["refuri"] = target
+ backlinks_node += ref
+ row += nodes.entry("", backlinks_node)
+ return row
+
+
+def setup(app: Sphinx):
+ app.add_directive("audit-event", AuditEvent)
+ app.add_directive("audit-event-table", AuditEventListDirective)
+ app.add_post_transform(AuditEventListTransform)
+ app.connect("builder-inited", initialise_audit_events)
+ app.connect("env-purge-doc", audit_events_purge)
+ app.connect("env-merge-info", audit_events_merge)
+ return {
+ "version": "1.0",
+ "parallel_read_safe": True,
+ "parallel_write_safe": True,
+ }
diff --git a/Doc/tools/extensions/c_annotations.py b/Doc/tools/extensions/c_annotations.py
index 7916b178f1c..50065d34a2c 100644
--- a/Doc/tools/extensions/c_annotations.py
+++ b/Doc/tools/extensions/c_annotations.py
@@ -1,226 +1,302 @@
-"""
- c_annotations.py
- ~~~~~~~~~~~~~~~~
-
- Supports annotations for C API elements:
+"""Support annotations for C API elements.
- * reference count annotations for C API functions. Based on
- refcount.py and anno-api.py in the old Python documentation tools.
+* Reference count annotations for C API functions.
+* Stable ABI annotations
+* Limited API annotations
- * stable API annotations
+Configuration:
+* Set ``refcount_file`` to the path to the reference count data file.
+* Set ``stable_abi_file`` to the path to stable ABI list.
+"""
- Usage:
- * Set the `refcount_file` config value to the path to the reference
- count data file.
- * Set the `stable_abi_file` config value to the path to stable ABI list.
+from __future__ import annotations
- :copyright: Copyright 2007-2014 by Georg Brandl.
- :license: Python license.
-"""
+import csv
+import dataclasses
+from pathlib import Path
+from typing import TYPE_CHECKING
-from os import path
+import sphinx
from docutils import nodes
-from docutils.parsers.rst import directives
-from docutils.parsers.rst import Directive
from docutils.statemachine import StringList
-from sphinx.locale import _ as sphinx_gettext
-import csv
-
from sphinx import addnodes
-from sphinx.domains.c import CObject
+from sphinx.locale import _ as sphinx_gettext
+from sphinx.util.docutils import SphinxDirective
+if TYPE_CHECKING:
+ from sphinx.application import Sphinx
+ from sphinx.util.typing import ExtensionMetadata
-REST_ROLE_MAP = {
- 'function': 'func',
- 'macro': 'macro',
- 'member': 'member',
- 'type': 'type',
- 'var': 'data',
+ROLE_TO_OBJECT_TYPE = {
+ "func": "function",
+ "macro": "macro",
+ "member": "member",
+ "type": "type",
+ "data": "var",
}
-class RCEntry:
- def __init__(self, name):
- self.name = name
- self.args = []
- self.result_type = ''
- self.result_refs = None
-
-
-class Annotations:
- def __init__(self, refcount_filename, stable_abi_file):
- self.refcount_data = {}
- with open(refcount_filename, encoding='utf8') as fp:
- for line in fp:
- line = line.strip()
- if line[:1] in ("", "#"):
- # blank lines and comments
- continue
- parts = line.split(":", 4)
- if len(parts) != 5:
- raise ValueError(f"Wrong field count in {line!r}")
- function, type, arg, refcount, comment = parts
- # Get the entry, creating it if needed:
- try:
- entry = self.refcount_data[function]
- except KeyError:
- entry = self.refcount_data[function] = RCEntry(function)
- if not refcount or refcount == "null":
- refcount = None
- else:
- refcount = int(refcount)
- # Update the entry with the new parameter or the result
- # information.
- if arg:
- entry.args.append((arg, type, refcount))
- else:
- entry.result_type = type
- entry.result_refs = refcount
-
- self.stable_abi_data = {}
- with open(stable_abi_file, encoding='utf8') as fp:
- for record in csv.DictReader(fp):
- name = record['name']
- self.stable_abi_data[name] = record
-
- def add_annotations(self, app, doctree):
- for node in doctree.findall(addnodes.desc_content):
- par = node.parent
- if par['domain'] != 'c':
- continue
- if not par[0].has_key('ids') or not par[0]['ids']:
- continue
- name = par[0]['ids'][0]
- if name.startswith("c."):
- name = name[2:]
-
- objtype = par['objtype']
-
- # Stable ABI annotation. These have two forms:
- # Part of the [Stable ABI](link).
- # Part of the [Stable ABI](link) since version X.Y.
- # For structs, there's some more info in the message:
- # Part of the [Limited API](link) (as an opaque struct).
- # Part of the [Stable ABI](link) (including all members).
- # Part of the [Limited API](link) (Only some members are part
- # of the stable ABI.).
- # ... all of which can have "since version X.Y" appended.
- record = self.stable_abi_data.get(name)
- if record:
- if record['role'] != objtype:
- raise ValueError(
- f"Object type mismatch in limited API annotation "
- f"for {name}: {record['role']!r} != {objtype!r}")
- stable_added = record['added']
- message = sphinx_gettext('Part of the')
- message = message.center(len(message) + 2)
- emph_node = nodes.emphasis(message, message,
- classes=['stableabi'])
- ref_node = addnodes.pending_xref(
- 'Stable ABI', refdomain="std", reftarget='stable',
- reftype='ref', refexplicit="False")
- struct_abi_kind = record['struct_abi_kind']
- if struct_abi_kind in {'opaque', 'members'}:
- ref_node += nodes.Text(sphinx_gettext('Limited API'))
- else:
- ref_node += nodes.Text(sphinx_gettext('Stable ABI'))
- emph_node += ref_node
- if struct_abi_kind == 'opaque':
- emph_node += nodes.Text(' ' + sphinx_gettext('(as an opaque struct)'))
- elif struct_abi_kind == 'full-abi':
- emph_node += nodes.Text(' ' + sphinx_gettext('(including all members)'))
- if record['ifdef_note']:
- emph_node += nodes.Text(' ' + record['ifdef_note'])
- if stable_added == '3.2':
- # Stable ABI was introduced in 3.2.
- pass
- else:
- emph_node += nodes.Text(' ' + sphinx_gettext('since version %s') % stable_added)
- emph_node += nodes.Text('.')
- if struct_abi_kind == 'members':
- emph_node += nodes.Text(
- ' ' + sphinx_gettext('(Only some members are part of the stable ABI.)'))
- node.insert(0, emph_node)
-
- # Unstable API annotation.
- if name.startswith('PyUnstable'):
- warn_node = nodes.admonition(
- classes=['unstable-c-api', 'warning'])
- message = sphinx_gettext('This is') + ' '
- emph_node = nodes.emphasis(message, message)
- ref_node = addnodes.pending_xref(
- 'Unstable API', refdomain="std",
- reftarget='unstable-c-api',
- reftype='ref', refexplicit="False")
- ref_node += nodes.Text(sphinx_gettext('Unstable API'))
- emph_node += ref_node
- emph_node += nodes.Text(sphinx_gettext('. It may change without warning in minor releases.'))
- warn_node += emph_node
- node.insert(0, warn_node)
-
- # Return value annotation
- if objtype != 'function':
- continue
- entry = self.refcount_data.get(name)
- if not entry:
- continue
- elif not entry.result_type.endswith("Object*"):
- continue
- classes = ['refcount']
- if entry.result_refs is None:
- rc = sphinx_gettext('Return value: Always NULL.')
- classes.append('return_null')
- elif entry.result_refs:
- rc = sphinx_gettext('Return value: New reference.')
- classes.append('return_new_ref')
- else:
- rc = sphinx_gettext('Return value: Borrowed reference.')
- classes.append('return_borrowed_ref')
- node.insert(0, nodes.emphasis(rc, rc, classes=classes))
-
-
-def init_annotations(app):
- annotations = Annotations(
- path.join(app.srcdir, app.config.refcount_file),
- path.join(app.srcdir, app.config.stable_abi_file),
+@dataclasses.dataclass(slots=True)
+class RefCountEntry:
+ # Name of the function.
+ name: str
+ # List of (argument name, type, refcount effect) tuples.
+ # (Currently not used. If it was, a dataclass might work better.)
+ args: list = dataclasses.field(default_factory=list)
+ # Return type of the function.
+ result_type: str = ""
+ # Reference count effect for the return value.
+ result_refs: int | None = None
+
+
+@dataclasses.dataclass(frozen=True, slots=True)
+class StableABIEntry:
+ # Role of the object.
+ # Source: Each [item_kind] in stable_abi.toml is mapped to a C Domain role.
+ role: str
+ # Name of the object.
+ # Source: [.*] in stable_abi.toml.
+ name: str
+ # Version when the object was added to the stable ABI.
+ # (Source: [.*.added] in stable_abi.toml.
+ added: str
+ # An explananatory blurb for the ifdef.
+ # Source: ``feature_macro.*.doc`` in stable_abi.toml.
+ ifdef_note: str
+ # Defines how much of the struct is exposed. Only relevant for structs.
+ # Source: [.*.struct_abi_kind] in stable_abi.toml.
+ struct_abi_kind: str
+
+
+def read_refcount_data(refcount_filename: Path) -> dict[str, RefCountEntry]:
+ refcount_data = {}
+ refcounts = refcount_filename.read_text(encoding="utf8")
+ for line in refcounts.splitlines():
+ line = line.strip()
+ if not line or line.startswith("#"):
+ # blank lines and comments
+ continue
+
+ # Each line is of the form
+ # function ':' type ':' [param name] ':' [refcount effect] ':' [comment]
+ parts = line.split(":", 4)
+ if len(parts) != 5:
+ raise ValueError(f"Wrong field count in {line!r}")
+ function, type, arg, refcount, _comment = parts
+
+ # Get the entry, creating it if needed:
+ try:
+ entry = refcount_data[function]
+ except KeyError:
+ entry = refcount_data[function] = RefCountEntry(function)
+ if not refcount or refcount == "null":
+ refcount = None
+ else:
+ refcount = int(refcount)
+ # Update the entry with the new parameter
+ # or the result information.
+ if arg:
+ entry.args.append((arg, type, refcount))
+ else:
+ entry.result_type = type
+ entry.result_refs = refcount
+
+ return refcount_data
+
+
+def read_stable_abi_data(stable_abi_file: Path) -> dict[str, StableABIEntry]:
+ stable_abi_data = {}
+ with open(stable_abi_file, encoding="utf8") as fp:
+ for record in csv.DictReader(fp):
+ name = record["name"]
+ stable_abi_data[name] = StableABIEntry(**record)
+
+ return stable_abi_data
+
+
+def add_annotations(app: Sphinx, doctree: nodes.document) -> None:
+ state = app.env.domaindata["c_annotations"]
+ refcount_data = state["refcount_data"]
+ stable_abi_data = state["stable_abi_data"]
+ for node in doctree.findall(addnodes.desc_content):
+ par = node.parent
+ if par["domain"] != "c":
+ continue
+ if not par[0].get("ids", None):
+ continue
+ name = par[0]["ids"][0].removeprefix("c.")
+ objtype = par["objtype"]
+
+ # Stable ABI annotation.
+ if record := stable_abi_data.get(name):
+ if ROLE_TO_OBJECT_TYPE[record.role] != objtype:
+ msg = (
+ f"Object type mismatch in limited API annotation for {name}: "
+ f"{ROLE_TO_OBJECT_TYPE[record.role]!r} != {objtype!r}"
+ )
+ raise ValueError(msg)
+ annotation = _stable_abi_annotation(record)
+ node.insert(0, annotation)
+
+ # Unstable API annotation.
+ if name.startswith("PyUnstable"):
+ annotation = _unstable_api_annotation()
+ node.insert(0, annotation)
+
+ # Return value annotation
+ if objtype != "function":
+ continue
+ if name not in refcount_data:
+ continue
+ entry = refcount_data[name]
+ if not entry.result_type.endswith("Object*"):
+ continue
+ annotation = _return_value_annotation(entry.result_refs)
+ node.insert(0, annotation)
+
+
+def _stable_abi_annotation(record: StableABIEntry) -> nodes.emphasis:
+ """Create the Stable ABI annotation.
+
+ These have two forms:
+ Part of the `Stable ABI `_.
+ Part of the `Stable ABI `_ since version X.Y.
+ For structs, there's some more info in the message:
+ Part of the `Limited API `_ (as an opaque struct).
+ Part of the `Stable ABI `_ (including all members).
+ Part of the `Limited API `_ (Only some members are part
+ of the stable ABI.).
+ ... all of which can have "since version X.Y" appended.
+ """
+ stable_added = record.added
+ message = sphinx_gettext("Part of the")
+ message = message.center(len(message) + 2)
+ emph_node = nodes.emphasis(message, message, classes=["stableabi"])
+ ref_node = addnodes.pending_xref(
+ "Stable ABI",
+ refdomain="std",
+ reftarget="stable",
+ reftype="ref",
+ refexplicit="False",
)
- app.connect('doctree-read', annotations.add_annotations)
+ struct_abi_kind = record.struct_abi_kind
+ if struct_abi_kind in {"opaque", "members"}:
+ ref_node += nodes.Text(sphinx_gettext("Limited API"))
+ else:
+ ref_node += nodes.Text(sphinx_gettext("Stable ABI"))
+ emph_node += ref_node
+ if struct_abi_kind == "opaque":
+ emph_node += nodes.Text(" " + sphinx_gettext("(as an opaque struct)"))
+ elif struct_abi_kind == "full-abi":
+ emph_node += nodes.Text(
+ " " + sphinx_gettext("(including all members)")
+ )
+ if record.ifdef_note:
+ emph_node += nodes.Text(f" {record.ifdef_note}")
+ if stable_added == "3.2":
+ # Stable ABI was introduced in 3.2.
+ pass
+ else:
+ emph_node += nodes.Text(
+ " " + sphinx_gettext("since version %s") % stable_added
+ )
+ emph_node += nodes.Text(".")
+ if struct_abi_kind == "members":
+ msg = " " + sphinx_gettext(
+ "(Only some members are part of the stable ABI.)"
+ )
+ emph_node += nodes.Text(msg)
+ return emph_node
- class LimitedAPIList(Directive):
- has_content = False
- required_arguments = 0
- optional_arguments = 0
- final_argument_whitespace = True
+def _unstable_api_annotation() -> nodes.admonition:
+ ref_node = addnodes.pending_xref(
+ "Unstable API",
+ nodes.Text(sphinx_gettext("Unstable API")),
+ refdomain="std",
+ reftarget="unstable-c-api",
+ reftype="ref",
+ refexplicit="False",
+ )
+ emph_node = nodes.emphasis(
+ "This is ",
+ sphinx_gettext("This is") + " ",
+ ref_node,
+ nodes.Text(
+ sphinx_gettext(
+ ". It may change without warning in minor releases."
+ )
+ ),
+ )
+ return nodes.admonition(
+ "",
+ emph_node,
+ classes=["unstable-c-api", "warning"],
+ )
- def run(self):
- content = []
- for record in annotations.stable_abi_data.values():
- role = REST_ROLE_MAP[record['role']]
- name = record['name']
- content.append(f'* :c:{role}:`{name}`')
- pnode = nodes.paragraph()
- self.state.nested_parse(StringList(content), 0, pnode)
- return [pnode]
+def _return_value_annotation(result_refs: int | None) -> nodes.emphasis:
+ classes = ["refcount"]
+ if result_refs is None:
+ rc = sphinx_gettext("Return value: Always NULL.")
+ classes.append("return_null")
+ elif result_refs:
+ rc = sphinx_gettext("Return value: New reference.")
+ classes.append("return_new_ref")
+ else:
+ rc = sphinx_gettext("Return value: Borrowed reference.")
+ classes.append("return_borrowed_ref")
+ return nodes.emphasis(rc, rc, classes=classes)
- app.add_directive('limited-api-list', LimitedAPIList)
+class LimitedAPIList(SphinxDirective):
+ has_content = False
+ required_arguments = 0
+ optional_arguments = 0
+ final_argument_whitespace = True
-def setup(app):
- app.add_config_value('refcount_file', '', True)
- app.add_config_value('stable_abi_file', '', True)
- app.connect('builder-inited', init_annotations)
+ def run(self) -> list[nodes.Node]:
+ state = self.env.domaindata["c_annotations"]
+ content = [
+ f"* :c:{record.role}:`{record.name}`"
+ for record in state["stable_abi_data"].values()
+ ]
+ node = nodes.paragraph()
+ self.state.nested_parse(StringList(content), 0, node)
+ return [node]
+
+
+def init_annotations(app: Sphinx) -> None:
+ # Using domaindata is a bit hack-ish,
+ # but allows storing state without a global variable or closure.
+ app.env.domaindata["c_annotations"] = state = {}
+ state["refcount_data"] = read_refcount_data(
+ Path(app.srcdir, app.config.refcount_file)
+ )
+ state["stable_abi_data"] = read_stable_abi_data(
+ Path(app.srcdir, app.config.stable_abi_file)
+ )
- # monkey-patch C object...
- CObject.option_spec = {
- 'noindex': directives.flag,
- 'stableabi': directives.flag,
- }
- old_handle_signature = CObject.handle_signature
- def new_handle_signature(self, sig, signode):
- signode.parent['stableabi'] = 'stableabi' in self.options
- return old_handle_signature(self, sig, signode)
- CObject.handle_signature = new_handle_signature
- return {'version': '1.0', 'parallel_read_safe': True}
+def setup(app: Sphinx) -> ExtensionMetadata:
+ app.add_config_value("refcount_file", "", "env", types={str})
+ app.add_config_value("stable_abi_file", "", "env", types={str})
+ app.add_directive("limited-api-list", LimitedAPIList)
+ app.connect("builder-inited", init_annotations)
+ app.connect("doctree-read", add_annotations)
+
+ if sphinx.version_info[:2] < (7, 2):
+ from docutils.parsers.rst import directives
+ from sphinx.domains.c import CObject
+
+ # monkey-patch C object...
+ CObject.option_spec |= {
+ "no-index-entry": directives.flag,
+ "no-contents-entry": directives.flag,
+ }
+
+ return {
+ "version": "1.0",
+ "parallel_read_safe": True,
+ "parallel_write_safe": True,
+ }
diff --git a/Doc/tools/extensions/escape4chm.py b/Doc/tools/extensions/escape4chm.py
deleted file mode 100644
index 89970975b90..00000000000
--- a/Doc/tools/extensions/escape4chm.py
+++ /dev/null
@@ -1,58 +0,0 @@
-"""
-Escape the `body` part of .chm source file to 7-bit ASCII, to fix visual
-effect on some MBCS Windows systems.
-
-https://bugs.python.org/issue32174
-"""
-
-import pathlib
-import re
-from html.entities import codepoint2name
-
-from sphinx.util.logging import getLogger
-
-# escape the characters which codepoint > 0x7F
-def _process(string):
- def escape(matchobj):
- codepoint = ord(matchobj.group(0))
-
- name = codepoint2name.get(codepoint)
- if name is None:
- return '%d;' % codepoint
- else:
- return '&%s;' % name
-
- return re.sub(r'[^\x00-\x7F]', escape, string)
-
-def escape_for_chm(app, pagename, templatename, context, doctree):
- # only works for .chm output
- if getattr(app.builder, 'name', '') != 'htmlhelp':
- return
-
- # escape the `body` part to 7-bit ASCII
- body = context.get('body')
- if body is not None:
- context['body'] = _process(body)
-
-def fixup_keywords(app, exception):
- # only works for .chm output
- if getattr(app.builder, 'name', '') != 'htmlhelp' or exception:
- return
-
- getLogger(__name__).info('fixing HTML escapes in keywords file...')
- outdir = pathlib.Path(app.builder.outdir)
- outname = app.builder.config.htmlhelp_basename
- with open(outdir / (outname + '.hhk'), 'rb') as f:
- index = f.read()
- with open(outdir / (outname + '.hhk'), 'wb') as f:
- f.write(index.replace(b''', b'''))
-
-def setup(app):
- # `html-page-context` event emitted when the HTML builder has
- # created a context dictionary to render a template with.
- app.connect('html-page-context', escape_for_chm)
- # `build-finished` event emitted when all the files have been
- # output.
- app.connect('build-finished', fixup_keywords)
-
- return {'version': '1.0', 'parallel_read_safe': True}
diff --git a/Doc/tools/extensions/glossary_search.py b/Doc/tools/extensions/glossary_search.py
index 7c93b1e4990..502b6cd95bc 100644
--- a/Doc/tools/extensions/glossary_search.py
+++ b/Doc/tools/extensions/glossary_search.py
@@ -1,63 +1,63 @@
-# -*- coding: utf-8 -*-
-"""
- glossary_search.py
- ~~~~~~~~~~~~~~~~
+"""Feature search results for glossary items prominently."""
- Feature search results for glossary items prominently.
+from __future__ import annotations
- :license: Python license.
-"""
import json
-import os.path
-from docutils.nodes import definition_list_item
+from pathlib import Path
+from typing import TYPE_CHECKING
+
+from docutils import nodes
from sphinx.addnodes import glossary
from sphinx.util import logging
+if TYPE_CHECKING:
+ from sphinx.application import Sphinx
+ from sphinx.util.typing import ExtensionMetadata
logger = logging.getLogger(__name__)
-STATIC_DIR = '_static'
-JSON = 'glossary.json'
-def process_glossary_nodes(app, doctree, fromdocname):
+def process_glossary_nodes(
+ app: Sphinx,
+ doctree: nodes.document,
+ _docname: str,
+) -> None:
if app.builder.format != 'html' or app.builder.embedded:
return
- terms = {}
+ if hasattr(app.env, 'glossary_terms'):
+ terms = app.env.glossary_terms
+ else:
+ terms = app.env.glossary_terms = {}
for node in doctree.findall(glossary):
- for glossary_item in node.findall(definition_list_item):
- term = glossary_item[0].astext().lower()
- definition = glossary_item[1]
+ for glossary_item in node.findall(nodes.definition_list_item):
+ term = glossary_item[0].astext()
+ definition = glossary_item[-1]
rendered = app.builder.render_partial(definition)
- terms[term] = {
- 'title': glossary_item[0].astext(),
- 'body': rendered['html_body']
+ terms[term.lower()] = {
+ 'title': term,
+ 'body': rendered['html_body'],
}
- if hasattr(app.env, 'glossary_terms'):
- app.env.glossary_terms.update(terms)
- else:
- app.env.glossary_terms = terms
-def on_build_finish(app, exc):
- if not hasattr(app.env, 'glossary_terms'):
- return
- if not app.env.glossary_terms:
+def write_glossary_json(app: Sphinx, _exc: Exception) -> None:
+ if not getattr(app.env, 'glossary_terms', None):
return
- logger.info(f'Writing {JSON}', color='green')
-
- dest_dir = os.path.join(app.outdir, STATIC_DIR)
- os.makedirs(dest_dir, exist_ok=True)
-
- with open(os.path.join(dest_dir, JSON), 'w') as f:
- json.dump(app.env.glossary_terms, f)
+ logger.info('Writing glossary.json', color='green')
+ dest = Path(app.outdir, '_static', 'glossary.json')
+ dest.parent.mkdir(exist_ok=True)
+ dest.write_text(json.dumps(app.env.glossary_terms), encoding='utf-8')
-def setup(app):
+def setup(app: Sphinx) -> ExtensionMetadata:
app.connect('doctree-resolved', process_glossary_nodes)
- app.connect('build-finished', on_build_finish)
+ app.connect('build-finished', write_glossary_json)
- return {'version': '0.1', 'parallel_read_safe': True}
+ return {
+ 'version': '1.0',
+ 'parallel_read_safe': True,
+ 'parallel_write_safe': True,
+ }
diff --git a/Doc/tools/extensions/lexers/__init__.py b/Doc/tools/extensions/lexers/__init__.py
new file mode 100644
index 00000000000..e12ac5be813
--- /dev/null
+++ b/Doc/tools/extensions/lexers/__init__.py
@@ -0,0 +1,15 @@
+from .asdl_lexer import ASDLLexer
+from .peg_lexer import PEGLexer
+
+
+def setup(app):
+ # Used for highlighting Parser/Python.asdl in library/ast.rst
+ app.add_lexer("asdl", ASDLLexer)
+ # Used for highlighting Grammar/python.gram in reference/grammar.rst
+ app.add_lexer("peg", PEGLexer)
+
+ return {
+ "version": "1.0",
+ "parallel_read_safe": True,
+ "parallel_write_safe": True,
+ }
diff --git a/Doc/tools/extensions/asdl_highlight.py b/Doc/tools/extensions/lexers/asdl_lexer.py
similarity index 62%
rename from Doc/tools/extensions/asdl_highlight.py
rename to Doc/tools/extensions/lexers/asdl_lexer.py
index 42863a4b3bc..3a74174a1f7 100644
--- a/Doc/tools/extensions/asdl_highlight.py
+++ b/Doc/tools/extensions/lexers/asdl_lexer.py
@@ -1,15 +1,6 @@
-import sys
-from pathlib import Path
+from pygments.lexer import RegexLexer, bygroups, include
+from pygments.token import Comment, Keyword, Name, Operator, Punctuation, Text
-CPYTHON_ROOT = Path(__file__).resolve().parent.parent.parent.parent
-sys.path.append(str(CPYTHON_ROOT / "Parser"))
-
-from pygments.lexer import RegexLexer, bygroups, include, words
-from pygments.token import (Comment, Keyword, Name, Operator,
- Punctuation, Text)
-
-from asdl import builtin_types
-from sphinx.highlighting import lexers
class ASDLLexer(RegexLexer):
name = "ASDL"
@@ -34,7 +25,10 @@ class ASDLLexer(RegexLexer):
r"(\w+)(\*\s|\?\s|\s)(\w+)",
bygroups(Name.Builtin.Pseudo, Operator, Name),
),
- (words(builtin_types), Name.Builtin),
+ # Keep in line with ``builtin_types`` from Parser/asdl.py.
+ # ASDL's 4 builtin types are
+ # constant, identifier, int, string
+ ("constant|identifier|int|string", Name.Builtin),
(r"attributes", Name.Builtin),
(
_name + _text_ws + "(=)",
@@ -46,8 +40,3 @@ class ASDLLexer(RegexLexer):
(r".", Text),
],
}
-
-
-def setup(app):
- lexers["asdl"] = ASDLLexer()
- return {'version': '1.0', 'parallel_read_safe': True}
diff --git a/Doc/tools/extensions/peg_highlight.py b/Doc/tools/extensions/lexers/peg_lexer.py
similarity index 94%
rename from Doc/tools/extensions/peg_highlight.py
rename to Doc/tools/extensions/lexers/peg_lexer.py
index 5ab5530d269..06f9f8eb312 100644
--- a/Doc/tools/extensions/peg_highlight.py
+++ b/Doc/tools/extensions/lexers/peg_lexer.py
@@ -1,8 +1,6 @@
from pygments.lexer import RegexLexer, bygroups, include
from pygments.token import Comment, Keyword, Name, Operator, Punctuation, Text
-from sphinx.highlighting import lexers
-
class PEGLexer(RegexLexer):
"""Pygments Lexer for PEG grammar (.gram) files
@@ -81,8 +79,3 @@ class PEGLexer(RegexLexer):
(r".", Text),
],
}
-
-
-def setup(app):
- lexers["peg"] = PEGLexer()
- return {"version": "1.0", "parallel_read_safe": True}
diff --git a/Doc/tools/extensions/patchlevel.py b/Doc/tools/extensions/patchlevel.py
index 617f28c2527..9ccaec3dd5c 100644
--- a/Doc/tools/extensions/patchlevel.py
+++ b/Doc/tools/extensions/patchlevel.py
@@ -1,68 +1,81 @@
-# -*- coding: utf-8 -*-
-"""
- patchlevel.py
- ~~~~~~~~~~~~~
+"""Extract version information from Include/patchlevel.h."""
- Extract version info from Include/patchlevel.h.
- Adapted from Doc/tools/getversioninfo.
+import re
+import sys
+from pathlib import Path
+from typing import Literal, NamedTuple
- :copyright: 2007-2008 by Georg Brandl.
- :license: Python license.
-"""
+CPYTHON_ROOT = Path(
+ __file__, # cpython/Doc/tools/extensions/patchlevel.py
+ "..", # cpython/Doc/tools/extensions
+ "..", # cpython/Doc/tools
+ "..", # cpython/Doc
+ "..", # cpython
+).resolve()
+PATCHLEVEL_H = CPYTHON_ROOT / "Include" / "patchlevel.h"
-from __future__ import print_function
+RELEASE_LEVELS = {
+ "PY_RELEASE_LEVEL_ALPHA": "alpha",
+ "PY_RELEASE_LEVEL_BETA": "beta",
+ "PY_RELEASE_LEVEL_GAMMA": "candidate",
+ "PY_RELEASE_LEVEL_FINAL": "final",
+}
-import os
-import re
-import sys
-def get_header_version_info(srcdir):
- patchlevel_h = os.path.join(srcdir, '..', 'Include', 'patchlevel.h')
+class version_info(NamedTuple): # noqa: N801
+ major: int #: Major release number
+ minor: int #: Minor release number
+ micro: int #: Patch release number
+ releaselevel: Literal["alpha", "beta", "candidate", "final"]
+ serial: int #: Serial release number
- # This won't pick out all #defines, but it will pick up the ones we
- # care about.
- rx = re.compile(r'\s*#define\s+([a-zA-Z][a-zA-Z_0-9]*)\s+([a-zA-Z_0-9]+)')
- d = {}
- with open(patchlevel_h) as f:
- for line in f:
- m = rx.match(line)
- if m is not None:
- name, value = m.group(1, 2)
- d[name] = value
+def get_header_version_info() -> version_info:
+ # Capture PY_ prefixed #defines.
+ pat = re.compile(r"\s*#define\s+(PY_\w*)\s+(\w+)", re.ASCII)
- release = version = '%s.%s' % (d['PY_MAJOR_VERSION'], d['PY_MINOR_VERSION'])
- micro = int(d['PY_MICRO_VERSION'])
- release += '.' + str(micro)
+ defines = {}
+ patchlevel_h = PATCHLEVEL_H.read_text(encoding="utf-8")
+ for line in patchlevel_h.splitlines():
+ if (m := pat.match(line)) is not None:
+ name, value = m.groups()
+ defines[name] = value
- level = d['PY_RELEASE_LEVEL']
- suffixes = {
- 'PY_RELEASE_LEVEL_ALPHA': 'a',
- 'PY_RELEASE_LEVEL_BETA': 'b',
- 'PY_RELEASE_LEVEL_GAMMA': 'rc',
- }
- if level != 'PY_RELEASE_LEVEL_FINAL':
- release += suffixes[level] + str(int(d['PY_RELEASE_SERIAL']))
- return version, release
+ return version_info(
+ major=int(defines["PY_MAJOR_VERSION"]),
+ minor=int(defines["PY_MINOR_VERSION"]),
+ micro=int(defines["PY_MICRO_VERSION"]),
+ releaselevel=RELEASE_LEVELS[defines["PY_RELEASE_LEVEL"]],
+ serial=int(defines["PY_RELEASE_SERIAL"]),
+ )
-def get_sys_version_info():
- major, minor, micro, level, serial = sys.version_info
- release = version = '%s.%s' % (major, minor)
- release += '.%s' % micro
- if level != 'final':
- release += '%s%s' % (level[0], serial)
+def format_version_info(info: version_info) -> tuple[str, str]:
+ version = f"{info.major}.{info.minor}"
+ release = f"{info.major}.{info.minor}.{info.micro}"
+ if info.releaselevel != "final":
+ suffix = {"alpha": "a", "beta": "b", "candidate": "rc"}
+ release += f"{suffix[info.releaselevel]}{info.serial}"
return version, release
def get_version_info():
try:
- return get_header_version_info('.')
- except (IOError, OSError):
- version, release = get_sys_version_info()
- print('Can\'t get version info from Include/patchlevel.h, ' \
- 'using version of this interpreter (%s).' % release, file=sys.stderr)
+ info = get_header_version_info()
+ return format_version_info(info)
+ except OSError:
+ version, release = format_version_info(sys.version_info)
+ print(
+ f"Failed to get version info from Include/patchlevel.h, "
+ f"using version of this interpreter ({release}).",
+ file=sys.stderr,
+ )
return version, release
-if __name__ == '__main__':
- print(get_header_version_info('.')[1])
+
+if __name__ == "__main__":
+ short_ver, full_ver = format_version_info(get_header_version_info())
+ if sys.argv[1:2] == ["--short"]:
+ print(short_ver)
+ else:
+ print(full_ver)
diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py
index 7a2a85346b3..6138246ccb4 100644
--- a/Doc/tools/extensions/pyspecific.py
+++ b/Doc/tools/extensions/pyspecific.py
@@ -15,14 +15,14 @@
from time import asctime
from pprint import pformat
-from docutils import nodes, utils
+from docutils import nodes
from docutils.io import StringOutput
-from docutils.parsers.rst import Directive
-from docutils.utils import new_document
+from docutils.parsers.rst import directives
+from docutils.utils import new_document, unescape
from sphinx import addnodes
from sphinx.builders import Builder
-from sphinx.domains.python import PyFunction, PyMethod
-from sphinx.errors import NoUri
+from sphinx.domains.changeset import VersionChange, versionlabels, versionlabel_classes
+from sphinx.domains.python import PyFunction, PyMethod, PyModule
from sphinx.locale import _ as sphinx_gettext
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective
@@ -48,11 +48,14 @@
std.token_re = re.compile(r'`((~?[\w-]*:)?\w+)`')
+# backport :no-index:
+PyModule.option_spec['no-index'] = directives.flag
+
# Support for marking up and linking to bugs.python.org issues
def issue_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
- issue = utils.unescape(text)
+ issue = unescape(text)
# sanity check: there are no bpo issues within these two values
if 47261 < int(issue) < 400000:
msg = inliner.reporter.error(f'The BPO ID {text!r} seems too high -- '
@@ -67,7 +70,7 @@ def issue_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
# Support for marking up and linking to GitHub issues
def gh_issue_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
- issue = utils.unescape(text)
+ issue = unescape(text)
# sanity check: all GitHub issues have ID >= 32426
# even though some of them are also valid BPO IDs
if int(issue) < 32426:
@@ -82,7 +85,7 @@ def gh_issue_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
# Support for marking up implementation details
-class ImplementationDetail(Directive):
+class ImplementationDetail(SphinxDirective):
has_content = True
final_argument_whitespace = True
@@ -179,143 +182,6 @@ def parse_platforms(self):
return platforms
-# Support for documenting audit event
-
-def audit_events_purge(app, env, docname):
- """This is to remove from env.all_audit_events old traces of removed
- documents.
- """
- if not hasattr(env, 'all_audit_events'):
- return
- fresh_all_audit_events = {}
- for name, event in env.all_audit_events.items():
- event["source"] = [(d, t) for d, t in event["source"] if d != docname]
- if event["source"]:
- # Only keep audit_events that have at least one source.
- fresh_all_audit_events[name] = event
- env.all_audit_events = fresh_all_audit_events
-
-
-def audit_events_merge(app, env, docnames, other):
- """In Sphinx parallel builds, this merges env.all_audit_events from
- subprocesses.
-
- all_audit_events is a dict of names, with values like:
- {'source': [(docname, target), ...], 'args': args}
- """
- if not hasattr(other, 'all_audit_events'):
- return
- if not hasattr(env, 'all_audit_events'):
- env.all_audit_events = {}
- for name, value in other.all_audit_events.items():
- if name in env.all_audit_events:
- env.all_audit_events[name]["source"].extend(value["source"])
- else:
- env.all_audit_events[name] = value
-
-
-class AuditEvent(Directive):
-
- has_content = True
- required_arguments = 1
- optional_arguments = 2
- final_argument_whitespace = True
-
- _label = [
- sphinx_gettext("Raises an :ref:`auditing event ` {name} with no arguments."),
- sphinx_gettext("Raises an :ref:`auditing event ` {name} with argument {args}."),
- sphinx_gettext("Raises an :ref:`auditing event ` {name} with arguments {args}."),
- ]
-
- @property
- def logger(self):
- cls = type(self)
- return logging.getLogger(cls.__module__ + "." + cls.__name__)
-
- def run(self):
- name = self.arguments[0]
- if len(self.arguments) >= 2 and self.arguments[1]:
- args = (a.strip() for a in self.arguments[1].strip("'\"").split(","))
- args = [a for a in args if a]
- else:
- args = []
-
- label = self._label[min(2, len(args))]
- text = label.format(name="``{}``".format(name),
- args=", ".join("``{}``".format(a) for a in args if a))
-
- env = self.state.document.settings.env
- if not hasattr(env, 'all_audit_events'):
- env.all_audit_events = {}
-
- new_info = {
- 'source': [],
- 'args': args
- }
- info = env.all_audit_events.setdefault(name, new_info)
- if info is not new_info:
- if not self._do_args_match(info['args'], new_info['args']):
- self.logger.warning(
- "Mismatched arguments for audit-event {}: {!r} != {!r}"
- .format(name, info['args'], new_info['args'])
- )
-
- ids = []
- try:
- target = self.arguments[2].strip("\"'")
- except (IndexError, TypeError):
- target = None
- if not target:
- target = "audit_event_{}_{}".format(
- re.sub(r'\W', '_', name),
- len(info['source']),
- )
- ids.append(target)
-
- info['source'].append((env.docname, target))
-
- pnode = nodes.paragraph(text, classes=["audit-hook"], ids=ids)
- pnode.line = self.lineno
- if self.content:
- self.state.nested_parse(self.content, self.content_offset, pnode)
- else:
- n, m = self.state.inline_text(text, self.lineno)
- pnode.extend(n + m)
-
- return [pnode]
-
- # This list of sets are allowable synonyms for event argument names.
- # If two names are in the same set, they are treated as equal for the
- # purposes of warning. This won't help if number of arguments is
- # different!
- _SYNONYMS = [
- {"file", "path", "fd"},
- ]
-
- def _do_args_match(self, args1, args2):
- if args1 == args2:
- return True
- if len(args1) != len(args2):
- return False
- for a1, a2 in zip(args1, args2):
- if a1 == a2:
- continue
- if any(a1 in s and a2 in s for s in self._SYNONYMS):
- continue
- return False
- return True
-
-
-class audit_event_list(nodes.General, nodes.Element):
- pass
-
-
-class AuditEventListDirective(Directive):
-
- def run(self):
- return [audit_event_list('')]
-
-
# Support for documenting decorators
class PyDecoratorMixin(object):
@@ -395,58 +261,34 @@ def run(self):
# Support for documenting version of removal in deprecations
-class DeprecatedRemoved(Directive):
- has_content = True
+class DeprecatedRemoved(VersionChange):
required_arguments = 2
- optional_arguments = 1
- final_argument_whitespace = True
- option_spec = {}
- _deprecated_label = sphinx_gettext('Deprecated since version {deprecated}, will be removed in version {removed}')
- _removed_label = sphinx_gettext('Deprecated since version {deprecated}, removed in version {removed}')
+ _deprecated_label = sphinx_gettext('Deprecated since version %s, will be removed in version %s')
+ _removed_label = sphinx_gettext('Deprecated since version %s, removed in version %s')
def run(self):
- node = addnodes.versionmodified()
- node.document = self.state.document
- node['type'] = 'deprecated-removed'
- version = (self.arguments[0], self.arguments[1])
- node['version'] = version
- env = self.state.document.settings.env
- current_version = tuple(int(e) for e in env.config.version.split('.'))
- removed_version = tuple(int(e) for e in self.arguments[1].split('.'))
+ # Replace the first two arguments (deprecated version and removed version)
+ # with a single tuple of both versions.
+ version_deprecated = self.arguments[0]
+ version_removed = self.arguments.pop(1)
+ self.arguments[0] = version_deprecated, version_removed
+
+ # Set the label based on if we have reached the removal version
+ current_version = tuple(map(int, self.config.version.split('.')))
+ removed_version = tuple(map(int, version_removed.split('.')))
if current_version < removed_version:
- label = self._deprecated_label
- else:
- label = self._removed_label
-
- text = label.format(deprecated=self.arguments[0], removed=self.arguments[1])
- if len(self.arguments) == 3:
- inodes, messages = self.state.inline_text(self.arguments[2],
- self.lineno+1)
- para = nodes.paragraph(self.arguments[2], '', *inodes, translatable=False)
- node.append(para)
+ versionlabels[self.name] = self._deprecated_label
+ versionlabel_classes[self.name] = 'deprecated'
else:
- messages = []
- if self.content:
- self.state.nested_parse(self.content, self.content_offset, node)
- if len(node):
- if isinstance(node[0], nodes.paragraph) and node[0].rawsource:
- content = nodes.inline(node[0].rawsource, translatable=True)
- content.source = node[0].source
- content.line = node[0].line
- content += node[0].children
- node[0].replace_self(nodes.paragraph('', '', content, translatable=False))
- node[0].insert(0, nodes.inline('', '%s: ' % text,
- classes=['versionmodified']))
- else:
- para = nodes.paragraph('', '',
- nodes.inline('', '%s.' % text,
- classes=['versionmodified']),
- translatable=False)
- node.append(para)
- env = self.state.document.settings.env
- env.get_domain('changeset').note_changeset(node)
- return [node] + messages
+ versionlabels[self.name] = self._removed_label
+ versionlabel_classes[self.name] = 'removed'
+ try:
+ return super().run()
+ finally:
+ # reset versionlabels and versionlabel_classes
+ versionlabels[self.name] = ''
+ versionlabel_classes[self.name] = ''
# Support for including Misc/NEWS
@@ -456,7 +298,7 @@ def run(self):
whatsnew_re = re.compile(r"(?im)^what's new in (.*?)\??$")
-class MiscNews(Directive):
+class MiscNews(SphinxDirective):
has_content = False
required_arguments = 1
optional_arguments = 0
@@ -471,7 +313,7 @@ def run(self):
if not source_dir:
source_dir = path.dirname(path.abspath(source))
fpath = path.join(source_dir, fname)
- self.state.document.settings.record_dependencies.add(fpath)
+ self.env.note_dependency(path.abspath(fpath))
try:
with io.open(fpath, encoding='utf-8') as fp:
content = fp.read()
@@ -603,70 +445,6 @@ def parse_monitoring_event(env, sig, signode):
return sig
-def process_audit_events(app, doctree, fromdocname):
- for node in doctree.findall(audit_event_list):
- break
- else:
- return
-
- env = app.builder.env
-
- table = nodes.table(cols=3)
- group = nodes.tgroup(
- '',
- nodes.colspec(colwidth=30),
- nodes.colspec(colwidth=55),
- nodes.colspec(colwidth=15),
- cols=3,
- )
- head = nodes.thead()
- body = nodes.tbody()
-
- table += group
- group += head
- group += body
-
- row = nodes.row()
- row += nodes.entry('', nodes.paragraph('', nodes.Text('Audit event')))
- row += nodes.entry('', nodes.paragraph('', nodes.Text('Arguments')))
- row += nodes.entry('', nodes.paragraph('', nodes.Text('References')))
- head += row
-
- for name in sorted(getattr(env, "all_audit_events", ())):
- audit_event = env.all_audit_events[name]
-
- row = nodes.row()
- node = nodes.paragraph('', nodes.Text(name))
- row += nodes.entry('', node)
-
- node = nodes.paragraph()
- for i, a in enumerate(audit_event['args']):
- if i:
- node += nodes.Text(", ")
- node += nodes.literal(a, nodes.Text(a))
- row += nodes.entry('', node)
-
- node = nodes.paragraph()
- backlinks = enumerate(sorted(set(audit_event['source'])), start=1)
- for i, (doc, label) in backlinks:
- if isinstance(label, str):
- ref = nodes.reference("", nodes.Text("[{}]".format(i)), internal=True)
- try:
- ref['refuri'] = "{}#{}".format(
- app.builder.get_relative_uri(fromdocname, doc),
- label,
- )
- except NoUri:
- continue
- node += ref
- row += nodes.entry('', node)
-
- body += row
-
- for node in doctree.findall(audit_event_list):
- node.replace_self(table)
-
-
def patch_pairindextypes(app, _env) -> None:
"""Remove all entries from ``pairindextypes`` before writing POT files.
@@ -696,8 +474,6 @@ def setup(app):
app.add_role('gh', gh_issue_role)
app.add_directive('impl-detail', ImplementationDetail)
app.add_directive('availability', Availability)
- app.add_directive('audit-event', AuditEvent)
- app.add_directive('audit-event-table', AuditEventListDirective)
app.add_directive('deprecated-removed', DeprecatedRemoved)
app.add_builder(PydocTopicsBuilder)
app.add_object_type('opcode', 'opcode', '%s (opcode)', parse_opcode_signature)
@@ -712,7 +488,4 @@ def setup(app):
app.add_directive_to_domain('py', 'abstractmethod', PyAbstractMethod)
app.add_directive('miscnews', MiscNews)
app.connect('env-check-consistency', patch_pairindextypes)
- app.connect('doctree-resolved', process_audit_events)
- app.connect('env-merge-info', audit_events_merge)
- app.connect('env-purge-doc', audit_events_purge)
return {'version': '1.0', 'parallel_read_safe': True}
diff --git a/Doc/tools/static/glossary_search.js b/Doc/tools/static/glossary_search.js
new file mode 100644
index 00000000000..13d728dc027
--- /dev/null
+++ b/Doc/tools/static/glossary_search.js
@@ -0,0 +1,47 @@
+"use strict";
+
+const GLOSSARY_PAGE = "glossary.html";
+
+const glossary_search = async () => {
+ const response = await fetch("_static/glossary.json");
+ if (!response.ok) {
+ throw new Error("Failed to fetch glossary.json");
+ }
+ const glossary = await response.json();
+
+ const params = new URLSearchParams(document.location.search).get("q");
+ if (!params) {
+ return;
+ }
+
+ const searchParam = params.toLowerCase();
+ const glossaryItem = glossary[searchParam];
+ if (!glossaryItem) {
+ return;
+ }
+
+ // set up the title text with a link to the glossary page
+ const glossaryTitle = document.getElementById("glossary-title");
+ glossaryTitle.textContent = "Glossary: " + glossaryItem.title;
+ const linkTarget = searchParam.replace(/ /g, "-");
+ glossaryTitle.href = GLOSSARY_PAGE + "#term-" + linkTarget;
+
+ // rewrite any anchor links (to other glossary terms)
+ // to have a full reference to the glossary page
+ const glossaryBody = document.getElementById("glossary-body");
+ glossaryBody.innerHTML = glossaryItem.body;
+ const anchorLinks = glossaryBody.querySelectorAll('a[href^="#"]');
+ anchorLinks.forEach(function (link) {
+ const currentUrl = link.getAttribute("href");
+ link.href = GLOSSARY_PAGE + currentUrl;
+ });
+
+ const glossaryResult = document.getElementById("glossary-result");
+ glossaryResult.style.display = "";
+};
+
+if (document.readyState !== "loading") {
+ glossary_search().catch(console.error);
+} else {
+ document.addEventListener("DOMContentLoaded", glossary_search);
+}
diff --git a/Doc/tools/templates/download.html b/Doc/tools/templates/download.html
index b5353d6fb77..45ec436fee7 100644
--- a/Doc/tools/templates/download.html
+++ b/Doc/tools/templates/download.html
@@ -1,64 +1,75 @@
{% extends "layout.html" %}
-{% set title = 'Download' %}
+{% set title = _('Download') %}
{% if daily is defined %}
- {% set dlbase = pathto('archives', 1) %}
+ {% set dl_base = pathto('archives', resource=True) %}
+ {% set dl_version = version %}
{% else %}
{#
The link below returns HTTP 404 until the first related alpha release.
This is expected; use daily documentation builds for CPython development.
#}
- {% set dlbase = 'https://docs.python.org/ftp/python/doc/' + release %}
+ {% set dl_base = 'https://www.python.org/ftp/python/doc/' + release %}
+ {% set dl_version = release %}
{% endif %}
{% block body %}
-
Download Python {{ release }} Documentation
+
{% trans %}Download Python {{ dl_version }} Documentation{% endtrans %}
-{% if last_updated %}
Last updated on: {{ last_updated }}.
{% endif %}
+{% if last_updated %}
{% trans %}Last updated on: {{ last_updated }}.{% endtrans %}
{% endif %}
-
To download an archive containing all the documents for this version of
-Python in one of various formats, follow one of links in this table.
+
{% trans %}To download an archive containing all the documents for this version of
+Python in one of various formats, follow one of links in this table.{% endtrans %}
These archives contain all the content in the documentation.
+
{% trans %}These archives contain all the content in the documentation.{% endtrans %}
-
Unpacking
+
{% trans %}Unpacking{% endtrans %}
-
Unix users should download the .tar.bz2 archives; these are bzipped tar
+
{% trans %}Unix users should download the .tar.bz2 archives; these are bzipped tar
archives and can be handled in the usual way using tar and the bzip2
program. The Info-ZIP unzip program can be
used to handle the ZIP archives if desired. The .tar.bz2 archives provide the
-best compression and fastest download times.
+best compression and fastest download times.{% endtrans %}
-
Windows users can use the ZIP archives since those are customary on that
-platform. These are created on Unix using the Info-ZIP zip program.
+
{% trans %}Windows users can use the ZIP archives since those are customary on that
+platform. These are created on Unix using the Info-ZIP zip program.{% endtrans %}
-
Problems
+
{% trans %}Problems{% endtrans %}
-
If you have comments or suggestions for the Python documentation, please send
-email to docs@python.org.
+
{% trans %}If you have comments or suggestions for the Python documentation, please send
+email to docs@python.org.{% endtrans %}
{% endblock %}
diff --git a/Doc/tutorial/appendix.rst b/Doc/tutorial/appendix.rst
index b8faf756698..da664f2f360 100644
--- a/Doc/tutorial/appendix.rst
+++ b/Doc/tutorial/appendix.rst
@@ -14,8 +14,8 @@ There are two variants of the interactive :term:`REPL`. The classic
basic interpreter is supported on all platforms with minimal line
control capabilities.
-On Unix-like systems (e.g. Linux or macOS) with :mod:`curses` and
-:mod:`readline` support, a new interactive shell is used by default.
+On Windows, or Unix-like systems with :mod:`curses` support,
+a new interactive shell is used by default.
This one supports color, multiline editing, history browsing, and
paste mode. To disable color, see :ref:`using-on-controlling-color` for
details. Function keys provide some additional functionality.
diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst
index 1b64741c349..492568961d8 100644
--- a/Doc/tutorial/classes.rst
+++ b/Doc/tutorial/classes.rst
@@ -276,8 +276,8 @@ definition looked like this::
then ``MyClass.i`` and ``MyClass.f`` are valid attribute references, returning
an integer and a function object, respectively. Class attributes can also be
assigned to, so you can change the value of ``MyClass.i`` by assignment.
-:attr:`!__doc__` is also a valid attribute, returning the docstring belonging to
-the class: ``"A simple example class"``.
+:attr:`~type.__doc__` is also a valid attribute, returning the docstring
+belonging to the class: ``"A simple example class"``.
Class *instantiation* uses function notation. Just pretend that the class
object is a parameterless function that returns a new instance of the class.
@@ -688,6 +688,11 @@ current class name with leading underscore(s) stripped. This mangling is done
without regard to the syntactic position of the identifier, as long as it
occurs within the definition of a class.
+.. seealso::
+
+ The :ref:`private name mangling specifications `
+ for details and special cases.
+
Name mangling is helpful for letting subclasses override methods without
breaking intraclass method calls. For example::
@@ -927,6 +932,6 @@ Examples::
.. [#] Except for one thing. Module objects have a secret read-only attribute called
:attr:`~object.__dict__` which returns the dictionary used to implement the module's
- namespace; the name :attr:`~object.__dict__` is an attribute but not a global name.
+ namespace; the name ``__dict__`` is an attribute but not a global name.
Obviously, using this violates the abstraction of namespace implementation, and
should be restricted to things like post-mortem debuggers.
diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst
index 77444f9cb83..fd765e58ff2 100644
--- a/Doc/tutorial/controlflow.rst
+++ b/Doc/tutorial/controlflow.rst
@@ -61,7 +61,7 @@ they appear in the sequence. For example (no pun intended):
::
>>> # Measure some strings:
- ... words = ['cat', 'window', 'defenestrate']
+ >>> words = ['cat', 'window', 'defenestrate']
>>> for w in words:
... print(w, len(w))
...
@@ -160,21 +160,59 @@ arguments. In chapter :ref:`tut-structures`, we will discuss in more detail abo
.. _tut-break:
-:keyword:`!break` and :keyword:`!continue` Statements, and :keyword:`!else` Clauses on Loops
-============================================================================================
+:keyword:`!break` and :keyword:`!continue` Statements
+=====================================================
The :keyword:`break` statement breaks out of the innermost enclosing
-:keyword:`for` or :keyword:`while` loop.
+:keyword:`for` or :keyword:`while` loop::
-A :keyword:`!for` or :keyword:`!while` loop can include an :keyword:`!else` clause.
+ >>> for n in range(2, 10):
+ ... for x in range(2, n):
+ ... if n % x == 0:
+ ... print(f"{n} equals {x} * {n//x}")
+ ... break
+ ...
+ 4 equals 2 * 2
+ 6 equals 2 * 3
+ 8 equals 2 * 4
+ 9 equals 3 * 3
+
+The :keyword:`continue` statement continues with the next
+iteration of the loop::
+
+ >>> for num in range(2, 10):
+ ... if num % 2 == 0:
+ ... print(f"Found an even number {num}")
+ ... continue
+ ... print(f"Found an odd number {num}")
+ ...
+ Found an even number 2
+ Found an odd number 3
+ Found an even number 4
+ Found an odd number 5
+ Found an even number 6
+ Found an odd number 7
+ Found an even number 8
+ Found an odd number 9
+
+.. _tut-for-else:
+
+:keyword:`!else` Clauses on Loops
+=================================
+
+In a :keyword:`!for` or :keyword:`!while` loop the :keyword:`!break` statement
+may be paired with an :keyword:`!else` clause. If the loop finishes without
+executing the :keyword:`!break`, the :keyword:`!else` clause executes.
In a :keyword:`for` loop, the :keyword:`!else` clause is executed
-after the loop reaches its final iteration.
+after the loop finishes its final iteration, that is, if no break occurred.
In a :keyword:`while` loop, it's executed after the loop's condition becomes false.
-In either kind of loop, the :keyword:`!else` clause is **not** executed
-if the loop was terminated by a :keyword:`break`.
+In either kind of loop, the :keyword:`!else` clause is **not** executed if the
+loop was terminated by a :keyword:`break`. Of course, other ways of ending the
+loop early, such as a :keyword:`return` or a raised exception, will also skip
+execution of the :keyword:`else` clause.
This is exemplified in the following :keyword:`!for` loop,
which searches for prime numbers::
@@ -198,32 +236,19 @@ which searches for prime numbers::
9 equals 3 * 3
(Yes, this is the correct code. Look closely: the ``else`` clause belongs to
-the :keyword:`for` loop, **not** the :keyword:`if` statement.)
+the ``for`` loop, **not** the ``if`` statement.)
-When used with a loop, the ``else`` clause has more in common with the
-``else`` clause of a :keyword:`try` statement than it does with that of
-:keyword:`if` statements: a :keyword:`try` statement's ``else`` clause runs
-when no exception occurs, and a loop's ``else`` clause runs when no ``break``
-occurs. For more on the :keyword:`!try` statement and exceptions, see
-:ref:`tut-handling`.
-
-The :keyword:`continue` statement, also borrowed from C, continues with the next
-iteration of the loop::
+One way to think of the else clause is to imagine it paired with the ``if``
+inside the loop. As the loop executes, it will run a sequence like
+if/if/if/else. The ``if`` is inside the loop, encountered a number of times. If
+the condition is ever true, a ``break`` will happen. If the condition is never
+true, the ``else`` clause outside the loop will execute.
- >>> for num in range(2, 10):
- ... if num % 2 == 0:
- ... print("Found an even number", num)
- ... continue
- ... print("Found an odd number", num)
- ...
- Found an even number 2
- Found an odd number 3
- Found an even number 4
- Found an odd number 5
- Found an even number 6
- Found an odd number 7
- Found an even number 8
- Found an odd number 9
+When used with a loop, the ``else`` clause has more in common with the ``else``
+clause of a :keyword:`try` statement than it does with that of ``if``
+statements: a ``try`` statement's ``else`` clause runs when no exception
+occurs, and a loop's ``else`` clause runs when no ``break`` occurs. For more on
+the ``try`` statement and exceptions, see :ref:`tut-handling`.
.. _tut-pass:
@@ -445,7 +470,7 @@ boundary::
... print()
...
>>> # Now call the function we just defined:
- ... fib(2000)
+ >>> fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
.. index::
diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst
index a1492298bdb..73f17adeea7 100644
--- a/Doc/tutorial/datastructures.rst
+++ b/Doc/tutorial/datastructures.rst
@@ -383,16 +383,16 @@ A tuple consists of a number of values separated by commas, for instance::
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
- ... u = t, (1, 2, 3, 4, 5)
+ >>> u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
- ... t[0] = 88888
+ >>> t[0] = 88888
Traceback (most recent call last):
File "", line 1, in
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
- ... v = ([1, 2, 3], [3, 2, 1])
+ >>> v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])
@@ -465,7 +465,7 @@ Here is a brief demonstration::
False
>>> # Demonstrate set operations on unique letters from two words
- ...
+ >>>
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # unique letters in a
diff --git a/Doc/tutorial/errors.rst b/Doc/tutorial/errors.rst
index 981b14f5a42..24fa01428fd 100644
--- a/Doc/tutorial/errors.rst
+++ b/Doc/tutorial/errors.rst
@@ -45,14 +45,20 @@ programs, however, and result in error messages as shown here::
>>> 10 * (1/0)
Traceback (most recent call last):
File "", line 1, in
+ 10 * (1/0)
+ ~^~
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
File "", line 1, in
+ 4 + spam*3
+ ^^^^
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
File "", line 1, in
+ '2' + 2
+ ~~~~^~~
TypeError: can only concatenate str (not "int") to str
The last line of the error message indicates what happened. Exceptions come in
@@ -252,6 +258,7 @@ exception to occur. For example::
>>> raise NameError('HiThere')
Traceback (most recent call last):
File "", line 1, in
+ raise NameError('HiThere')
NameError: HiThere
The sole argument to :keyword:`raise` indicates the exception to be raised.
@@ -275,6 +282,7 @@ re-raise the exception::
An exception flew by!
Traceback (most recent call last):
File "", line 2, in
+ raise NameError('HiThere')
NameError: HiThere
@@ -294,12 +302,15 @@ message::
...
Traceback (most recent call last):
File "", line 2, in
+ open("database.sqlite")
+ ~~~~^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'database.sqlite'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "", line 4, in
+ raise RuntimeError("unable to handle error")
RuntimeError: unable to handle error
To indicate that an exception is a direct consequence of another, the
@@ -320,6 +331,8 @@ This can be useful when you are transforming exceptions. For example::
...
Traceback (most recent call last):
File "", line 2, in
+ func()
+ ~~~~^^
File "", line 2, in func
ConnectionError
@@ -327,6 +340,7 @@ This can be useful when you are transforming exceptions. For example::
Traceback (most recent call last):
File "", line 4, in
+ raise RuntimeError('Failed to open database') from exc
RuntimeError: Failed to open database
It also allows disabling automatic exception chaining using the ``from None``
@@ -339,6 +353,7 @@ idiom::
...
Traceback (most recent call last):
File "", line 4, in
+ raise RuntimeError from None
RuntimeError
For more information about chaining mechanics, see :ref:`bltin-exceptions`.
@@ -381,6 +396,7 @@ example::
Goodbye, world!
Traceback (most recent call last):
File "", line 2, in
+ raise KeyboardInterrupt
KeyboardInterrupt
If a :keyword:`finally` clause is present, the :keyword:`!finally`
@@ -448,7 +464,11 @@ A more complicated example::
executing finally clause
Traceback (most recent call last):
File "", line 1, in
+ divide("2", "0")
+ ~~~~~~^^^^^^^^^^
File "", line 3, in divide
+ result = x / y
+ ~~^~~
TypeError: unsupported operand type(s) for /: 'str' and 'str'
As you can see, the :keyword:`finally` clause is executed in any event. The
@@ -511,8 +531,11 @@ caught like any other exception. ::
>>> f()
+ Exception Group Traceback (most recent call last):
| File "", line 1, in
+ | f()
+ | ~^^
| File "", line 3, in f
- | ExceptionGroup: there were problems
+ | raise ExceptionGroup('there were problems', excs)
+ | ExceptionGroup: there were problems (2 sub-exceptions)
+-+---------------- 1 ----------------
| OSError: error 1
+---------------- 2 ----------------
@@ -560,10 +583,15 @@ other clauses and eventually to be reraised. ::
There were SystemErrors
+ Exception Group Traceback (most recent call last):
| File "", line 2, in
+ | f()
+ | ~^^
| File "", line 2, in f
- | ExceptionGroup: group1
+ | raise ExceptionGroup(
+ | ...<12 lines>...
+ | )
+ | ExceptionGroup: group1 (1 sub-exception)
+-+---------------- 1 ----------------
- | ExceptionGroup: group2
+ | ExceptionGroup: group2 (1 sub-exception)
+-+---------------- 1 ----------------
| RecursionError: 4
+------------------------------------
@@ -607,6 +635,7 @@ includes all notes, in the order they were added, after the exception. ::
...
Traceback (most recent call last):
File "", line 2, in
+ raise TypeError('bad type')
TypeError: bad type
Add some information
Add some more information
@@ -630,23 +659,33 @@ exception in the group has a note indicating when this error has occurred. ::
>>> raise ExceptionGroup('We have some problems', excs)
+ Exception Group Traceback (most recent call last):
| File "", line 1, in
+ | raise ExceptionGroup('We have some problems', excs)
| ExceptionGroup: We have some problems (3 sub-exceptions)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "", line 3, in
+ | f()
+ | ~^^
| File "", line 2, in f
+ | raise OSError('operation failed')
| OSError: operation failed
| Happened in Iteration 1
+---------------- 2 ----------------
| Traceback (most recent call last):
| File "", line 3, in
+ | f()
+ | ~^^
| File "", line 2, in f
+ | raise OSError('operation failed')
| OSError: operation failed
| Happened in Iteration 2
+---------------- 3 ----------------
| Traceback (most recent call last):
| File "", line 3, in
+ | f()
+ | ~^^
| File "", line 2, in f
+ | raise OSError('operation failed')
| OSError: operation failed
| Happened in Iteration 3
+------------------------------------
diff --git a/Doc/tutorial/floatingpoint.rst b/Doc/tutorial/floatingpoint.rst
index 0795e2fef98..dfe2d1d3a83 100644
--- a/Doc/tutorial/floatingpoint.rst
+++ b/Doc/tutorial/floatingpoint.rst
@@ -6,7 +6,7 @@
.. _tut-fp-issues:
**************************************************
-Floating Point Arithmetic: Issues and Limitations
+Floating-Point Arithmetic: Issues and Limitations
**************************************************
.. sectionauthor:: Tim Peters
@@ -88,7 +88,7 @@ the one with 17 significant digits, ``0.10000000000000001``. Starting with
Python 3.1, Python (on most systems) is now able to choose the shortest of
these and simply display ``0.1``.
-Note that this is in the very nature of binary floating-point: this is not a bug
+Note that this is in the very nature of binary floating point: this is not a bug
in Python, and it is not a bug in your code either. You'll see the same kind of
thing in all languages that support your hardware's floating-point arithmetic
(although some languages may not *display* the difference by default, or in all
@@ -148,13 +148,13 @@ Binary floating-point arithmetic holds many surprises like this. The problem
with "0.1" is explained in precise detail below, in the "Representation Error"
section. See `Examples of Floating Point Problems
`_ for
-a pleasant summary of how binary floating-point works and the kinds of
+a pleasant summary of how binary floating point works and the kinds of
problems commonly encountered in practice. Also see
`The Perils of Floating Point `_
for a more complete account of other common surprises.
As that says near the end, "there are no easy answers." Still, don't be unduly
-wary of floating-point! The errors in Python float operations are inherited
+wary of floating point! The errors in Python float operations are inherited
from the floating-point hardware, and on most machines are on the order of no
more than 1 part in 2\*\*53 per operation. That's more than adequate for most
tasks, but you do need to keep in mind that it's not decimal arithmetic and
@@ -230,7 +230,7 @@ accumulate to the point where they affect the final total:
>>> sum([0.1] * 10) == 1.0
True
-The :func:`math.fsum()` goes further and tracks all of the "lost digits"
+The :func:`math.fsum` goes further and tracks all of the "lost digits"
as values are added onto a running total so that the result has only a
single rounding. This is slower than :func:`sum` but will be more
accurate in uncommon cases where large magnitude inputs mostly cancel
diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst
index b93a0e8cec2..2e6fd419b21 100644
--- a/Doc/tutorial/inputoutput.rst
+++ b/Doc/tutorial/inputoutput.rst
@@ -87,12 +87,12 @@ Some examples::
>>> print(s)
The value of x is 32.5, and y is 40000...
>>> # The repr() of a string adds string quotes and backslashes:
- ... hello = 'hello, world\n'
+ >>> hello = 'hello, world\n'
>>> hellos = repr(hello)
>>> print(hellos)
'hello, world\n'
>>> # The argument to repr() may be any Python object:
- ... repr((x, y, ('spam', 'eggs')))
+ >>> repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"
The :mod:`string` module contains a :class:`~string.Template` class that offers
diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst
index 0f16dae8b14..054bac59c95 100644
--- a/Doc/tutorial/introduction.rst
+++ b/Doc/tutorial/introduction.rst
@@ -62,7 +62,7 @@ For example::
20
>>> (50 - 5*6) / 4
5.0
- >>> 8 / 5 # division always returns a floating point number
+ >>> 8 / 5 # division always returns a floating-point number
1.6
The integer numbers (e.g. ``2``, ``4``, ``20``) have type :class:`int`,
@@ -501,8 +501,8 @@ together. For instance, we can write an initial sub-sequence of the
as follows::
>>> # Fibonacci series:
- ... # the sum of two elements defines the next
- ... a, b = 0, 1
+ >>> # the sum of two elements defines the next
+ >>> a, b = 0, 1
>>> while a < 10:
... print(a)
... a, b = b, a+b
@@ -544,7 +544,7 @@ This example introduces several new features.
* The :func:`print` function writes the value of the argument(s) it is given.
It differs from just writing the expression you want to write (as we did
earlier in the calculator examples) in the way it handles multiple arguments,
- floating point quantities, and strings. Strings are printed without quotes,
+ floating-point quantities, and strings. Strings are printed without quotes,
and a space is inserted between items, so you can format things nicely, like
this::
diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst
index 9def2a57149..e96e3431925 100644
--- a/Doc/tutorial/stdlib.rst
+++ b/Doc/tutorial/stdlib.rst
@@ -138,7 +138,7 @@ Mathematics
===========
The :mod:`math` module gives access to the underlying C library functions for
-floating point math::
+floating-point math::
>>> import math
>>> math.cos(math.pi / 4)
diff --git a/Doc/tutorial/stdlib2.rst b/Doc/tutorial/stdlib2.rst
index 8eaf5892558..4f460b8e6ec 100644
--- a/Doc/tutorial/stdlib2.rst
+++ b/Doc/tutorial/stdlib2.rst
@@ -352,11 +352,11 @@ not want to run a full list sort::
.. _tut-decimal-fp:
-Decimal Floating Point Arithmetic
+Decimal Floating-Point Arithmetic
=================================
The :mod:`decimal` module offers a :class:`~decimal.Decimal` datatype for
-decimal floating point arithmetic. Compared to the built-in :class:`float`
+decimal floating-point arithmetic. Compared to the built-in :class:`float`
implementation of binary floating point, the class is especially helpful for
* financial applications and other uses which require exact decimal
diff --git a/Doc/using/android.rst b/Doc/using/android.rst
new file mode 100644
index 00000000000..957705f7f5e
--- /dev/null
+++ b/Doc/using/android.rst
@@ -0,0 +1,65 @@
+.. _using-android:
+
+=======================
+Using Python on Android
+=======================
+
+Python on Android is unlike Python on desktop platforms. On a desktop platform,
+Python is generally installed as a system resource that can be used by any user
+of that computer. Users then interact with Python by running a :program:`python`
+executable and entering commands at an interactive prompt, or by running a
+Python script.
+
+On Android, there is no concept of installing as a system resource. The only unit
+of software distribution is an "app". There is also no console where you could
+run a :program:`python` executable, or interact with a Python REPL.
+
+As a result, the only way you can use Python on Android is in embedded mode – that
+is, by writing a native Android application, embedding a Python interpreter
+using ``libpython``, and invoking Python code using the :ref:`Python embedding
+API `. The full Python interpreter, the standard library, and all
+your Python code is then packaged into your app for its own private use.
+
+The Python standard library has some notable omissions and restrictions on
+Android. See the :ref:`API availability guide ` for
+details.
+
+Adding Python to an Android app
+-------------------------------
+
+These instructions are only needed if you're planning to compile Python for
+Android yourself. Most users should *not* need to do this. Instead, use one of
+the following tools, which will provide a much easier experience:
+
+* `Briefcase `__, from the BeeWare project
+* `Buildozer `__, from the Kivy project
+* `Chaquopy `__
+* `pyqtdeploy `__
+* `Termux `__
+
+If you're sure you want to do all of this manually, read on. You can use the
+:source:`testbed app ` as a guide; each step below contains a
+link to the relevant file.
+
+* Build Python by following the instructions in :source:`Android/README.md`.
+
+* Add code to your :source:`build.gradle `
+ file to copy the following items into your project. All except your own Python
+ code can be copied from ``cross-build/HOST/prefix/lib``:
+
+ * In your JNI libraries:
+
+ * ``libpython*.*.so``
+ * ``lib*_python.so`` (external libraries such as OpenSSL)
+
+ * In your assets:
+
+ * ``python*.*`` (the Python standard library)
+ * ``python*.*/site-packages`` (your own Python code)
+
+* Add code to your app to :source:`extract the assets to the filesystem
+ `.
+
+* Add code to your app to :source:`start Python in embedded mode
+ `. This will need to be C code
+ called via JNI.
diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst
index 0620f7d7114..8f54a0fdebe 100644
--- a/Doc/using/cmdline.rst
+++ b/Doc/using/cmdline.rst
@@ -24,7 +24,7 @@ Command line
When invoking Python, you may specify any of these options::
- python [-bBdEhiIOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]
+ python [-bBdEhiIOPqRsSuvVWx?] [-c command | -m module-name | script | - ] [args]
The most common use case is, of course, a simple invocation of a script::
@@ -441,6 +441,7 @@ Miscellaneous options
-Wdefault # Warn once per call location
-Werror # Convert to exceptions
-Walways # Warn every time
+ -Wall # Same as -Walways
-Wmodule # Warn once per calling module
-Wonce # Warn once per Python process
-Wignore # Never warn
@@ -615,9 +616,9 @@ Miscellaneous options
.. versionadded:: 3.13
* :samp:`-X gil={0,1}` forces the GIL to be disabled or enabled,
- respectively. Only available in builds configured with
+ respectively. Setting to ``0`` is only available in builds configured with
:option:`--disable-gil`. See also :envvar:`PYTHON_GIL` and
- :ref:`free-threaded-cpython`.
+ :ref:`whatsnew313-free-threaded-cpython`.
.. versionadded:: 3.13
@@ -786,6 +787,15 @@ conflict.
This variable can also be modified by Python code using :data:`os.environ`
to force inspect mode on program termination.
+ .. audit-event:: cpython.run_stdin "" ""
+
+ .. versionchanged:: 3.12.5 (also 3.11.10, 3.10.15, 3.9.20, and 3.8.20)
+ Emits audit events.
+
+ .. versionchanged:: 3.13
+ Uses PyREPL if possible, in which case :envvar:`PYTHONSTARTUP` is
+ also executed. Emits audit events.
+
.. envvar:: PYTHONUNBUFFERED
@@ -909,6 +919,7 @@ conflict.
PYTHONWARNINGS=default # Warn once per call location
PYTHONWARNINGS=error # Convert to exceptions
PYTHONWARNINGS=always # Warn every time
+ PYTHONWARNINGS=all # Same as PYTHONWARNINGS=always
PYTHONWARNINGS=module # Warn once per calling module
PYTHONWARNINGS=once # Warn once per Python process
PYTHONWARNINGS=ignore # Never warn
@@ -1014,7 +1025,7 @@ conflict.
'surrogatepass' are used.
This may also be enabled at runtime with
- :func:`sys._enablelegacywindowsfsencoding()`.
+ :func:`sys._enablelegacywindowsfsencoding`.
.. availability:: Windows.
@@ -1204,12 +1215,11 @@ conflict.
.. envvar:: PYTHON_GIL
If this variable is set to ``1``, the global interpreter lock (GIL) will be
- forced on. Setting it to ``0`` forces the GIL off.
+ forced on. Setting it to ``0`` forces the GIL off (needs Python configured with
+ the :option:`--disable-gil` build option).
See also the :option:`-X gil <-X>` command-line option, which takes
- precedence over this variable, and :ref:`free-threaded-cpython`.
-
- Needs Python configured with the :option:`--disable-gil` build option.
+ precedence over this variable, and :ref:`whatsnew313-free-threaded-cpython`.
.. versionadded:: 3.13
diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst
index 428ee527527..052289bd827 100644
--- a/Doc/using/configure.rst
+++ b/Doc/using/configure.rst
@@ -16,8 +16,8 @@ Features and minimum versions required to build CPython:
* On Windows, Microsoft Visual Studio 2017 or later is required.
-* Support for `IEEE 754 `_ floating
- point numbers and `floating point Not-a-Number (NaN)
+* Support for `IEEE 754 `_
+ floating-point numbers and `floating-point Not-a-Number (NaN)
`_.
* Support for threads.
@@ -299,7 +299,7 @@ General Options
Defines the ``Py_GIL_DISABLED`` macro and adds ``"t"`` to
:data:`sys.abiflags`.
- See :ref:`free-threaded-cpython` for more detail.
+ See :ref:`whatsnew313-free-threaded-cpython` for more detail.
.. versionadded:: 3.13
@@ -427,7 +427,7 @@ Options for third-party dependencies
.. option:: PANEL_CFLAGS
.. option:: PANEL_LIBS
- C compiler and Linker flags for PANEL, overriding ``pkg-config``.
+ C compiler and linker flags for PANEL, overriding ``pkg-config``.
C compiler and linker flags for ``libpanel`` or ``libpanelw``, used by
:mod:`curses.panel` module, overriding ``pkg-config``.
@@ -615,7 +615,7 @@ also be used to improve performance.
.. option:: --without-mimalloc
- Disable the fast mimalloc allocator :ref:`mimalloc `
+ Disable the fast :ref:`mimalloc ` allocator
(enabled by default).
See also :envvar:`PYTHONMALLOC` environment variable.
@@ -945,6 +945,17 @@ See :source:`Mac/README.rst`.
Specify the name for the python framework on macOS only valid when
:option:`--enable-framework` is set (default: ``Python``).
+.. option:: --with-app-store-compliance
+.. option:: --with-app-store-compliance=PATCH-FILE
+
+ The Python standard library contains strings that are known to trigger
+ automated inspection tool errors when submitted for distribution by
+ the macOS and iOS App Stores. If enabled, this option will apply the list of
+ patches that are known to correct app store compliance. A custom patch
+ file can also be specified. This option is disabled by default.
+
+ .. versionadded:: 3.13
+
iOS Options
-----------
@@ -1090,7 +1101,7 @@ Remove built files.
make distclean
^^^^^^^^^^^^^^
-In addition to the the work done by ``make clean``, remove files
+In addition to the work done by ``make clean``, remove files
created by the configure script. ``configure`` will have to be run
before building again. [#]_
diff --git a/Doc/using/index.rst b/Doc/using/index.rst
index f55a12f1ab8..90fdfc0bec0 100644
--- a/Doc/using/index.rst
+++ b/Doc/using/index.rst
@@ -12,11 +12,13 @@ interpreter and things that make working with Python easier.
.. toctree::
:numbered:
+ :maxdepth: 2
cmdline.rst
unix.rst
configure.rst
windows.rst
mac.rst
+ android.rst
ios.rst
editors.rst
diff --git a/Doc/using/ios.rst b/Doc/using/ios.rst
index 71fc29c450c..4d4eb2031ee 100644
--- a/Doc/using/ios.rst
+++ b/Doc/using/ios.rst
@@ -33,6 +33,17 @@ running, so you only need to deal with the Python code itself.
Python at runtime on iOS
========================
+iOS version compatibility
+-------------------------
+
+The minimum supported iOS version is specified at compile time, using the
+:option:`--host` option to ``configure``. By default, when compiled for iOS,
+Python will be compiled with a minimum supported iOS version of 13.0. To use a
+different minimum iOS version, provide the version number as part of the
+:option:`!--host` argument - for example,
+``--host=arm64-apple-ios15.4-simulator`` would compile an ARM64 simulator build
+with a deployment target of 15.4.
+
Platform identification
-----------------------
@@ -42,17 +53,17 @@ the simulator or a physical device.
Information about the specific runtime environment, including the iOS version,
device model, and whether the device is a simulator, can be obtained using
-:func:`platform.ios_ver()`. :func:`platform.system()` will report ``iOS`` or
+:func:`platform.ios_ver`. :func:`platform.system` will report ``iOS`` or
``iPadOS``, depending on the device.
-:func:`os.uname()` reports kernel-level details; it will report a name of
+:func:`os.uname` reports kernel-level details; it will report a name of
``Darwin``.
Standard library availability
-----------------------------
The Python standard library has some notable omissions and restrictions on
-iOS. See the :ref:`API availability guide for iOS ` for
+iOS. See the :ref:`API availability guide for iOS ` for
details.
Binary extension modules
@@ -312,3 +323,21 @@ modules in your app, some additional steps will be required:
* If you're using a separate folder for third-party packages, ensure that folder
is included as part of the ``PYTHONPATH`` configuration in step 10.
+
+App Store Compliance
+====================
+
+The only mechanism for distributing apps to third-party iOS devices is to
+submit the app to the iOS App Store; apps submitted for distribution must pass
+Apple's app review process. This process includes a set of automated validation
+rules that inspect the submitted application bundle for problematic code.
+
+The Python standard library contains some code that is known to violate these
+automated rules. While these violations appear to be false positives, Apple's
+review rules cannot be challenged; so, it is necessary to modify the Python
+standard library for an app to pass App Store review.
+
+The Python source tree contains
+:source:`a patch file ` that will remove
+all code that is known to cause issues with the App Store review process. This
+patch is applied automatically when building for iOS.
diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst
index 31d37aad2a7..4b6c884f3d4 100644
--- a/Doc/using/mac.rst
+++ b/Doc/using/mac.rst
@@ -2,140 +2,223 @@
.. _using-on-mac:
*********************
-Using Python on a Mac
+Using Python on macOS
*********************
-:Author: Bob Savage
+.. sectionauthor:: Bob Savage
+.. sectionauthor:: Ned Deily
+This document aims to give an overview of macOS-specific behavior you should
+know about to get started with Python on Mac computers.
+Python on a Mac running macOS is very similar to Python on other Unix-derived platforms,
+but there are some differences in installation and some features.
-Python on a Mac running macOS is in principle very similar to Python on
-any other Unix platform, but there are a number of additional features such as
-the integrated development environment (IDE) and the Package Manager that are
-worth pointing out.
+There are various ways to obtain and install Python for macOS.
+Pre-built versions of the most recent versions of Python are available
+from a number of distributors. Much of this document describes use of
+the Pythons provided by the CPython release team for download from
+the `python.org website `_. See
+:ref:`alternative_bundles` for some other options.
+.. |usemac_x_dot_y| replace:: 3.13
+.. |usemac_python_x_dot_y_literal| replace:: ``python3.13``
+.. |usemac_python_x_dot_y_t_literal| replace:: ``python3.13t``
+.. |usemac_python_x_dot_y_t_literal_config| replace:: ``python3.13t-config``
+.. |usemac_applications_folder_name| replace:: ``Python 3.13``
+.. |usemac_applications_folder_version| replace:: ``/Applications/Python 3.13/``
.. _getting-osx:
.. _getting-and-installing-macpython:
-Getting and Installing Python
-=============================
+Using Python for macOS from ``python.org``
+==========================================
-macOS used to come with Python 2.7 pre-installed between versions
-10.8 and `12.3 `_.
-You are invited to install the most recent version of Python 3 from the `Python
-website `__.
-A current "universal2 binary" build of Python, which runs natively on the Mac's
-new Apple Silicon and legacy Intel processors, is available there.
+Installation steps
+------------------
-What you get after installing is a number of things:
+For `current Python versions `_
+(other than those in ``security`` status), the release team produces a
+**Python for macOS** installer package for each new release.
+A list of available installers
+is available `here `_.
+We recommend using the most recent supported Python version where possible.
+Current installers provide a
+`universal2 binary `_ build
+of Python which runs natively on all Macs (Apple Silicon and Intel) that are
+supported by a wide range of macOS versions,
+currently typically from at least **macOS 10.13 High Sierra** on.
-* A |python_version_literal| folder in your :file:`Applications` folder. In here
- you find IDLE, the development environment that is a standard part of official
+The downloaded file is a standard macOS installer package file (``.pkg``).
+File integrity information (checksum, size, sigstore signature, etc) for each file is included
+on the release download page. Installer packages and their contents are signed and notarized
+with ``Python Software Foundation`` Apple Developer ID certificates
+to meet `macOS Gatekeeper requirements `_.
+
+For a default installation, double-click on the downloaded installer package file.
+This should launch the standard macOS Installer app and display the first of several
+installer windows steps.
+
+.. image:: mac_installer_01_introduction.png
+
+Clicking on the **Continue** button brings up the **Read Me** for this installer.
+Besides other important information, the **Read Me** documents which Python version is
+going to be installed and on what versions of macOS it is supported. You may need
+to scroll through to read the whole file. By default, this **Read Me** will also be
+installed in |usemac_applications_folder_version| and available to read anytime.
+
+.. image:: mac_installer_02_readme.png
+
+Clicking on **Continue** proceeds to display the license for Python and for
+other included software. You will then need to **Agree** to the license terms
+before proceeding to the next step. This license file will also be installed
+and available to be read later.
+
+.. image:: mac_installer_03_license.png
+
+After the license terms are accepted, the next step is the **Installation Type**
+display. For most uses, the standard set of installation operations is appropriate.
+
+.. image:: mac_installer_04_installation_type.png
+
+By pressing the **Customize** button, you can choose to omit or select certain package
+components of the installer. Click on each package name to see a description of
+what it installs.
+To also install support for the optional experimental free-threaded feature,
+see :ref:`install-freethreaded-macos`.
+
+.. image:: mac_installer_05_custom_install.png
+
+In either case, clicking **Install** will begin the install process by asking
+permission to install new software. A macOS user name with ``Administrator`` privilege
+is needed as the installed Python will be available to all users of the Mac.
+
+When the installation is complete, the **Summary** window will appear.
+
+.. image:: mac_installer_06_summary.png
+
+Double-click on the :command:`Install Certificates.command`
+icon or file in the |usemac_applications_folder_version| window to complete the
+installation.
+
+.. image:: mac_installer_07_applications.png
+
+This will open a temporary :program:`Terminal` shell window that
+will use the new Python to download and install SSL root certificates
+for its use.
+
+.. image:: mac_installer_08_install_certificates.png
+
+If ``Successfully installed certifi`` and ``update complete`` appears
+in the terminal window, the installation is complete.
+Close this terminal window and the installer window.
+
+A default install will include:
+
+* A |usemac_applications_folder_name| folder in your :file:`Applications` folder. In here
+ you find :program:`IDLE`, the development environment that is a standard part of official
Python distributions; and :program:`Python Launcher`, which handles double-clicking Python
- scripts from the Finder.
+ scripts from the macOS `Finder `_.
* A framework :file:`/Library/Frameworks/Python.framework`, which includes the
Python executable and libraries. The installer adds this location to your shell
- path. To uninstall Python, you can remove these three things. A
- symlink to the Python executable is placed in :file:`/usr/local/bin/`.
+ path. To uninstall Python, you can remove these three things.
+ Symlinks to the Python executable are placed in :file:`/usr/local/bin/`.
.. note::
- On macOS 10.8-12.3, the Apple-provided build of Python is installed in
- :file:`/System/Library/Frameworks/Python.framework` and :file:`/usr/bin/python`,
- respectively. You should never modify or delete these, as they are
- Apple-controlled and are used by Apple- or third-party software. Remember that
- if you choose to install a newer Python version from python.org, you will have
- two different but functional Python installations on your computer, so it will
- be important that your paths and usages are consistent with what you want to do.
-
-IDLE includes a Help menu that allows you to access Python documentation. If you
-are completely new to Python you should start reading the tutorial introduction
-in that document.
-
-If you are familiar with Python on other Unix platforms you should read the
-section on running Python scripts from the Unix shell.
-
+ Recent versions of macOS include a :command:`python3` command in :file:`/usr/bin/python3`
+ that links to a usually older and incomplete version of Python provided by and for use by
+ the Apple development tools, :program:`Xcode` or the :program:`Command Line Tools for Xcode`.
+ You should never modify or attempt to delete this installation, as it is
+ Apple-controlled and is used by Apple-provided or third-party software. If
+ you choose to install a newer Python version from ``python.org``, you will have
+ two different but functional Python installations on your computer that
+ can co-exist. The default installer options should ensure that its :command:`python3`
+ will be used instead of the system :command:`python3`.
How to run a Python script
--------------------------
-Your best way to get started with Python on macOS is through the IDLE
-integrated development environment; see section :ref:`ide` and use the Help menu
-when the IDE is running.
+There are two ways to invoke the Python interpreter.
+If you are familiar with using a Unix shell in a terminal
+window, you can invoke |usemac_python_x_dot_y_literal| or ``python3`` optionally
+followed by one or more command line options (described in :ref:`using-on-general`).
+The Python tutorial also has a useful section on
+:ref:`using Python interactively from a shell `.
+
+You can also invoke the interpreter through an integrated
+development environment.
+:ref:`idle` is a basic editor and interpreter environment
+which is included with the standard distribution of Python.
+:program:`IDLE` includes a Help menu that allows you to access Python documentation. If you
+are completely new to Python, you can read the tutorial introduction
+in that document.
+
+There are many other editors and IDEs available, see :ref:`editors`
+for more information.
-If you want to run Python scripts from the Terminal window command line or from
-the Finder you first need an editor to create your script. macOS comes with a
-number of standard Unix command line editors, :program:`vim`
-:program:`nano` among them. If you want a more Mac-like editor,
-:program:`BBEdit` from Bare Bones Software (see
-https://www.barebones.com/products/bbedit/index.html) are good choices, as is
-:program:`TextMate` (see https://macromates.com). Other editors include
-:program:`MacVim` (https://macvim.org) and :program:`Aquamacs`
-(https://aquamacs.org).
+To run a Python script file from the terminal window, you can
+invoke the interpreter with the name of the script file:
-To run your script from the Terminal window you must make sure that
-:file:`/usr/local/bin` is in your shell search path.
+ |usemac_python_x_dot_y_literal| ``myscript.py``
-To run your script from the Finder you have two options:
+To run your script from the Finder, you can either:
* Drag it to :program:`Python Launcher`.
* Select :program:`Python Launcher` as the default application to open your
- script (or any ``.py`` script) through the finder Info window and double-click it.
+ script (or any ``.py`` script) through the Finder Info window and double-click it.
:program:`Python Launcher` has various preferences to control how your script is
launched. Option-dragging allows you to change these for one invocation, or use
- its Preferences menu to change things globally.
-
+ its ``Preferences`` menu to change things globally.
-.. _osx-gui-scripts:
-
-Running scripts with a GUI
---------------------------
+Be aware that running the script directly from the macOS Finder might
+produce different results than when running from a terminal window as
+the script will not be run in the usual shell environment including
+any setting of environment variables in shell profiles.
+And, as with any other script or program,
+be certain of what you are about to run.
-With older versions of Python, there is one macOS quirk that you need to be
-aware of: programs that talk to the Aqua window manager (in other words,
-anything that has a GUI) need to be run in a special way. Use :program:`pythonw`
-instead of :program:`python` to start such scripts.
+.. _alternative_bundles:
-With Python 3.9, you can use either :program:`python` or :program:`pythonw`.
+Alternative Distributions
+=========================
+Besides the standard ``python.org`` for macOS installer, there are third-party
+distributions for macOS that may include additional functionality.
+Some popular distributions and their key features:
-Configuration
--------------
+`ActivePython `_
+ Installer with multi-platform compatibility, documentation
-Python on macOS honors all standard Unix environment variables such as
-:envvar:`PYTHONPATH`, but setting these variables for programs started from the
-Finder is non-standard as the Finder does not read your :file:`.profile` or
-:file:`.cshrc` at startup. You need to create a file
-:file:`~/.MacOSX/environment.plist`. See Apple's
-`Technical Q&A QA1067 `__
-for details.
+`Anaconda `_
+ Popular scientific modules (such as numpy, scipy, and pandas) and the
+ ``conda`` package manager.
-For more information on installation Python packages, see section
-:ref:`mac-package-manager`.
+`Homebrew `_
+ Package manager for macOS including multiple versions of Python and many
+ third-party Python-based packages (including numpy, scipy, and pandas).
+`MacPorts `_
+ Another package manager for macOS including multiple versions of Python and many
+ third-party Python-based packages. May include pre-built versions of Python and
+ many packages for older versions of macOS.
-.. _ide:
-
-The IDE
-=======
-
-Python ships with the standard IDLE development environment. A good
-introduction to using IDLE can be found at
-https://www.hashcollision.org/hkn/python/idle_intro/index.html.
-
+Note that distributions might not include the latest versions of Python or
+other libraries, and are not maintained or supported by the core Python team.
.. _mac-package-manager:
Installing Additional Python Packages
=====================================
-This section has moved to the `Python Packaging User Guide`_.
+Refer to the `Python Packaging User Guide`_ for more information.
.. _Python Packaging User Guide: https://packaging.python.org/en/latest/tutorials/installing-packages/
+.. _osx-gui-scripts:
+
.. _gui-programming-on-the-mac:
GUI Programming
@@ -143,36 +226,209 @@ GUI Programming
There are several options for building GUI applications on the Mac with Python.
-*PyObjC* is a Python binding to Apple's Objective-C/Cocoa framework, which is
-the foundation of most modern Mac development. Information on PyObjC is
-available from :pypi:`pyobjc`.
-
The standard Python GUI toolkit is :mod:`tkinter`, based on the cross-platform
-Tk toolkit (https://www.tcl.tk). An Aqua-native version of Tk is bundled with
-macOS by Apple, and the latest version can be downloaded and installed from
-https://www.activestate.com; it can also be built from source.
+Tk toolkit (https://www.tcl.tk). A macOS-native version of Tk is included with
+the installer.
-A number of alternative macOS GUI toolkits are available:
+*PyObjC* is a Python binding to Apple's Objective-C/Cocoa framework.
+Information on PyObjC is available from :pypi:`pyobjc`.
-* `PySide `__: Official Python bindings to the
- `Qt GUI toolkit `__.
+A number of alternative macOS GUI toolkits are available including:
-* `PyQt `__: Alternative
+* `PySide `_: Official Python bindings to the
+ `Qt GUI toolkit `_.
+
+* `PyQt `_: Alternative
Python bindings to Qt.
-* `Kivy `__: A cross-platform GUI toolkit that supports
+* `Kivy `_: A cross-platform GUI toolkit that supports
desktop and mobile platforms.
-* `Toga `__: Part of the `BeeWare Project
- `__; supports desktop, mobile, web and console apps.
+* `Toga `_: Part of the `BeeWare Project
+ `_; supports desktop, mobile, web and console apps.
-* `wxPython `__: A cross-platform toolkit that
+* `wxPython `_: A cross-platform toolkit that
supports desktop operating systems.
+
+Advanced Topics
+===============
+
+.. _install-freethreaded-macos:
+
+Installing Free-threaded Binaries
+---------------------------------
+
+.. versionadded:: 3.13 (Experimental)
+
+.. note::
+
+ Everything described in this section is considered experimental,
+ and should be expected to change in future releases.
+
+The ``python.org`` :ref:`Python for macOS `
+installer package can optionally install an additional build of
+Python |usemac_x_dot_y| that supports :pep:`703`, the experimental free-threading feature
+(running with the :term:`global interpreter lock` disabled).
+Check the release page on ``python.org`` for possible updated information.
+
+Because this feature is still considered experimental, the support for it
+is not installed by default. It is packaged as a separate install option,
+available by clicking the **Customize** button on the **Installation Type**
+step of the installer as described above.
+
+.. image:: mac_installer_09_custom_install_free_threaded.png
+
+If the box next to the **Free-threaded Python** package name is checked,
+a separate :file:`PythonT.framework` will also be installed
+alongside the normal :file:`Python.framework` in :file:`/Library/Frameworks`.
+This configuration allows a free-threaded Python |usemac_x_dot_y| build to co-exist
+on your system with a traditional (GIL only) Python |usemac_x_dot_y| build with
+minimal risk while installing or testing. This installation layout is itself
+experimental and is subject to change in future releases.
+
+Known cautions and limitations:
+
+- The **UNIX command-line tools** package, which is selected by default,
+ will install links in :file:`/usr/local/bin` for |usemac_python_x_dot_y_t_literal|,
+ the free-threaded interpreter, and |usemac_python_x_dot_y_t_literal_config|,
+ a configuration utility which may be useful for package builders.
+ Since :file:`/usr/local/bin` is typically included in your shell ``PATH``,
+ in most cases no changes to your ``PATH`` environment variables should
+ be needed to use |usemac_python_x_dot_y_t_literal|.
+
+- For this release, the **Shell profile updater** package and the
+ :file:`Update Shell Profile.command` in |usemac_applications_folder_version|
+ do not support the free-threaded package.
+
+- The free-threaded build and the traditional build have separate search
+ paths and separate :file:`site-packages` directories so, by default,
+ if you need a package available in both builds, it may need to be installed in both.
+ The free-threaded package will install a separate instance of :program:`pip` for use
+ with |usemac_python_x_dot_y_t_literal|.
+
+ - To install a package using :command:`pip` without a :command:`venv`:
+
+ |usemac_python_x_dot_y_t_literal| ``-m pip install ``
+
+- When working with multiple Python environments, it is usually safest and easiest
+ to :ref:`create and use virtual environments `.
+ This can avoid possible command name conflicts and confusion about which Python is in use:
+
+ |usemac_python_x_dot_y_t_literal| ``-m venv ``
+
+ then :command:`activate`.
+
+- To run a free-threaded version of IDLE:
+
+ |usemac_python_x_dot_y_t_literal| ``-m idlelib``
+
+- The interpreters in both builds respond to the same
+ :ref:`PYTHON environment variables `
+ which may have unexpected results, for example, if you have ``PYTHONPATH``
+ set in a shell profile. If necessary, there are
+ :ref:`command line options ` like ``-E``
+ to ignore these environment variables.
+
+- The free-threaded build links to the third-party shared libraries,
+ such as ``OpenSSL`` and ``Tk``, installed in the traditional framework.
+ This means that both builds also share one set of trust certificates
+ as installed by the :command:`Install Certificates.command` script,
+ thus it only needs to be run once.
+
+- If you cannot depend on the link in ``/usr/local/bin`` pointing to the
+ ``python.org`` free-threaded |usemac_python_x_dot_y_t_literal| (for example, if you want
+ to install your own version there or some other distribution does),
+ you can explicitly set your shell ``PATH`` environment variable to
+ include the ``PythonT`` framework ``bin`` directory:
+
+ .. code-block:: sh
+
+ export PATH="/Library/Frameworks/PythonT.framework/Versions/3.13/bin":"$PATH"
+
+ The traditional framework installation by default does something similar,
+ except for :file:`Python.framework`. Be aware that having both framework ``bin``
+ directories in ``PATH`` can lead to confusion if there are duplicate names
+ like ``python3.13`` in both; which one is actually used depends on the order
+ they appear in ``PATH``. The ``which python3.x`` or ``which python3.xt``
+ commands can show which path is being used. Using virtual environments
+ can help avoid such ambiguities. Another option might be to create
+ a shell :command:`alias` to the desired interpreter, like:
+
+ .. code-block:: sh
+
+ alias py3.13="/Library/Frameworks/Python.framework/Versions/3.13/bin/python3.13"
+ alias py3.13t="/Library/Frameworks/PythonT.framework/Versions/3.13/bin/python3.13t"
+
+Installing using the command line
+---------------------------------
+
+If you want to use automation to install the ``python.org`` installer package
+(rather than by using the familiar macOS :program:`Installer` GUI app),
+the macOS command line :command:`installer` utility lets you select non-default
+options, too. If you are not familiar with :command:`installer`, it can be
+somewhat cryptic (see :command:`man installer` for more information).
+As an example, the following shell snippet shows one way to do it,
+using the ``3.13.0b2`` release and selecting the free-threaded interpreter
+option:
+
+.. code-block:: sh
+
+ RELEASE="python-3.13.0b2-macos11.pkg"
+
+ # download installer pkg
+ curl -O https://www.python.org/ftp/python/3.13.0/${RELEASE}
+
+ # create installer choicechanges to customize the install:
+ # enable the PythonTFramework-3.13 package
+ # while accepting the other defaults (install all other packages)
+ cat > ./choicechanges.plist <
+
+
+
+
+ attributeSetting
+ 1
+ choiceAttribute
+ selected
+ choiceIdentifier
+ org.python.Python.PythonTFramework-3.13
+
+
+
+ EOF
+
+ sudo installer -pkg ./${RELEASE} -applyChoiceChangesXML ./choicechanges.plist -target /
+
+
+You can then test that both installer builds are now available with something like:
+
+.. code-block:: console
+
+ $ # test that the free-threaded interpreter was installed if the Unix Command Tools package was enabled
+ $ /usr/local/bin/python3.13t -VV
+ Python 3.13.0b2 experimental free-threading build (v3.13.0b2:3a83b172af, Jun 5 2024, 12:57:31) [Clang 15.0.0 (clang-1500.3.9.4)]
+ $ # and the traditional interpreter
+ $ /usr/local/bin/python3.13 -VV
+ Python 3.13.0b2 (v3.13.0b2:3a83b172af, Jun 5 2024, 12:50:24) [Clang 15.0.0 (clang-1500.3.9.4)]
+ $ # test that they are also available without the prefix if /usr/local/bin is on $PATH
+ $ python3.13t -VV
+ Python 3.13.0b2 experimental free-threading build (v3.13.0b2:3a83b172af, Jun 5 2024, 12:57:31) [Clang 15.0.0 (clang-1500.3.9.4)]
+ $ python3.13 -VV
+ Python 3.13.0b2 (v3.13.0b2:3a83b172af, Jun 5 2024, 12:50:24) [Clang 15.0.0 (clang-1500.3.9.4)]
+
+.. note::
+
+ Current ``python.org`` installers only install to fixed locations like
+ :file:`/Library/Frameworks/`, :file:`/Applications`, and :file:`/usr/local/bin`.
+ You cannot use the :command:`installer` ``-domain`` option to install to
+ other locations.
+
.. _distributing-python-applications-on-the-mac:
Distributing Python Applications
-================================
+--------------------------------
A range of tools exist for converting your Python code into a standalone
distributable application:
@@ -180,22 +436,39 @@ distributable application:
* :pypi:`py2app`: Supports creating macOS ``.app``
bundles from a Python project.
-* `Briefcase `__: Part of the `BeeWare Project
- `__; a cross-platform packaging tool that supports
+* `Briefcase `_: Part of the `BeeWare Project
+ `_; a cross-platform packaging tool that supports
creation of ``.app`` bundles on macOS, as well as managing signing and
notarization.
-* `PyInstaller `__: A cross-platform packaging tool that creates
+* `PyInstaller `_: A cross-platform packaging tool that creates
a single file or folder as a distributable artifact.
-Other Resources
-===============
+App Store Compliance
+--------------------
+
+Apps submitted for distribution through the macOS App Store must pass Apple's
+app review process. This process includes a set of automated validation rules
+that inspect the submitted application bundle for problematic code.
-The Pythonmac-SIG mailing list is an excellent support resource for Python users
-and developers on the Mac:
+The Python standard library contains some code that is known to violate these
+automated rules. While these violations appear to be false positives, Apple's
+review rules cannot be challenged. Therefore, it is necessary to modify the
+Python standard library for an app to pass App Store review.
-https://www.python.org/community/sigs/current/pythonmac-sig/
+The Python source tree contains
+:source:`a patch file ` that will remove
+all code that is known to cause issues with the App Store review process. This
+patch is applied automatically when CPython is configured with the
+:option:`--with-app-store-compliance` option.
-Another useful resource is the MacPython wiki:
+This patch is not normally required to use CPython on a Mac; nor is it required
+if you are distributing an app *outside* the macOS App Store. It is *only*
+required if you are using the macOS App Store as a distribution channel.
+
+Other Resources
+===============
-https://wiki.python.org/moin/MacPython
+The `python.org Help page `_ has links to many useful resources.
+The `Pythonmac-SIG mailing list `_
+is another support resource specifically for Python users and developers on the Mac.
diff --git a/Doc/using/mac_installer_01_introduction.png b/Doc/using/mac_installer_01_introduction.png
new file mode 100644
index 00000000000..1999f3a3759
Binary files /dev/null and b/Doc/using/mac_installer_01_introduction.png differ
diff --git a/Doc/using/mac_installer_02_readme.png b/Doc/using/mac_installer_02_readme.png
new file mode 100644
index 00000000000..a36efaf7d50
Binary files /dev/null and b/Doc/using/mac_installer_02_readme.png differ
diff --git a/Doc/using/mac_installer_03_license.png b/Doc/using/mac_installer_03_license.png
new file mode 100644
index 00000000000..598c22a13d9
Binary files /dev/null and b/Doc/using/mac_installer_03_license.png differ
diff --git a/Doc/using/mac_installer_04_installation_type.png b/Doc/using/mac_installer_04_installation_type.png
new file mode 100644
index 00000000000..9498fd06240
Binary files /dev/null and b/Doc/using/mac_installer_04_installation_type.png differ
diff --git a/Doc/using/mac_installer_05_custom_install.png b/Doc/using/mac_installer_05_custom_install.png
new file mode 100644
index 00000000000..3a201d2f446
Binary files /dev/null and b/Doc/using/mac_installer_05_custom_install.png differ
diff --git a/Doc/using/mac_installer_06_summary.png b/Doc/using/mac_installer_06_summary.png
new file mode 100644
index 00000000000..1af6eee2c66
Binary files /dev/null and b/Doc/using/mac_installer_06_summary.png differ
diff --git a/Doc/using/mac_installer_07_applications.png b/Doc/using/mac_installer_07_applications.png
new file mode 100644
index 00000000000..940219cad6f
Binary files /dev/null and b/Doc/using/mac_installer_07_applications.png differ
diff --git a/Doc/using/mac_installer_08_install_certificates.png b/Doc/using/mac_installer_08_install_certificates.png
new file mode 100644
index 00000000000..c125eeb18aa
Binary files /dev/null and b/Doc/using/mac_installer_08_install_certificates.png differ
diff --git a/Doc/using/mac_installer_09_custom_install_free_threaded.png b/Doc/using/mac_installer_09_custom_install_free_threaded.png
new file mode 100644
index 00000000000..0f69c55eddb
Binary files /dev/null and b/Doc/using/mac_installer_09_custom_install_free_threaded.png differ
diff --git a/Doc/using/venv-create.inc b/Doc/using/venv-create.inc
deleted file mode 100644
index 354eb1541ce..00000000000
--- a/Doc/using/venv-create.inc
+++ /dev/null
@@ -1,121 +0,0 @@
-Creation of :ref:`virtual environments ` is done by executing the
-command ``venv``::
-
- python -m venv /path/to/new/virtual/environment
-
-Running this command creates the target directory (creating any parent
-directories that don't exist already) and places a ``pyvenv.cfg`` file in it
-with a ``home`` key pointing to the Python installation from which the command
-was run (a common name for the target directory is ``.venv``). It also creates
-a ``bin`` (or ``Scripts`` on Windows) subdirectory containing a copy/symlink
-of the Python binary/binaries (as appropriate for the platform or arguments
-used at environment creation time). It also creates an (initially empty)
-``lib/pythonX.Y/site-packages`` subdirectory (on Windows, this is
-``Lib\site-packages``). If an existing directory is specified, it will be
-re-used.
-
-.. versionchanged:: 3.5
- The use of ``venv`` is now recommended for creating virtual environments.
-
-.. deprecated:: 3.6
- ``pyvenv`` was the recommended tool for creating virtual environments for
- Python 3.3 and 3.4, and is
- :ref:`deprecated in Python 3.6 `.
-
-.. highlight:: none
-
-On Windows, invoke the ``venv`` command as follows::
-
- c:\>Python35\python -m venv c:\path\to\myenv
-
-Alternatively, if you configured the ``PATH`` and ``PATHEXT`` variables for
-your :ref:`Python installation `::
-
- c:\>python -m venv c:\path\to\myenv
-
-The command, if run with ``-h``, will show the available options::
-
- usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear]
- [--upgrade] [--without-pip] [--prompt PROMPT] [--upgrade-deps]
- [--without-scm-ignore-file]
- ENV_DIR [ENV_DIR ...]
-
- Creates virtual Python environments in one or more target directories.
-
- positional arguments:
- ENV_DIR A directory to create the environment in.
-
- options:
- -h, --help show this help message and exit
- --system-site-packages
- Give the virtual environment access to the system
- site-packages dir.
- --symlinks Try to use symlinks rather than copies, when
- symlinks are not the default for the platform.
- --copies Try to use copies rather than symlinks, even when
- symlinks are the default for the platform.
- --clear Delete the contents of the environment directory if
- it already exists, before environment creation.
- --upgrade Upgrade the environment directory to use this
- version of Python, assuming Python has been upgraded
- in-place.
- --without-pip Skips installing or upgrading pip in the virtual
- environment (pip is bootstrapped by default)
- --prompt PROMPT Provides an alternative prompt prefix for this
- environment.
- --upgrade-deps Upgrade core dependencies (pip) to the latest
- version in PyPI
- --without-scm-ignore-file
- Skips adding the default SCM ignore file to the
- environment directory (the default is a .gitignore
- file).
-
- Once an environment has been created, you may wish to activate it, e.g. by
- sourcing an activate script in its bin directory.
-
-.. versionchanged:: 3.13
-
- ``--without-scm-ignore-file`` was added along with creating an ignore file
- for ``git`` by default.
-
-.. versionchanged:: 3.12
-
- ``setuptools`` is no longer a core venv dependency.
-
-.. versionchanged:: 3.9
- Add ``--upgrade-deps`` option to upgrade pip + setuptools to the latest on PyPI
-
-.. versionchanged:: 3.4
- Installs pip by default, added the ``--without-pip`` and ``--copies``
- options
-
-.. versionchanged:: 3.4
- In earlier versions, if the target directory already existed, an error was
- raised, unless the ``--clear`` or ``--upgrade`` option was provided.
-
-.. note::
- While symlinks are supported on Windows, they are not recommended. Of
- particular note is that double-clicking ``python.exe`` in File Explorer
- will resolve the symlink eagerly and ignore the virtual environment.
-
-.. note::
- On Microsoft Windows, it may be required to enable the ``Activate.ps1``
- script by setting the execution policy for the user. You can do this by
- issuing the following PowerShell command:
-
- PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
-
- See `About Execution Policies
- `_
- for more information.
-
-The created ``pyvenv.cfg`` file also includes the
-``include-system-site-packages`` key, set to ``true`` if ``venv`` is
-run with the ``--system-site-packages`` option, ``false`` otherwise.
-
-Unless the ``--without-pip`` option is given, :mod:`ensurepip` will be
-invoked to bootstrap ``pip`` into the virtual environment.
-
-Multiple paths can be given to ``venv``, in which case an identical virtual
-environment will be created, according to the given options, at each provided
-path.
diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst
index ef98d32e867..136236f51eb 100644
--- a/Doc/using/windows.rst
+++ b/Doc/using/windows.rst
@@ -608,7 +608,7 @@ key features:
Popular scientific modules (such as numpy, scipy and pandas) and the
``conda`` package manager.
-`Enthought Deployment Manager `_
+`Enthought Deployment Manager `_
"The Next Generation Python Environment and Package Manager".
Previously Enthought provided Canopy, but it `reached end of life in 2016
@@ -1305,7 +1305,7 @@ shipped with PyWin32. It is an embeddable IDE with a built-in debugger.
.. seealso::
- `Win32 How Do I...? `_
+ `Win32 How Do I...? `_
by Tim Golden
`Python and COM `_
diff --git a/Doc/whatsnew/2.1.rst b/Doc/whatsnew/2.1.rst
index b4002f06e92..f23f27c994d 100644
--- a/Doc/whatsnew/2.1.rst
+++ b/Doc/whatsnew/2.1.rst
@@ -443,8 +443,8 @@ Python syntax::
f.grammar = "A ::= B (C D)*"
The dictionary containing attributes can be accessed as the function's
-:attr:`~object.__dict__`. Unlike the :attr:`~object.__dict__` attribute of class instances, in
-functions you can actually assign a new dictionary to :attr:`~object.__dict__`, though
+:attr:`~function.__dict__`. Unlike the :attr:`~type.__dict__` attribute of class instances, in
+functions you can actually assign a new dictionary to :attr:`~function.__dict__`, though
the new value is restricted to a regular Python dictionary; you *can't* be
tricky and set it to a :class:`!UserDict` instance, or any other random object
that behaves like a mapping.
@@ -644,9 +644,9 @@ New and Improved Modules
lists the function arguments and the local variables for each frame.
* Various functions in the :mod:`time` module, such as :func:`~time.asctime` and
- :func:`~time.localtime`, require a floating point argument containing the time in
+ :func:`~time.localtime`, require a floating-point argument containing the time in
seconds since the epoch. The most common use of these functions is to work with
- the current time, so the floating point argument has been made optional; when a
+ the current time, so the floating-point argument has been made optional; when a
value isn't provided, the current time will be used. For example, log file
entries usually need a string containing the current time; in Python 2.1,
``time.asctime()`` can be used, instead of the lengthier
diff --git a/Doc/whatsnew/2.2.rst b/Doc/whatsnew/2.2.rst
index d4dbe0570fb..856be5ecfa5 100644
--- a/Doc/whatsnew/2.2.rst
+++ b/Doc/whatsnew/2.2.rst
@@ -171,7 +171,7 @@ attributes of their own:
* :attr:`~definition.__name__` is the attribute's name.
-* :attr:`!__doc__` is the attribute's docstring.
+* :attr:`~definition.__doc__` is the attribute's docstring.
* ``__get__(object)`` is a method that retrieves the attribute value from
*object*.
@@ -186,7 +186,8 @@ are::
descriptor = obj.__class__.x
descriptor.__get__(obj)
-For methods, :meth:`!descriptor.__get__` returns a temporary object that's
+For methods, :meth:`descriptor.__get__ ` returns a temporary
+object that's
callable, and wraps up the instance and the method to be called on it. This is
also why static methods and class methods are now possible; they have
descriptors that wrap up just the method, or the method and the class. As a
@@ -1249,7 +1250,7 @@ Some of the more notable changes are:
* The :func:`pow` built-in function no longer supports 3 arguments when
floating-point numbers are supplied. ``pow(x, y, z)`` returns ``(x**y) % z``,
- but this is never useful for floating point numbers, and the final result varies
+ but this is never useful for floating-point numbers, and the final result varies
unpredictably depending on the platform. A call such as ``pow(2.0, 8.0, 7.0)``
will now raise a :exc:`TypeError` exception.
diff --git a/Doc/whatsnew/2.3.rst b/Doc/whatsnew/2.3.rst
index 8adf36e316c..ac463f82cfb 100644
--- a/Doc/whatsnew/2.3.rst
+++ b/Doc/whatsnew/2.3.rst
@@ -1113,10 +1113,10 @@ Here are all of the changes that Python 2.3 makes to the core Python language.
* One of the noted incompatibilities between old- and new-style classes has been
- removed: you can now assign to the :attr:`~definition.__name__` and :attr:`~class.__bases__`
+ removed: you can now assign to the :attr:`~type.__name__` and :attr:`~type.__bases__`
attributes of new-style classes. There are some restrictions on what can be
- assigned to :attr:`~class.__bases__` along the lines of those relating to assigning to
- an instance's :attr:`~instance.__class__` attribute.
+ assigned to :attr:`!__bases__` along the lines of those relating to assigning to
+ an instance's :attr:`~object.__class__` attribute.
.. ======================================================================
@@ -1382,7 +1382,7 @@ complete list of changes, or look through the CVS logs for all the details.
In Python 2.4, the default will change to always returning floats.
Application developers should enable this feature only if all their libraries
- work properly when confronted with floating point time stamps, or if they use
+ work properly when confronted with floating-point time stamps, or if they use
the tuple API. If used, the feature should be activated on an application level
instead of trying to enable it on a per-use basis.
@@ -1925,8 +1925,8 @@ Changes to Python's build process and to the C API include:
dependence on a system version or local installation of Expat.
* If you dynamically allocate type objects in your extension, you should be
- aware of a change in the rules relating to the :attr:`!__module__` and
- :attr:`~definition.__name__` attributes. In summary, you will want to ensure the type's
+ aware of a change in the rules relating to the :attr:`~type.__module__` and
+ :attr:`~type.__name__` attributes. In summary, you will want to ensure the type's
dictionary contains a ``'__module__'`` key; making the module name the part of
the type name leading up to the final period will no longer have the desired
effect. For more detail, read the API reference documentation or the source.
diff --git a/Doc/whatsnew/2.4.rst b/Doc/whatsnew/2.4.rst
index 7e235d4370e..7628cfefe0e 100644
--- a/Doc/whatsnew/2.4.rst
+++ b/Doc/whatsnew/2.4.rst
@@ -684,11 +684,11 @@ includes a quick-start tutorial and a reference.
Written by Facundo Batista and implemented by Facundo Batista, Eric Price,
Raymond Hettinger, Aahz, and Tim Peters.
- http://www.lahey.com/float.htm
+ `http://www.lahey.com/float.htm `__
The article uses Fortran code to illustrate many of the problems that
floating-point inaccuracy can cause.
- http://speleotrove.com/decimal/
+ https://speleotrove.com/decimal/
A description of a decimal-based representation. This representation is being
proposed as a standard, and underlies the new Python decimal type. Much of this
material was written by Mike Cowlishaw, designer of the Rexx language.
@@ -757,7 +757,7 @@ API that perform ASCII-only conversions, ignoring the locale setting:
:c:expr:`double` to an ASCII string.
The code for these functions came from the GLib library
-(https://developer-old.gnome.org/glib/2.26/), whose developers kindly
+(`https://developer-old.gnome.org/glib/2.26/ `__), whose developers kindly
relicensed the relevant functions and donated them to the Python Software
Foundation. The :mod:`locale` module can now change the numeric locale,
letting extensions such as GTK+ produce the correct results.
diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst
index fc2de712485..3c9c2049b89 100644
--- a/Doc/whatsnew/2.6.rst
+++ b/Doc/whatsnew/2.6.rst
@@ -1453,7 +1453,7 @@ that will be the numerator and denominator of the resulting fraction. ::
Fraction(5, 3)
For converting floating-point numbers to rationals,
-the float type now has an :meth:`as_integer_ratio()` method that returns
+the float type now has an :meth:`as_integer_ratio` method that returns
the numerator and denominator for a fraction that evaluates to the same
floating-point value::
@@ -2273,7 +2273,7 @@ changes, or look through the Subversion logs for all the details.
(Contributed by Guido van Rossum from work for Google App Engine;
:issue:`3487`.)
-* The :mod:`rlcompleter` module's :meth:`Completer.complete()` method
+* The :mod:`rlcompleter` module's :meth:`Completer.complete` method
will now ignore exceptions triggered while evaluating a name.
(Fixed by Lorenz Quack; :issue:`2250`.)
@@ -2566,7 +2566,7 @@ changes, or look through the Subversion logs for all the details.
:meth:`tracer`, and :meth:`speed` methods.
* The ability to set new shapes for the turtle, and to
define a new coordinate system.
- * Turtles now have an :meth:`undo()` method that can roll back actions.
+ * Turtles now have an :meth:`undo` method that can roll back actions.
* Simple support for reacting to input events such as mouse and keyboard
activity, making it possible to write simple games.
* A :file:`turtle.cfg` file can be used to customize the starting appearance
@@ -3051,7 +3051,7 @@ Changes to Python's build process and to the C API include:
* Several functions return information about the platform's
floating-point support. :c:func:`PyFloat_GetMax` returns
- the maximum representable floating point value,
+ the maximum representable floating-point value,
and :c:func:`PyFloat_GetMin` returns the minimum
positive value. :c:func:`PyFloat_GetInfo` returns an object
containing more information from the :file:`float.h` file, such as
diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst
index c45f0887b41..0e4dee0bd24 100644
--- a/Doc/whatsnew/2.7.rst
+++ b/Doc/whatsnew/2.7.rst
@@ -291,7 +291,7 @@ modules.
configuration files can now be read, modified, and then written back
in their original order.
-* The :meth:`~collections.somenamedtuple._asdict()` method for
+* The :meth:`~collections.somenamedtuple._asdict` method for
:func:`collections.namedtuple` now returns an ordered dictionary with the
values appearing in the same order as the underlying tuple indices.
@@ -1198,7 +1198,7 @@ changes, or look through the Subversion logs for all the details.
of the operands. Previously such comparisons would fall back to
Python's default rules for comparing objects, which produced arbitrary
results based on their type. Note that you still cannot combine
- :class:`!Decimal` and floating-point in other operations such as addition,
+ :class:`!Decimal` and floating point in other operations such as addition,
since you should be explicitly choosing how to convert between float and
:class:`!Decimal`. (Fixed by Mark Dickinson; :issue:`2531`.)
@@ -1548,7 +1548,7 @@ changes, or look through the Subversion logs for all the details.
*ciphers* argument that's a string listing the encryption algorithms
to be allowed; the format of the string is described
`in the OpenSSL documentation
- `__.
+ `__.
(Added by Antoine Pitrou; :issue:`8322`.)
Another change makes the extension load all of OpenSSL's ciphers and
@@ -2680,14 +2680,12 @@ automatic ``PATH`` modifications to have ``pip`` available from the command
line by default, otherwise it can still be accessed through the Python
launcher for Windows as ``py -m pip``.
-As `discussed in the PEP`__, platform packagers may choose not to install
+As :pep:`discussed in the PEP <0477#disabling-ensurepip-by-downstream-distributors>`,
+platform packagers may choose not to install
these commands by default, as long as, when invoked, they provide clear and
simple directions on how to install them on that platform (usually using
the system package manager).
-__ https://peps.python.org/pep-0477/#disabling-ensurepip-by-downstream-distributors
-
-
Documentation Changes
~~~~~~~~~~~~~~~~~~~~~
diff --git a/Doc/whatsnew/3.1.rst b/Doc/whatsnew/3.1.rst
index 69b273e5838..b9606beb5f9 100644
--- a/Doc/whatsnew/3.1.rst
+++ b/Doc/whatsnew/3.1.rst
@@ -205,9 +205,9 @@ Some smaller changes made to the core Python language are:
(Contributed by Mark Dickinson; :issue:`4707`.)
-* Python now uses David Gay's algorithm for finding the shortest floating
- point representation that doesn't change its value. This should help
- mitigate some of the confusion surrounding binary floating point
+* Python now uses David Gay's algorithm for finding the shortest floating-point
+ representation that doesn't change its value. This should help
+ mitigate some of the confusion surrounding binary floating-point
numbers.
The significance is easily seen with a number like ``1.1`` which does not
@@ -215,7 +215,7 @@ Some smaller changes made to the core Python language are:
equivalent, an expression like ``float('1.1')`` evaluates to the nearest
representable value which is ``0x1.199999999999ap+0`` in hex or
``1.100000000000000088817841970012523233890533447265625`` in decimal. That
- nearest value was and still is used in subsequent floating point
+ nearest value was and still is used in subsequent floating-point
calculations.
What is new is how the number gets displayed. Formerly, Python used a
@@ -224,7 +224,7 @@ Some smaller changes made to the core Python language are:
using 17 digits was that it relied on IEEE-754 guarantees to assure that
``eval(repr(1.1))`` would round-trip exactly to its original value. The
disadvantage is that many people found the output to be confusing (mistaking
- intrinsic limitations of binary floating point representation as being a
+ intrinsic limitations of binary floating-point representation as being a
problem with Python itself).
The new algorithm for ``repr(1.1)`` is smarter and returns ``'1.1'``.
@@ -236,8 +236,8 @@ Some smaller changes made to the core Python language are:
it does not change the underlying values. So, it is still the case that
``1.1 + 2.2 != 3.3`` even though the representations may suggest otherwise.
- The new algorithm depends on certain features in the underlying floating
- point implementation. If the required features are not found, the old
+ The new algorithm depends on certain features in the underlying floating-point
+ implementation. If the required features are not found, the old
algorithm will continue to be used. Also, the text pickle protocols
assure cross-platform portability by using the old algorithm.
@@ -550,7 +550,7 @@ Porting to Python 3.1
This section lists previously described changes and other bugfixes
that may require changes to your code:
-* The new floating point string representations can break existing doctests.
+* The new floating-point string representations can break existing doctests.
For example::
def e():
diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst
index b939ccd1790..e4699fbf8ed 100644
--- a/Doc/whatsnew/3.10.rst
+++ b/Doc/whatsnew/3.10.rst
@@ -1233,7 +1233,7 @@ also now un-stringize stringized annotations.
itertools
---------
-Add :func:`itertools.pairwise()`.
+Add :func:`itertools.pairwise`.
(Contributed by Raymond Hettinger in :issue:`38200`.)
linecache
@@ -1245,14 +1245,14 @@ When a module does not define ``__loader__``, fall back to ``__spec__.loader``.
os
--
-Add :func:`os.cpu_count()` support for VxWorks RTOS.
+Add :func:`os.cpu_count` support for VxWorks RTOS.
(Contributed by Peixing Xin in :issue:`41440`.)
Add a new function :func:`os.eventfd` and related helpers to wrap the
``eventfd2`` syscall on Linux.
(Contributed by Christian Heimes in :issue:`41001`.)
-Add :func:`os.splice()` that allows to move data between two file
+Add :func:`os.splice` that allows to move data between two file
descriptors without copying between kernel address space and user
address space, where one of the file descriptors must refer to a
pipe. (Contributed by Pablo Galindo in :issue:`41625`.)
@@ -1292,7 +1292,7 @@ functions in the :mod:`os` module.
platform
--------
-Add :func:`platform.freedesktop_os_release()` to retrieve operation system
+Add :func:`platform.freedesktop_os_release` to retrieve operation system
identification from `freedesktop.org os-release
`_ standard file.
(Contributed by Christian Heimes in :issue:`28468`.)
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index b601bd453f5..d59f24406c9 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -2032,8 +2032,8 @@ Removed C APIs are :ref:`listed separately `.
It was introduced in Python 3.4 but has been broken since Python 3.7.
(Contributed by Inada Naoki in :issue:`23882`.)
-* Removed the undocumented private :meth:`!float.__set_format__()` method,
- previously known as :meth:`!float.__setformat__()` in Python 3.7.
+* Removed the undocumented private :meth:`!float.__set_format__` method,
+ previously known as :meth:`!float.__setformat__` in Python 3.7.
Its docstring said: "You probably don't want to use this function.
It exists mainly to be used in Python's test suite."
(Contributed by Victor Stinner in :issue:`46852`.)
@@ -2138,7 +2138,7 @@ Build Changes
:issue:`45440` and :issue:`46640`.)
* Support for `IEEE 754 `_
- floating point numbers.
+ floating-point numbers.
(Contributed by Victor Stinner in :issue:`46917`.)
* The :c:macro:`!Py_NO_NAN` macro has been removed.
diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst
index 8e2c85a5821..0799c354dde 100644
--- a/Doc/whatsnew/3.12.rst
+++ b/Doc/whatsnew/3.12.rst
@@ -59,7 +59,7 @@ Summary -- Release highlights
.. This section singles out the most important changes in Python 3.12.
Brevity is key.
-Python 3.12 is the latest stable release of the Python programming language,
+Python 3.12 is a stable release of the Python programming language,
with a mix of changes to the language and the standard library.
The library changes focus on cleaning up deprecated APIs, usability, and correctness.
Of note, the :mod:`!distutils` package has been removed from the standard library.
@@ -154,7 +154,7 @@ Important deprecations, removals or restrictions:
reducing the size of every :class:`str` object by at least 8 bytes.
* :pep:`632`: Remove the :mod:`!distutils` package.
- See `the migration guide `_
+ See :pep:`the migration guide <0632#migration-advice>`
for advice replacing the APIs it provided.
The third-party `Setuptools `__
package continues to provide :mod:`!distutils`,
@@ -359,7 +359,7 @@ create an interpreter with its own GIL:
/* The new interpreter is now active in the current thread. */
For further examples how to use the C-API for sub-interpreters with a
-per-interpreter GIL, see :source:`Modules/_xxsubinterpretersmodule.c`.
+per-interpreter GIL, see ``Modules/_xxsubinterpretersmodule.c``.
(Contributed by Eric Snow in :gh:`104210`, etc.)
@@ -1254,7 +1254,7 @@ Deprecated
We added the warning to raise awareness as issues encountered by code doing
this are becoming more frequent. See the :func:`os.fork` documentation for
more details along with `this discussion on fork being incompatible with threads
- `_ for *why* we're now surfacing this
+ `_ for *why* we're now surfacing this
longstanding platform compatibility problem to developers.
When this warning appears due to usage of :mod:`multiprocessing` or
@@ -1319,7 +1319,7 @@ Deprecated
(Contributed by Brett Cannon in :gh:`65961`.)
* The bitwise inversion operator (``~``) on bool is deprecated. It will throw an
- error in Python 3.14. Use ``not`` for logical negation of bools instead.
+ error in Python 3.16. Use ``not`` for logical negation of bools instead.
In the rare case that you really need the bitwise inversion of the underlying
``int``, convert to int explicitly: ``~int(x)``. (Contributed by Tim Hoffmann
in :gh:`103487`.)
@@ -1330,155 +1330,15 @@ Deprecated
therefore it will be removed in 3.14.
(Contributed by Nikita Sobolev in :gh:`101866`.)
-Pending Removal in Python 3.13
-------------------------------
-
-The following modules and APIs have been deprecated in earlier Python releases,
-and will be removed in Python 3.13.
-
-Modules (see :pep:`594`):
-
-* :mod:`!aifc`
-* :mod:`!audioop`
-* :mod:`!cgi`
-* :mod:`!cgitb`
-* :mod:`!chunk`
-* :mod:`!crypt`
-* :mod:`!imghdr`
-* :mod:`!mailcap`
-* :mod:`!msilib`
-* :mod:`!nis`
-* :mod:`!nntplib`
-* :mod:`!ossaudiodev`
-* :mod:`!pipes`
-* :mod:`!sndhdr`
-* :mod:`!spwd`
-* :mod:`!sunau`
-* :mod:`!telnetlib`
-* :mod:`!uu`
-* :mod:`!xdrlib`
-
-Other modules:
-
-* :mod:`!lib2to3`, and the :program:`2to3` program (:gh:`84540`)
-
-APIs:
-
-* :class:`!configparser.LegacyInterpolation` (:gh:`90765`)
-* ``locale.resetlocale()`` (:gh:`90817`)
-* :meth:`!turtle.RawTurtle.settiltangle` (:gh:`50096`)
-* :func:`!unittest.findTestCases` (:gh:`50096`)
-* :func:`!unittest.getTestCaseNames` (:gh:`50096`)
-* :func:`!unittest.makeSuite` (:gh:`50096`)
-* :meth:`!unittest.TestProgram.usageExit` (:gh:`67048`)
-* :class:`!webbrowser.MacOSX` (:gh:`86421`)
-* :class:`classmethod` descriptor chaining (:gh:`89519`)
-* :mod:`importlib.resources` deprecated methods:
-
- * ``contents()``
- * ``is_resource()``
- * ``open_binary()``
- * ``open_text()``
- * ``path()``
- * ``read_binary()``
- * ``read_text()``
-
- Use :func:`importlib.resources.files()` instead. Refer to `importlib-resources: Migrating from Legacy
- `_ (:gh:`106531`)
-
-Pending Removal in Python 3.14
-------------------------------
-
-The following APIs have been deprecated
-and will be removed in Python 3.14.
-
-* :mod:`argparse`: The *type*, *choices*, and *metavar* parameters
- of :class:`!argparse.BooleanOptionalAction`
-
-* :mod:`ast`:
-
- * :class:`!ast.Num`
- * :class:`!ast.Str`
- * :class:`!ast.Bytes`
- * :class:`!ast.NameConstant`
- * :class:`!ast.Ellipsis`
-
-* :mod:`asyncio`:
-
- * :class:`!asyncio.MultiLoopChildWatcher`
- * :class:`!asyncio.FastChildWatcher`
- * :class:`!asyncio.AbstractChildWatcher`
- * :class:`!asyncio.SafeChildWatcher`
- * :func:`!asyncio.set_child_watcher`
- * :func:`!asyncio.get_child_watcher`,
- * :meth:`!asyncio.AbstractEventLoopPolicy.set_child_watcher`
- * :meth:`!asyncio.AbstractEventLoopPolicy.get_child_watcher`
-
-* :mod:`collections.abc`: :class:`!collections.abc.ByteString`.
-
-* :mod:`email`: the *isdst* parameter in :func:`email.utils.localtime`.
-
-* :mod:`importlib.abc`:
-
- * :class:`!importlib.abc.ResourceReader`
- * :class:`!importlib.abc.Traversable`
- * :class:`!importlib.abc.TraversableResources`
-
-* :mod:`itertools`: Support for copy, deepcopy, and pickle operations.
-
-* :mod:`pkgutil`:
-
- * :func:`!pkgutil.find_loader`
- * :func:`!pkgutil.get_loader`.
-
-* :mod:`pty`:
-
- * :func:`!pty.master_open`
- * :func:`!pty.slave_open`
-
-* :mod:`shutil`: The *onerror* argument of :func:`shutil.rmtree`
-
-* :mod:`typing`: :class:`!typing.ByteString`
-
-* The ``__package__`` and ``__cached__`` attributes on module objects.
-
-* The :attr:`~codeobject.co_lnotab` attribute of code objects.
-
-Pending Removal in Python 3.15
-------------------------------
+.. include:: ../deprecations/pending-removal-in-3.13.rst
-The following APIs have been deprecated
-and will be removed in Python 3.15.
+.. include:: ../deprecations/pending-removal-in-3.14.rst
-APIs:
+.. include:: ../deprecations/pending-removal-in-3.15.rst
-* :func:`locale.getdefaultlocale` (:gh:`90817`)
-
-
-Pending Removal in Future Versions
-----------------------------------
-
-The following APIs were deprecated in earlier Python versions and will be removed,
-although there is currently no date scheduled for their removal.
-
-* :mod:`array`'s ``'u'`` format code (:gh:`57281`)
-
-* :class:`typing.Text` (:gh:`92332`)
-
-* :mod:`xml.etree.ElementTree`: Testing the truth value of an
- :class:`xml.etree.ElementTree.Element` is deprecated. In a future release it
- will always return True. Prefer explicit ``len(elem)`` or
- ``elem is not None`` tests instead.
-
-* Currently Python accepts numeric literals immediately followed by keywords,
- for example ``0in x``, ``1or x``, ``0if 1else 2``. It allows confusing
- and ambiguous expressions like ``[0x1for x in y]`` (which can be
- interpreted as ``[0x1 for x in y]`` or ``[0x1f or x in y]``).
- A syntax warning is raised if the numeric literal is
- immediately followed by one of keywords :keyword:`and`, :keyword:`else`,
- :keyword:`for`, :keyword:`if`, :keyword:`in`, :keyword:`is` and :keyword:`or`.
- In a future release it will be changed to a syntax error. (:gh:`87999`)
+.. include:: ../deprecations/pending-removal-in-3.16.rst
+.. include:: ../deprecations/pending-removal-in-future.rst
Removed
=======
@@ -1562,9 +1422,9 @@ hashlib
-------
* Remove the pure Python implementation of :mod:`hashlib`'s
- :func:`hashlib.pbkdf2_hmac()`, deprecated in Python 3.10. Python 3.10 and
+ :func:`hashlib.pbkdf2_hmac`, deprecated in Python 3.10. Python 3.10 and
newer requires OpenSSL 1.1.1 (:pep:`644`): this OpenSSL version provides
- a C implementation of :func:`~hashlib.pbkdf2_hmac()` which is faster.
+ a C implementation of :func:`~hashlib.pbkdf2_hmac` which is faster.
(Contributed by Victor Stinner in :gh:`94199`.)
importlib
@@ -1573,7 +1433,7 @@ importlib
* Many previously deprecated cleanups in :mod:`importlib` have now been
completed:
- * References to, and support for :meth:`!module_repr()` has been removed.
+ * References to, and support for :meth:`!module_repr` has been removed.
(Contributed by Barry Warsaw in :gh:`97850`.)
* ``importlib.util.set_package``, ``importlib.util.set_loader`` and
@@ -2027,7 +1887,7 @@ New Features
The :c:macro:`Py_TPFLAGS_MANAGED_DICT` and :c:macro:`Py_TPFLAGS_MANAGED_WEAKREF`
flags have been added. This allows extensions classes to support object
- ``__dict__`` and weakrefs with less bookkeeping,
+ :attr:`~object.__dict__` and weakrefs with less bookkeeping,
using less memory and with faster access.
* API for performing calls using
@@ -2146,7 +2006,7 @@ Porting to Python 3.12
internal-only field directly.
To get a list of subclasses, call the Python method
- :py:meth:`~class.__subclasses__` (using :c:func:`PyObject_CallMethod`,
+ :py:meth:`~type.__subclasses__` (using :c:func:`PyObject_CallMethod`,
for example).
* Add support of more formatting options (left aligning, octals, uppercase
@@ -2165,7 +2025,7 @@ Porting to Python 3.12
:c:func:`PyUnicode_FromFormatV`.
(Contributed by Philip Georgi in :gh:`95504`.)
-* Extension classes wanting to add a ``__dict__`` or weak reference slot
+* Extension classes wanting to add a :attr:`~object.__dict__` or weak reference slot
should use :c:macro:`Py_TPFLAGS_MANAGED_DICT` and
:c:macro:`Py_TPFLAGS_MANAGED_WEAKREF` instead of ``tp_dictoffset`` and
``tp_weaklistoffset``, respectively.
@@ -2350,92 +2210,13 @@ Deprecated
overrides :c:member:`~PyTypeObject.tp_new` is deprecated.
Call the metaclass instead.
-Pending Removal in Python 3.14
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-* The ``ma_version_tag`` field in :c:type:`PyDictObject` for extension modules
- (:pep:`699`; :gh:`101193`).
-
-* Global configuration variables:
+.. Add deprecations above alphabetically, not here at the end.
- * :c:var:`Py_DebugFlag`: use :c:member:`PyConfig.parser_debug`
- * :c:var:`Py_VerboseFlag`: use :c:member:`PyConfig.verbose`
- * :c:var:`Py_QuietFlag`: use :c:member:`PyConfig.quiet`
- * :c:var:`Py_InteractiveFlag`: use :c:member:`PyConfig.interactive`
- * :c:var:`Py_InspectFlag`: use :c:member:`PyConfig.inspect`
- * :c:var:`Py_OptimizeFlag`: use :c:member:`PyConfig.optimization_level`
- * :c:var:`Py_NoSiteFlag`: use :c:member:`PyConfig.site_import`
- * :c:var:`Py_BytesWarningFlag`: use :c:member:`PyConfig.bytes_warning`
- * :c:var:`Py_FrozenFlag`: use :c:member:`PyConfig.pathconfig_warnings`
- * :c:var:`Py_IgnoreEnvironmentFlag`: use :c:member:`PyConfig.use_environment`
- * :c:var:`Py_DontWriteBytecodeFlag`: use :c:member:`PyConfig.write_bytecode`
- * :c:var:`Py_NoUserSiteDirectory`: use :c:member:`PyConfig.user_site_directory`
- * :c:var:`Py_UnbufferedStdioFlag`: use :c:member:`PyConfig.buffered_stdio`
- * :c:var:`Py_HashRandomizationFlag`: use :c:member:`PyConfig.use_hash_seed`
- and :c:member:`PyConfig.hash_seed`
- * :c:var:`Py_IsolatedFlag`: use :c:member:`PyConfig.isolated`
- * :c:var:`Py_LegacyWindowsFSEncodingFlag`: use :c:member:`PyPreConfig.legacy_windows_fs_encoding`
- * :c:var:`Py_LegacyWindowsStdioFlag`: use :c:member:`PyConfig.legacy_windows_stdio`
- * :c:var:`!Py_FileSystemDefaultEncoding`: use :c:member:`PyConfig.filesystem_encoding`
- * :c:var:`!Py_HasFileSystemDefaultEncoding`: use :c:member:`PyConfig.filesystem_encoding`
- * :c:var:`!Py_FileSystemDefaultEncodeErrors`: use :c:member:`PyConfig.filesystem_errors`
- * :c:var:`!Py_UTF8Mode`: use :c:member:`PyPreConfig.utf8_mode` (see :c:func:`Py_PreInitialize`)
+.. include:: ../deprecations/c-api-pending-removal-in-3.14.rst
- The :c:func:`Py_InitializeFromConfig` API should be used with
- :c:type:`PyConfig` instead.
+.. include:: ../deprecations/c-api-pending-removal-in-3.15.rst
-* Creating :c:data:`immutable types ` with mutable
- bases (:gh:`95388`).
-
-Pending Removal in Python 3.15
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-* :c:func:`PyImport_ImportModuleNoBlock`: use :c:func:`PyImport_ImportModule`
-* :c:type:`!Py_UNICODE_WIDE` type: use :c:type:`wchar_t`
-* :c:type:`Py_UNICODE` type: use :c:type:`wchar_t`
-* Python initialization functions:
-
- * :c:func:`PySys_ResetWarnOptions`: clear :data:`sys.warnoptions` and
- :data:`!warnings.filters`
- * :c:func:`Py_GetExecPrefix`: get :data:`sys.exec_prefix`
- * :c:func:`Py_GetPath`: get :data:`sys.path`
- * :c:func:`Py_GetPrefix`: get :data:`sys.prefix`
- * :c:func:`Py_GetProgramFullPath`: get :data:`sys.executable`
- * :c:func:`Py_GetProgramName`: get :data:`sys.executable`
- * :c:func:`Py_GetPythonHome`: get :c:member:`PyConfig.home` or
- the :envvar:`PYTHONHOME` environment variable
-
-Pending Removal in Future Versions
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The following APIs are deprecated and will be removed,
-although there is currently no date scheduled for their removal.
-
-* :c:macro:`Py_TPFLAGS_HAVE_FINALIZE`: unneeded since Python 3.8
-* :c:func:`PyErr_Fetch`: use :c:func:`PyErr_GetRaisedException`
-* :c:func:`PyErr_NormalizeException`: use :c:func:`PyErr_GetRaisedException`
-* :c:func:`PyErr_Restore`: use :c:func:`PyErr_SetRaisedException`
-* :c:func:`PyModule_GetFilename`: use :c:func:`PyModule_GetFilenameObject`
-* :c:func:`PyOS_AfterFork`: use :c:func:`PyOS_AfterFork_Child`
-* :c:func:`PySlice_GetIndicesEx`: use :c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices`
-* :c:func:`!PyUnicode_AsDecodedObject`: use :c:func:`PyCodec_Decode`
-* :c:func:`!PyUnicode_AsDecodedUnicode`: use :c:func:`PyCodec_Decode`
-* :c:func:`!PyUnicode_AsEncodedObject`: use :c:func:`PyCodec_Encode`
-* :c:func:`!PyUnicode_AsEncodedUnicode`: use :c:func:`PyCodec_Encode`
-* :c:func:`PyUnicode_READY`: unneeded since Python 3.12
-* :c:func:`!PyErr_Display`: use :c:func:`PyErr_DisplayException`
-* :c:func:`!_PyErr_ChainExceptions`: use ``_PyErr_ChainExceptions1``
-* :c:member:`!PyBytesObject.ob_shash` member:
- call :c:func:`PyObject_Hash` instead
-* :c:member:`!PyDictObject.ma_version_tag` member
-* Thread Local Storage (TLS) API:
-
- * :c:func:`PyThread_create_key`: use :c:func:`PyThread_tss_alloc`
- * :c:func:`PyThread_delete_key`: use :c:func:`PyThread_tss_free`
- * :c:func:`PyThread_set_key_value`: use :c:func:`PyThread_tss_set`
- * :c:func:`PyThread_get_key_value`: use :c:func:`PyThread_tss_get`
- * :c:func:`PyThread_delete_key_value`: use :c:func:`PyThread_tss_delete`
- * :c:func:`PyThread_ReInitTLS`: unneeded since Python 3.7
+.. include:: ../deprecations/c-api-pending-removal-in-future.rst
Removed
-------
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 992d39e3152..a47d5e077a3 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -3,7 +3,7 @@
What's New In Python 3.13
****************************
-:Editor: Thomas Wouters
+:Editors: Adam Turner and Thomas Wouters
.. Rules for maintenance:
@@ -46,19 +46,13 @@
when researching a change.
This article explains the new features in Python 3.13, compared to 3.12.
-
+Python 3.13 was released on October 7, 2024.
For full details, see the :ref:`changelog `.
.. seealso::
:pep:`719` -- Python 3.13 Release Schedule
-.. note::
-
- Prerelease users should be aware that this document is currently in draft
- form. It will be updated substantially as Python 3.13 moves towards release,
- so it's worth checking back even after reading earlier versions.
-
Summary -- Release Highlights
=============================
@@ -66,14 +60,38 @@ Summary -- Release Highlights
.. This section singles out the most important changes in Python 3.13.
Brevity is key.
-Python 3.13 beta is the pre-release of the next version of the Python
-programming language, with a mix of changes to the language, the
-implementation and the standard library. The biggest changes to the
-implementation include a new interactive interpreter, and experimental
-support for dropping the Global Interpreter Lock (:pep:`703`) and a
-Just-In-Time compiler (:pep:`744`). The library changes contain removal of
-deprecated APIs and modules, as well as the usual improvements in
-user-friendliness and correctness.
+Python 3.13 is the latest stable release of the Python programming
+language, with a mix of changes to the language, the implementation
+and the standard library.
+The biggest changes include a new `interactive interpreter
+`_,
+experimental support for running in a `free-threaded mode
+`_ (:pep:`703`),
+and a `Just-In-Time compiler `_ (:pep:`744`).
+
+Error messages continue to improve, with tracebacks now highlighted in color
+by default. The :func:`locals` builtin now has :ref:`defined semantics
+` for changing the returned mapping,
+and type parameters now support default values.
+
+The library changes contain removal of deprecated APIs and modules,
+as well as the usual improvements in user-friendliness and correctness.
+Several legacy standard library modules have now `been removed
+`_ following their deprecation in Python 3.11 (:pep:`594`).
+
+This article doesn't attempt to provide a complete specification
+of all new features, but instead gives a convenient overview.
+For full details refer to the documentation,
+such as the :ref:`Library Reference `
+and :ref:`Language Reference `.
+To understand the complete implementation and design rationale for a change,
+refer to the PEP for a particular new feature;
+but note that PEPs usually are not kept up-to-date
+once a feature has been fully implemented.
+See `Porting to Python 3.13`_ for guidance on upgrading from
+earlier versions of Python.
+
+--------------
.. PEP-sized items next.
@@ -82,118 +100,160 @@ Interpreter improvements:
* A greatly improved :ref:`interactive interpreter
` and
:ref:`improved error messages `.
-
-* Color support in the new :ref:`interactive interpreter
- `,
- as well as in :ref:`tracebacks `
- and :ref:`doctest ` output. This can be disabled through the
- :envvar:`PYTHON_COLORS` and |NO_COLOR|_ environment variables.
-
-* :pep:`744`: A basic :ref:`JIT compiler ` was added.
- It is currently disabled by default (though we may turn it on later).
- Performance improvements are modest -- we expect to be improving this
- over the next few releases.
-
* :pep:`667`: The :func:`locals` builtin now has
:ref:`defined semantics ` when mutating the
returned mapping. Python debuggers and similar tools may now more reliably
update local variables in optimized scopes even during concurrent code
execution.
+* :pep:`703`: CPython 3.13 has experimental support for running with the
+ :term:`global interpreter lock` disabled. See :ref:`Free-threaded CPython
+ ` for more details.
+* :pep:`744`: A basic :ref:`JIT compiler ` was added.
+ It is currently disabled by default (though we may turn it on later).
+ Performance improvements are modest -- we expect to improve this
+ over the next few releases.
+* Color support in the new :ref:`interactive interpreter
+ `,
+ as well as in :ref:`tracebacks `
+ and :ref:`doctest ` output.
+ This can be disabled through the :envvar:`PYTHON_COLORS` and |NO_COLOR|_
+ environment variables.
+
+Python data model improvements:
+
+* :attr:`~type.__static_attributes__` stores the names of attributes accessed
+ through ``self.X`` in any function in a class body.
+* :attr:`~type.__firstlineno__` records the first line number of a class
+ definition.
+
+Significant improvements in the standard library:
+
+* Add a new :exc:`PythonFinalizationError` exception, raised when an operation
+ is blocked during :term:`finalization `.
+* The :mod:`argparse` module now supports deprecating command-line options,
+ positional arguments, and subcommands.
+* The new functions :func:`base64.z85encode` and :func:`base64.z85decode`
+ support encoding and decoding `Z85 data`_.
+* The :mod:`copy` module now has a :func:`copy.replace` function,
+ with support for many builtin types and any class defining
+ the :func:`~object.__replace__` method.
+* The new :mod:`dbm.sqlite3` module is now the default :mod:`dbm` backend.
+* The :mod:`os` module has a :ref:`suite of new functions `
+ for working with Linux's timer notification file descriptors.
+* The :mod:`random` module now has a :ref:`command-line interface `.
+
+Security improvements:
+
+* :func:`ssl.create_default_context` sets :data:`ssl.VERIFY_X509_PARTIAL_CHAIN`
+ and :data:`ssl.VERIFY_X509_STRICT` as default flags.
+
+C API improvements:
+
+* The :c:data:`Py_mod_gil` slot is now used to indicate that
+ an extension module supports running with the :term:`GIL` disabled.
+* The :doc:`PyTime C API ` has been added,
+ providing access to system clocks.
+* :c:type:`PyMutex` is a new lightweight mutex that occupies a single byte.
+* There is a new :ref:`suite of functions `
+ for generating :pep:`669` monitoring events in the C API.
New typing features:
* :pep:`696`: Type parameters (:data:`typing.TypeVar`, :data:`typing.ParamSpec`,
and :data:`typing.TypeVarTuple`) now support defaults.
-
-* :pep:`702`: Support for marking deprecations in the type system using the
- new :func:`warnings.deprecated` decorator.
-
-* :pep:`742`: :data:`typing.TypeIs` was added, providing more intuitive
- type narrowing behavior.
-
-* :pep:`705`: :data:`typing.ReadOnly` was added, to mark an item of a
+* :pep:`702`: The new :func:`warnings.deprecated` decorator adds support
+ for marking deprecations in the type system and at runtime.
+* :pep:`705`: :data:`typing.ReadOnly` can be used to mark an item of a
:class:`typing.TypedDict` as read-only for type checkers.
-
-Free-threading:
-
-* :pep:`703`: CPython 3.13 has experimental support for running with the
- :term:`global interpreter lock` disabled when built with ``--disable-gil``.
- See :ref:`Free-threaded CPython ` for more details.
+* :pep:`742`: :data:`typing.TypeIs` provides more intuitive
+ type narrowing behavior, as an alternative to :data:`typing.TypeGuard`.
Platform support:
-* :pep:`730`: Apple's iOS is now an officially supported platform. Official
- Android support (:pep:`738`) is in the works as well.
+* :pep:`730`: Apple's iOS is now an :ref:`officially supported platform
+ `, at :pep:`tier 3 <11#tier-3>`.
+* :pep:`738`: Android is now an :ref:`officially supported platform
+ `, at :pep:`tier 3 <11#tier-3>`.
+* ``wasm32-wasi`` is now supported as a :pep:`tier 2 <11#tier-2>` platform.
+* ``wasm32-emscripten`` is no longer an officially supported platform.
-Removed modules:
+Important removals:
* :ref:`PEP 594 `: The remaining 19 "dead batteries"
- have been removed from the standard library:
+ (legacy stdlib modules) have been removed from the standard library:
:mod:`!aifc`, :mod:`!audioop`, :mod:`!cgi`, :mod:`!cgitb`, :mod:`!chunk`,
:mod:`!crypt`, :mod:`!imghdr`, :mod:`!mailcap`, :mod:`!msilib`, :mod:`!nis`,
- :mod:`!nntplib`, :mod:`!ossaudiodev`, :mod:`!pipes`, :mod:`!sndhdr`, :mod:`!spwd`,
- :mod:`!sunau`, :mod:`!telnetlib`, :mod:`!uu` and :mod:`!xdrlib`.
-
-* Also removed were the :mod:`!tkinter.tix` and :mod:`!lib2to3` modules, and the
- ``2to3`` program.
+ :mod:`!nntplib`, :mod:`!ossaudiodev`, :mod:`!pipes`, :mod:`!sndhdr`,
+ :mod:`!spwd`, :mod:`!sunau`, :mod:`!telnetlib`, :mod:`!uu` and :mod:`!xdrlib`.
+* Remove the :program:`2to3` tool and :mod:`!lib2to3` module
+ (deprecated in Python 3.11).
+* Remove the :mod:`!tkinter.tix` module (deprecated in Python 3.6).
+* Remove the :func:`!locale.resetlocale` function.
+* Remove the :mod:`!typing.io` and :mod:`!typing.re` namespaces.
+* Remove chained :class:`classmethod` descriptors.
Release schedule changes:
-* :pep:`602` ("Annual Release Cycle for Python") has been updated:
+:pep:`602` ("Annual Release Cycle for Python") has been updated
+to extend the full support ('bugfix') period for new releases to two years.
+This updated policy means that:
+
+* Python 3.9--3.12 have one and a half years of full support,
+ followed by three and a half years of security fixes.
+* Python 3.13 and later have two years of full support,
+ followed by three years of security fixes.
- * Python 3.9 - 3.12 have one and a half years of full support,
- followed by three and a half years of security fixes.
- * Python 3.13 and later have two years of full support,
- followed by three years of security fixes.
New Features
============
+
.. _whatsnew313-better-interactive-interpreter:
-A Better Interactive Interpreter
+A better interactive interpreter
--------------------------------
-On Unix-like systems like Linux or macOS as well as Windows, Python now
-uses a new :term:`interactive` shell. When the user starts the
-:term:`REPL` from an interactive terminal the interactive shell now
-supports the following new features:
+Python now uses a new :term:`interactive` shell by default, based on code
+from the `PyPy project`_.
+When the user starts the :term:`REPL` from an interactive terminal,
+the following new features are now supported:
-* Colorized prompts.
* Multiline editing with history preservation.
+* Direct support for REPL-specific commands like :kbd:`help`, :kbd:`exit`,
+ and :kbd:`quit`, without the need to call them as functions.
+* Prompts and tracebacks with :ref:`color enabled by default
+ `.
* Interactive help browsing using :kbd:`F1` with a separate command
history.
* History browsing using :kbd:`F2` that skips output as well as the
:term:`>>>` and :term:`...` prompts.
* "Paste mode" with :kbd:`F3` that makes pasting larger blocks of code
easier (press :kbd:`F3` again to return to the regular prompt).
-* The ability to issue REPL-specific commands like :kbd:`help`, :kbd:`exit`,
- and :kbd:`quit` without the need to use call parentheses after the command
- name.
-
-If the new interactive shell is not desired, it can be disabled via
-the :envvar:`PYTHON_BASIC_REPL` environment variable.
-
-The new shell requires :mod:`curses` on Unix-like systems.
+To disable the new interactive shell,
+set the :envvar:`PYTHON_BASIC_REPL` environment variable.
For more on interactive mode, see :ref:`tut-interac`.
(Contributed by Pablo Galindo Salgado, Łukasz Langa, and
Lysandros Nikolaou in :gh:`111201` based on code from the PyPy project.
Windows support contributed by Dino Viehland and Anthony Shaw.)
+.. _`PyPy project`: https://pypy.org/
+
+
.. _whatsnew313-improved-error-messages:
-Improved Error Messages
+Improved error messages
-----------------------
-* The interpreter now colorizes error messages when displaying tracebacks by default.
- This feature can be controlled via the new :envvar:`PYTHON_COLORS` environment
- variable as well as the canonical |NO_COLOR|_ and |FORCE_COLOR|_ environment
- variables. See also :ref:`using-on-controlling-color`.
+* The interpreter now uses color by default when displaying tracebacks in the
+ terminal. This feature :ref:`can be controlled `
+ via the new :envvar:`PYTHON_COLORS` environment variable as well as
+ the canonical |NO_COLOR|_ and |FORCE_COLOR|_ environment variables.
(Contributed by Pablo Galindo Salgado in :gh:`112730`.)
.. Apparently this how you hack together a formatted link:
+ (https://www.docutils.org/docs/ref/rst/directives.html#replacement-text)
.. |FORCE_COLOR| replace:: ``FORCE_COLOR``
.. _FORCE_COLOR: https://force-color.org/
@@ -205,880 +265,1027 @@ Improved Error Messages
standard library module. When this results in errors, we now
display a more helpful error message:
- .. code-block:: shell-session
+ .. code-block:: pytb
- $ python random.py
- Traceback (most recent call last):
- File "/home/random.py", line 1, in
- import random; print(random.randint(5))
- ^^^^^^^^^^^^^
- File "/home/random.py", line 1, in
- import random; print(random.randint(5))
- ^^^^^^^^^^^^^^
- AttributeError: module 'random' has no attribute 'randint' (consider renaming '/home/random.py' since it has the same name as the standard library module named 'random' and the import system gives it precedence)
+ $ python random.py
+ Traceback (most recent call last):
+ File "/home/me/random.py", line 1, in
+ import random
+ File "/home/me/random.py", line 3, in
+ print(random.randint(5))
+ ^^^^^^^^^^^^^^
+ AttributeError: module 'random' has no attribute 'randint' (consider renaming '/home/me/random.py' since it has the same name as the standard library module named 'random' and the import system gives it precedence)
Similarly, if a script has the same name as a third-party
- module it attempts to import, and this results in errors,
+ module that it attempts to import and this results in errors,
we also display a more helpful error message:
- .. code-block:: shell-session
+ .. code-block:: pytb
- $ python numpy.py
- Traceback (most recent call last):
- File "/home/numpy.py", line 1, in
- import numpy as np; np.array([1,2,3])
- ^^^^^^^^^^^^^^^^^^
- File "/home/numpy.py", line 1, in
- import numpy as np; np.array([1,2,3])
- ^^^^^^^^
- AttributeError: module 'numpy' has no attribute 'array' (consider renaming '/home/numpy.py' if it has the same name as a third-party module you intended to import)
+ $ python numpy.py
+ Traceback (most recent call last):
+ File "/home/me/numpy.py", line 1, in
+ import numpy as np
+ File "/home/me/numpy.py", line 3, in
+ np.array([1, 2, 3])
+ ^^^^^^^^
+ AttributeError: module 'numpy' has no attribute 'array' (consider renaming '/home/me/numpy.py' if it has the same name as a third-party module you intended to import)
(Contributed by Shantanu Jain in :gh:`95754`.)
-* When an incorrect keyword argument is passed to a function, the error message
- now potentially suggests the correct keyword argument.
- (Contributed by Pablo Galindo Salgado and Shantanu Jain in :gh:`107944`.)
+* The error message now tries to suggest the correct keyword argument
+ when an incorrect keyword argument is passed to a function.
- >>> "better error messages!".split(max_split=1)
- Traceback (most recent call last):
- File "", line 1, in
- "better error messages!".split(max_split=1)
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
- TypeError: split() got an unexpected keyword argument 'max_split'. Did you mean 'maxsplit'?
+ .. code-block:: pycon
-* Classes have a new :attr:`~class.__static_attributes__` attribute, populated by the compiler,
- with a tuple of names of attributes of this class which are accessed
- through ``self.X`` from any function in its body. (Contributed by Irit Katriel
- in :gh:`115775`.)
+ >>> "Better error messages!".split(max_split=1)
+ Traceback (most recent call last):
+ File "", line 1, in
+ "Better error messages!".split(max_split=1)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
+ TypeError: split() got an unexpected keyword argument 'max_split'. Did you mean 'maxsplit'?
-.. _whatsnew313-locals-semantics:
+ (Contributed by Pablo Galindo Salgado and Shantanu Jain in :gh:`107944`.)
-Defined mutation semantics for ``locals()``
--------------------------------------------
-Historically, the expected result of mutating the return value of :func:`locals`
-has been left to individual Python implementations to define.
-
-Through :pep:`667`, Python 3.13 standardises the historical behaviour of CPython
-for most code execution scopes, but changes
-:term:`optimized scopes ` (functions, generators, coroutines,
-comprehensions, and generator expressions) to explicitly return independent
-snapshots of the currently assigned local variables, including locally
-referenced nonlocal variables captured in closures.
-
-This change to the semantics of :func:`locals` in optimized scopes also affects the default
-behaviour of code execution functions that implicitly target ``locals()`` if no explicit
-namespace is provided (such as :func:`exec` and :func:`eval`). In previous versions, whether
-or not changes could be accessed by calling ``locals()`` after calling the code execution
-function was implementation dependent. In CPython specifically, such code would typically
-appear to work as desired, but could sometimes fail in optimized scopes based on other code
-(including debuggers and code execution tracing tools) potentially resetting the shared
-snapshot in that scope. Now, the code will always run against an independent snapshot of the
-local variables in optimized scopes, and hence the changes will never be visible in
-subsequent calls to ``locals()``. To access the changes made in these cases, an explicit
-namespace reference must now be passed to the relevant function. Alternatively, it may make
-sense to update affected code to use a higher level code execution API that returns the
-resulting code execution namespace (e.g. :func:`runpy.run_path` when executing Python
-files from disk).
+.. _whatsnew313-free-threaded-cpython:
-To ensure debuggers and similar tools can reliably update local variables in
-scopes affected by this change, :attr:`FrameType.f_locals ` now
-returns a write-through proxy to the frame's local and locally referenced
-nonlocal variables in these scopes, rather than returning an inconsistently
-updated shared ``dict`` instance with undefined runtime semantics.
+Free-threaded CPython
+---------------------
-See :pep:`667` for more details, including related C API changes and deprecations. Porting
-notes are also provided below for the affected :ref:`Python APIs `
-and :ref:`C APIs `.
+CPython now has experimental support for running in a free-threaded mode,
+with the :term:`global interpreter lock` (GIL) disabled.
+This is an experimental feature and therefore is not enabled by default.
+The free-threaded mode requires a different executable,
+usually called ``python3.13t`` or ``python3.13t.exe``.
+Pre-built binaries marked as *free-threaded* can be installed as part of
+the official :ref:`Windows `
+and :ref:`macOS ` installers,
+or CPython can be built from source with the :option:`--disable-gil` option.
-(PEP and implementation contributed by Mark Shannon and Tian Gao in
-:gh:`74929`. Documentation updates provided by Guido van Rossum and
-Alyssa Coghlan.)
+Free-threaded execution allows for full utilization of the available
+processing power by running threads in parallel on available CPU cores.
+While not all software will benefit from this automatically, programs
+designed with threading in mind will run faster on multi-core hardware.
+**The free-threaded mode is experimental** and work is ongoing to improve it:
+expect some bugs and a substantial single-threaded performance hit.
+Free-threaded builds of CPython support optionally running with the GIL
+enabled at runtime using the environment variable :envvar:`PYTHON_GIL` or
+the command-line option :option:`-X gil=1`.
-Incremental Garbage Collection
-------------------------------
+To check if the current interpreter supports free-threading, :option:`python -VV <-V>`
+and :attr:`sys.version` contain "experimental free-threading build".
+The new :func:`!sys._is_gil_enabled` function can be used to check whether
+the GIL is actually disabled in the running process.
-* The cycle garbage collector is now incremental.
- This means that maximum pause times are reduced
- by an order of magnitude or more for larger heaps.
+C-API extension modules need to be built specifically for the free-threaded
+build. Extensions that support running with the :term:`GIL` disabled should
+use the :c:data:`Py_mod_gil` slot. Extensions using single-phase init should
+use :c:func:`PyUnstable_Module_SetGIL` to indicate whether they support
+running with the GIL disabled. Importing C extensions that don't use these
+mechanisms will cause the GIL to be enabled, unless the GIL was explicitly
+disabled with the :envvar:`PYTHON_GIL` environment variable or the
+:option:`-X gil=0` option.
+pip 24.1 or newer is required to install packages with C extensions in the
+free-threaded build.
-Support For Mobile Platforms
-----------------------------
+This work was made possible thanks to many individuals and
+organizations, including the large community of contributors to Python
+and third-party projects to test and enable free-threading support.
+Notable contributors include:
+Sam Gross, Ken Jin, Donghee Na, Itamar Oren, Matt Page, Brett Simmers,
+Dino Viehland, Carl Meyer, Nathan Goldbaum, Ralf Gommers,
+Lysandros Nikolaou, and many others.
+Many of these contributors are employed by Meta, which has
+provided significant engineering resources to support this project.
-* iOS is now a :pep:`11` supported platform. ``arm64-apple-ios``
- (iPhone and iPad devices released after 2013) and
- ``arm64-apple-ios-simulator`` (Xcode iOS simulator running on Apple Silicon
- hardware) are now tier 3 platforms.
+.. seealso::
- ``x86_64-apple-ios-simulator`` (Xcode iOS simulator running on older x86_64
- hardware) is not a tier 3 supported platform, but will be supported on a
- best-effort basis.
+ :pep:`703` "Making the Global Interpreter Lock Optional in CPython"
+ contains rationale and information surrounding this work.
- See :pep:`730`: for more details.
+ `Porting Extension Modules to Support Free-Threading
+ `_: A community-maintained
+ porting guide for extension authors.
- (PEP written and implementation contributed by Russell Keith-Magee in
- :gh:`114099`.)
.. _whatsnew313-jit-compiler:
-Experimental JIT Compiler
-=========================
+An experimental just-in-time (JIT) compiler
+-------------------------------------------
-When CPython is configured using the ``--enable-experimental-jit`` option,
-a just-in-time compiler is added which may speed up some Python programs.
+When CPython is configured and built using
+the :option:`!--enable-experimental-jit` option,
+a just-in-time (JIT) compiler is added which may speed up some Python programs.
+On Windows, use ``PCbuild/build.bat --experimental-jit`` to enable the JIT
+or ``--experimental-jit-interpreter`` to enable the Tier 2 interpreter.
+Build requirements and further supporting information `are contained at`__
+:file:`Tools/jit/README.md`.
-The internal architecture is roughly as follows.
+__ https://github.com/python/cpython/blob/main/Tools/jit/README.md
-* We start with specialized *Tier 1 bytecode*.
- See :ref:`What's new in 3.11 ` for details.
+The :option:`!--enable-experimental-jit` option takes these (optional) values,
+defaulting to ``yes`` if :option:`!--enable-experimental-jit` is present
+without the optional value.
-* When the Tier 1 bytecode gets hot enough, it gets translated
- to a new, purely internal *Tier 2 IR*, a.k.a. micro-ops ("uops").
+* ``no``: Disable the entire Tier 2 and JIT pipeline.
+* ``yes``: Enable the JIT.
+ To disable the JIT at runtime, pass the environment variable ``PYTHON_JIT=0``.
+* ``yes-off``: Build the JIT but disable it by default.
+ To enable the JIT at runtime, pass the environment variable ``PYTHON_JIT=1``.
+* ``interpreter``: Enable the Tier 2 interpreter but disable the JIT.
+ The interpreter can be disabled by running with ``PYTHON_JIT=0``.
-* The Tier 2 IR uses the same stack-based VM as Tier 1, but the
- instruction format is better suited to translation to machine code.
+The internal architecture is roughly as follows:
+* We start with specialized *Tier 1 bytecode*.
+ See :ref:`What's new in 3.11 ` for details.
+* When the Tier 1 bytecode gets hot enough, it gets translated
+ to a new purely internal intermediate representation (IR),
+ called the *Tier 2 IR*, and sometimes referred to as micro-ops ("uops").
+* The Tier 2 IR uses the same stack-based virtual machine as Tier 1,
+ but the instruction format is better suited to translation to machine code.
* We have several optimization passes for Tier 2 IR, which are applied
before it is interpreted or translated to machine code.
-
* There is a Tier 2 interpreter, but it is mostly intended for debugging
the earlier stages of the optimization pipeline.
The Tier 2 interpreter can be enabled by configuring Python
with ``--enable-experimental-jit=interpreter``.
-
* When the JIT is enabled, the optimized
Tier 2 IR is translated to machine code, which is then executed.
-
* The machine code translation process uses a technique called
*copy-and-patch*. It has no runtime dependencies, but there is a new
build-time dependency on LLVM.
-The ``--enable-experimental-jit`` flag has the following optional values:
-
-* ``no`` (default) -- Disable the entire Tier 2 and JIT pipeline.
-
-* ``yes`` (default if the flag is present without optional value)
- -- Enable the JIT. To disable the JIT at runtime,
- pass the environment variable ``PYTHON_JIT=0``.
-
-* ``yes-off`` -- Build the JIT but disable it by default.
- To enable the JIT at runtime, pass the environment variable
- ``PYTHON_JIT=1``.
-
-* ``interpreter`` -- Enable the Tier 2 interpreter but disable the JIT.
- The interpreter can be disabled by running with
- ``PYTHON_JIT=0``.
-
-(On Windows, use ``PCbuild/build.bat --experimental-jit`` to enable the JIT
-or ``--experimental-jit-interpreter`` to enable the Tier 2 interpreter.)
-
-See :pep:`744` for more details.
+.. seealso:: :pep:`744`
(JIT by Brandt Bucher, inspired by a paper by Haoran Xu and Fredrik Kjolstad.
Tier 2 IR by Mark Shannon and Guido van Rossum.
Tier 2 optimizer by Ken Jin.)
-.. _free-threaded-cpython:
-
-Free-threaded CPython
-=====================
-CPython will run with the :term:`global interpreter lock` (GIL) disabled when
-configured using the ``--disable-gil`` option at build time. This is an
-experimental feature and therefore isn't used by default. Users need to
-either compile their own interpreter, or install one of the experimental
-builds that are marked as *free-threaded*. See :pep:`703` "Making the Global
-Interpreter Lock Optional in CPython" for more detail.
+.. _whatsnew313-locals-semantics:
-Free-threaded execution allows for full utilization of the available
-processing power by running threads in parallel on available CPU cores.
-While not all software will benefit from this automatically, programs
-designed with threading in mind will run faster on multicore hardware.
+Defined mutation semantics for :py:func:`locals`
+------------------------------------------------
+
+Historically, the expected result of mutating the return value of
+:func:`locals` has been left to individual Python implementations to define.
+Starting from Python 3.13, :pep:`667` standardises
+the historical behavior of CPython for most code execution scopes,
+but changes :term:`optimized scopes `
+(functions, generators, coroutines, comprehensions, and generator expressions)
+to explicitly return independent snapshots of the currently assigned local
+variables, including locally referenced nonlocal variables captured in closures.
+
+This change to the semantics of :func:`locals` in optimized scopes also
+affects the default behavior of code execution functions that implicitly
+target :func:`!locals` if no explicit namespace is provided
+(such as :func:`exec` and :func:`eval`).
+In previous versions, whether or not changes could be accessed by calling
+:func:`!locals` after calling the code execution function was
+implementation-dependent. In CPython specifically, such code would typically
+appear to work as desired, but could sometimes fail in optimized scopes based
+on other code (including debuggers and code execution tracing tools)
+potentially resetting the shared snapshot in that scope.
+Now, the code will always run against an independent snapshot of
+the local variables in optimized scopes, and hence the changes will never
+be visible in subsequent calls to :func:`!locals`.
+To access the changes made in these cases, an explicit namespace reference
+must now be passed to the relevant function.
+Alternatively, it may make sense to update affected code to use a higher level
+code execution API that returns the resulting code execution namespace
+(e.g. :func:`runpy.run_path` when executing Python files from disk).
-Work is still ongoing: expect some bugs and a substantial single-threaded
-performance hit.
+To ensure debuggers and similar tools can reliably update local variables in
+scopes affected by this change, :attr:`FrameType.f_locals ` now
+returns a write-through proxy to the frame's local and locally referenced
+nonlocal variables in these scopes, rather than returning an inconsistently
+updated shared ``dict`` instance with undefined runtime semantics.
-The free-threaded build still supports optionally running with the GIL
-enabled at runtime using the environment variable :envvar:`PYTHON_GIL` or
-the command line option :option:`-X gil`.
+See :pep:`667` for more details, including related C API changes
+and deprecations. Porting notes are also provided below for the affected
+:ref:`Python APIs ` and :ref:`C APIs
+`.
-To check if the current interpreter is configured with ``--disable-gil``,
-use ``sysconfig.get_config_var("Py_GIL_DISABLED")``. To check if the :term:`GIL`
-is actually disabled in the running process, the :func:`!sys._is_gil_enabled`
-function can be used.
+(PEP and implementation contributed by Mark Shannon and Tian Gao in
+:gh:`74929`. Documentation updates provided by Guido van Rossum and
+Alyssa Coghlan.)
-C-API extension modules need to be built specifically for the free-threaded
-build. Extensions that support running with the :term:`GIL` disabled should
-use the :c:data:`Py_mod_gil` slot. Extensions using single-phase init should
-use :c:func:`PyUnstable_Module_SetGIL` to indicate whether they support
-running with the GIL disabled. Importing C extensions that don't use these
-mechanisms will cause the GIL to be enabled, unless the GIL was explicitly
-disabled with the :envvar:`PYTHON_GIL` environment variable or the
-:option:`-X gil=0` option.
-pip 24.1b1 or newer is required to install packages with C extensions in the
-free-threaded build.
+.. _whatsnew313-platform-support:
-Other Language Changes
-======================
+Support for mobile platforms
+----------------------------
-* Allow the *count* argument of :meth:`str.replace` to be a keyword.
- (Contributed by Hugo van Kemenade in :gh:`106487`.)
+:pep:`730`: iOS is now a :pep:`11` supported platform, with the
+``arm64-apple-ios`` and ``arm64-apple-ios-simulator`` targets at tier 3
+(iPhone and iPad devices released after 2013 and the Xcode iOS simulator
+running on Apple silicon hardware, respectively).
+``x86_64-apple-ios-simulator``
+(the Xcode iOS simulator running on older ``x86_64`` hardware)
+is not a tier 3 supported platform, but will have best-effort support.
+(PEP written and implementation contributed by Russell Keith-Magee in
+:gh:`114099`.)
-* Compiler now strip indents from docstrings.
- This will reduce the size of :term:`bytecode cache ` (e.g. ``.pyc`` file).
- For example, cache file size for ``sqlalchemy.orm.session`` in SQLAlchemy 2.0
- is reduced by about 5%.
- This change will affect tools using docstrings, like :mod:`doctest`.
- (Contributed by Inada Naoki in :gh:`81283`.)
+:pep:`738`: Android is now a :pep:`11` supported platform, with the
+``aarch64-linux-android`` and ``x86_64-linux-android`` targets at tier 3.
+The 32-bit targets ``arm-linux-androideabi`` and ``i686-linux-android``
+are not tier 3 supported platforms, but will have best-effort support.
+(PEP written and implementation contributed by Malcolm Smith in
+:gh:`116622`.)
-* The :func:`compile` built-in can now accept a new flag,
- ``ast.PyCF_OPTIMIZED_AST``, which is similar to ``ast.PyCF_ONLY_AST``
- except that the returned ``AST`` is optimized according to the value
- of the ``optimize`` argument.
- (Contributed by Irit Katriel in :gh:`108113`).
+.. seealso:: :pep:`730`, :pep:`738`
-* :mod:`multiprocessing`, :mod:`concurrent.futures`, :mod:`compileall`:
- Replace :func:`os.cpu_count` with :func:`os.process_cpu_count` to select the
- default number of worker threads and processes. Get the CPU affinity
- if supported.
- (Contributed by Victor Stinner in :gh:`109649`.)
-* :func:`os.path.realpath` now resolves MS-DOS style file names even if
- the file is not accessible.
- (Contributed by Moonsik Park in :gh:`82367`.)
+Other Language Changes
+======================
-* Fixed a bug where a :keyword:`global` declaration in an :keyword:`except` block
- is rejected when the global is used in the :keyword:`else` block.
- (Contributed by Irit Katriel in :gh:`111123`.)
+* The compiler now strips common leading whitespace
+ from every line in a docstring.
+ This reduces the size of the :term:`bytecode cache `
+ (such as ``.pyc`` files), with reductions in file size of around 5%,
+ for example in :mod:`!sqlalchemy.orm.session` from SQLAlchemy 2.0.
+ This change affects tools that use docstrings, such as :mod:`doctest`.
+
+ .. doctest::
+
+ >>> def spam():
+ ... """
+ ... This is a docstring with
+ ... leading whitespace.
+ ...
+ ... It even has multiple paragraphs!
+ ... """
+ ...
+ >>> spam.__doc__
+ '\nThis is a docstring with\n leading whitespace.\n\nIt even has multiple paragraphs!\n'
-* Many functions now emit a warning if a boolean value is passed as
- a file descriptor argument.
- This can help catch some errors earlier.
- (Contributed by Serhiy Storchaka in :gh:`82626`.)
+ (Contributed by Inada Naoki in :gh:`81283`.)
-* Added a new environment variable :envvar:`PYTHON_FROZEN_MODULES`. It
- determines whether or not frozen modules are ignored by the import machinery,
- equivalent of the :option:`-X frozen_modules <-X>` command-line option.
- (Contributed by Yilei Yang in :gh:`111374`.)
+* :ref:`Annotation scopes ` within class scopes
+ can now contain lambdas and comprehensions.
+ Comprehensions that are located within class scopes
+ are not inlined into their parent scope.
-* Add :ref:`support for the perf profiler ` working without
- frame pointers through the new environment variable
- :envvar:`PYTHON_PERF_JIT_SUPPORT` and command-line option :option:`-X perf_jit
- <-X>` (Contributed by Pablo Galindo in :gh:`118518`.)
+ .. code-block:: python
-* The new :envvar:`PYTHON_HISTORY` environment variable can be used to change
- the location of a ``.python_history`` file.
- (Contributed by Levi Sabah, Zackery Spytz and Hugo van Kemenade in
- :gh:`73965`.)
+ class C[T]:
+ type Alias = lambda: T
-* Add :exc:`PythonFinalizationError` exception. This exception derived from
- :exc:`RuntimeError` is raised when an operation is blocked during
- the :term:`Python finalization `.
+ (Contributed by Jelle Zijlstra in :gh:`109118` and :gh:`118160`.)
- The following functions now raise PythonFinalizationError, instead of
- :exc:`RuntimeError`:
+* :ref:`Future statements ` are no longer triggered by
+ relative imports of the :mod:`__future__` module,
+ meaning that statements of the form ``from .__future__ import ...``
+ are now simply standard relative imports, with no special features activated.
+ (Contributed by Jeremiah Gabriel Pascual in :gh:`118216`.)
- * :func:`_thread.start_new_thread`.
- * :class:`subprocess.Popen`.
- * :func:`os.fork`.
- * :func:`os.forkpty`.
+* :keyword:`global` declarations are now permitted in :keyword:`except` blocks
+ when that global is used in the :keyword:`else` block.
+ Previously this raised an erroneous :exc:`SyntaxError`.
+ (Contributed by Irit Katriel in :gh:`111123`.)
- (Contributed by Victor Stinner in :gh:`114570`.)
+* Add :envvar:`PYTHON_FROZEN_MODULES`, a new environment variable that
+ determines whether frozen modules are ignored by the import machinery,
+ equivalent to the :option:`-X frozen_modules <-X>` command-line option.
+ (Contributed by Yilei Yang in :gh:`111374`.)
-* Added :attr:`!name` and :attr:`!mode` attributes for compressed
- and archived file-like objects in modules :mod:`bz2`, :mod:`lzma`,
- :mod:`tarfile` and :mod:`zipfile`.
- (Contributed by Serhiy Storchaka in :gh:`115961`.)
+* Add :ref:`support for the perf profiler ` working
+ without `frame pointers `_ through
+ the new environment variable :envvar:`PYTHON_PERF_JIT_SUPPORT`
+ and command-line option :option:`-X perf_jit <-X>`.
+ (Contributed by Pablo Galindo in :gh:`118518`.)
-* Allow controlling Expat >=2.6.0 reparse deferral (:cve:`2023-52425`)
- by adding five new methods:
+* The location of a :file:`.python_history` file can be changed via the
+ new :envvar:`PYTHON_HISTORY` environment variable.
+ (Contributed by Levi Sabah, Zackery Spytz and Hugo van Kemenade
+ in :gh:`73965`.)
- * :meth:`xml.etree.ElementTree.XMLParser.flush`
- * :meth:`xml.etree.ElementTree.XMLPullParser.flush`
- * :meth:`xml.parsers.expat.xmlparser.GetReparseDeferralEnabled`
- * :meth:`xml.parsers.expat.xmlparser.SetReparseDeferralEnabled`
- * :meth:`!xml.sax.expatreader.ExpatParser.flush`
+* Classes have a new :attr:`~type.__static_attributes__` attribute.
+ This is populated by the compiler with a tuple of the class's attribute names
+ which are assigned through ``self.`` from any function in its body.
+ (Contributed by Irit Katriel in :gh:`115775`.)
- (Contributed by Sebastian Pipping in :gh:`115623`.)
+* The compiler now creates a :attr:`!__firstlineno__` attribute on classes
+ with the line number of the first line of the class definition.
+ (Contributed by Serhiy Storchaka in :gh:`118465`.)
-* The :func:`ssl.create_default_context` API now includes
- :data:`ssl.VERIFY_X509_PARTIAL_CHAIN` and :data:`ssl.VERIFY_X509_STRICT`
- in its default flags.
+* The :func:`exec` and :func:`eval` builtins now accept
+ the *globals* and *locals* arguments as keywords.
+ (Contributed by Raphael Gaschignard in :gh:`105879`)
- .. note::
+* The :func:`compile` builtin now accepts a new flag,
+ ``ast.PyCF_OPTIMIZED_AST``, which is similar to ``ast.PyCF_ONLY_AST``
+ except that the returned AST is optimized according to
+ the value of the *optimize* argument.
+ (Contributed by Irit Katriel in :gh:`108113`).
- :data:`ssl.VERIFY_X509_STRICT` may reject pre-:rfc:`5280` or malformed
- certificates that the underlying OpenSSL implementation otherwise would
- accept. While disabling this is not recommended, you can do so using::
+* Add a :attr:`~property.__name__` attribute on :class:`property` objects.
+ (Contributed by Eugene Toder in :gh:`101860`.)
- ctx = ssl.create_default_context()
- ctx.verify_flags &= ~ssl.VERIFY_X509_STRICT
+* Add :exc:`PythonFinalizationError`, a new exception derived from
+ :exc:`RuntimeError` and used to signal when operations are blocked
+ during :term:`finalization `.
+ The following callables now raise :exc:`!PythonFinalizationError`,
+ instead of :exc:`RuntimeError`:
- (Contributed by William Woodruff in :gh:`112389`.)
+ * :func:`_thread.start_new_thread`
+ * :func:`os.fork`
+ * :func:`os.forkpty`
+ * :class:`subprocess.Popen`
-* The :class:`configparser.ConfigParser` now accepts unnamed sections before named
- ones if configured to do so.
- (Contributed by Pedro Sousa Lacerda in :gh:`66449`.)
+ (Contributed by Victor Stinner in :gh:`114570`.)
-* :ref:`annotation scope ` within class scopes can now
- contain lambdas and comprehensions. Comprehensions that are located within
- class scopes are not inlined into their parent scope. (Contributed by
- Jelle Zijlstra in :gh:`109118` and :gh:`118160`.)
+* Allow the *count* argument of :meth:`str.replace` to be a keyword.
+ (Contributed by Hugo van Kemenade in :gh:`106487`.)
-* Classes have a new :attr:`!__firstlineno__` attribute,
- populated by the compiler, with the line number of the first line
- of the class definition.
- (Contributed by Serhiy Storchaka in :gh:`118465`.)
+* Many functions now emit a warning if a boolean value is passed as
+ a file descriptor argument.
+ This can help catch some errors earlier.
+ (Contributed by Serhiy Storchaka in :gh:`82626`.)
-* ``from __future__ import ...`` statements are now just normal
- relative imports if dots are present before the module name.
- (Contributed by Jeremiah Gabriel Pascual in :gh:`118216`.)
+* Added :attr:`!name` and :attr:`!mode` attributes
+ for compressed and archived file-like objects in
+ the :mod:`bz2`, :mod:`lzma`, :mod:`tarfile`, and :mod:`zipfile` modules.
+ (Contributed by Serhiy Storchaka in :gh:`115961`.)
New Modules
===========
-* None.
+* :mod:`dbm.sqlite3`: An SQLite backend for :mod:`dbm`.
+ (Contributed by Raymond Hettinger and Erlend E. Aasland in :gh:`100414`.)
Improved Modules
================
+
argparse
--------
-* Add parameter *deprecated* in methods
- :meth:`~argparse.ArgumentParser.add_argument` and :meth:`!add_parser`
- which allows to deprecate command-line options, positional arguments and
- subcommands.
+* Add the *deprecated* parameter to the
+ :meth:`~argparse.ArgumentParser.add_argument`
+ and :meth:`!add_parser` methods, to enable deprecating
+ command-line options, positional arguments, and subcommands.
(Contributed by Serhiy Storchaka in :gh:`83648`.)
+
array
-----
-* Add ``'w'`` type code (``Py_UCS4``) that can be used for Unicode strings.
- It can be used instead of ``'u'`` type code, which is deprecated.
+* Add the ``'w'`` type code (``Py_UCS4``) for Unicode characters.
+ It should be used instead of the deprecated ``'u'`` type code.
(Contributed by Inada Naoki in :gh:`80480`.)
-* Add ``clear()`` method in order to implement ``MutableSequence``.
+* Register :class:`array.array` as a :class:`~collections.abc.MutableSequence`
+ by implementing the :meth:`~array.array.clear` method.
(Contributed by Mike Zimin in :gh:`114894`.)
+
ast
---
-* The constructors of node types in the :mod:`ast` module are now stricter
- in the arguments they accept, and have more intuitive behaviour when
- arguments are omitted.
+* The constructors of node types in the :mod:`ast` module are now
+ stricter in the arguments they accept,
+ with more intuitive behavior when arguments are omitted.
If an optional field on an AST node is not included as an argument when
constructing an instance, the field will now be set to ``None``. Similarly,
if a list field is omitted, that field will now be set to an empty list,
- and if a :class:`!ast.expr_context` field is omitted, it defaults to
+ and if an :class:`!expr_context` field is omitted, it defaults to
:class:`Load() `.
(Previously, in all cases, the attribute would be missing on the newly
constructed AST node instance.)
- If other arguments are omitted, a :exc:`DeprecationWarning` is emitted.
- This will cause an exception in Python 3.15. Similarly, passing a keyword
- argument that does not map to a field on the AST node is now deprecated,
+ In all other cases, where a required argument is omitted,
+ the node constructor will emit a :exc:`DeprecationWarning`.
+ This will raise an exception in Python 3.15.
+ Similarly, passing a keyword argument to the constructor
+ that does not map to a field on the AST node is now deprecated,
and will raise an exception in Python 3.15.
- These changes do not apply to user-defined subclasses of :class:`ast.AST`,
- unless the class opts in to the new behavior by setting the attribute
- :attr:`ast.AST._field_types`.
+ These changes do not apply to user-defined subclasses of :class:`ast.AST`
+ unless the class opts in to the new behavior
+ by defining the :attr:`.AST._field_types` mapping.
(Contributed by Jelle Zijlstra in :gh:`105858`, :gh:`117486`, and :gh:`118851`.)
* :func:`ast.parse` now accepts an optional argument *optimize*
- which is passed on to the :func:`compile` built-in. This makes it
- possible to obtain an optimized AST.
+ which is passed on to :func:`compile`.
+ This makes it possible to obtain an optimized AST.
(Contributed by Irit Katriel in :gh:`108113`.)
+
asyncio
-------
+* :func:`asyncio.as_completed` now returns an object that is both an
+ :term:`asynchronous iterator` and a plain :term:`iterator`
+ of :term:`awaitables `.
+ The awaitables yielded by asynchronous iteration include original task
+ or future objects that were passed in,
+ making it easier to associate results with the tasks being completed.
+ (Contributed by Justin Arthur in :gh:`77714`.)
+
* :meth:`asyncio.loop.create_unix_server` will now automatically remove
the Unix socket when the server is closed.
(Contributed by Pierre Ossman in :gh:`111246`.)
-* :meth:`asyncio.DatagramTransport.sendto` will now send zero-length
- datagrams if called with an empty bytes object. The transport flow
- control also now accounts for the datagram header when calculating
- the buffer size.
+* :meth:`.DatagramTransport.sendto` will now send zero-length
+ datagrams if called with an empty bytes object.
+ The transport flow control also now accounts for the datagram header
+ when calculating the buffer size.
(Contributed by Jamie Phan in :gh:`115199`.)
-* Add :meth:`asyncio.Server.close_clients` and
- :meth:`asyncio.Server.abort_clients` methods which allow to more
- forcefully close an asyncio server.
- (Contributed by Pierre Ossman in :gh:`113538`.)
+* Add :meth:`Queue.shutdown `
+ and :exc:`~asyncio.QueueShutDown` to manage queue termination.
+ (Contributed by Laurie Opperman and Yves Duprat in :gh:`104228`.)
-* :func:`asyncio.as_completed` now returns an object that is both an
- :term:`asynchronous iterator` and a plain :term:`iterator` of awaitables.
- The awaitables yielded by asynchronous iteration include original task or
- future objects that were passed in, making it easier to associate results
- with the tasks being completed.
- (Contributed by Justin Arthur in :gh:`77714`.)
+* Add the :meth:`.Server.close_clients` and :meth:`.Server.abort_clients`
+ methods, which more forcefully close an asyncio server.
+ (Contributed by Pierre Ossman in :gh:`113538`.)
-* When :func:`asyncio.TaskGroup.create_task` is called on an inactive
- :class:`asyncio.TaskGroup`, the given coroutine will be closed (which
- prevents a :exc:`RuntimeWarning` about the given coroutine being
- never awaited).
- (Contributed by Arthur Tacca and Jason Zhang in :gh:`115957`.)
+* Accept a tuple of separators in :meth:`.StreamReader.readuntil`,
+ stopping when any one of them is encountered.
+ (Contributed by Bruce Merry in :gh:`81322`.)
-* Improved behavior of :class:`asyncio.TaskGroup` when an external cancellation
- collides with an internal cancellation. For example, when two task groups
- are nested and both experience an exception in a child task simultaneously,
- it was possible that the outer task group would hang, because its internal
- cancellation was swallowed by the inner task group.
+* Improve the behavior of :class:`~asyncio.TaskGroup` when
+ an external cancellation collides with an internal cancellation.
+ For example, when two task groups are nested
+ and both experience an exception in a child task simultaneously,
+ it was possible that the outer task group would hang,
+ because its internal cancellation was swallowed by the inner task group.
- In the case where a task group is cancelled externally and also must
- raise an :exc:`ExceptionGroup`, it will now call the parent task's
- :meth:`~asyncio.Task.cancel` method. This ensures that a
- :exc:`asyncio.CancelledError` will be raised at the next
- :keyword:`await`, so the cancellation is not lost.
+ In the case where a task group is cancelled externally
+ and also must raise an :exc:`ExceptionGroup`,
+ it will now call the parent task's :meth:`~asyncio.Task.cancel` method.
+ This ensures that a :exc:`~asyncio.CancelledError` will be raised
+ at the next :keyword:`await`, so the cancellation is not lost.
- An added benefit of these changes is that task groups now preserve the
- cancellation count (:meth:`asyncio.Task.cancelling`).
+ An added benefit of these changes is that task groups now preserve
+ the cancellation count (:meth:`~asyncio.Task.cancelling`).
- In order to handle some corner cases, :meth:`asyncio.Task.uncancel` may now
- reset the undocumented ``_must_cancel`` flag when the cancellation count
- reaches zero.
+ In order to handle some corner cases, :meth:`~asyncio.Task.uncancel` may now
+ reset the undocumented ``_must_cancel`` flag
+ when the cancellation count reaches zero.
(Inspired by an issue reported by Arthur Tacca in :gh:`116720`.)
-* Add :meth:`asyncio.Queue.shutdown` (along with
- :exc:`asyncio.QueueShutDown`) for queue termination.
- (Contributed by Laurie Opperman and Yves Duprat in :gh:`104228`.)
+* When :meth:`.TaskGroup.create_task` is called on an inactive
+ :class:`~asyncio.TaskGroup`, the given coroutine will be closed (which
+ prevents a :exc:`RuntimeWarning` about the given coroutine being
+ never awaited).
+ (Contributed by Arthur Tacca and Jason Zhang in :gh:`115957`.)
-* Accept a tuple of separators in :meth:`asyncio.StreamReader.readuntil`,
- stopping when one of them is encountered.
- (Contributed by Bruce Merry in :gh:`81322`.)
base64
------
-* Add :func:`base64.z85encode` and :func:`base64.z85decode` functions which allow encoding
- and decoding Z85 data.
- See `Z85 specification `_ for more information.
+* Add :func:`~base64.z85encode` and :func:`~base64.z85decode` functions
+ for encoding :class:`bytes` as `Z85 data`_
+ and decoding Z85-encoded data to :class:`!bytes`.
(Contributed by Matan Perelman in :gh:`75299`.)
+ .. _Z85 data: https://rfc.zeromq.org/spec/32/
+
+
+compileall
+----------
+
+* The default number of worker threads and processes is now selected using
+ :func:`os.process_cpu_count` instead of :func:`os.cpu_count`.
+ (Contributed by Victor Stinner in :gh:`109649`.)
+
+
+concurrent.futures
+------------------
+
+* The default number of worker threads and processes is now selected using
+ :func:`os.process_cpu_count` instead of :func:`os.cpu_count`.
+ (Contributed by Victor Stinner in :gh:`109649`.)
+
+
+configparser
+------------
+
+* :class:`~configparser.ConfigParser` now has support for unnamed sections,
+ which allows for top-level key-value pairs.
+ This can be enabled with the new *allow_unnamed_section* parameter.
+ (Contributed by Pedro Sousa Lacerda in :gh:`66449`.)
+
+
copy
----
-* Add :func:`copy.replace` function which allows to create a modified copy of
- an object, which is especially useful for immutable objects.
- It supports named tuples created with the factory function
- :func:`collections.namedtuple`, :class:`~dataclasses.dataclass` instances,
- various :mod:`datetime` objects, :class:`~inspect.Signature` objects,
- :class:`~inspect.Parameter` objects, :ref:`code object `, and
- any user classes which define the :meth:`!__replace__` method.
+* The new :func:`~copy.replace` function and the :meth:`replace protocol
+ ` make creating modified copies of objects much simpler.
+ This is especially useful when working with immutable objects.
+ The following types support the :func:`~copy.replace` function
+ and implement the replace protocol:
+
+ * :func:`collections.namedtuple`
+ * :class:`dataclasses.dataclass`
+ * :class:`datetime.datetime`, :class:`datetime.date`, :class:`datetime.time`
+ * :class:`inspect.Signature`, :class:`inspect.Parameter`
+ * :class:`types.SimpleNamespace`
+ * :ref:`code objects `
+
+ Any user-defined class can also support :func:`copy.replace` by defining
+ the :meth:`~object.__replace__` method.
(Contributed by Serhiy Storchaka in :gh:`108751`.)
+
+ctypes
+------
+
+* As a consequence of necessary internal refactoring, initialization of
+ internal metaclasses now happens in ``__init__`` rather
+ than in ``__new__``. This affects projects that subclass these internal
+ metaclasses to provide custom initialization.
+ Generally:
+
+ - Custom logic that was done in ``__new__`` after calling ``super().__new__``
+ should be moved to ``__init__``.
+ - To create a class, call the metaclass, not only the metaclass's
+ ``__new__`` method.
+
+ See :gh:`124520` for discussion and links to changes in some affected
+ projects.
+
+
dbm
---
-* Add :meth:`dbm.gnu.gdbm.clear` and :meth:`dbm.ndbm.ndbm.clear` methods that remove all items
- from the database.
+* Add :mod:`dbm.sqlite3`, a new module which implements an SQLite backend,
+ and make it the default :mod:`!dbm` backend.
+ (Contributed by Raymond Hettinger and Erlend E. Aasland in :gh:`100414`.)
+
+* Allow removing all items from the database through
+ the new :meth:`.gdbm.clear` and :meth:`.ndbm.clear` methods.
(Contributed by Donghee Na in :gh:`107122`.)
-* Add new :mod:`dbm.sqlite3` backend, and make it the default :mod:`!dbm` backend.
- (Contributed by Raymond Hettinger and Erlend E. Aasland in :gh:`100414`.)
dis
---
* Change the output of :mod:`dis` module functions to show logical
labels for jump targets and exception handlers, rather than offsets.
- The offsets can be added with the new ``-O`` command line option or
- the ``show_offsets`` parameter.
+ The offsets can be added with the new
+ :option:`-O ` command-line option
+ or the *show_offsets* argument.
(Contributed by Irit Katriel in :gh:`112137`.)
-* :meth:`~dis.get_instructions` no longer represents cache entries as
- separate instructions. Instead, it returns them as part of the
- :class:`~dis.Instruction`, in the new *cache_info* field. The
- *show_caches* argument to :meth:`~dis.get_instructions` is
- deprecated and no longer has any effect.
+* :meth:`~dis.get_instructions` no longer represents cache entries
+ as separate instructions.
+ Instead, it returns them as part of the :class:`~dis.Instruction`,
+ in the new *cache_info* field.
+ The *show_caches* argument to :meth:`~dis.get_instructions` is deprecated
+ and no longer has any effect.
(Contributed by Irit Katriel in :gh:`112962`.)
+
.. _whatsnew313-doctest:
doctest
-------
-* Color is added to the output by default.
+* :mod:`doctest` output is now colored by default.
This can be controlled via the new :envvar:`PYTHON_COLORS` environment
- variable as well as the canonical |NO_COLOR|_ and |FORCE_COLOR|_ environment
- variables. See also :ref:`using-on-controlling-color`.
+ variable as well as the canonical |NO_COLOR|_
+ and |FORCE_COLOR|_ environment variables.
+ See also :ref:`using-on-controlling-color`.
(Contributed by Hugo van Kemenade in :gh:`117225`.)
-* The :meth:`doctest.DocTestRunner.run` method now counts the number of skipped
- tests. Add :attr:`doctest.DocTestRunner.skips` and
- :attr:`doctest.TestResults.skipped` attributes.
+* The :meth:`.DocTestRunner.run` method now counts the number of skipped tests.
+ Add the :attr:`.DocTestRunner.skips` and :attr:`.TestResults.skipped` attributes.
(Contributed by Victor Stinner in :gh:`108794`.)
+
email
-----
-* :func:`email.utils.getaddresses` and :func:`email.utils.parseaddr` now return
- ``('', '')`` 2-tuples in more situations where invalid email addresses are
- encountered instead of potentially inaccurate values. Add optional *strict*
- parameter to these two functions: use ``strict=False`` to get the old
- behavior, accept malformed inputs.
- ``getattr(email.utils, 'supports_strict_parsing', False)`` can be used to
- check if the *strict* parameter is available.
+* Headers with embedded newlines are now quoted on output.
+ The :mod:`~email.generator` will now refuse to serialize (write) headers
+ that are improperly folded or delimited, such that they would be parsed as
+ multiple headers or joined with adjacent data.
+ If you need to turn this safety feature off,
+ set :attr:`~email.policy.Policy.verify_generated_headers`.
+ (Contributed by Bas Bloemsaat and Petr Viktorin in :gh:`121650`.)
+
+* :func:`~email.utils.getaddresses` and :func:`~email.utils.parseaddr` now
+ return ``('', '')`` pairs in more situations where invalid email addresses
+ are encountered instead of potentially inaccurate values.
+ The two functions have a new optional *strict* parameter (default ``True``).
+ To get the old behavior (accepting malformed input), use ``strict=False``.
+ ``getattr(email.utils, 'supports_strict_parsing', False)`` can be used
+ to check if the *strict* parameter is available.
(Contributed by Thomas Dwyer and Victor Stinner for :gh:`102988` to improve
the :cve:`2023-27043` fix.)
+
fractions
---------
-* Formatting for objects of type :class:`fractions.Fraction` now supports
- the standard format specification mini-language rules for fill, alignment,
- sign handling, minimum width and grouping. (Contributed by Mark Dickinson
- in :gh:`111320`.)
-
-gc
---
+* :class:`~fractions.Fraction` objects now support the standard
+ :ref:`format specification mini-language ` rules
+ for fill, alignment, sign handling, minimum width, and grouping.
+ (Contributed by Mark Dickinson in :gh:`111320`.)
-* The cyclic garbage collector is now incremental, which changes the meanings
- of the results of :meth:`gc.get_threshold` and :meth:`gc.set_threshold` as
- well as :meth:`gc.get_count` and :meth:`gc.get_stats`.
-
- * :meth:`gc.get_threshold` returns a three-item tuple for backwards compatibility.
- The first value is the threshold for young collections, as before; the second
- value determines the rate at which the old collection is scanned (the
- default is 10, and higher values mean that the old collection is scanned more slowly).
- The third value is meaningless and is always zero.
- * :meth:`gc.set_threshold` ignores any items after the second.
- * :meth:`gc.get_count` and :meth:`gc.get_stats`
- return the same format of results as before.
- The only difference is that instead of the results referring to
- the young, aging and old generations, the results refer to the
- young generation and the aging and collecting spaces of the old generation.
-
- In summary, code that attempted to manipulate the behavior of the cycle GC may
- not work exactly as intended, but it is very unlikely to be harmful.
- All other code will work just fine.
glob
----
-* Add :func:`glob.translate` function that converts a path specification with
- shell-style wildcards to a regular expression.
+* Add :func:`~glob.translate`, a function to convert a path specification
+ with shell-style wildcards to a regular expression.
(Contributed by Barney Gale in :gh:`72904`.)
+
importlib
---------
-* Previously deprecated :mod:`importlib.resources` functions are un-deprecated:
-
- * :func:`~importlib.resources.is_resource()`
- * :func:`~importlib.resources.open_binary()`
- * :func:`~importlib.resources.open_text()`
- * :func:`~importlib.resources.path()`
- * :func:`~importlib.resources.read_binary()`
- * :func:`~importlib.resources.read_text()`
+* The following functions in :mod:`importlib.resources` now allow accessing
+ a directory (or tree) of resources, using multiple positional arguments
+ (the *encoding* and *errors* arguments in the text-reading functions
+ are now keyword-only):
- All now allow for a directory (or tree) of resources, using multiple positional
- arguments.
+ * :func:`~importlib.resources.is_resource`
+ * :func:`~importlib.resources.open_binary`
+ * :func:`~importlib.resources.open_text`
+ * :func:`~importlib.resources.path`
+ * :func:`~importlib.resources.read_binary`
+ * :func:`~importlib.resources.read_text`
- For text-reading functions, the *encoding* and *errors* must now be given as
- keyword arguments.
+ These functions are no longer deprecated and are not scheduled for removal.
+ (Contributed by Petr Viktorin in :gh:`106532`.)
- The :func:`~importlib.resources.contents()` remains deprecated in favor of
- the full-featured :class:`~importlib.resources.abc.Traversable` API.
+* :func:`~importlib.resources.contents` remains deprecated in favor of
+ the fully-featured :class:`~importlib.resources.abc.Traversable` API.
However, there is now no plan to remove it.
-
(Contributed by Petr Viktorin in :gh:`106532`.)
+
io
--
-* The :class:`io.IOBase` finalizer now logs the ``close()`` method errors with
- :data:`sys.unraisablehook`. Previously, errors were ignored silently by default,
- and only logged in :ref:`Python Development Mode ` or on :ref:`Python
- built on debug mode `.
+* The :class:`~io.IOBase` finalizer now logs any errors raised by
+ the :meth:`~io.IOBase.close` method with :data:`sys.unraisablehook`.
+ Previously, errors were ignored silently by default,
+ and only logged in :ref:`Python Development Mode `
+ or when using a :ref:`Python debug build `.
(Contributed by Victor Stinner in :gh:`62948`.)
+
ipaddress
---------
-* Add the :attr:`ipaddress.IPv4Address.ipv6_mapped` property, which returns the IPv4-mapped IPv6 address.
+* Add the :attr:`.IPv4Address.ipv6_mapped` property,
+ which returns the IPv4-mapped IPv6 address.
(Contributed by Charles Machalow in :gh:`109466`.)
+
* Fix ``is_global`` and ``is_private`` behavior in
- :class:`~ipaddress.IPv4Address`,
- :class:`~ipaddress.IPv6Address`,
- :class:`~ipaddress.IPv4Network` and
- :class:`~ipaddress.IPv6Network`.
+ :class:`~ipaddress.IPv4Address`, :class:`~ipaddress.IPv6Address`,
+ :class:`~ipaddress.IPv4Network`, and :class:`~ipaddress.IPv6Network`.
+ (Contributed by Jakub Stasiak in :gh:`113171`.)
+
itertools
---------
-* Added a ``strict`` option to :func:`itertools.batched`.
- This raises a :exc:`ValueError` if the final batch is shorter
+* :func:`~itertools.batched` has a new *strict* parameter,
+ which raises a :exc:`ValueError` if the final batch is shorter
than the specified batch size.
(Contributed by Raymond Hettinger in :gh:`113202`.)
+
marshal
-------
* Add the *allow_code* parameter in module functions.
- Passing ``allow_code=False`` prevents serialization and de-serialization of
- code objects which are incompatible between Python versions.
+ Passing ``allow_code=False`` prevents serialization and de-serialization
+ of code objects which are incompatible between Python versions.
(Contributed by Serhiy Storchaka in :gh:`113626`.)
+
math
----
-* A new function :func:`~math.fma` for fused multiply-add operations has been
- added. This function computes ``x * y + z`` with only a single round, and so
- avoids any intermediate loss of precision. It wraps the ``fma()`` function
- provided by C99, and follows the specification of the IEEE 754
- "fusedMultiplyAdd" operation for special cases.
+* The new function :func:`~math.fma` performs fused multiply-add operations.
+ This computes ``x * y + z`` with only a single round,
+ and so avoids any intermediate loss of precision.
+ It wraps the ``fma()`` function provided by C99,
+ and follows the specification of the IEEE 754 "fusedMultiplyAdd" operation
+ for special cases.
(Contributed by Mark Dickinson and Victor Stinner in :gh:`73468`.)
+
mimetypes
---------
-* Add the :func:`~mimetypes.guess_file_type` function which works with file path.
- Passing file path instead of URL in :func:`~mimetypes.guess_type` is :term:`soft deprecated`.
+* Add the :func:`~mimetypes.guess_file_type` function to guess a MIME type
+ from a filesystem path.
+ Using paths with :func:`~mimetypes.guess_type` is now :term:`soft deprecated`.
(Contributed by Serhiy Storchaka in :gh:`66543`.)
+
mmap
----
-* The :class:`mmap.mmap` class now has an :meth:`~mmap.mmap.seekable` method
+* :class:`~mmap.mmap` is now protected from crashing on Windows when the
+ mapped memory is inaccessible due to file system errors or access violations.
+ (Contributed by Jannis Weigend in :gh:`118209`.)
+
+* :class:`~mmap.mmap` has a new :meth:`~mmap.mmap.seekable` method
that can be used when a seekable file-like object is required.
The :meth:`~mmap.mmap.seek` method now returns the new absolute position.
(Contributed by Donghee Na and Sylvie Liberman in :gh:`111835`.)
-* :class:`mmap.mmap` now has a *trackfd* parameter on Unix; if it is ``False``,
- the file descriptor specified by *fileno* will not be duplicated.
+
+* The new UNIX-only *trackfd* parameter for :class:`~mmap.mmap` controls
+ file descriptor duplication;
+ if false, the file descriptor specified by *fileno* will not be duplicated.
(Contributed by Zackery Spytz and Petr Viktorin in :gh:`78502`.)
-* :class:`mmap.mmap` is now protected from crashing on Windows when the mapped memory
- is inaccessible due to file system errors or access violations.
- (Contributed by Jannis Weigend in :gh:`118209`.)
-opcode
-------
-* Move ``opcode.ENABLE_SPECIALIZATION`` to ``_opcode.ENABLE_SPECIALIZATION``.
- This field was added in 3.12, it was never documented and is not intended for
- external usage. (Contributed by Irit Katriel in :gh:`105481`.)
+multiprocessing
+---------------
+
+* The default number of worker threads and processes is now selected using
+ :func:`os.process_cpu_count` instead of :func:`os.cpu_count`.
+ (Contributed by Victor Stinner in :gh:`109649`.)
-* Removed ``opcode.is_pseudo``, ``opcode.MIN_PSEUDO_OPCODE`` and
- ``opcode.MAX_PSEUDO_OPCODE``, which were added in 3.12, were never
- documented or exposed through ``dis``, and were not intended to be
- used externally.
os
--
-* Add :func:`os.process_cpu_count` function to get the number of logical CPUs
- usable by the calling thread of the current process.
+* Add :func:`~os.process_cpu_count` function to get the number
+ of logical CPU cores usable by the calling thread of the current process.
(Contributed by Victor Stinner in :gh:`109649`.)
-* Add a low level interface for Linux's timer notification file descriptors
- via :func:`os.timerfd_create`,
- :func:`os.timerfd_settime`, :func:`os.timerfd_settime_ns`,
- :func:`os.timerfd_gettime`, and :func:`os.timerfd_gettime_ns`,
- :const:`os.TFD_NONBLOCK`, :const:`os.TFD_CLOEXEC`,
- :const:`os.TFD_TIMER_ABSTIME`, and :const:`os.TFD_TIMER_CANCEL_ON_SET`
- (Contributed by Masaru Tsuchiyama in :gh:`108277`.)
-
-* :func:`os.cpu_count` and :func:`os.process_cpu_count` can be overridden through
- the new environment variable :envvar:`PYTHON_CPU_COUNT` or the new command-line option
- :option:`-X cpu_count <-X>`. This option is useful for users who need to limit
- CPU resources of a container system without having to modify the container (application code).
+* :func:`~os.cpu_count` and :func:`~os.process_cpu_count` can be overridden
+ through the new environment variable :envvar:`PYTHON_CPU_COUNT`
+ or the new command-line option :option:`-X cpu_count <-X>`.
+ This option is useful for users who need to limit CPU resources
+ of a container system without having to modify application code
+ or the container itself.
(Contributed by Donghee Na in :gh:`109595`.)
-* Add support of :func:`os.lchmod` and the *follow_symlinks* argument
- in :func:`os.chmod` on Windows.
- Note that the default value of *follow_symlinks* in :func:`!os.lchmod` is
- ``False`` on Windows.
+* Add a :ref:`low level interface ` to Linux's
+ :manpage:`timer file descriptors `
+ via :func:`~os.timerfd_create`,
+ :func:`~os.timerfd_settime`, :func:`~os.timerfd_settime_ns`,
+ :func:`~os.timerfd_gettime`, :func:`~os.timerfd_gettime_ns`,
+ :const:`~os.TFD_NONBLOCK`, :const:`~os.TFD_CLOEXEC`,
+ :const:`~os.TFD_TIMER_ABSTIME`, and :const:`~os.TFD_TIMER_CANCEL_ON_SET`
+ (Contributed by Masaru Tsuchiyama in :gh:`108277`.)
+
+* :func:`~os.lchmod` and the *follow_symlinks* argument of :func:`~os.chmod`
+ are both now available on Windows.
+ Note that the default value of *follow_symlinks*
+ in :func:`!lchmod` is ``False`` on Windows.
(Contributed by Serhiy Storchaka in :gh:`59616`.)
-* Add support of :func:`os.fchmod` and a file descriptor
- in :func:`os.chmod` on Windows.
+* :func:`~os.fchmod` and support for file descriptors in :func:`~os.chmod`
+ are both now available on Windows.
(Contributed by Serhiy Storchaka in :gh:`113191`.)
-* :func:`os.posix_spawn` now accepts ``env=None``, which makes the newly spawned
- process use the current process environment.
+* On Windows, :func:`~os.mkdir` and :func:`~os.makedirs` now support passing
+ a *mode* value of ``0o700`` to apply access control to the new directory.
+ This implicitly affects :func:`tempfile.mkdtemp`
+ and is a mitigation for :cve:`2024-4030`.
+ Other values for *mode* continue to be ignored.
+ (Contributed by Steve Dower in :gh:`118486`.)
+
+* :func:`~os.posix_spawn` now accepts ``None`` for the *env* argument,
+ which makes the newly spawned process use the current process environment.
(Contributed by Jakub Kulik in :gh:`113119`.)
-* :func:`os.posix_spawn` gains an :attr:`os.POSIX_SPAWN_CLOSEFROM` attribute for
- use in ``file_actions=`` on platforms that support
+* :func:`~os.posix_spawn` can now use the :attr:`~os.POSIX_SPAWN_CLOSEFROM`
+ attribute in the *file_actions* parameter on platforms that support
:c:func:`!posix_spawn_file_actions_addclosefrom_np`.
(Contributed by Jakub Kulik in :gh:`113117`.)
-* :func:`os.mkdir` and :func:`os.makedirs` on Windows now support passing a
- *mode* value of ``0o700`` to apply access control to the new directory. This
- implicitly affects :func:`tempfile.mkdtemp` and is a mitigation for
- :cve:`2024-4030`. Other values for *mode* continue to be ignored.
- (Contributed by Steve Dower in :gh:`118486`.)
os.path
-------
-* Add :func:`os.path.isreserved` to check if a path is reserved on the current
- system. This function is only available on Windows.
+* Add :func:`~os.path.isreserved` to check if a path is reserved
+ on the current system.
+ This function is only available on Windows.
(Contributed by Barney Gale in :gh:`88569`.)
-* On Windows, :func:`os.path.isabs` no longer considers paths starting with
- exactly one (back)slash to be absolute.
+
+* On Windows, :func:`~os.path.isabs` no longer considers paths
+ starting with exactly one slash (``\`` or ``/``) to be absolute.
(Contributed by Barney Gale and Jon Foster in :gh:`44626`.)
-* Add support of *dir_fd* and *follow_symlinks* keyword arguments in
- :func:`shutil.chown`.
- (Contributed by Berker Peksag and Tahia K in :gh:`62308`)
+* :func:`~os.path.realpath` now resolves MS-DOS style file names
+ even if the file is not accessible.
+ (Contributed by Moonsik Park in :gh:`82367`.)
+
pathlib
-------
-* Add :exc:`pathlib.UnsupportedOperation`, which is raised instead of
+* Add :exc:`~pathlib.UnsupportedOperation`, which is raised instead of
:exc:`NotImplementedError` when a path operation isn't supported.
(Contributed by Barney Gale in :gh:`89812`.)
-* Add :meth:`pathlib.Path.from_uri`, a new constructor to create a :class:`pathlib.Path`
- object from a 'file' URI (``file://``).
+* Add a new constructor for creating :class:`~pathlib.Path` objects
+ from 'file' URIs (``file:///``), :meth:`.Path.from_uri`.
(Contributed by Barney Gale in :gh:`107465`.)
-* Add :meth:`pathlib.PurePath.full_match` for matching paths with
+* Add :meth:`.PurePath.full_match` for matching paths with
shell-style wildcards, including the recursive wildcard "``**``".
(Contributed by Barney Gale in :gh:`73435`.)
-* Add :attr:`pathlib.PurePath.parser` class attribute that stores the
- implementation of :mod:`os.path` used for low-level path parsing and
- joining: either ``posixpath`` or ``ntpath``.
+* Add the :attr:`.PurePath.parser` class attribute to store the
+ implementation of :mod:`os.path` used
+ for low-level path parsing and joining.
+ This will be either :mod:`!posixpath` or :mod:`!ntpath`.
-* Add *recurse_symlinks* keyword-only argument to :meth:`pathlib.Path.glob`
- and :meth:`~pathlib.Path.rglob`.
+* Add *recurse_symlinks* keyword-only argument to
+ :meth:`.Path.glob` and :meth:`~pathlib.Path.rglob`.
(Contributed by Barney Gale in :gh:`77609`.)
-* Add *follow_symlinks* keyword-only argument to :meth:`~pathlib.Path.is_file`,
- :meth:`~pathlib.Path.is_dir`, :meth:`~pathlib.Path.owner`,
- :meth:`~pathlib.Path.group`.
- (Contributed by Barney Gale in :gh:`105793`, and Kamil Turek in
- :gh:`107962`.)
-
-* Return files and directories from :meth:`pathlib.Path.glob` and
- :meth:`~pathlib.Path.rglob` when given a pattern that ends with "``**``". In
- earlier versions, only directories were returned.
+* :meth:`.Path.glob` and :meth:`~pathlib.Path.rglob`
+ now return files and directories when given a pattern that ends with "``**``".
+ Previously, only directories were returned.
(Contributed by Barney Gale in :gh:`70303`.)
+* Add the *follow_symlinks* keyword-only argument to
+ :meth:`Path.is_file `,
+ :meth:`Path.is_dir `,
+ :meth:`.Path.owner`, and :meth:`.Path.group`.
+ (Contributed by Barney Gale in :gh:`105793` and Kamil Turek in :gh:`107962`.)
+
+
pdb
---
-* Add ability to move between chained exceptions during post mortem debugging in :func:`~pdb.pm` using
- the new ``exceptions [exc_number]`` command for Pdb. (Contributed by Matthias
- Bussonnier in :gh:`106676`.)
-
-* Expressions/statements whose prefix is a pdb command are now correctly
- identified and executed.
- (Contributed by Tian Gao in :gh:`108464`.)
+* :func:`breakpoint` and :func:`~pdb.set_trace` now enter the debugger immediately
+ rather than on the next line of code to be executed. This change prevents the
+ debugger from breaking outside of the context when :func:`!breakpoint` is positioned
+ at the end of the context.
+ (Contributed by Tian Gao in :gh:`118579`.)
-* ``sys.path[0]`` will no longer be replaced by the directory of the script
- being debugged when ``sys.flags.safe_path`` is set (via the :option:`-P`
- command line option or :envvar:`PYTHONSAFEPATH` environment variable).
+* ``sys.path[0]`` is no longer replaced by the directory of the script
+ being debugged when :attr:`sys.flags.safe_path` is set.
(Contributed by Tian Gao and Christian Walther in :gh:`111762`.)
-* :mod:`zipapp` is supported as a debugging target.
+* :mod:`zipapp` is now supported as a debugging target.
(Contributed by Tian Gao in :gh:`118501`.)
-* ``breakpoint()`` and ``pdb.set_trace()`` now enter the debugger immediately
- rather than on the next line of code to be executed. This change prevents the
- debugger from breaking outside of the context when ``breakpoint()`` is positioned
- at the end of the context.
- (Contributed by Tian Gao in :gh:`118579`.)
+* Add ability to move between chained exceptions during
+ post-mortem debugging in :func:`~pdb.pm` using
+ the new :pdbcmd:`exceptions [exc_number] ` command for Pdb.
+ (Contributed by Matthias Bussonnier in :gh:`106676`.)
+
+* Expressions and statements whose prefix is a pdb command are now correctly
+ identified and executed.
+ (Contributed by Tian Gao in :gh:`108464`.)
+
queue
-----
-* Add :meth:`queue.Queue.shutdown` (along with :exc:`queue.ShutDown`) for queue
- termination.
+* Add :meth:`Queue.shutdown ` and :exc:`~queue.ShutDown`
+ to manage queue termination.
(Contributed by Laurie Opperman and Yves Duprat in :gh:`104750`.)
+
random
------
* Add a :ref:`command-line interface `.
(Contributed by Hugo van Kemenade in :gh:`118131`.)
+
re
--
-* Rename :exc:`!re.error` to :exc:`re.PatternError` for improved clarity.
+
+* Rename :exc:`!re.error` to :exc:`~re.PatternError` for improved clarity.
:exc:`!re.error` is kept for backward compatibility.
-site
-----
-* :file:`.pth` files are now decoded by UTF-8 first, and then by the
- :term:`locale encoding` if the UTF-8 decoding fails.
+shutil
+------
+
+* Support the *dir_fd* and *follow_symlinks* keyword arguments
+ in :func:`~shutil.chown`.
+ (Contributed by Berker Peksag and Tahia K in :gh:`62308`)
+
+
+site
+----
+
+* :file:`.pth` files are now decoded using UTF-8 first,
+ and then with the :term:`locale encoding` if UTF-8 decoding fails.
(Contributed by Inada Naoki in :gh:`117802`.)
+
sqlite3
-------
-* A :exc:`ResourceWarning` is now emitted if a :class:`sqlite3.Connection`
+* A :exc:`ResourceWarning` is now emitted if a :class:`~sqlite3.Connection`
object is not :meth:`closed ` explicitly.
(Contributed by Erlend E. Aasland in :gh:`105539`.)
-* Add *filter* keyword-only parameter to :meth:`sqlite3.Connection.iterdump`
+* Add the *filter* keyword-only parameter to :meth:`.Connection.iterdump`
for filtering database objects to dump.
(Contributed by Mariusz Felisiak in :gh:`91602`.)
+
+ssl
+---
+
+* The :func:`~ssl.create_default_context` API now includes
+ :data:`~ssl.VERIFY_X509_PARTIAL_CHAIN` and :data:`~ssl.VERIFY_X509_STRICT`
+ in its default flags.
+
+ .. note::
+
+ :data:`~ssl.VERIFY_X509_STRICT` may reject pre-:rfc:`5280`
+ or malformed certificates that the underlying OpenSSL implementation
+ might otherwise accept.
+ Whilst disabling this is not recommended, you can do so using:
+
+ .. code-block:: python
+
+ import ssl
+
+ ctx = ssl.create_default_context()
+ ctx.verify_flags &= ~ssl.VERIFY_X509_STRICT
+
+ (Contributed by William Woodruff in :gh:`112389`.)
+
+
statistics
----------
-* Add :func:`statistics.kde` for kernel density estimation.
+* Add :func:`~statistics.kde` for kernel density estimation.
This makes it possible to estimate a continuous probability density function
- from a fixed number of discrete samples. Also added :func:`statistics.kde_random`
- for sampling from the estimated probability density function.
+ from a fixed number of discrete samples.
+ (Contributed by Raymond Hettinger in :gh:`115863`.)
+
+* Add :func:`~statistics.kde_random` for sampling from an
+ estimated probability density function created by :func:`~statistics.kde`.
(Contributed by Raymond Hettinger in :gh:`115863`.)
+
.. _whatsnew313-subprocess:
subprocess
----------
-* The :mod:`subprocess` module now uses the :func:`os.posix_spawn` function in
- more situations. Notably in the default case of ``close_fds=True`` on more
- recent versions of platforms including Linux, FreeBSD, and Solaris where the
- C library provides :c:func:`!posix_spawn_file_actions_addclosefrom_np`.
- On Linux this should perform similar to our existing Linux :c:func:`!vfork`
- based code. A private control knob :attr:`!subprocess._USE_POSIX_SPAWN` can
- be set to ``False`` if you need to force :mod:`subprocess` not to ever use
- :func:`os.posix_spawn`. Please report your reason and platform details in
- the CPython issue tracker if you set this so that we can improve our API
- selection logic for everyone.
+* The :mod:`subprocess` module now uses the :func:`~os.posix_spawn` function in
+ more situations.
+
+ Notably, when *close_fds* is ``True`` (the default),
+ :func:`~os.posix_spawn` will be used when the C library provides
+ :c:func:`!posix_spawn_file_actions_addclosefrom_np`,
+ which includes recent versions of Linux, FreeBSD, and Solaris.
+ On Linux, this should perform similarly to the existing
+ Linux :c:func:`!vfork` based code.
+
+ A private control knob :attr:`!subprocess._USE_POSIX_SPAWN` can
+ be set to ``False`` if you need to force :mod:`subprocess`
+ to never use :func:`~os.posix_spawn`.
+ Please report your reason and platform details in
+ the :ref:`issue tracker ` if you set this
+ so that we can improve our API selection logic for everyone.
(Contributed by Jakub Kulik in :gh:`113117`.)
+
sys
---
-* Add the :func:`sys._is_interned` function to test if the string was interned.
+* Add the :func:`~sys._is_interned` function to test if a string was interned.
This function is not guaranteed to exist in all implementations of Python.
(Contributed by Serhiy Storchaka in :gh:`78573`.)
+
tempfile
--------
* On Windows, the default mode ``0o700`` used by :func:`tempfile.mkdtemp` now
- limits access to the new directory due to changes to :func:`os.mkdir`. This
- is a mitigation for :cve:`2024-4030`.
+ limits access to the new directory due to changes to :func:`os.mkdir`.
+ This is a mitigation for :cve:`2024-4030`.
(Contributed by Steve Dower in :gh:`118486`.)
+
time
----
-* On Windows, :func:`time.monotonic()` now uses the
- ``QueryPerformanceCounter()`` clock to have a resolution better than 1 us,
- instead of the ``GetTickCount64()`` clock which has a resolution of 15.6 ms.
+* On Windows, :func:`~time.monotonic` now uses the
+ ``QueryPerformanceCounter()`` clock for a resolution of 1 microsecond,
+ instead of the ``GetTickCount64()`` clock which has
+ a resolution of 15.6 milliseconds.
(Contributed by Victor Stinner in :gh:`88494`.)
-* On Windows, :func:`time.time()` now uses the
- ``GetSystemTimePreciseAsFileTime()`` clock to have a resolution better
- than 1 μs, instead of the ``GetSystemTimeAsFileTime()`` clock which has a
- resolution of 15.6 ms.
+* On Windows, :func:`~time.time` now uses the
+ ``GetSystemTimePreciseAsFileTime()`` clock for a resolution of 1 microsecond,
+ instead of the ``GetSystemTimeAsFileTime()`` clock which has
+ a resolution of 15.6 milliseconds.
(Contributed by Victor Stinner in :gh:`63207`.)
@@ -1093,20 +1300,21 @@ tkinter
* The :mod:`tkinter` widget method :meth:`!wm_attributes` now accepts
the attribute name without the minus prefix to get window attributes,
- e.g. ``w.wm_attributes('alpha')`` and allows to specify attributes and
- values to set as keyword arguments, e.g. ``w.wm_attributes(alpha=0.5)``.
- Add new optional keyword-only parameter *return_python_dict*: calling
- ``w.wm_attributes(return_python_dict=True)`` returns the attributes as
- a dict instead of a tuple.
+ for example ``w.wm_attributes('alpha')``
+ and allows specifying attributes and values to set as keyword arguments,
+ for example ``w.wm_attributes(alpha=0.5)``.
+ (Contributed by Serhiy Storchaka in :gh:`43457`.)
+
+* :meth:`!wm_attributes` can now return attributes as a :class:`dict`,
+ by using the new optional keyword-only parameter *return_python_dict*.
(Contributed by Serhiy Storchaka in :gh:`43457`.)
-* Add new optional keyword-only parameter *return_ints* in
- the :meth:`!Text.count` method.
- Passing ``return_ints=True`` makes it always returning the single count
- as an integer instead of a 1-tuple or ``None``.
+* :meth:`!Text.count` can now return a simple :class:`int`
+ when the new optional keyword-only parameter *return_ints* is used.
+ Otherwise, the single count is returned as a 1-tuple or ``None``.
(Contributed by Serhiy Storchaka in :gh:`97928`.)
-* Add support of the "vsapi" element type in
+* Support the "vsapi" element type in
the :meth:`~tkinter.ttk.Style.element_create` method of
:class:`tkinter.ttk.Style`.
(Contributed by Serhiy Storchaka in :gh:`68166`.)
@@ -1114,307 +1322,375 @@ tkinter
* Add the :meth:`!after_info` method for Tkinter widgets.
(Contributed by Cheryl Sabella in :gh:`77020`.)
-* Add the :class:`!PhotoImage` method :meth:`!copy_replace` to copy a region
- from one image to other image, possibly with pixel zooming and/or
- subsampling.
- Add *from_coords* parameter to :class:`!PhotoImage` methods :meth:`!copy()`,
- :meth:`!zoom()` and :meth:`!subsample()`.
- Add *zoom* and *subsample* parameters to :class:`!PhotoImage` method
- :meth:`!copy()`.
+* Add a new :meth:`!copy_replace` method to :class:`!PhotoImage`
+ to copy a region from one image to another,
+ possibly with pixel zooming, subsampling, or both.
(Contributed by Serhiy Storchaka in :gh:`118225`.)
-* Add the :class:`!PhotoImage` methods :meth:`!read` to read
- an image from a file and :meth:`!data` to get the image data.
- Add *background* and *grayscale* parameters to :class:`!PhotoImage` method
- :meth:`!write`.
+* Add *from_coords* parameter to the :class:`!PhotoImage` methods
+ :meth:`!copy`, :meth:`!zoom` and :meth:`!subsample`.
+ Add *zoom* and *subsample* parameters to the :class:`!PhotoImage` method
+ :meth:`!copy`.
+ (Contributed by Serhiy Storchaka in :gh:`118225`.)
+
+* Add the :class:`!PhotoImage` methods
+ :meth:`!read` to read an image from a file
+ and :meth:`!data` to get the image data.
+ Add *background* and *grayscale* parameters to the :meth:`!write` method.
(Contributed by Serhiy Storchaka in :gh:`118271`.)
+
traceback
---------
-* Add *show_group* parameter to :func:`traceback.TracebackException.format_exception_only`
- to format the nested exceptions of a :exc:`BaseExceptionGroup` instance, recursively.
+* Add the :attr:`~traceback.TracebackException.exc_type_str` attribute
+ to :class:`~traceback.TracebackException`,
+ which holds a string display of the *exc_type*.
+ Deprecate the :attr:`~traceback.TracebackException.exc_type` attribute,
+ which holds the type object itself.
+ Add parameter *save_exc_type* (default ``True``)
+ to indicate whether ``exc_type`` should be saved.
+ (Contributed by Irit Katriel in :gh:`112332`.)
+
+* Add a new *show_group* keyword-only parameter to
+ :meth:`.TracebackException.format_exception_only` to (recursively) format
+ the nested exceptions of a :exc:`BaseExceptionGroup` instance.
(Contributed by Irit Katriel in :gh:`105292`.)
-* Add the field *exc_type_str* to :class:`~traceback.TracebackException`, which
- holds a string display of the *exc_type*. Deprecate the field *exc_type*
- which holds the type object itself. Add parameter *save_exc_type* (default
- ``True``) to indicate whether ``exc_type`` should be saved.
- (Contributed by Irit Katriel in :gh:`112332`.)
types
-----
-* :class:`~types.SimpleNamespace` constructor now allows specifying initial
- values of attributes as a positional argument which must be a mapping or
- an iterable of key-value pairs.
+* :class:`~types.SimpleNamespace` can now take a single positional argument
+ to initialise the namespace's arguments.
+ This argument must either be a mapping or an iterable of key-value pairs.
(Contributed by Serhiy Storchaka in :gh:`108191`.)
+
typing
------
-* Add :func:`typing.get_protocol_members` to return the set of members
- defining a :class:`typing.Protocol`. Add :func:`typing.is_protocol` to
- check whether a class is a :class:`typing.Protocol`. (Contributed by Jelle Zijlstra in
- :gh:`104873`.)
+* :pep:`705`: Add :data:`~typing.ReadOnly`, a special typing construct
+ to mark a :class:`~typing.TypedDict` item as read-only for type checkers.
+
+* :pep:`742`: Add :data:`~typing.TypeIs`, a typing construct
+ that can be used to instruct a type checker how to narrow a type.
+
+* Add :data:`~typing.NoDefault`, a sentinel object used to represent
+ the defaults of some parameters in the :mod:`typing` module.
+ (Contributed by Jelle Zijlstra in :gh:`116126`.)
+
+* Add :func:`~typing.get_protocol_members` to return the set of members
+ defining a :class:`typing.Protocol`.
+ (Contributed by Jelle Zijlstra in :gh:`104873`.)
+
+* Add :func:`~typing.is_protocol` to check whether a class
+ is a :class:`~typing.Protocol`.
+ (Contributed by Jelle Zijlstra in :gh:`104873`.)
-* Add :data:`typing.ReadOnly`, a special typing construct to mark
- an item of a :class:`typing.TypedDict` as read-only for type checkers.
- See :pep:`705` for more details.
+* :data:`~typing.ClassVar` can now be nested in :data:`~typing.Final`,
+ and vice versa.
+ (Contributed by Mehdi Drissi in :gh:`89547`.)
-* Add :data:`typing.NoDefault`, a sentinel object used to represent the defaults
- of some parameters in the :mod:`typing` module. (Contributed by Jelle Zijlstra in
- :gh:`116126`.)
unicodedata
-----------
-* The Unicode database has been updated to version 15.1.0. (Contributed by
- James Gerity in :gh:`109559`.)
+* Update the Unicode database to `version 15.1.0`__.
+ (Contributed by James Gerity in :gh:`109559`.)
+
+ __ https://www.unicode.org/versions/Unicode15.1.0/
+
venv
----
-* Add support for adding source control management (SCM) ignore files to a
- virtual environment's directory. By default, Git is supported. This is
- implemented as opt-in via the API which can be extended to support other SCMs
- (:class:`venv.EnvBuilder` and :func:`venv.create`), and opt-out via the CLI
- (using ``--without-scm-ignore-files``). (Contributed by Brett Cannon in
- :gh:`108125`.)
+* Add support for creating source control management (SCM) ignore files
+ in a virtual environment's directory.
+ By default, Git is supported.
+ This is implemented as opt-in via the API,
+ which can be extended to support other SCMs
+ (:class:`~venv.EnvBuilder` and :func:`~venv.create`),
+ and opt-out via the CLI, using :option:`!--without-scm-ignore-files`.
+ (Contributed by Brett Cannon in :gh:`108125`.)
+
warnings
--------
-* The new :func:`warnings.deprecated` decorator provides a way to communicate
- deprecations to :term:`static type checkers ` and
- to warn on usage of deprecated classes and functions. A runtime deprecation
- warning may also be emitted when a decorated function or class is used at runtime.
- See :pep:`702`. (Contributed by Jelle Zijlstra in :gh:`104003`.)
+* :pep:`702`: The new :func:`warnings.deprecated` decorator provides a way to
+ communicate deprecations to a :term:`static type checker`
+ and to warn on usage of deprecated classes and functions.
+ A :exc:`DeprecationWarning` may also be emitted when
+ a decorated function or class is used at runtime.
+ (Contributed by Jelle Zijlstra in :gh:`104003`.)
-xml.etree.ElementTree
----------------------
+
+xml
+---
+
+* Allow controlling Expat >=2.6.0 reparse deferral (:cve:`2023-52425`)
+ by adding five new methods:
+
+ * :meth:`xml.etree.ElementTree.XMLParser.flush`
+ * :meth:`xml.etree.ElementTree.XMLPullParser.flush`
+ * :meth:`xml.parsers.expat.xmlparser.GetReparseDeferralEnabled`
+ * :meth:`xml.parsers.expat.xmlparser.SetReparseDeferralEnabled`
+ * :meth:`!xml.sax.expatreader.ExpatParser.flush`
+
+ (Contributed by Sebastian Pipping in :gh:`115623`.)
* Add the :meth:`!close` method for the iterator returned by
- :func:`~xml.etree.ElementTree.iterparse` for explicit cleaning up.
+ :func:`~xml.etree.ElementTree.iterparse` for explicit cleanup.
(Contributed by Serhiy Storchaka in :gh:`69893`.)
+
zipimport
---------
-* Gains support for ZIP64 format files. Everybody loves huge code right?
+* Add support for ZIP64_ format files.
+ Everybody loves huge data, right?
(Contributed by Tim Hatch in :gh:`94146`.)
-.. Add improved modules above alphabetically, not here at the end.
+ .. _ZIP64: https://en.wikipedia.org/wiki/Zip_(file_format)#ZIP64
+
Optimizations
=============
-* :func:`textwrap.indent` is now ~30% faster than before for large input.
+* Several standard library modules have had
+ their import times significantly improved.
+ For example, the import time of the :mod:`typing` module
+ has been reduced by around a third by removing dependencies
+ on :mod:`re` and :mod:`contextlib`.
+ Other modules to enjoy import-time speedups include
+ :mod:`email.utils`, :mod:`enum`, :mod:`functools`,
+ :mod:`importlib.metadata`, and :mod:`threading`.
+ (Contributed by Alex Waygood, Shantanu Jain, Adam Turner, Daniel Hollas,
+ and others in :gh:`109653`.)
+
+* :func:`textwrap.indent` is now around 30% faster than before for large input.
(Contributed by Inada Naoki in :gh:`107369`.)
-* The :mod:`subprocess` module uses :func:`os.posix_spawn` in more situations
- including the default where ``close_fds=True`` on many modern platforms. This
- should provide a noteworthy performance increase launching processes on
- FreeBSD and Solaris. See the :ref:`subprocess `
- section above for details.
+* The :mod:`subprocess` module now uses the :func:`~os.posix_spawn` function in
+ more situations, including when *close_fds* is ``True`` (the default)
+ on many modern platforms.
+ This should provide a notable performance increase
+ when launching processes on FreeBSD and Solaris.
+ See the :ref:`subprocess ` section above for details.
(Contributed by Jakub Kulik in :gh:`113117`.)
-* Several standard library modules have had their import times significantly
- improved. For example, the import time of the :mod:`typing` module has been
- reduced by around a third by removing dependencies on :mod:`re` and
- :mod:`contextlib`. Other modules to enjoy import-time speedups include
- :mod:`importlib.metadata`, :mod:`threading`, :mod:`enum`, :mod:`functools`
- and :mod:`email.utils`.
- (Contributed by Alex Waygood, Shantanu Jain, Adam Turner, Daniel Hollas and
- others in :gh:`109653`.)
Removed Modules And APIs
========================
-.. _whatsnew313-pep594:
-
-PEP 594: dead batteries (and other module removals)
----------------------------------------------------
-
-* :pep:`594` removed 19 modules from the standard library,
- deprecated in Python 3.11:
-
- * :mod:`!aifc`.
- (Contributed by Victor Stinner in :gh:`104773`.)
-
- * :mod:`!audioop`.
- (Contributed by Victor Stinner in :gh:`104773`.)
-
- * :mod:`!chunk`.
- (Contributed by Victor Stinner in :gh:`104773`.)
-
- * :mod:`!cgi` and :mod:`!cgitb`.
-
- * ``cgi.FieldStorage`` can typically be replaced with
- :func:`urllib.parse.parse_qsl` for ``GET`` and ``HEAD`` requests,
- and the :mod:`email.message` module or :pypi:`multipart`
- PyPI project for ``POST`` and ``PUT``.
-
- * ``cgi.parse()`` can be replaced by calling :func:`urllib.parse.parse_qs`
- directly on the desired query string, except for ``multipart/form-data``
- input, which can be handled as described for ``cgi.parse_multipart()``.
-
- * ``cgi.parse_header()`` can be replaced with the functionality in the
- :mod:`email` package, which implements the same MIME RFCs. For example,
- with :class:`email.message.EmailMessage`::
-
- from email.message import EmailMessage
- msg = EmailMessage()
- msg['content-type'] = 'application/json; charset="utf8"'
- main, params = msg.get_content_type(), msg['content-type'].params
-
- * ``cgi.parse_multipart()`` can be replaced with the functionality in the
- :mod:`email` package (e.g. :class:`email.message.EmailMessage` and
- :class:`email.message.Message`) which implements the same MIME RFCs, or
- with the :pypi:`multipart` PyPI project.
-
- (Contributed by Victor Stinner in :gh:`104773`.)
-
- * :mod:`!crypt` module and its private :mod:`!_crypt` extension.
- The :mod:`hashlib` module is a potential replacement for certain use cases.
- Otherwise, the following PyPI projects can be used:
-
- * :pypi:`bcrypt`:
- Modern password hashing for your software and your servers.
- * :pypi:`passlib`:
- Comprehensive password hashing framework supporting over 30 schemes.
- * :pypi:`argon2-cffi`:
- The secure Argon2 password hashing algorithm.
- * :pypi:`legacycrypt`:
- :mod:`ctypes` wrapper to the POSIX crypt library call and associated functionality.
- * :pypi:`crypt_r`:
- Fork of the :mod:`!crypt` module, wrapper to the :manpage:`crypt_r(3)` library
- call and associated functionality.
-
- (Contributed by Victor Stinner in :gh:`104773`.)
-
- * :mod:`!imghdr`: use the projects :pypi:`filetype`,
- :pypi:`puremagic`, or :pypi:`python-magic` instead.
- The ``puremagic.what()`` function can be used to replace
- the ``imghdr.what()`` function for all file formats that
- were supported by ``imghdr``.
- (Contributed by Victor Stinner in :gh:`104773`.)
-
- * :mod:`!mailcap`.
- The :mod:`mimetypes` module provides an alternative.
- (Contributed by Victor Stinner in :gh:`104773`.)
-
- * :mod:`!msilib`.
- (Contributed by Zachary Ware in :gh:`104773`.)
-
- * :mod:`!nis`.
- (Contributed by Victor Stinner in :gh:`104773`.)
-
- * :mod:`!nntplib`:
- the :pypi:`nntplib` PyPI project can be used instead.
- (Contributed by Victor Stinner in :gh:`104773`.)
-
- * :mod:`!ossaudiodev`: use the
- `pygame project `_ for audio playback.
- (Contributed by Victor Stinner in :gh:`104780`.)
- * :mod:`!pipes`: use the :mod:`subprocess` module instead.
- (Contributed by Victor Stinner in :gh:`104773`.)
-
- * :mod:`!sndhdr`: use the projects :pypi:`filetype`,
- :pypi:`puremagic`, or :pypi:`python-magic` instead.
- (Contributed by Victor Stinner in :gh:`104773`.)
-
- * :mod:`!spwd`:
- the :pypi:`python-pam` project can be used instead.
- (Contributed by Victor Stinner in :gh:`104773`.)
+.. _whatsnew313-pep594:
- * :mod:`!sunau`.
- (Contributed by Victor Stinner in :gh:`104773`.)
+PEP 594: Remove "dead batteries" from the standard library
+----------------------------------------------------------
+
+:pep:`594` proposed removing 19 modules from the standard library,
+colloquially referred to as 'dead batteries' due to their
+historic, obsolete, or insecure status.
+All of the following modules were deprecated in Python 3.11,
+and are now removed:
+
+* :mod:`!aifc`
+* :mod:`!audioop`
+* :mod:`!chunk`
+* :mod:`!cgi` and :mod:`!cgitb`
+
+ * :class:`!cgi.FieldStorage` can typically be replaced with
+ :func:`urllib.parse.parse_qsl` for ``GET`` and ``HEAD`` requests,
+ and the :mod:`email.message` module or the :pypi:`multipart` library
+ for ``POST`` and ``PUT`` requests.
+
+ * :func:`!cgi.parse` can be replaced by calling
+ :func:`urllib.parse.parse_qs` directly on the desired query string,
+ unless the input is ``multipart/form-data``,
+ which should be replaced as described below for :func:`!cgi.parse_multipart`.
+
+ * :func:`!cgi.parse_header` can be replaced with the functionality
+ in the :mod:`email` package, which implements the same MIME RFCs.
+ For example, with :class:`email.message.EmailMessage`:
+
+ .. code-block:: python
+
+ from email.message import EmailMessage
+
+ msg = EmailMessage()
+ msg['content-type'] = 'application/json; charset="utf8"'
+ main, params = msg.get_content_type(), msg['content-type'].params
+
+ * :func:`!cgi.parse_multipart` can be replaced with the functionality
+ in the :mod:`email` package, which implements the same MIME RFCs,
+ or with the :pypi:`multipart` library.
+ For example, the :class:`email.message.EmailMessage`
+ and :class:`email.message.Message` classes.
+
+* :mod:`!crypt` and the private :mod:`!_crypt` extension.
+ The :mod:`hashlib` module may be an appropriate replacement
+ when simply hashing a value is required.
+ Otherwise, various third-party libraries on PyPI are available:
+
+ * :pypi:`bcrypt`:
+ Modern password hashing for your software and your servers.
+ * :pypi:`passlib`:
+ Comprehensive password hashing framework supporting over 30 schemes.
+ * :pypi:`argon2-cffi`:
+ The secure Argon2 password hashing algorithm.
+ * :pypi:`legacycrypt`:
+ :mod:`ctypes` wrapper to the POSIX crypt library call
+ and associated functionality.
+ * :pypi:`crypt_r`:
+ Fork of the :mod:`!crypt` module,
+ wrapper to the :manpage:`crypt_r(3)` library call
+ and associated functionality.
+
+* :mod:`!imghdr`:
+ The :pypi:`filetype`, :pypi:`puremagic`, or :pypi:`python-magic` libraries
+ should be used as replacements.
+ For example, the :func:`!puremagic.what` function can be used
+ to replace the :func:`!imghdr.what` function for all file formats
+ that were supported by :mod:`!imghdr`.
+* :mod:`!mailcap`:
+ Use the :mod:`mimetypes` module instead.
+* :mod:`!msilib`
+* :mod:`!nis`
+* :mod:`!nntplib`:
+ Use the :pypi:`pynntp` library from PyPI instead.
+* :mod:`!ossaudiodev`:
+ For audio playback, use the :pypi:`pygame` library from PyPI instead.
+* :mod:`!pipes`:
+ Use the :mod:`subprocess` module instead.
+* :mod:`!sndhdr`:
+ The :pypi:`filetype`, :pypi:`puremagic`, or :pypi:`python-magic` libraries
+ should be used as replacements.
+* :mod:`!spwd`:
+ Use the :pypi:`python-pam` library from PyPI instead.
+* :mod:`!sunau`
+* :mod:`!telnetlib`,
+ Use the :pypi:`telnetlib3` or :pypi:`Exscript` libraries from PyPI instead.
+* :mod:`!uu`:
+ Use the :mod:`base64` module instead, as a modern alternative.
+* :mod:`!xdrlib`
+
+(Contributed by Victor Stinner and Zachary Ware in :gh:`104773` and :gh:`104780`.)
+
+
+2to3
+----
- * :mod:`!telnetlib`, use the projects :pypi:`telnetlib3` or
- :pypi:`Exscript` instead.
- (Contributed by Victor Stinner in :gh:`104773`.)
+* Remove the :program:`2to3` program and the :mod:`!lib2to3` module,
+ previously deprecated in Python 3.11.
+ (Contributed by Victor Stinner in :gh:`104780`.)
- * :mod:`!uu`: the :mod:`base64` module is a modern alternative.
- (Contributed by Victor Stinner in :gh:`104773`.)
- * :mod:`!xdrlib`.
- (Contributed by Victor Stinner in :gh:`104773`.)
+builtins
+--------
-* Remove the ``2to3`` program and the :mod:`!lib2to3` module,
- deprecated in Python 3.11.
- (Contributed by Victor Stinner in :gh:`104780`.)
+* Remove support for chained :class:`classmethod` descriptors
+ (introduced in :gh:`63272`).
+ These can no longer be used to wrap other descriptors,
+ such as :class:`property`.
+ The core design of this feature was flawed and led to several problems.
+ To "pass-through" a :class:`classmethod`, consider using
+ the :attr:`!__wrapped__` attribute that was added in Python 3.10.
+ (Contributed by Raymond Hettinger in :gh:`89519`.)
+
+* Raise a :exc:`RuntimeError` when calling :meth:`frame.clear`
+ on a suspended frame (as has always been the case for an executing frame).
+ (Contributed by Irit Katriel in :gh:`79932`.)
-* Remove the :mod:`!tkinter.tix` module, deprecated in Python 3.6. The
- third-party Tix library which the module wrapped is unmaintained.
- (Contributed by Zachary Ware in :gh:`75552`.)
configparser
------------
-* Remove the undocumented :class:`!configparser.LegacyInterpolation` class,
+* Remove the undocumented :class:`!LegacyInterpolation` class,
deprecated in the docstring since Python 3.2,
- and with a deprecation warning since Python 3.11.
+ and at runtime since Python 3.11.
(Contributed by Hugo van Kemenade in :gh:`104886`.)
-importlib
----------
-* Remove deprecated :meth:`~object.__getitem__` access for
- :class:`!importlib.metadata.EntryPoint` objects.
+importlib.metadata
+------------------
+
+* Remove deprecated subscript (:meth:`~object.__getitem__`) access for
+ :ref:`EntryPoint ` objects.
(Contributed by Jason R. Coombs in :gh:`113175`.)
+
locale
------
-* Remove ``locale.resetlocale()`` function deprecated in Python 3.11:
- use ``locale.setlocale(locale.LC_ALL, "")`` instead.
+* Remove the :func:`!locale.resetlocale` function, deprecated in Python 3.11.
+ Use ``locale.setlocale(locale.LC_ALL, "")`` instead.
(Contributed by Victor Stinner in :gh:`104783`.)
-logging
--------
-* :mod:`logging`: Remove undocumented and untested ``Logger.warn()`` and
- ``LoggerAdapter.warn()`` methods and ``logging.warn()`` function. Deprecated
- since Python 3.3, they were aliases to the :meth:`logging.Logger.warning`
- method, :meth:`!logging.LoggerAdapter.warning` method and
- :func:`logging.warning` function.
- (Contributed by Victor Stinner in :gh:`105376`.)
+opcode
+------
+
+* Move :attr:`!opcode.ENABLE_SPECIALIZATION` to :attr:`!_opcode.ENABLE_SPECIALIZATION`.
+ This field was added in 3.12, it was never documented,
+ and is not intended for external use.
+ (Contributed by Irit Katriel in :gh:`105481`.)
+
+* Remove :func:`!opcode.is_pseudo`, :attr:`!opcode.MIN_PSEUDO_OPCODE`,
+ and :attr:`!opcode.MAX_PSEUDO_OPCODE`, which were added in Python 3.12,
+ but were neither documented nor exposed through :mod:`dis`,
+ and were not intended to be used externally.
+ (Contributed by Irit Katriel in :gh:`105481`.)
+
pathlib
-------
-* Remove support for using :class:`pathlib.Path` objects as context managers.
- This functionality was deprecated and made a no-op in Python 3.9.
+* Remove the ability to use :class:`~pathlib.Path` objects as context managers.
+ This functionality was deprecated and has had no effect since Python 3.9.
+ (Contributed by Barney Gale in :gh:`83863`.)
+
re
--
-* Remove undocumented, never working, and deprecated ``re.template`` function
- and ``re.TEMPLATE`` flag (and ``re.T`` alias).
+* Remove the undocumented, deprecated, and broken
+ :func:`!re.template` function and :attr:`!re.TEMPLATE` / :attr:`!re.T` flag.
(Contributed by Serhiy Storchaka and Nikita Sobolev in :gh:`105687`.)
+tkinter.tix
+-----------
+
+* Remove the :mod:`!tkinter.tix` module, deprecated in Python 3.6.
+ The third-party Tix library which the module wrapped is unmaintained.
+ (Contributed by Zachary Ware in :gh:`75552`.)
+
+
turtle
------
-* Remove the :meth:`!turtle.RawTurtle.settiltangle` method,
- deprecated in docs since Python 3.1
- and with a deprecation warning since Python 3.11.
+* Remove the :meth:`!RawTurtle.settiltangle` method,
+ deprecated in the documentation since Python 3.1
+ and at runtime since Python 3.11.
(Contributed by Hugo van Kemenade in :gh:`104876`.)
+
typing
------
-* Namespaces ``typing.io`` and ``typing.re``, deprecated in Python 3.8,
- are now removed. The items in those namespaces can be imported directly
- from :mod:`typing`. (Contributed by Sebastian Rittau in :gh:`92871`.)
+* Remove the :mod:`!typing.io` and :mod:`!typing.re` namespaces,
+ deprecated since Python 3.8.
+ The items in those namespaces can be imported directly
+ from the :mod:`typing` module.
+ (Contributed by Sebastian Rittau in :gh:`92871`.)
-* Remove support for the keyword-argument method of creating
- :class:`typing.TypedDict` types, deprecated in Python 3.11.
+* Remove the keyword-argument method of creating
+ :class:`~typing.TypedDict` types, deprecated in Python 3.11.
(Contributed by Tomas Roun in :gh:`104786`.)
+
unittest
--------
@@ -1426,776 +1702,785 @@ unittest
Use :class:`~unittest.TestLoader` methods instead:
- * :meth:`unittest.TestLoader.loadTestsFromModule`
- * :meth:`unittest.TestLoader.loadTestsFromTestCase`
- * :meth:`unittest.TestLoader.getTestCaseNames`
+ * :meth:`~unittest.TestLoader.loadTestsFromModule`
+ * :meth:`~unittest.TestLoader.loadTestsFromTestCase`
+ * :meth:`~unittest.TestLoader.getTestCaseNames`
(Contributed by Hugo van Kemenade in :gh:`104835`.)
-* Remove the untested and undocumented :meth:`!unittest.TestProgram.usageExit`
+* Remove the untested and undocumented :meth:`!TestProgram.usageExit`
method, deprecated in Python 3.11.
(Contributed by Hugo van Kemenade in :gh:`104992`.)
+
urllib
------
-* Remove *cafile*, *capath* and *cadefault* parameters of the
- :func:`urllib.request.urlopen` function, deprecated in Python 3.6: pass
- the *context* parameter instead. Use
- :meth:`ssl.SSLContext.load_cert_chain` to load specific certificates, or
- let :func:`ssl.create_default_context` select the system's trusted CA
- certificates for you.
+* Remove the *cafile*, *capath*, and *cadefault* parameters of the
+ :func:`urllib.request.urlopen` function, deprecated in Python 3.6.
+ Use the *context* parameter instead with an :class:`~ssl.SSLContext` instance.
+ The :meth:`ssl.SSLContext.load_cert_chain` function
+ can be used to load specific certificates,
+ or let :func:`ssl.create_default_context` select
+ the operating system's trusted certificate authority (CA) certificates.
(Contributed by Victor Stinner in :gh:`105382`.)
+
webbrowser
----------
-* Remove the untested and undocumented :mod:`webbrowser` :class:`!MacOSX` class,
+* Remove the untested and undocumented :class:`!MacOSX` class,
deprecated in Python 3.11.
Use the :class:`!MacOSXOSAScript` class (introduced in Python 3.2) instead.
(Contributed by Hugo van Kemenade in :gh:`104804`.)
-* Remove deprecated ``webbrowser.MacOSXOSAScript._name`` attribute.
- Use :attr:`webbrowser.MacOSXOSAScript.name `
+* Remove the deprecated :attr:`!MacOSXOSAScript._name` attribute.
+ Use the :attr:`MacOSXOSAScript.name `
attribute instead.
(Contributed by Nikita Sobolev in :gh:`105546`.)
+
New Deprecations
================
-* Removed chained :class:`classmethod` descriptors (introduced in
- :gh:`63272`). This can no longer be used to wrap other descriptors
- such as :class:`property`. The core design of this feature was flawed
- and caused a number of downstream problems. To "pass-through" a
- :class:`classmethod`, consider using the :attr:`!__wrapped__`
- attribute that was added in Python 3.10. (Contributed by Raymond
- Hettinger in :gh:`89519`.)
-
-* :mod:`array`: :mod:`array`'s ``'u'`` format code, deprecated in docs since Python 3.3,
- emits :exc:`DeprecationWarning` since 3.13
- and will be removed in Python 3.16.
- Use the ``'w'`` format code instead.
- (Contributed by Hugo van Kemenade in :gh:`80480`.)
-
-* :mod:`ctypes`: Deprecate undocumented :func:`!ctypes.SetPointerType`
- and :func:`!ctypes.ARRAY` functions.
- Replace ``ctypes.ARRAY(item_type, size)`` with ``item_type * size``.
- (Contributed by Victor Stinner in :gh:`105733`.)
-
-* :mod:`decimal`: Deprecate non-standard format specifier "N" for
- :class:`decimal.Decimal`.
- It was not documented and only supported in the C implementation.
- (Contributed by Serhiy Storchaka in :gh:`89902`.)
-
-* :mod:`dis`: The ``dis.HAVE_ARGUMENT`` separator is deprecated. Check
- membership in :data:`~dis.hasarg` instead.
- (Contributed by Irit Katriel in :gh:`109319`.)
-
-* :ref:`frame-objects`:
- Calling :meth:`frame.clear` on a suspended frame raises :exc:`RuntimeError`
- (as has always been the case for an executing frame).
- (Contributed by Irit Katriel in :gh:`79932`.)
+* :ref:`User-defined functions `:
-* :mod:`getopt` and :mod:`optparse` modules: They are now
- :term:`soft deprecated`: the :mod:`argparse` module should be used for new projects.
- Previously, the :mod:`optparse` module was already deprecated, its removal
- was not scheduled, and no warnings was emitted: so there is no change in
- practice.
- (Contributed by Victor Stinner in :gh:`106535`.)
-
-* :mod:`gettext`: Emit deprecation warning for non-integer numbers in
- :mod:`gettext` functions and methods that consider plural forms even if the
- translation was not found.
- (Contributed by Serhiy Storchaka in :gh:`88434`.)
-
-* :mod:`glob`: The undocumented :func:`!glob.glob0` and :func:`!glob.glob1`
- functions are deprecated. Use :func:`glob.glob` and pass a directory to its
- *root_dir* argument instead.
- (Contributed by Barney Gale in :gh:`117337`.)
-
-* :mod:`http.server`: :class:`http.server.CGIHTTPRequestHandler` now emits a
- :exc:`DeprecationWarning` as it will be removed in 3.15. Process-based CGI
- HTTP servers have been out of favor for a very long time. This code was
- outdated, unmaintained, and rarely used. It has a high potential for both
- security and functionality bugs. This includes removal of the ``--cgi``
- flag to the ``python -m http.server`` command line in 3.15.
-
-* :mod:`mimetypes`: Passing file path instead of URL in :func:`~mimetypes.guess_type` is
- :term:`soft deprecated`. Use :func:`~mimetypes.guess_file_type` instead.
- (Contributed by Serhiy Storchaka in :gh:`66543`.)
+ * Deprecate assignment to a function's :attr:`~function.__code__` attribute,
+ where the new code object's type does not match the function's type.
+ The different types are:
+ plain function, generator, async generator, and coroutine.
+ (Contributed by Irit Katriel in :gh:`81137`.)
-* :mod:`re`: Passing optional arguments *maxsplit*, *count* and *flags* in module-level
- functions :func:`re.split`, :func:`re.sub` and :func:`re.subn` as positional
- arguments is now deprecated. In future Python versions these parameters will be
- :ref:`keyword-only `.
- (Contributed by Serhiy Storchaka in :gh:`56166`.)
+* :mod:`array`:
-* :mod:`pathlib`:
- :meth:`pathlib.PurePath.is_reserved` is deprecated and scheduled for
- removal in Python 3.15. Use :func:`os.path.isreserved` to detect reserved
- paths on Windows.
+ * Deprecate the ``'u'`` format code (:c:type:`wchar_t`) at runtime.
+ This format code has been deprecated in documentation since Python 3.3,
+ and will be removed in Python 3.16.
+ Use the ``'w'`` format code (:c:type:`Py_UCS4`)
+ for Unicode characters instead.
+ (Contributed by Hugo van Kemenade in :gh:`80480`.)
-* :mod:`platform`:
- :func:`~platform.java_ver` is deprecated and will be removed in 3.15.
- It was largely untested, had a confusing API,
- and was only useful for Jython support.
- (Contributed by Nikita Sobolev in :gh:`116349`.)
+* :mod:`ctypes`:
+
+ * Deprecate the undocumented :func:`!SetPointerType` function,
+ to be removed in Python 3.15.
+ (Contributed by Victor Stinner in :gh:`105733`.)
+
+ * :term:`Soft-deprecate ` the :func:`~ctypes.ARRAY`
+ function in favour of ``type * length`` multiplication.
+ (Contributed by Victor Stinner in :gh:`105733`.)
+
+* :mod:`decimal`:
+
+ * Deprecate the non-standard and undocumented :class:`~decimal.Decimal`
+ format specifier ``'N'``,
+ which is only supported in the :mod:`!decimal` module's C implementation.
+ (Contributed by Serhiy Storchaka in :gh:`89902`.)
+
+* :mod:`dis`:
+
+ * Deprecate the :attr:`!HAVE_ARGUMENT` separator.
+ Check membership in :data:`~dis.hasarg` instead.
+ (Contributed by Irit Katriel in :gh:`109319`.)
-* :mod:`pydoc`: Deprecate undocumented :func:`!pydoc.ispackage` function.
- (Contributed by Zackery Spytz in :gh:`64020`.)
+* :mod:`getopt` and :mod:`optparse`:
-* :mod:`sqlite3`: Passing more than one positional argument to
- :func:`sqlite3.connect` and the :class:`sqlite3.Connection` constructor is
- deprecated. The remaining parameters will become keyword-only in Python 3.15.
+ * Both modules are now :term:`soft deprecated`,
+ with :mod:`argparse` preferred for new projects.
+ This is a new soft-deprecation for the :mod:`!getopt` module,
+ whereas the :mod:`!optparse` module was already *de facto* soft deprecated.
+ (Contributed by Victor Stinner in :gh:`106535`.)
- Deprecate passing name, number of arguments, and the callable as keyword
- arguments for the following :class:`sqlite3.Connection` APIs:
+* :mod:`gettext`:
- * :meth:`~sqlite3.Connection.create_function`
- * :meth:`~sqlite3.Connection.create_aggregate`
+ * Deprecate non-integer numbers as arguments to functions and methods
+ that consider plural forms in the :mod:`!gettext` module,
+ even if no translation was found.
+ (Contributed by Serhiy Storchaka in :gh:`88434`.)
+
+* :mod:`glob`:
+
+ * Deprecate the undocumented :func:`!glob0` and :func:`!glob1` functions.
+ Use :func:`~glob.glob` and pass a :term:`path-like object` specifying
+ the root directory to the *root_dir* parameter instead.
+ (Contributed by Barney Gale in :gh:`117337`.)
+
+* :mod:`http.server`:
+
+ * Deprecate :class:`~http.server.CGIHTTPRequestHandler`,
+ to be removed in Python 3.15.
+ Process-based CGI HTTP servers have been out of favor for a very long time.
+ This code was outdated, unmaintained, and rarely used.
+ It has a high potential for both security and functionality bugs.
+ (Contributed by Gregory P. Smith in :gh:`109096`.)
+
+ * Deprecate the :option:`!--cgi` flag to
+ the :program:`python -m http.server` command-line interface,
+ to be removed in Python 3.15.
+ (Contributed by Gregory P. Smith in :gh:`109096`.)
+
+* :mod:`mimetypes`:
+
+ * :term:`Soft-deprecate ` file path arguments
+ to :func:`~mimetypes.guess_type`,
+ use :func:`~mimetypes.guess_file_type` instead.
+ (Contributed by Serhiy Storchaka in :gh:`66543`.)
+
+* :mod:`re`:
+
+ * Deprecate passing the optional *maxsplit*, *count*, or *flags* arguments
+ as positional arguments to the module-level
+ :func:`~re.split`, :func:`~re.sub`, and :func:`~re.subn` functions.
+ These parameters will become :ref:`keyword-only `
+ in a future version of Python.
+ (Contributed by Serhiy Storchaka in :gh:`56166`.)
+
+* :mod:`pathlib`:
+
+ * Deprecate :meth:`.PurePath.is_reserved`,
+ to be removed in Python 3.15.
+ Use :func:`os.path.isreserved` to detect reserved paths on Windows.
+ (Contributed by Barney Gale in :gh:`88569`.)
+
+* :mod:`platform`:
- Deprecate passing the callback callable by keyword for the following
- :class:`sqlite3.Connection` APIs:
+ * Deprecate :func:`~platform.java_ver`,
+ to be removed in Python 3.15.
+ This function is only useful for Jython support, has a confusing API,
+ and is largely untested.
+ (Contributed by Nikita Sobolev in :gh:`116349`.)
- * :meth:`~sqlite3.Connection.set_authorizer`
- * :meth:`~sqlite3.Connection.set_progress_handler`
- * :meth:`~sqlite3.Connection.set_trace_callback`
+* :mod:`pydoc`:
- The affected parameters will become positional-only in Python 3.15.
+ * Deprecate the undocumented :func:`!ispackage` function.
+ (Contributed by Zackery Spytz in :gh:`64020`.)
- (Contributed by Erlend E. Aasland in :gh:`107948` and :gh:`108278`.)
+* :mod:`sqlite3`:
-* :mod:`sys`: :func:`sys._enablelegacywindowsfsencoding` function.
- Replace it with the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment variable.
- (Contributed by Inada Naoki in :gh:`73427`.)
+ * Deprecate passing more than one positional argument to
+ the :func:`~sqlite3.connect` function
+ and the :class:`~sqlite3.Connection` constructor.
+ The remaining parameters will become keyword-only in Python 3.15.
+ (Contributed by Erlend E. Aasland in :gh:`107948`.)
+
+ * Deprecate passing name, number of arguments, and the callable as keyword
+ arguments for :meth:`.Connection.create_function`
+ and :meth:`.Connection.create_aggregate`
+ These parameters will become positional-only in Python 3.15.
+ (Contributed by Erlend E. Aasland in :gh:`108278`.)
+
+ * Deprecate passing the callback callable by keyword for the
+ :meth:`~sqlite3.Connection.set_authorizer`,
+ :meth:`~sqlite3.Connection.set_progress_handler`, and
+ :meth:`~sqlite3.Connection.set_trace_callback`
+ :class:`~sqlite3.Connection` methods.
+ The callback callables will become positional-only in Python 3.15.
+ (Contributed by Erlend E. Aasland in :gh:`108278`.)
+
+* :mod:`sys`:
+
+ * Deprecate the :func:`~sys._enablelegacywindowsfsencoding` function,
+ to be removed in Python 3.16.
+ Use the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment variable instead.
+ (Contributed by Inada Naoki in :gh:`73427`.)
* :mod:`tarfile`:
- The undocumented and unused ``tarfile`` attribute of :class:`tarfile.TarFile`
- is deprecated and scheduled for removal in Python 3.16.
-* :mod:`traceback`: The field *exc_type* of :class:`traceback.TracebackException`
- is deprecated. Use *exc_type_str* instead.
+ * Deprecate the undocumented and unused :attr:`!TarFile.tarfile` attribute,
+ to be removed in Python 3.16.
+ (Contributed in :gh:`115256`.)
+
+* :mod:`traceback`:
+
+ * Deprecate the :attr:`.TracebackException.exc_type` attribute.
+ Use :attr:`.TracebackException.exc_type_str` instead.
+ (Contributed by Irit Katriel in :gh:`112332`.)
* :mod:`typing`:
- * Creating a :class:`typing.NamedTuple` class using keyword arguments to denote
- the fields (``NT = NamedTuple("NT", x=int, y=int)``) is deprecated, and will
- be disallowed in Python 3.15. Use the class-based syntax or the functional
- syntax instead. (Contributed by Alex Waygood in :gh:`105566`.)
-
- * When using the functional syntax to create a :class:`typing.NamedTuple`
- class or a :class:`typing.TypedDict` class, failing to pass a value to the
- 'fields' parameter (``NT = NamedTuple("NT")`` or ``TD = TypedDict("TD")``) is
- deprecated. Passing ``None`` to the 'fields' parameter
- (``NT = NamedTuple("NT", None)`` or ``TD = TypedDict("TD", None)``) is also
- deprecated. Both will be disallowed in Python 3.15. To create a NamedTuple
- class with 0 fields, use ``class NT(NamedTuple): pass`` or
- ``NT = NamedTuple("NT", [])``. To create a TypedDict class with 0 fields, use
- ``class TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})``.
+ * Deprecate the undocumented keyword argument syntax for creating
+ :class:`~typing.NamedTuple` classes
+ (e.g. ``Point = NamedTuple("Point", x=int, y=int)``),
+ to be removed in Python 3.15.
+ Use the class-based syntax or the functional syntax instead.
+ (Contributed by Alex Waygood in :gh:`105566`.)
+
+ * Deprecate omitting the *fields* parameter when creating
+ a :class:`~typing.NamedTuple` or :class:`typing.TypedDict` class,
+ and deprecate passing ``None`` to the *fields* parameter of both types.
+ Python 3.15 will require a valid sequence for the *fields* parameter.
+ To create a NamedTuple class with zero fields,
+ use ``class NT(NamedTuple): pass`` or ``NT = NamedTuple("NT", ())``.
+ To create a TypedDict class with zero fields,
+ use ``class TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})``.
(Contributed by Alex Waygood in :gh:`105566` and :gh:`105570`.)
- * :func:`typing.no_type_check_decorator` is deprecated, and scheduled for
- removal in Python 3.15. After eight years in the :mod:`typing` module, it
- has yet to be supported by any major type checkers.
+ * Deprecate the :func:`typing.no_type_check_decorator` decorator function,
+ to be removed in in Python 3.15.
+ After eight years in the :mod:`typing` module,
+ it has yet to be supported by any major type checker.
(Contributed by Alex Waygood in :gh:`106309`.)
- * :data:`typing.AnyStr` is deprecated. In Python 3.16, it will be removed from
- ``typing.__all__``, and a :exc:`DeprecationWarning` will be emitted when it
- is imported or accessed. It will be removed entirely in Python 3.18. Use
- the new :ref:`type parameter syntax ` instead.
+ * Deprecate :data:`typing.AnyStr`.
+ In Python 3.16, it will be removed from ``typing.__all__``,
+ and a :exc:`DeprecationWarning` will be emitted at runtime
+ when it is imported or accessed.
+ It will be removed entirely in Python 3.18.
+ Use the new :ref:`type parameter syntax ` instead.
(Contributed by Michael The in :gh:`107116`.)
-* :ref:`user-defined-funcs`:
- Assignment to a function's :attr:`~function.__code__` attribute where the new code
- object's type does not match the function's type, is deprecated. The
- different types are: plain function, generator, async generator and
- coroutine.
- (Contributed by Irit Katriel in :gh:`81137`.)
+* :mod:`wave`:
-* :mod:`wave`: Deprecate the ``getmark()``, ``setmark()`` and ``getmarkers()``
- methods of the :class:`wave.Wave_read` and :class:`wave.Wave_write` classes.
- They will be removed in Python 3.15.
- (Contributed by Victor Stinner in :gh:`105096`.)
+ * Deprecate the :meth:`~wave.Wave_read.getmark`, :meth:`!setmark`,
+ and :meth:`~wave.Wave_read.getmarkers` methods of
+ the :class:`~wave.Wave_read` and :class:`~wave.Wave_write` classes,
+ to be removed in Python 3.15.
+ (Contributed by Victor Stinner in :gh:`105096`.)
.. Add deprecations above alphabetically, not here at the end.
-Pending Removal in Python 3.14
-------------------------------
+.. include:: ../deprecations/pending-removal-in-3.14.rst
-* :mod:`argparse`: The *type*, *choices*, and *metavar* parameters
- of :class:`!argparse.BooleanOptionalAction` are deprecated
- and will be removed in 3.14.
- (Contributed by Nikita Sobolev in :gh:`92248`.)
+.. include:: ../deprecations/pending-removal-in-3.15.rst
-* :mod:`ast`: The following features have been deprecated in documentation
- since Python 3.8, now cause a :exc:`DeprecationWarning` to be emitted at
- runtime when they are accessed or used, and will be removed in Python 3.14:
+.. include:: ../deprecations/pending-removal-in-3.16.rst
- * :class:`!ast.Num`
- * :class:`!ast.Str`
- * :class:`!ast.Bytes`
- * :class:`!ast.NameConstant`
- * :class:`!ast.Ellipsis`
+.. include:: ../deprecations/pending-removal-in-future.rst
- Use :class:`ast.Constant` instead.
- (Contributed by Serhiy Storchaka in :gh:`90953`.)
+CPython Bytecode Changes
+========================
-* :mod:`collections.abc`: Deprecated :class:`~collections.abc.ByteString`.
- Prefer :class:`!Sequence` or :class:`~collections.abc.Buffer`.
- For use in typing, prefer a union, like ``bytes | bytearray``,
- or :class:`collections.abc.Buffer`.
- (Contributed by Shantanu Jain in :gh:`91896`.)
+* The oparg of :opcode:`YIELD_VALUE` is now
+ ``1`` if the yield is part of a yield-from or await, and ``0`` otherwise.
+ The oparg of :opcode:`RESUME` was changed to add a bit indicating
+ if the except-depth is 1, which is needed to optimize closing of generators.
+ (Contributed by Irit Katriel in :gh:`111354`.)
-* :mod:`email`: Deprecated the *isdst* parameter in :func:`email.utils.localtime`.
- (Contributed by Alan Williams in :gh:`72346`.)
-* :mod:`importlib`: ``__package__`` and ``__cached__`` will cease to be set or
- taken into consideration by the import system (:gh:`97879`).
+C API Changes
+=============
-* :mod:`importlib.abc` deprecated classes:
+New Features
+------------
- * :class:`!importlib.abc.ResourceReader`
- * :class:`!importlib.abc.Traversable`
- * :class:`!importlib.abc.TraversableResources`
+* Add the :ref:`PyMonitoring C API `
+ for generating :pep:`669` monitoring events:
+
+ * :c:type:`PyMonitoringState`
+ * :c:func:`PyMonitoring_FirePyStartEvent`
+ * :c:func:`PyMonitoring_FirePyResumeEvent`
+ * :c:func:`PyMonitoring_FirePyReturnEvent`
+ * :c:func:`PyMonitoring_FirePyYieldEvent`
+ * :c:func:`PyMonitoring_FireCallEvent`
+ * :c:func:`PyMonitoring_FireLineEvent`
+ * :c:func:`PyMonitoring_FireJumpEvent`
+ * :c:func:`PyMonitoring_FireBranchEvent`
+ * :c:func:`PyMonitoring_FireCReturnEvent`
+ * :c:func:`PyMonitoring_FirePyThrowEvent`
+ * :c:func:`PyMonitoring_FireRaiseEvent`
+ * :c:func:`PyMonitoring_FireCRaiseEvent`
+ * :c:func:`PyMonitoring_FireReraiseEvent`
+ * :c:func:`PyMonitoring_FireExceptionHandledEvent`
+ * :c:func:`PyMonitoring_FirePyUnwindEvent`
+ * :c:func:`PyMonitoring_FireStopIterationEvent`
+ * :c:func:`PyMonitoring_EnterScope`
+ * :c:func:`PyMonitoring_ExitScope`
+
+ (Contributed by Irit Katriel in :gh:`111997`).
+
+* Add :c:type:`PyMutex`, a lightweight mutex that occupies a single byte,
+ and the new :c:func:`PyMutex_Lock` and :c:func:`PyMutex_Unlock` functions.
+ :c:func:`!PyMutex_Lock` will release the :term:`GIL` (if currently held)
+ if the operation needs to block.
+ (Contributed by Sam Gross in :gh:`108724`.)
- Use :mod:`importlib.resources.abc` classes instead:
+* Add the :ref:`PyTime C API ` to provide access to system clocks:
- * :class:`importlib.resources.abc.Traversable`
- * :class:`importlib.resources.abc.TraversableResources`
+ * :c:type:`PyTime_t`.
+ * :c:var:`PyTime_MIN` and :c:var:`PyTime_MAX`.
+ * :c:func:`PyTime_AsSecondsDouble`.
+ * :c:func:`PyTime_Monotonic`.
+ * :c:func:`PyTime_MonotonicRaw`.
+ * :c:func:`PyTime_PerfCounter`.
+ * :c:func:`PyTime_PerfCounterRaw`.
+ * :c:func:`PyTime_Time`.
+ * :c:func:`PyTime_TimeRaw`.
- (Contributed by Jason R. Coombs and Hugo van Kemenade in :gh:`93963`.)
+ (Contributed by Victor Stinner and Petr Viktorin in :gh:`110850`.)
-* :mod:`itertools` had undocumented, inefficient, historically buggy,
- and inconsistent support for copy, deepcopy, and pickle operations.
- This will be removed in 3.14 for a significant reduction in code
- volume and maintenance burden.
- (Contributed by Raymond Hettinger in :gh:`101588`.)
+* Add the :c:func:`PyDict_ContainsString` function
+ with the same behavior as :c:func:`PyDict_Contains`,
+ but *key* is specified as a :c:expr:`const char*` UTF-8 encoded bytes string,
+ rather than a :c:expr:`PyObject*`.
+ (Contributed by Victor Stinner in :gh:`108314`.)
-* :mod:`multiprocessing`: The default start method will change to a safer one on
- Linux, BSDs, and other non-macOS POSIX platforms where ``'fork'`` is currently
- the default (:gh:`84559`). Adding a runtime warning about this was deemed too
- disruptive as the majority of code is not expected to care. Use the
- :func:`~multiprocessing.get_context` or
- :func:`~multiprocessing.set_start_method` APIs to explicitly specify when
- your code *requires* ``'fork'``. See :ref:`multiprocessing-start-methods`.
+* Add the :c:func:`PyDict_GetItemRef` and :c:func:`PyDict_GetItemStringRef`
+ functions,
+ which behave similarly to :c:func:`PyDict_GetItemWithError`,
+ but return a :term:`strong reference` instead of a :term:`borrowed reference`.
+ Moreover, these functions return ``-1`` on error,
+ removing the need to check :c:func:`!PyErr_Occurred`.
+ (Contributed by Victor Stinner in :gh:`106004`.)
-* :mod:`pathlib`: :meth:`~pathlib.PurePath.is_relative_to` and
- :meth:`~pathlib.PurePath.relative_to`: passing additional arguments is
- deprecated.
+* Add the :c:func:`PyDict_SetDefaultRef` function,
+ which behaves similarly to :c:func:`PyDict_SetDefault`,
+ but returns a :term:`strong reference` instead of a :term:`borrowed reference`.
+ This function returns ``-1`` on error,
+ ``0`` on insertion,
+ and ``1`` if the key was already present in the dictionary.
+ (Contributed by Sam Gross in :gh:`112066`.)
-* :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`.)
+* Add the :c:func:`PyDict_Pop` and :c:func:`PyDict_PopString` functions
+ to remove a key from a dictionary and optionally return the removed value.
+ This is similar to :meth:`dict.pop`,
+ though there is no default value,
+ and :exc:`KeyError` is not raised for missing keys.
+ (Contributed by Stefan Behnel and Victor Stinner in :gh:`111262`.)
-* :mod:`pty`:
+* Add the :c:func:`PyMapping_GetOptionalItem`
+ and :c:func:`PyMapping_GetOptionalItemString` functions
+ as alternatives to :c:func:`PyObject_GetItem`
+ and :c:func:`PyMapping_GetItemString` respectively.
+ The new functions do not raise :exc:`KeyError`
+ if the requested key is missing from the mapping.
+ These variants are more convenient and faster
+ if a missing key should not be treated as a failure.
+ (Contributed by Serhiy Storchaka in :gh:`106307`.)
- * ``master_open()``: use :func:`pty.openpty`.
- * ``slave_open()``: use :func:`pty.openpty`.
+* Add the :c:func:`PyObject_GetOptionalAttr`
+ and :c:func:`PyObject_GetOptionalAttrString` functions
+ as alternatives to :c:func:`PyObject_GetAttr`
+ and :c:func:`PyObject_GetAttrString` respectively.
+ The new functions do not raise :exc:`AttributeError`
+ if the requested attribute is not found on the object.
+ These variants are more convenient and faster
+ if the missing attribute should not be treated as a failure.
+ (Contributed by Serhiy Storchaka in :gh:`106521`.)
-* :mod:`sqlite3`:
+* Add the :c:func:`PyErr_FormatUnraisable` function
+ as an extension to :c:func:`PyErr_WriteUnraisable`
+ that allows customizing the warning message.
+ (Contributed by Serhiy Storchaka in :gh:`108082`.)
- * :data:`~sqlite3.version` and :data:`~sqlite3.version_info`.
+* Add new functions that return a :term:`strong reference` instead of
+ a :term:`borrowed reference` for frame locals, globals, and builtins,
+ as part of :ref:`PEP 667 `:
- * :meth:`~sqlite3.Cursor.execute` and :meth:`~sqlite3.Cursor.executemany`
- if :ref:`named placeholders ` are used and
- *parameters* is a sequence instead of a :class:`dict`.
+ * :c:func:`PyEval_GetFrameBuiltins` replaces :c:func:`PyEval_GetBuiltins`
+ * :c:func:`PyEval_GetFrameGlobals` replaces :c:func:`PyEval_GetGlobals`
+ * :c:func:`PyEval_GetFrameLocals` replaces :c:func:`PyEval_GetLocals`
- * date and datetime adapter, date and timestamp converter:
- see the :mod:`sqlite3` documentation for suggested replacement recipes.
+ (Contributed by Mark Shannon and Tian Gao in :gh:`74929`.)
-* :class:`types.CodeType`: Accessing :attr:`~codeobject.co_lnotab` was
- deprecated in :pep:`626`
- since 3.10 and was planned to be removed in 3.12,
- but it only got a proper :exc:`DeprecationWarning` in 3.12.
- May be removed in 3.14.
- (Contributed by Nikita Sobolev in :gh:`101866`.)
+* Add the :c:func:`Py_GetConstant` and :c:func:`Py_GetConstantBorrowed`
+ functions to get :term:`strong `
+ or :term:`borrowed ` references to constants.
+ For example, ``Py_GetConstant(Py_CONSTANT_ZERO)`` returns a strong reference
+ to the constant zero.
+ (Contributed by Victor Stinner in :gh:`115754`.)
-* :mod:`typing`: :class:`~typing.ByteString`, deprecated since Python 3.9,
- now causes a :exc:`DeprecationWarning` to be emitted when it is used.
+* Add the :c:func:`PyImport_AddModuleRef` function
+ as a replacement for :c:func:`PyImport_AddModule`
+ that returns a :term:`strong reference` instead of a :term:`borrowed reference`.
+ (Contributed by Victor Stinner in :gh:`105922`.)
-* :mod:`urllib`:
- :class:`!urllib.parse.Quoter` is deprecated: it was not intended to be a
- public API.
- (Contributed by Gregory P. Smith in :gh:`88168`.)
+* Add the :c:func:`Py_IsFinalizing` function to check
+ whether the main Python interpreter is
+ :term:`shutting down `.
+ (Contributed by Victor Stinner in :gh:`108014`.)
-Pending Removal in Python 3.15
-------------------------------
+* Add the :c:func:`PyList_GetItemRef` function
+ as a replacement for :c:func:`PyList_GetItem`
+ that returns a :term:`strong reference` instead of a :term:`borrowed reference`.
+ (Contributed by Sam Gross in :gh:`114329`.)
-* :class:`http.server.CGIHTTPRequestHandler` will be removed along with its
- related ``--cgi`` flag to ``python -m http.server``. It was obsolete and
- rarely used. No direct replacement exists. *Anything* is better than CGI
- to interface a web server with a request handler.
+* Add the :c:func:`PyList_Extend` and :c:func:`PyList_Clear` functions,
+ mirroring the Python :meth:`!list.extend` and :meth:`!list.clear` methods.
+ (Contributed by Victor Stinner in :gh:`111138`.)
-* :class:`locale`: :func:`locale.getdefaultlocale` was deprecated in Python 3.11
- and originally planned for removal in Python 3.13 (:gh:`90817`),
- but removal has been postponed to Python 3.15.
- Use :func:`locale.setlocale()`, :func:`locale.getencoding()` and
- :func:`locale.getlocale()` instead.
- (Contributed by Hugo van Kemenade in :gh:`111187`.)
+* Add the :c:func:`PyLong_AsInt` function.
+ It behaves similarly to :c:func:`PyLong_AsLong`,
+ but stores the result in a C :c:expr:`int` instead of a C :c:expr:`long`.
+ (Contributed by Victor Stinner in :gh:`108014`.)
-* :mod:`pathlib`:
- :meth:`pathlib.PurePath.is_reserved` is deprecated and scheduled for
- removal in Python 3.15. Use :func:`os.path.isreserved` to detect reserved
- paths on Windows.
+* Add the :c:func:`PyLong_AsNativeBytes`, :c:func:`PyLong_FromNativeBytes`,
+ and :c:func:`PyLong_FromUnsignedNativeBytes` functions
+ to simplify converting between native integer types
+ and Python :class:`int` objects.
+ (Contributed by Steve Dower in :gh:`111140`.)
-* :mod:`platform`:
- :func:`~platform.java_ver` is deprecated and will be removed in 3.15.
- It was largely untested, had a confusing API,
- and was only useful for Jython support.
- (Contributed by Nikita Sobolev in :gh:`116349`.)
-
-* :mod:`threading`:
- Passing any arguments to :func:`threading.RLock` is now deprecated.
- C version allows any numbers of args and kwargs,
- but they are just ignored. Python version does not allow any arguments.
- All arguments will be removed from :func:`threading.RLock` in Python 3.15.
- (Contributed by Nikita Sobolev in :gh:`102029`.)
-
-* :class:`typing.NamedTuple`:
-
- * The undocumented keyword argument syntax for creating :class:`!NamedTuple` classes
- (``NT = NamedTuple("NT", x=int)``) is deprecated, and will be disallowed in
- 3.15. Use the class-based syntax or the functional syntax instead.
-
- * When using the functional syntax to create a :class:`!NamedTuple` class, failing to
- pass a value to the *fields* parameter (``NT = NamedTuple("NT")``) is
- deprecated. Passing ``None`` to the *fields* parameter
- (``NT = NamedTuple("NT", None)``) is also deprecated. Both will be
- disallowed in Python 3.15. To create a :class:`!NamedTuple` class with 0 fields, use
- ``class NT(NamedTuple): pass`` or ``NT = NamedTuple("NT", [])``.
-
-* :class:`typing.TypedDict`: When using the functional syntax to create a
- :class:`!TypedDict` class, failing to pass a value to the *fields* parameter (``TD =
- TypedDict("TD")``) is deprecated. Passing ``None`` to the *fields* parameter
- (``TD = TypedDict("TD", None)``) is also deprecated. Both will be disallowed
- in Python 3.15. To create a :class:`!TypedDict` class with 0 fields, use ``class
- TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})``.
-
-* :mod:`wave`: Deprecate the ``getmark()``, ``setmark()`` and ``getmarkers()``
- methods of the :class:`wave.Wave_read` and :class:`wave.Wave_write` classes.
- They will be removed in Python 3.15.
- (Contributed by Victor Stinner in :gh:`105096`.)
-
-Pending Removal in Python 3.16
-------------------------------
-
-* :class:`array.array` ``'u'`` type (:c:type:`wchar_t`):
- use the ``'w'`` type instead (``Py_UCS4``).
-
-Pending Removal in Future Versions
-----------------------------------
-
-The following APIs were deprecated in earlier Python versions and will be removed,
-although there is currently no date scheduled for their removal.
-
-* :mod:`argparse`: Nesting argument groups and nesting mutually exclusive
- groups are deprecated.
-
-* :mod:`builtins`:
-
- * ``~bool``, bitwise inversion on bool.
- * ``bool(NotImplemented)``.
- * Generators: ``throw(type, exc, tb)`` and ``athrow(type, exc, tb)``
- signature is deprecated: use ``throw(exc)`` and ``athrow(exc)`` instead,
- the single argument signature.
- * Currently Python accepts numeric literals immediately followed by keywords,
- for example ``0in x``, ``1or x``, ``0if 1else 2``. It allows confusing and
- ambiguous expressions like ``[0x1for x in y]`` (which can be interpreted as
- ``[0x1 for x in y]`` or ``[0x1f or x in y]``). A syntax warning is raised
- if the numeric literal is immediately followed by one of keywords
- :keyword:`and`, :keyword:`else`, :keyword:`for`, :keyword:`if`,
- :keyword:`in`, :keyword:`is` and :keyword:`or`. In a future release it
- will be changed to a syntax error. (:gh:`87999`)
- * Support for ``__index__()`` and ``__int__()`` method returning non-int type:
- these methods will be required to return an instance of a strict subclass of
- :class:`int`.
- * Support for ``__float__()`` method returning a strict subclass of
- :class:`float`: these methods will be required to return an instance of
- :class:`float`.
- * Support for ``__complex__()`` method returning a strict subclass of
- :class:`complex`: these methods will be required to return an instance of
- :class:`complex`.
- * Delegation of ``int()`` to ``__trunc__()`` method.
-
-* :mod:`calendar`: ``calendar.January`` and ``calendar.February`` constants are
- deprecated and replaced by :data:`calendar.JANUARY` and
- :data:`calendar.FEBRUARY`.
- (Contributed by Prince Roshan in :gh:`103636`.)
-
-* :attr:`codeobject.co_lnotab`: use the :meth:`codeobject.co_lines` method
- instead.
-
-* :mod:`datetime`:
-
- * :meth:`~datetime.datetime.utcnow`:
- use ``datetime.datetime.now(tz=datetime.UTC)``.
- * :meth:`~datetime.datetime.utcfromtimestamp`:
- use ``datetime.datetime.fromtimestamp(timestamp, tz=datetime.UTC)``.
-
-* :mod:`gettext`: Plural value must be an integer.
-
-* :mod:`importlib`:
-
- * ``load_module()`` method: use ``exec_module()`` instead.
- * :func:`~importlib.util.cache_from_source` *debug_override* parameter is
- deprecated: use the *optimization* parameter instead.
-
-* :mod:`importlib.metadata`:
-
- * ``EntryPoints`` tuple interface.
- * Implicit ``None`` on return values.
-
-* :mod:`mailbox`: Use of StringIO input and text mode is deprecated, use
- BytesIO and binary mode instead.
-
-* :mod:`os`: Calling :func:`os.register_at_fork` in multi-threaded process.
-
-* :class:`!pydoc.ErrorDuringImport`: A tuple value for *exc_info* parameter is
- deprecated, use an exception instance.
-
-* :mod:`re`: More strict rules are now applied for numerical group references
- and group names in regular expressions. Only sequence of ASCII digits is now
- accepted as a numerical reference. The group name in bytes patterns and
- replacement strings can now only contain ASCII letters and digits and
- underscore.
- (Contributed by Serhiy Storchaka in :gh:`91760`.)
-
-* :mod:`!sre_compile`, :mod:`!sre_constants` and :mod:`!sre_parse` modules.
-
-* :mod:`shutil`: :func:`~shutil.rmtree`'s *onerror* parameter is deprecated in
- Python 3.12; use the *onexc* parameter instead.
-
-* :mod:`ssl` options and protocols:
-
- * :class:`ssl.SSLContext` without protocol argument is deprecated.
- * :class:`ssl.SSLContext`: :meth:`~ssl.SSLContext.set_npn_protocols` and
- :meth:`!selected_npn_protocol` are deprecated: use ALPN
- instead.
- * ``ssl.OP_NO_SSL*`` options
- * ``ssl.OP_NO_TLS*`` options
- * ``ssl.PROTOCOL_SSLv3``
- * ``ssl.PROTOCOL_TLS``
- * ``ssl.PROTOCOL_TLSv1``
- * ``ssl.PROTOCOL_TLSv1_1``
- * ``ssl.PROTOCOL_TLSv1_2``
- * ``ssl.TLSVersion.SSLv3``
- * ``ssl.TLSVersion.TLSv1``
- * ``ssl.TLSVersion.TLSv1_1``
-
-* :func:`sysconfig.is_python_build` *check_home* parameter is deprecated and
- ignored.
-
-* :mod:`threading` methods:
-
- * :meth:`!threading.Condition.notifyAll`: use :meth:`~threading.Condition.notify_all`.
- * :meth:`!threading.Event.isSet`: use :meth:`~threading.Event.is_set`.
- * :meth:`!threading.Thread.isDaemon`, :meth:`threading.Thread.setDaemon`:
- use :attr:`threading.Thread.daemon` attribute.
- * :meth:`!threading.Thread.getName`, :meth:`threading.Thread.setName`:
- use :attr:`threading.Thread.name` attribute.
- * :meth:`!threading.currentThread`: use :meth:`threading.current_thread`.
- * :meth:`!threading.activeCount`: use :meth:`threading.active_count`.
-
-* :class:`typing.Text` (:gh:`92332`).
-
-* :class:`unittest.IsolatedAsyncioTestCase`: it is deprecated to return a value
- that is not ``None`` from a test case.
-
-* :mod:`urllib.parse` deprecated functions: :func:`~urllib.parse.urlparse` instead
-
- * ``splitattr()``
- * ``splithost()``
- * ``splitnport()``
- * ``splitpasswd()``
- * ``splitport()``
- * ``splitquery()``
- * ``splittag()``
- * ``splittype()``
- * ``splituser()``
- * ``splitvalue()``
- * ``to_bytes()``
+* Add :c:func:`PyModule_Add` function, which is similar to
+ :c:func:`PyModule_AddObjectRef` and :c:func:`PyModule_AddObject`,
+ but always steals a reference to the value.
+ (Contributed by Serhiy Storchaka in :gh:`86493`.)
-* :mod:`urllib.request`: :class:`~urllib.request.URLopener` and
- :class:`~urllib.request.FancyURLopener` style of invoking requests is
- deprecated. Use newer :func:`~urllib.request.urlopen` functions and methods.
+* Add the :c:func:`PyObject_GenericHash` function
+ that implements the default hashing function of a Python object.
+ (Contributed by Serhiy Storchaka in :gh:`113024`.)
-* :mod:`wsgiref`: ``SimpleHandler.stdout.write()`` should not do partial
- writes.
+* Add the :c:func:`Py_HashPointer` function to hash a raw pointer.
+ (Contributed by Victor Stinner in :gh:`111545`.)
-* :mod:`xml.etree.ElementTree`: Testing the truth value of an
- :class:`~xml.etree.ElementTree.Element` is deprecated. In a future release it
- it will always return ``True``. Prefer explicit ``len(elem)`` or
- ``elem is not None`` tests instead.
+* Add the :c:func:`PyObject_VisitManagedDict` and
+ :c:func:`PyObject_ClearManagedDict` functions.
+ which must be called by the traverse and clear functions of a type using
+ the :c:macro:`Py_TPFLAGS_MANAGED_DICT` flag.
+ The `pythoncapi-compat project`_ can be used to
+ use these functions with Python 3.11 and 3.12.
+ (Contributed by Victor Stinner in :gh:`107073`.)
-* :meth:`zipimport.zipimporter.load_module` is deprecated:
- use :meth:`~zipimport.zipimporter.exec_module` instead.
+* Add the :c:func:`PyRefTracer_SetTracer`
+ and :c:func:`PyRefTracer_GetTracer` functions,
+ which enable tracking object creation and destruction
+ in the same way that the :mod:`tracemalloc` module does.
+ (Contributed by Pablo Galindo in :gh:`93502`.)
+* Add the :c:func:`PySys_AuditTuple` function
+ as an alternative to :c:func:`PySys_Audit`
+ that takes event arguments as a Python :class:`tuple` object.
+ (Contributed by Victor Stinner in :gh:`85283`.)
-CPython Bytecode Changes
-========================
+* Add the :c:func:`PyThreadState_GetUnchecked()` function
+ as an alternative to :c:func:`PyThreadState_Get()`
+ that doesn't kill the process with a fatal error if it is ``NULL``.
+ The caller is responsible for checking if the result is ``NULL``.
+ (Contributed by Victor Stinner in :gh:`108867`.)
-* The oparg of ``YIELD_VALUE`` is now ``1`` if the yield is part of a
- yield-from or await, and ``0`` otherwise. The oparg of ``RESUME`` was
- changed to add a bit indicating whether the except-depth is 1, which
- is needed to optimize closing of generators.
- (Contributed by Irit Katriel in :gh:`111354`.)
+* Add the :c:func:`PyType_GetFullyQualifiedName` function
+ to get the type's fully qualified name.
+ The module name is prepended if :attr:`type.__module__` is
+ a string and is not equal to either ``'builtins'`` or ``'__main__'``.
+ (Contributed by Victor Stinner in :gh:`111696`.)
+* Add the :c:func:`PyType_GetModuleName` function
+ to get the type's module name. This is equivalent to getting the
+ :attr:`type.__module__` attribute.
+ (Contributed by Eric Snow and Victor Stinner in :gh:`111696`.)
-C API Changes
-=============
+* Add the :c:func:`PyUnicode_EqualToUTF8AndSize`
+ and :c:func:`PyUnicode_EqualToUTF8` functions
+ to compare a Unicode object with a :c:expr:`const char*` UTF-8 encoded string
+ and ``1`` if they are equal or ``0`` otherwise.
+ These functions do not raise exceptions.
+ (Contributed by Serhiy Storchaka in :gh:`110289`.)
-New Features
-------------
+* Add the :c:func:`PyWeakref_GetRef` function
+ as an alternative to :c:func:`PyWeakref_GetObject`
+ that returns a :term:`strong reference`
+ or ``NULL`` if the referent is no longer live.
+ (Contributed by Victor Stinner in :gh:`105927`.)
+
+* Add fixed variants of functions which silently ignore errors:
+
+ * :c:func:`PyObject_HasAttrWithError` replaces :c:func:`PyObject_HasAttr`.
+ * :c:func:`PyObject_HasAttrStringWithError`
+ replaces :c:func:`PyObject_HasAttrString`.
+ * :c:func:`PyMapping_HasKeyWithError` replaces :c:func:`PyMapping_HasKey`.
+ * :c:func:`PyMapping_HasKeyStringWithError`
+ replaces :c:func:`PyMapping_HasKeyString`.
+
+ The new functions return ``-1`` for errors
+ and the standard ``1`` for true and ``0`` for false.
+
+ (Contributed by Serhiy Storchaka in :gh:`108511`.)
+
+
+Changed C APIs
+--------------
-* You no longer have to define the ``PY_SSIZE_T_CLEAN`` macro before including
- :file:`Python.h` when using ``#`` formats in
+* The *keywords* parameter of :c:func:`PyArg_ParseTupleAndKeywords`
+ and :c:func:`PyArg_VaParseTupleAndKeywords`
+ now has type :c:expr:`char * const *` in C
+ and :c:expr:`const char * const *` in C++,
+ instead of :c:expr:`char **`.
+ In C++, this makes these functions compatible with arguments
+ of type :c:expr:`const char * const *`, :c:expr:`const char **`,
+ or :c:expr:`char * const *` without an explicit type cast.
+ In C, the functions only support arguments of type :c:expr:`char * const *`.
+ This can be overridden with the :c:macro:`PY_CXX_CONST` macro.
+ (Contributed by Serhiy Storchaka in :gh:`65210`.)
+
+* :c:func:`PyArg_ParseTupleAndKeywords` now supports
+ non-ASCII keyword parameter names.
+ (Contributed by Serhiy Storchaka in :gh:`110815`.)
+
+* The :c:func:`!PyCode_GetFirstFree` function is now unstable API
+ and is now named :c:func:`PyUnstable_Code_GetFirstFree`.
+ (Contributed by Bogdan Romanyuk in :gh:`115781`.)
+
+* The :c:func:`PyDict_GetItem`, :c:func:`PyDict_GetItemString`,
+ :c:func:`PyMapping_HasKey`, :c:func:`PyMapping_HasKeyString`,
+ :c:func:`PyObject_HasAttr`, :c:func:`PyObject_HasAttrString`,
+ and :c:func:`PySys_GetObject` functions,
+ each of which clears all errors which occurred when calling them
+ now reports these errors using :func:`sys.unraisablehook`.
+ You may replace them with other functions as recommended in the documentation.
+ (Contributed by Serhiy Storchaka in :gh:`106672`.)
+
+* Add support for the ``%T``, ``%#T``, ``%N`` and ``%#N`` formats
+ to :c:func:`PyUnicode_FromFormat`:
+
+ * ``%T``: Get the fully qualified name of an object type
+ * ``%#T``: As above, but use a colon as the separator
+ * ``%N``: Get the fully qualified name of a type
+ * ``%#N``: As above, but use a colon as the separator
+
+ See :pep:`737` for more information.
+ (Contributed by Victor Stinner in :gh:`111696`.)
+
+* You no longer have to define the ``PY_SSIZE_T_CLEAN`` macro before
+ including :file:`Python.h` when using ``#`` formats in
:ref:`format codes `.
APIs accepting the format codes always use ``Py_ssize_t`` for ``#`` formats.
(Contributed by Inada Naoki in :gh:`104922`.)
-* The *keywords* parameter of :c:func:`PyArg_ParseTupleAndKeywords` and
- :c:func:`PyArg_VaParseTupleAndKeywords` now has type :c:expr:`char * const *`
- in C and :c:expr:`const char * const *` in C++, instead of :c:expr:`char **`.
- It makes these functions compatible with arguments of type
- :c:expr:`const char * const *`, :c:expr:`const char **` or
- :c:expr:`char * const *` in C++ and :c:expr:`char * const *` in C
- without an explicit type cast.
- This can be overridden with the :c:macro:`PY_CXX_CONST` macro.
- (Contributed by Serhiy Storchaka in :gh:`65210`.)
+* If Python is built in :ref:`debug mode `
+ or :option:`with assertions <--with-assertions>`,
+ :c:func:`PyTuple_SET_ITEM` and :c:func:`PyList_SET_ITEM`
+ now check the index argument with an assertion.
+ (Contributed by Victor Stinner in :gh:`106168`.)
-* Add :c:func:`PyImport_AddModuleRef`: similar to
- :c:func:`PyImport_AddModule`, but return a :term:`strong reference` instead
- of a :term:`borrowed reference`.
- (Contributed by Victor Stinner in :gh:`105922`.)
-* Add :c:func:`PyWeakref_GetRef` function: similar to
- :c:func:`PyWeakref_GetObject` but returns a :term:`strong reference`, or
- ``NULL`` if the referent is no longer live.
- (Contributed by Victor Stinner in :gh:`105927`.)
+Limited C API Changes
+---------------------
-* Add :c:func:`PyObject_GetOptionalAttr` and
- :c:func:`PyObject_GetOptionalAttrString`, variants of
- :c:func:`PyObject_GetAttr` and :c:func:`PyObject_GetAttrString` which
- don't raise :exc:`AttributeError` if the attribute is not found.
- These variants are more convenient and faster if the missing attribute
- should not be treated as a failure.
- (Contributed by Serhiy Storchaka in :gh:`106521`.)
+* The following functions are now included in the Limited C API:
-* Add :c:func:`PyMapping_GetOptionalItem` and
- :c:func:`PyMapping_GetOptionalItemString`: variants of
- :c:func:`PyObject_GetItem` and :c:func:`PyMapping_GetItemString` which don't
- raise :exc:`KeyError` if the key is not found.
- These variants are more convenient and faster if the missing key should not
- be treated as a failure.
- (Contributed by Serhiy Storchaka in :gh:`106307`.)
+ * :c:func:`PyMem_RawMalloc`
+ * :c:func:`PyMem_RawCalloc`
+ * :c:func:`PyMem_RawRealloc`
+ * :c:func:`PyMem_RawFree`
+ * :c:func:`PySys_Audit`
+ * :c:func:`PySys_AuditTuple`
+ * :c:func:`PyType_GetModuleByDef`
-* Add fixed variants of functions which silently ignore errors:
+ (Contributed by Victor Stinner in :gh:`85283`, :gh:`85283`, and :gh:`116936`.)
- - :c:func:`PyObject_HasAttrWithError` replaces :c:func:`PyObject_HasAttr`.
- - :c:func:`PyObject_HasAttrStringWithError` replaces :c:func:`PyObject_HasAttrString`.
- - :c:func:`PyMapping_HasKeyWithError` replaces :c:func:`PyMapping_HasKey`.
- - :c:func:`PyMapping_HasKeyStringWithError` replaces :c:func:`PyMapping_HasKeyString`.
+* Python built with :option:`--with-trace-refs` (tracing references)
+ now supports the :ref:`Limited API `.
+ (Contributed by Victor Stinner in :gh:`108634`.)
- New functions return not only ``1`` for true and ``0`` for false, but also
- ``-1`` for error.
- (Contributed by Serhiy Storchaka in :gh:`108511`.)
+Removed C APIs
+--------------
-* If Python is built in :ref:`debug mode ` or :option:`with
- assertions <--with-assertions>`, :c:func:`PyTuple_SET_ITEM` and
- :c:func:`PyList_SET_ITEM` now check the index argument with an assertion.
- (Contributed by Victor Stinner in :gh:`106168`.)
+* Remove several functions, macros, variables, etc
+ with names prefixed by ``_Py`` or ``_PY`` (which are considered private).
+ If your project is affected by one of these removals
+ and you believe that the removed API should remain available,
+ please :ref:`open a new issue ` to request a public C API
+ and add ``cc: @vstinner`` to the issue to notify Victor Stinner.
+ (Contributed by Victor Stinner in :gh:`106320`.)
-* Add :c:func:`PyModule_Add` function: similar to
- :c:func:`PyModule_AddObjectRef` and :c:func:`PyModule_AddObject` but
- always steals a reference to the value.
- (Contributed by Serhiy Storchaka in :gh:`86493`.)
+* Remove old buffer protocols deprecated in Python 3.0.
+ Use :ref:`bufferobjects` instead.
-* Add :c:func:`PyDict_GetItemRef` and :c:func:`PyDict_GetItemStringRef`
- functions: similar to :c:func:`PyDict_GetItemWithError` but returning a
- :term:`strong reference` instead of a :term:`borrowed reference`. Moreover,
- these functions return -1 on error and so checking ``PyErr_Occurred()`` is
- not needed.
- (Contributed by Victor Stinner in :gh:`106004`.)
+ * :c:func:`!PyObject_CheckReadBuffer`:
+ Use :c:func:`PyObject_CheckBuffer` to test
+ whether the object supports the buffer protocol.
+ Note that :c:func:`PyObject_CheckBuffer` doesn't guarantee
+ that :c:func:`PyObject_GetBuffer` will succeed.
+ To test if the object is actually readable,
+ see the next example of :c:func:`PyObject_GetBuffer`.
-* Added :c:func:`PyDict_SetDefaultRef`, which is similar to
- :c:func:`PyDict_SetDefault` but returns a :term:`strong reference` instead of
- a :term:`borrowed reference`. This function returns ``-1`` on error, ``0`` on
- insertion, and ``1`` if the key was already present in the dictionary.
- (Contributed by Sam Gross in :gh:`112066`.)
+ * :c:func:`!PyObject_AsCharBuffer`, :c:func:`!PyObject_AsReadBuffer`:
+ Use :c:func:`PyObject_GetBuffer` and :c:func:`PyBuffer_Release` instead:
-* Add :c:func:`PyDict_ContainsString` function: same as
- :c:func:`PyDict_Contains`, but *key* is specified as a :c:expr:`const char*`
- UTF-8 encoded bytes string, rather than a :c:expr:`PyObject*`.
- (Contributed by Victor Stinner in :gh:`108314`.)
+ .. code-block:: c
-* Added :c:func:`PyList_GetItemRef` function: similar to
- :c:func:`PyList_GetItem` but returns a :term:`strong reference` instead of
- a :term:`borrowed reference`.
+ Py_buffer view;
+ if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) {
+ return NULL;
+ }
+ // Use `view.buf` and `view.len` to read from the buffer.
+ // You may need to cast buf as `(const char*)view.buf`.
+ PyBuffer_Release(&view);
-* Add :c:func:`Py_IsFinalizing` function: check if the main Python interpreter is
- :term:`shutting down `.
- (Contributed by Victor Stinner in :gh:`108014`.)
+ * :c:func:`!PyObject_AsWriteBuffer`:
+ Use :c:func:`PyObject_GetBuffer` and :c:func:`PyBuffer_Release` instead:
-* Add :c:func:`PyLong_AsInt` function: similar to :c:func:`PyLong_AsLong`, but
- store the result in a C :c:expr:`int` instead of a C :c:expr:`long`.
- Previously, it was known as the private function :c:func:`!_PyLong_AsInt`
- (with an underscore prefix).
- (Contributed by Victor Stinner in :gh:`108014`.)
+ .. code-block:: c
-* Python built with :file:`configure` :option:`--with-trace-refs` (tracing
- references) now supports the :ref:`Limited API `.
- (Contributed by Victor Stinner in :gh:`108634`.)
+ Py_buffer view;
+ if (PyObject_GetBuffer(obj, &view, PyBUF_WRITABLE) < 0) {
+ return NULL;
+ }
+ // Use `view.buf` and `view.len` to write to the buffer.
+ PyBuffer_Release(&view);
-* Add :c:func:`PyObject_VisitManagedDict` and
- :c:func:`PyObject_ClearManagedDict` functions which must be called by the
- traverse and clear functions of a type using
- :c:macro:`Py_TPFLAGS_MANAGED_DICT` flag. The `pythoncapi-compat project
- `__ can be used to get these
- functions on Python 3.11 and 3.12.
- (Contributed by Victor Stinner in :gh:`107073`.)
+ (Contributed by Inada Naoki in :gh:`85275`.)
-* Add :c:func:`PyUnicode_EqualToUTF8AndSize` and :c:func:`PyUnicode_EqualToUTF8`
- functions: compare Unicode object with a :c:expr:`const char*` UTF-8 encoded
- string and return true (``1``) if they are equal, or false (``0``) otherwise.
- These functions do not raise exceptions.
- (Contributed by Serhiy Storchaka in :gh:`110289`.)
+* Remove various functions deprecated in Python 3.9:
-* Add :c:func:`PyThreadState_GetUnchecked()` function: similar to
- :c:func:`PyThreadState_Get()`, but don't kill the process with a fatal error
- if it is NULL. The caller is responsible to check if the result is NULL.
- Previously, the function was private and known as
- ``_PyThreadState_UncheckedGet()``.
- (Contributed by Victor Stinner in :gh:`108867`.)
+ * :c:func:`!PyEval_CallObject`, :c:func:`!PyEval_CallObjectWithKeywords`:
+ Use :c:func:`PyObject_CallNoArgs` or :c:func:`PyObject_Call` instead.
-* Add :c:func:`PySys_AuditTuple` function: similar to :c:func:`PySys_Audit`,
- but pass event arguments as a Python :class:`tuple` object.
- (Contributed by Victor Stinner in :gh:`85283`.)
+ .. warning::
-* :c:func:`PyArg_ParseTupleAndKeywords` now supports non-ASCII keyword
- parameter names.
- (Contributed by Serhiy Storchaka in :gh:`110815`.)
+ In :c:func:`PyObject_Call`, positional arguments must be a :class:`tuple`
+ and must not be ``NULL``,
+ and keyword arguments must be a :class:`dict` or ``NULL``,
+ whereas the removed functions checked argument types
+ and accepted ``NULL`` positional and keyword arguments.
+ To replace ``PyEval_CallObjectWithKeywords(func, NULL, kwargs)`` with
+ :c:func:`PyObject_Call`,
+ pass an empty tuple as positional arguments using
+ :c:func:`PyTuple_New(0) `.
-* Add :c:func:`PyMem_RawMalloc`, :c:func:`PyMem_RawCalloc`,
- :c:func:`PyMem_RawRealloc` and :c:func:`PyMem_RawFree` to the limited C API
- (version 3.13).
- (Contributed by Victor Stinner in :gh:`85283`.)
+ * :c:func:`!PyEval_CallFunction`:
+ Use :c:func:`PyObject_CallFunction` instead.
+ * :c:func:`!PyEval_CallMethod`:
+ Use :c:func:`PyObject_CallMethod` instead.
+ * :c:func:`!PyCFunction_Call`:
+ Use :c:func:`PyObject_Call` instead.
-* Add :c:func:`PySys_Audit` and :c:func:`PySys_AuditTuple` functions to the
- limited C API.
- (Contributed by Victor Stinner in :gh:`85283`.)
+ (Contributed by Victor Stinner in :gh:`105107`.)
-* Add :c:func:`PyErr_FormatUnraisable` function: similar to
- :c:func:`PyErr_WriteUnraisable`, but allow customizing the warning message.
- (Contributed by Serhiy Storchaka in :gh:`108082`.)
+* Remove the following old functions to configure the Python initialization,
+ deprecated in Python 3.11:
-* Add :c:func:`PyList_Extend` and :c:func:`PyList_Clear` functions: similar to
- Python ``list.extend()`` and ``list.clear()`` methods.
- (Contributed by Victor Stinner in :gh:`111138`.)
+ * :c:func:`!PySys_AddWarnOptionUnicode`:
+ Use :c:member:`PyConfig.warnoptions` instead.
+ * :c:func:`!PySys_AddWarnOption`:
+ Use :c:member:`PyConfig.warnoptions` instead.
+ * :c:func:`!PySys_AddXOption`:
+ Use :c:member:`PyConfig.xoptions` instead.
+ * :c:func:`!PySys_HasWarnOptions`:
+ Use :c:member:`PyConfig.xoptions` instead.
+ * :c:func:`!PySys_SetPath`:
+ Set :c:member:`PyConfig.module_search_paths` instead.
+ * :c:func:`!Py_SetPath`:
+ Set :c:member:`PyConfig.module_search_paths` instead.
+ * :c:func:`!Py_SetStandardStreamEncoding`:
+ Set :c:member:`PyConfig.stdio_encoding` instead,
+ and set also maybe :c:member:`PyConfig.legacy_windows_stdio` (on Windows).
+ * :c:func:`!_Py_SetProgramFullPath`:
+ Set :c:member:`PyConfig.executable` instead.
-* Add :c:func:`PyDict_Pop` and :c:func:`PyDict_PopString` functions: remove a
- key from a dictionary and optionally return the removed value. This is
- similar to :meth:`dict.pop`, but without the default value and not raising
- :exc:`KeyError` if the key is missing.
- (Contributed by Stefan Behnel and Victor Stinner in :gh:`111262`.)
+ Use the new :c:type:`PyConfig` API of the :ref:`Python Initialization
+ Configuration ` instead (:pep:`587`), added to Python 3.8.
+ (Contributed by Victor Stinner in :gh:`105145`.)
-* Add :c:func:`Py_HashPointer` function to hash a pointer.
- (Contributed by Victor Stinner in :gh:`111545`.)
+* Remove :c:func:`!PyEval_AcquireLock` and :c:func:`!PyEval_ReleaseLock` functions,
+ deprecated in Python 3.2.
+ They didn't update the current thread state.
+ They can be replaced with:
-* Add :c:func:`PyObject_GenericHash` function that implements the default
- hashing function of a Python object.
- (Contributed by Serhiy Storchaka in :gh:`113024`.)
+ * :c:func:`PyEval_SaveThread` and :c:func:`PyEval_RestoreThread`;
+ * low-level :c:func:`PyEval_AcquireThread` and :c:func:`PyEval_RestoreThread`;
+ * or :c:func:`PyGILState_Ensure` and :c:func:`PyGILState_Release`.
-* Add PyTime C API:
+ (Contributed by Victor Stinner in :gh:`105182`.)
- * :c:type:`PyTime_t` type.
- * :c:var:`PyTime_MIN` and :c:var:`PyTime_MAX` constants.
- * Add functions:
+* Remove the :c:func:`!PyEval_ThreadsInitialized` function,
+ deprecated in Python 3.9.
+ Since Python 3.7, :c:func:`!Py_Initialize` always creates the GIL:
+ calling :c:func:`!PyEval_InitThreads` does nothing and
+ :c:func:`!PyEval_ThreadsInitialized` always returns non-zero.
+ (Contributed by Victor Stinner in :gh:`105182`.)
- * :c:func:`PyTime_AsSecondsDouble`.
- * :c:func:`PyTime_Monotonic`.
- * :c:func:`PyTime_MonotonicRaw`.
- * :c:func:`PyTime_PerfCounter`.
- * :c:func:`PyTime_PerfCounterRaw`.
- * :c:func:`PyTime_Time`.
- * :c:func:`PyTime_TimeRaw`.
+* Remove the :c:func:`!_PyInterpreterState_Get` alias to
+ :c:func:`PyInterpreterState_Get()`
+ which was kept for backward compatibility with Python 3.8.
+ The `pythoncapi-compat project`_ can be used to get
+ :c:func:`PyInterpreterState_Get()` on Python 3.8 and older.
+ (Contributed by Victor Stinner in :gh:`106320`.)
- (Contributed by Victor Stinner and Petr Viktorin in :gh:`110850`.)
+* Remove the private :c:func:`!_PyObject_FastCall` function:
+ use :c:func:`!PyObject_Vectorcall` which is available since Python 3.8
+ (:pep:`590`).
+ (Contributed by Victor Stinner in :gh:`106023`.)
-* Add :c:func:`PyLong_AsNativeBytes`, :c:func:`PyLong_FromNativeBytes` and
- :c:func:`PyLong_FromUnsignedNativeBytes` functions to simplify converting
- between native integer types and Python :class:`int` objects.
- (Contributed by Steve Dower in :gh:`111140`.)
+* Remove the ``cpython/pytime.h`` header file,
+ which only contained private functions.
+ (Contributed by Victor Stinner in :gh:`106316`.)
-* Add :c:func:`PyType_GetFullyQualifiedName` function to get the type's fully
- qualified name. Equivalent to ``f"{type.__module__}.{type.__qualname__}"``,
- or ``type.__qualname__`` if ``type.__module__`` is not a string or is equal
- to ``"builtins"``.
- (Contributed by Victor Stinner in :gh:`111696`.)
+* Remove the undocumented ``PY_TIMEOUT_MAX`` constant from the limited C API.
+ (Contributed by Victor Stinner in :gh:`110014`.)
-* Add :c:func:`PyType_GetModuleName` function to get the type's module name.
- Equivalent to getting the ``type.__module__`` attribute.
- (Contributed by Eric Snow and Victor Stinner in :gh:`111696`.)
+* Remove the old trashcan macros ``Py_TRASHCAN_SAFE_BEGIN``
+ and ``Py_TRASHCAN_SAFE_END``.
+ Replace both with the new macros ``Py_TRASHCAN_BEGIN``
+ and ``Py_TRASHCAN_END``.
+ (Contributed by Irit Katriel in :gh:`105111`.)
-* Add support for ``%T``, ``%#T``, ``%N`` and ``%#N`` formats to
- :c:func:`PyUnicode_FromFormat`: format the fully qualified name of an object
- type and of a type: call :c:func:`PyType_GetModuleName`. See :pep:`737` for
- more information.
- (Contributed by Victor Stinner in :gh:`111696`.)
+Deprecated C APIs
+-----------------
-* Add :c:func:`Py_GetConstant` and :c:func:`Py_GetConstantBorrowed` functions
- to get constants. For example, ``Py_GetConstant(Py_CONSTANT_ZERO)`` returns a
- :term:`strong reference` to the constant zero.
- (Contributed by Victor Stinner in :gh:`115754`.)
+* Deprecate old Python initialization functions:
-* Add :c:func:`PyType_GetModuleByDef` to the limited C API
- (Contributed by Victor Stinner in :gh:`116936`.)
+ * :c:func:`PySys_ResetWarnOptions`:
+ Clear :data:`sys.warnoptions` and :data:`!warnings.filters` instead.
+ * :c:func:`Py_GetExecPrefix`:
+ Get :data:`sys.exec_prefix` instead.
+ * :c:func:`Py_GetPath`:
+ Get :data:`sys.path` instead.
+ * :c:func:`Py_GetPrefix`:
+ Get :data:`sys.prefix` instead.
+ * :c:func:`Py_GetProgramFullPath`:
+ Get :data:`sys.executable` instead.
+ * :c:func:`Py_GetProgramName`:
+ Get :data:`sys.executable` instead.
+ * :c:func:`Py_GetPythonHome`:
+ Get :c:member:`PyConfig.home`
+ or the :envvar:`PYTHONHOME` environment variable instead.
-* Add two new functions to the C-API, :c:func:`PyRefTracer_SetTracer` and
- :c:func:`PyRefTracer_GetTracer`, that allows to track object creation and
- destruction the same way the :mod:`tracemalloc` module does. (Contributed
- by Pablo Galindo in :gh:`93502`.)
+ (Contributed by Victor Stinner in :gh:`105145`.)
-* Add :c:func:`PyEval_GetFrameBuiltins`, :c:func:`PyEval_GetFrameGlobals`, and
- :c:func:`PyEval_GetFrameLocals` to the C API. These replacements for
- :c:func:`PyEval_GetBuiltins`, :c:func:`PyEval_GetGlobals`, and
- :c:func:`PyEval_GetLocals` return :term:`strong references `
- rather than borrowed references. (Added as part of :pep:`667`.)
+* :term:`Soft deprecate ` the
+ :c:func:`PyEval_GetBuiltins`, :c:func:`PyEval_GetGlobals`,
+ and :c:func:`PyEval_GetLocals` functions,
+ which return a :term:`borrowed reference`.
+ (Soft deprecated as part of :pep:`667`.)
-* Add :c:type:`PyMutex` API, a lightweight mutex that occupies a single byte.
- The :c:func:`PyMutex_Lock` function will release the GIL (if currently held)
- if the operation needs to block.
- (Contributed by Sam Gross in :gh:`108724`.)
+* Deprecate the :c:func:`PyImport_ImportModuleNoBlock` function,
+ which is just an alias to :c:func:`PyImport_ImportModule` since Python 3.3.
+ (Contributed by Victor Stinner in :gh:`105396`.)
-Build Changes
-=============
+* :term:`Soft deprecate ` the
+ :c:func:`PyModule_AddObject` function.
+ It should be replaced with :c:func:`PyModule_Add`
+ or :c:func:`PyModule_AddObjectRef`.
+ (Contributed by Serhiy Storchaka in :gh:`86493`.)
-* The :file:`configure` option :option:`--with-system-libmpdec` now defaults
- to ``yes``. The bundled copy of ``libmpdecimal`` will be removed in Python
- 3.15.
+* Deprecate the old ``Py_UNICODE`` and ``PY_UNICODE_TYPE`` types
+ and the :c:macro:`!Py_UNICODE_WIDE` define.
+ Use the :c:type:`wchar_t` type directly instead.
+ Since Python 3.3, ``Py_UNICODE`` and ``PY_UNICODE_TYPE``
+ are just aliases to :c:type:`!wchar_t`.
+ (Contributed by Victor Stinner in :gh:`105156`.)
-* Autoconf 2.71 and aclocal 1.16.4 are now required to regenerate
- the :file:`configure` script.
- (Contributed by Christian Heimes in :gh:`89886`.)
+* Deprecate the :c:func:`PyWeakref_GetObject` and
+ :c:func:`PyWeakref_GET_OBJECT` functions,
+ which return a :term:`borrowed reference`.
+ Replace them with the new :c:func:`PyWeakref_GetRef` function,
+ which returns a :term:`strong reference`.
+ The `pythoncapi-compat project`_ can be used to get
+ :c:func:`PyWeakref_GetRef` on Python 3.12 and older.
+ (Contributed by Victor Stinner in :gh:`105927`.)
-* SQLite 3.15.2 or newer is required to build the :mod:`sqlite3` extension module.
- (Contributed by Erlend Aasland in :gh:`105875`.)
+.. Add deprecations above alphabetically, not here at the end.
-* Python built with :file:`configure` :option:`--with-trace-refs` (tracing
- references) is now ABI compatible with the Python release build and
- :ref:`debug build `.
- (Contributed by Victor Stinner in :gh:`108634`.)
+.. include:: ../deprecations/c-api-pending-removal-in-3.14.rst
-* Building CPython now requires a compiler with support for the C11 atomic
- library, GCC built-in atomic functions, or MSVC interlocked intrinsics.
+.. include:: ../deprecations/c-api-pending-removal-in-3.15.rst
-* The ``errno``, ``fcntl``, ``grp``, ``md5``, ``pwd``, ``resource``,
- ``termios``, ``winsound``,
- ``_ctypes_test``, ``_multiprocessing.posixshmem``, ``_scproxy``, ``_stat``,
- ``_statistics``, ``_testconsole``, ``_testimportmultiple`` and ``_uuid``
- C extensions are now built with the :ref:`limited C API `.
- (Contributed by Victor Stinner in :gh:`85283`.)
+.. include:: ../deprecations/c-api-pending-removal-in-future.rst
+
+.. _pythoncapi-compat project: https://github.com/python/pythoncapi-compat/
+
+Build Changes
+=============
+
+* ``arm64-apple-ios`` and ``arm64-apple-ios-simulator`` are both
+ now :pep:`11` tier 3 platforms.
+ (:ref:`PEP 730 ` written
+ and implementation contributed by Russell Keith-Magee in :gh:`114099`.)
+
+* ``aarch64-linux-android`` and ``x86_64-linux-android`` are both
+ now :pep:`11` tier 3 platforms.
+ (:ref:`PEP 738 ` written
+ and implementation contributed by Malcolm Smith in :gh:`116622`.)
* ``wasm32-wasi`` is now a :pep:`11` tier 2 platform.
(Contributed by Brett Cannon in :gh:`115192`.)
@@ -2203,15 +2488,45 @@ Build Changes
* ``wasm32-emscripten`` is no longer a :pep:`11` supported platform.
(Contributed by Brett Cannon in :gh:`115192`.)
-* Python now bundles the `mimalloc library `__.
- It is licensed under the MIT license; see :ref:`mimalloc license `.
+* Building CPython now requires a compiler with support for the C11 atomic
+ library, GCC built-in atomic functions, or MSVC interlocked intrinsics.
+
+* Autoconf 2.71 and aclocal 1.16.4 are now required to regenerate
+ the :file:`configure` script.
+ (Contributed by Christian Heimes in :gh:`89886`.)
+
+* SQLite 3.15.2 or newer is required to build
+ the :mod:`sqlite3` extension module.
+ (Contributed by Erlend Aasland in :gh:`105875`.)
+
+* CPython now bundles the `mimalloc library`_ by default.
+ It is licensed under the MIT license;
+ see :ref:`mimalloc license `.
The bundled mimalloc has custom changes, see :gh:`113141` for details.
(Contributed by Dino Viehland in :gh:`109914`.)
+ .. _mimalloc library: https://github.com/microsoft/mimalloc/
+
+* The :file:`configure` option :option:`--with-system-libmpdec`
+ now defaults to ``yes``.
+ The bundled copy of ``libmpdecimal`` will be removed in Python 3.15.
+
+* Python built with :file:`configure` :option:`--with-trace-refs`
+ (tracing references) is now ABI compatible with the Python release build
+ and :ref:`debug build `.
+ (Contributed by Victor Stinner in :gh:`108634`.)
+
* On POSIX systems, the pkg-config (``.pc``) filenames now include the ABI
flags. For example, the free-threaded build generates ``python-3.13t.pc``
and the debug build generates ``python-3.13d.pc``.
+* The ``errno``, ``fcntl``, ``grp``, ``md5``, ``pwd``, ``resource``,
+ ``termios``, ``winsound``,
+ ``_ctypes_test``, ``_multiprocessing.posixshmem``, ``_scproxy``, ``_stat``,
+ ``_statistics``, ``_testconsole``, ``_testimportmultiple`` and ``_uuid``
+ C extensions are now built with the :ref:`limited C API `.
+ (Contributed by Victor Stinner in :gh:`85283`.)
+
Porting to Python 3.13
======================
@@ -2222,84 +2537,89 @@ that may require changes to your code.
Changes in the Python API
-------------------------
-* An :exc:`OSError` is now raised by :func:`getpass.getuser` for any failure to
- retrieve a username, instead of :exc:`ImportError` on non-Unix platforms or
- :exc:`KeyError` on Unix platforms where the password database is empty.
+.. _pep667-porting-notes-py:
+
+* :ref:`PEP 667 ` introduces several changes
+ to the semantics of :func:`locals` and :attr:`f_locals