mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
Merge branch 'python:main' into pyrepl-module-completion-check-for-already-imported-modules
This commit is contained in:
commit
e3f1ddb88b
268 changed files with 6793 additions and 3830 deletions
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
|
|
@ -86,6 +86,10 @@ Modules/makesetup @erlend-aasland @AA-Turner @emmatyping
|
||||||
Modules/Setup* @erlend-aasland @AA-Turner @emmatyping
|
Modules/Setup* @erlend-aasland @AA-Turner @emmatyping
|
||||||
Tools/build/regen-configure.sh @AA-Turner
|
Tools/build/regen-configure.sh @AA-Turner
|
||||||
|
|
||||||
|
# generate-build-details
|
||||||
|
Tools/build/generate-build-details.py @FFY00
|
||||||
|
Lib/test/test_build_details.py @FFY00
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Documentation
|
# Documentation
|
||||||
|
|
|
||||||
3
.github/actionlint.yaml
vendored
3
.github/actionlint.yaml
vendored
|
|
@ -1,6 +1,7 @@
|
||||||
self-hosted-runner:
|
self-hosted-runner:
|
||||||
# Pending https://github.com/rhysd/actionlint/issues/533
|
# Pending https://github.com/rhysd/actionlint/issues/533
|
||||||
labels: ["windows-11-arm"]
|
# and https://github.com/rhysd/actionlint/issues/571
|
||||||
|
labels: ["windows-11-arm", "macos-15-intel"]
|
||||||
|
|
||||||
config-variables: null
|
config-variables: null
|
||||||
|
|
||||||
|
|
|
||||||
27
.github/workflows/build.yml
vendored
27
.github/workflows/build.yml
vendored
|
|
@ -202,24 +202,16 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
# Cirrus and macos-14 are M1, macos-13 is default GHA Intel.
|
# macos-14 is M1, macos-15-intel is Intel.
|
||||||
# macOS 13 only runs tests against the GIL-enabled CPython.
|
# macos-15-intel only runs tests against the GIL-enabled CPython.
|
||||||
# Cirrus used for upstream, macos-14 for forks.
|
|
||||||
os:
|
os:
|
||||||
- ghcr.io/cirruslabs/macos-runner:sonoma
|
|
||||||
- macos-14
|
- macos-14
|
||||||
- macos-13
|
- macos-15-intel
|
||||||
is-fork: # only used for the exclusion trick
|
|
||||||
- ${{ github.repository_owner != 'python' }}
|
|
||||||
free-threading:
|
free-threading:
|
||||||
- false
|
- false
|
||||||
- true
|
- true
|
||||||
exclude:
|
exclude:
|
||||||
- os: ghcr.io/cirruslabs/macos-runner:sonoma
|
- os: macos-15-intel
|
||||||
is-fork: true
|
|
||||||
- os: macos-14
|
|
||||||
is-fork: false
|
|
||||||
- os: macos-13
|
|
||||||
free-threading: true
|
free-threading: true
|
||||||
uses: ./.github/workflows/reusable-macos.yml
|
uses: ./.github/workflows/reusable-macos.yml
|
||||||
with:
|
with:
|
||||||
|
|
@ -273,7 +265,7 @@ jobs:
|
||||||
# Keep 1.1.1w in our list despite it being upstream EOL and otherwise
|
# Keep 1.1.1w in our list despite it being upstream EOL and otherwise
|
||||||
# unsupported as it most resembles other 1.1.1-work-a-like ssl APIs
|
# unsupported as it most resembles other 1.1.1-work-a-like ssl APIs
|
||||||
# supported by important vendors such as AWS-LC.
|
# supported by important vendors such as AWS-LC.
|
||||||
openssl_ver: [1.1.1w, 3.0.17, 3.2.5, 3.3.4, 3.4.2, 3.5.2]
|
openssl_ver: [1.1.1w, 3.0.18, 3.2.6, 3.3.5, 3.4.3, 3.5.4]
|
||||||
# See Tools/ssl/make_ssl_data.py for notes on adding a new version
|
# See Tools/ssl/make_ssl_data.py for notes on adding a new version
|
||||||
env:
|
env:
|
||||||
OPENSSL_VER: ${{ matrix.openssl_ver }}
|
OPENSSL_VER: ${{ matrix.openssl_ver }}
|
||||||
|
|
@ -409,9 +401,8 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
# Use the same runs-on configuration as build-macos and build-ubuntu.
|
|
||||||
- arch: aarch64
|
- arch: aarch64
|
||||||
runs-on: ${{ github.repository_owner == 'python' && 'ghcr.io/cirruslabs/macos-runner:sonoma' || 'macos-14' }}
|
runs-on: macos-14
|
||||||
- arch: x86_64
|
- arch: x86_64
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
|
|
@ -421,7 +412,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Build and test
|
- name: Build and test
|
||||||
run: ./Android/android.py ci ${{ matrix.arch }}-linux-android
|
run: ./Android/android.py ci --fast-ci ${{ matrix.arch }}-linux-android
|
||||||
|
|
||||||
build-wasi:
|
build-wasi:
|
||||||
name: 'WASI'
|
name: 'WASI'
|
||||||
|
|
@ -438,7 +429,7 @@ jobs:
|
||||||
needs: build-context
|
needs: build-context
|
||||||
if: needs.build-context.outputs.run-tests == 'true'
|
if: needs.build-context.outputs.run-tests == 'true'
|
||||||
env:
|
env:
|
||||||
OPENSSL_VER: 3.0.16
|
OPENSSL_VER: 3.0.18
|
||||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
@ -558,7 +549,7 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-24.04]
|
os: [ubuntu-24.04]
|
||||||
env:
|
env:
|
||||||
OPENSSL_VER: 3.0.16
|
OPENSSL_VER: 3.0.18
|
||||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||||
ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0
|
ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0
|
||||||
steps:
|
steps:
|
||||||
|
|
|
||||||
7
.github/workflows/jit.yml
vendored
7
.github/workflows/jit.yml
vendored
|
|
@ -81,7 +81,7 @@ jobs:
|
||||||
runner: windows-11-arm
|
runner: windows-11-arm
|
||||||
- target: x86_64-apple-darwin/clang
|
- target: x86_64-apple-darwin/clang
|
||||||
architecture: x86_64
|
architecture: x86_64
|
||||||
runner: macos-13
|
runner: macos-15-intel
|
||||||
- target: aarch64-apple-darwin/clang
|
- target: aarch64-apple-darwin/clang
|
||||||
architecture: aarch64
|
architecture: aarch64
|
||||||
runner: macos-14
|
runner: macos-14
|
||||||
|
|
@ -106,15 +106,10 @@ jobs:
|
||||||
./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }}
|
./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }}
|
||||||
./PCbuild/rt.bat ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
./PCbuild/rt.bat ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||||
|
|
||||||
# The `find` line is required as a result of https://github.com/actions/runner-images/issues/9966.
|
|
||||||
# This is a bug in the macOS runner image where the pre-installed Python is installed in the same
|
|
||||||
# directory as the Homebrew Python, which causes the build to fail for macos-13. This line removes
|
|
||||||
# the symlink to the pre-installed Python so that the Homebrew Python is used instead.
|
|
||||||
- name: macOS
|
- name: macOS
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
brew update
|
brew update
|
||||||
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
|
|
||||||
brew install llvm@${{ matrix.llvm }}
|
brew install llvm@${{ matrix.llvm }}
|
||||||
export SDKROOT="$(xcrun --show-sdk-path)"
|
export SDKROOT="$(xcrun --show-sdk-path)"
|
||||||
# Set MACOSX_DEPLOYMENT_TARGET and -Werror=unguarded-availability to
|
# Set MACOSX_DEPLOYMENT_TARGET and -Werror=unguarded-availability to
|
||||||
|
|
|
||||||
31
.github/workflows/project-updater.yml
vendored
31
.github/workflows/project-updater.yml
vendored
|
|
@ -1,31 +0,0 @@
|
||||||
name: Update GH projects
|
|
||||||
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types:
|
|
||||||
- opened
|
|
||||||
- labeled
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
add-to-project:
|
|
||||||
name: Add issues to projects
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 10
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
# if an issue has any of these labels, it will be added
|
|
||||||
# to the corresponding project
|
|
||||||
- { project: 2, label: "release-blocker, deferred-blocker" }
|
|
||||||
- { project: 32, label: sprint }
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/add-to-project@v1.0.0
|
|
||||||
with:
|
|
||||||
project-url: https://github.com/orgs/python/projects/${{ matrix.project }}
|
|
||||||
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
|
|
||||||
labeled: ${{ matrix.label }}
|
|
||||||
6
.github/workflows/reusable-macos.yml
vendored
6
.github/workflows/reusable-macos.yml
vendored
|
|
@ -60,15 +60,15 @@ jobs:
|
||||||
--prefix=/opt/python-dev \
|
--prefix=/opt/python-dev \
|
||||||
--with-openssl="$(brew --prefix openssl@3.0)"
|
--with-openssl="$(brew --prefix openssl@3.0)"
|
||||||
- name: Build CPython
|
- name: Build CPython
|
||||||
if : ${{ inputs.free-threading || inputs.os != 'macos-13' }}
|
if : ${{ inputs.free-threading || inputs.os != 'macos-15-intel' }}
|
||||||
run: gmake -j8
|
run: gmake -j8
|
||||||
- name: Build CPython for compiler warning check
|
- name: Build CPython for compiler warning check
|
||||||
if : ${{ !inputs.free-threading && inputs.os == 'macos-13' }}
|
if : ${{ !inputs.free-threading && inputs.os == 'macos-15-intel' }}
|
||||||
run: set -o pipefail; gmake -j8 --output-sync 2>&1 | tee compiler_output_macos.txt
|
run: set -o pipefail; gmake -j8 --output-sync 2>&1 | tee compiler_output_macos.txt
|
||||||
- name: Display build info
|
- name: Display build info
|
||||||
run: make pythoninfo
|
run: make pythoninfo
|
||||||
- name: Check compiler warnings
|
- name: Check compiler warnings
|
||||||
if : ${{ !inputs.free-threading && inputs.os == 'macos-13' }}
|
if : ${{ !inputs.free-threading && inputs.os == 'macos-15-intel' }}
|
||||||
run: >-
|
run: >-
|
||||||
python3 Tools/build/check_warnings.py
|
python3 Tools/build/check_warnings.py
|
||||||
--compiler-output-file-path=compiler_output_macos.txt
|
--compiler-output-file-path=compiler_output_macos.txt
|
||||||
|
|
|
||||||
2
.github/workflows/reusable-ubuntu.yml
vendored
2
.github/workflows/reusable-ubuntu.yml
vendored
|
|
@ -30,7 +30,7 @@ jobs:
|
||||||
runs-on: ${{ inputs.os }}
|
runs-on: ${{ inputs.os }}
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
env:
|
env:
|
||||||
OPENSSL_VER: 3.0.15
|
OPENSSL_VER: 3.0.18
|
||||||
PYTHONSTRICTEXTENSIONBUILD: 1
|
PYTHONSTRICTEXTENSIONBUILD: 1
|
||||||
TERM: linux
|
TERM: linux
|
||||||
steps:
|
steps:
|
||||||
|
|
|
||||||
9
.github/workflows/tail-call.yml
vendored
9
.github/workflows/tail-call.yml
vendored
|
|
@ -58,7 +58,7 @@ jobs:
|
||||||
# runner: windows-2022
|
# runner: windows-2022
|
||||||
- target: x86_64-apple-darwin/clang
|
- target: x86_64-apple-darwin/clang
|
||||||
architecture: x86_64
|
architecture: x86_64
|
||||||
runner: macos-13
|
runner: macos-15-intel
|
||||||
- target: aarch64-apple-darwin/clang
|
- target: aarch64-apple-darwin/clang
|
||||||
architecture: aarch64
|
architecture: aarch64
|
||||||
runner: macos-14
|
runner: macos-14
|
||||||
|
|
@ -101,17 +101,10 @@ jobs:
|
||||||
set LLVMInstallDir=C:\Program Files\LLVM
|
set LLVMInstallDir=C:\Program Files\LLVM
|
||||||
./PCbuild/build.bat --tail-call-interp -p ${{ matrix.architecture }}
|
./PCbuild/build.bat --tail-call-interp -p ${{ matrix.architecture }}
|
||||||
|
|
||||||
# The `find` line is required as a result of https://github.com/actions/runner-images/issues/9966.
|
|
||||||
# This is a bug in the macOS runner image where the pre-installed Python is installed in the same
|
|
||||||
# directory as the Homebrew Python, which causes the build to fail for macos-13. This line removes
|
|
||||||
# the symlink to the pre-installed Python so that the Homebrew Python is used instead.
|
|
||||||
# Note: when a new LLVM is released, the homebrew installation directory changes, so the builds will fail.
|
|
||||||
# We either need to upgrade LLVM or change the directory being pointed to.
|
|
||||||
- name: Native macOS (release)
|
- name: Native macOS (release)
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
brew update
|
brew update
|
||||||
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
|
|
||||||
brew install llvm@${{ matrix.llvm }}
|
brew install llvm@${{ matrix.llvm }}
|
||||||
export SDKROOT="$(xcrun --show-sdk-path)"
|
export SDKROOT="$(xcrun --show-sdk-path)"
|
||||||
export PATH="/usr/local/opt/llvm@${{ matrix.llvm }}/bin:$PATH"
|
export PATH="/usr/local/opt/llvm@${{ matrix.llvm }}/bin:$PATH"
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,10 @@ repos:
|
||||||
name: Run Ruff (lint) on Tools/peg_generator/
|
name: Run Ruff (lint) on Tools/peg_generator/
|
||||||
args: [--exit-non-zero-on-fix, --config=Tools/peg_generator/.ruff.toml]
|
args: [--exit-non-zero-on-fix, --config=Tools/peg_generator/.ruff.toml]
|
||||||
files: ^Tools/peg_generator/
|
files: ^Tools/peg_generator/
|
||||||
|
- id: ruff-check
|
||||||
|
name: Run Ruff (lint) on Tools/wasm/
|
||||||
|
args: [--exit-non-zero-on-fix, --config=Tools/wasm/.ruff.toml]
|
||||||
|
files: ^Tools/wasm/
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
name: Run Ruff (format) on Doc/
|
name: Run Ruff (format) on Doc/
|
||||||
args: [--check]
|
args: [--check]
|
||||||
|
|
@ -34,6 +38,10 @@ repos:
|
||||||
name: Run Ruff (format) on Tools/build/check_warnings.py
|
name: Run Ruff (format) on Tools/build/check_warnings.py
|
||||||
args: [--check, --config=Tools/build/.ruff.toml]
|
args: [--check, --config=Tools/build/.ruff.toml]
|
||||||
files: ^Tools/build/check_warnings.py
|
files: ^Tools/build/check_warnings.py
|
||||||
|
- id: ruff-format
|
||||||
|
name: Run Ruff (format) on Tools/wasm/
|
||||||
|
args: [--check, --config=Tools/wasm/.ruff.toml]
|
||||||
|
files: ^Tools/wasm/
|
||||||
|
|
||||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||||
rev: 25.9.0
|
rev: 25.9.0
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import argparse
|
import argparse
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
|
|
@ -184,10 +185,16 @@ def make_build_python(context):
|
||||||
run(["make", "-j", str(os.cpu_count())])
|
run(["make", "-j", str(os.cpu_count())])
|
||||||
|
|
||||||
|
|
||||||
|
# To create new builds of these dependencies, usually all that's necessary is to
|
||||||
|
# push a tag to the cpython-android-source-deps repository, and GitHub Actions
|
||||||
|
# will do the rest.
|
||||||
|
#
|
||||||
|
# If you're a member of the Python core team, and you'd like to be able to push
|
||||||
|
# these tags yourself, please contact Malcolm Smith or Russell Keith-Magee.
|
||||||
def unpack_deps(host, prefix_dir):
|
def unpack_deps(host, prefix_dir):
|
||||||
os.chdir(prefix_dir)
|
os.chdir(prefix_dir)
|
||||||
deps_url = "https://github.com/beeware/cpython-android-source-deps/releases/download"
|
deps_url = "https://github.com/beeware/cpython-android-source-deps/releases/download"
|
||||||
for name_ver in ["bzip2-1.0.8-3", "libffi-3.4.4-3", "openssl-3.0.15-4",
|
for name_ver in ["bzip2-1.0.8-3", "libffi-3.4.4-3", "openssl-3.0.18-0",
|
||||||
"sqlite-3.50.4-0", "xz-5.4.6-1", "zstd-1.5.7-1"]:
|
"sqlite-3.50.4-0", "xz-5.4.6-1", "zstd-1.5.7-1"]:
|
||||||
filename = f"{name_ver}-{host}.tar.gz"
|
filename = f"{name_ver}-{host}.tar.gz"
|
||||||
download(f"{deps_url}/{name_ver}/{filename}")
|
download(f"{deps_url}/{name_ver}/{filename}")
|
||||||
|
|
@ -546,27 +553,33 @@ async def gradle_task(context):
|
||||||
task_prefix = "connected"
|
task_prefix = "connected"
|
||||||
env["ANDROID_SERIAL"] = context.connected
|
env["ANDROID_SERIAL"] = context.connected
|
||||||
|
|
||||||
if context.command:
|
if context.ci_mode:
|
||||||
mode = "-c"
|
context.args[0:0] = [
|
||||||
module = context.command
|
# See _add_ci_python_opts in libregrtest/main.py.
|
||||||
else:
|
"-W", "error", "-bb", "-E",
|
||||||
mode = "-m"
|
|
||||||
module = context.module or "test"
|
# Randomization is disabled because order-dependent failures are
|
||||||
|
# much less likely to pass on a rerun in single-process mode.
|
||||||
|
"-m", "test",
|
||||||
|
f"--{context.ci_mode}-ci", "--single-process", "--no-randomize"
|
||||||
|
]
|
||||||
|
|
||||||
|
if not any(arg in context.args for arg in ["-c", "-m"]):
|
||||||
|
context.args[0:0] = ["-m", "test"]
|
||||||
|
|
||||||
args = [
|
args = [
|
||||||
gradlew, "--console", "plain", f"{task_prefix}DebugAndroidTest",
|
gradlew, "--console", "plain", f"{task_prefix}DebugAndroidTest",
|
||||||
] + [
|
] + [
|
||||||
# Build-time properties
|
f"-P{name}={value}"
|
||||||
f"-Ppython.{name}={value}"
|
|
||||||
for name, value in [
|
for name, value in [
|
||||||
("sitePackages", context.site_packages), ("cwd", context.cwd)
|
("python.sitePackages", context.site_packages),
|
||||||
] if value
|
("python.cwd", context.cwd),
|
||||||
] + [
|
(
|
||||||
# Runtime properties
|
"android.testInstrumentationRunnerArguments.pythonArgs",
|
||||||
f"-Pandroid.testInstrumentationRunnerArguments.python{name}={value}"
|
json.dumps(context.args),
|
||||||
for name, value in [
|
),
|
||||||
("Mode", mode), ("Module", module), ("Args", join_command(context.args))
|
]
|
||||||
] if value
|
if value
|
||||||
]
|
]
|
||||||
if context.verbose >= 2:
|
if context.verbose >= 2:
|
||||||
args.append("--info")
|
args.append("--info")
|
||||||
|
|
@ -734,15 +747,14 @@ def ci(context):
|
||||||
else:
|
else:
|
||||||
with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir:
|
with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir:
|
||||||
print("::group::Tests")
|
print("::group::Tests")
|
||||||
|
|
||||||
# Prove the package is self-contained by using it to run the tests.
|
# Prove the package is self-contained by using it to run the tests.
|
||||||
shutil.unpack_archive(package_path, temp_dir)
|
shutil.unpack_archive(package_path, temp_dir)
|
||||||
|
launcher_args = [
|
||||||
# Randomization is disabled because order-dependent failures are
|
"--managed", "maxVersion", "-v", f"--{context.ci_mode}-ci"
|
||||||
# much less likely to pass on a rerun in single-process mode.
|
]
|
||||||
launcher_args = ["--managed", "maxVersion", "-v"]
|
|
||||||
test_args = ["--fast-ci", "--single-process", "--no-randomize"]
|
|
||||||
run(
|
run(
|
||||||
["./android.py", "test", *launcher_args, "--", *test_args],
|
["./android.py", "test", *launcher_args],
|
||||||
cwd=temp_dir
|
cwd=temp_dir
|
||||||
)
|
)
|
||||||
print("::endgroup::")
|
print("::endgroup::")
|
||||||
|
|
@ -825,18 +837,11 @@ def add_parser(*args, **kwargs):
|
||||||
test.add_argument(
|
test.add_argument(
|
||||||
"--cwd", metavar="DIR", type=abspath,
|
"--cwd", metavar="DIR", type=abspath,
|
||||||
help="Directory to copy as the app's working directory.")
|
help="Directory to copy as the app's working directory.")
|
||||||
|
|
||||||
mode_group = test.add_mutually_exclusive_group()
|
|
||||||
mode_group.add_argument(
|
|
||||||
"-c", dest="command", help="Execute the given Python code.")
|
|
||||||
mode_group.add_argument(
|
|
||||||
"-m", dest="module", help="Execute the module with the given name.")
|
|
||||||
test.epilog = (
|
|
||||||
"If neither -c nor -m are passed, the default is '-m test', which will "
|
|
||||||
"run Python's own test suite.")
|
|
||||||
test.add_argument(
|
test.add_argument(
|
||||||
"args", nargs="*", help=f"Arguments to add to sys.argv. "
|
"args", nargs="*", help=f"Python command-line arguments. "
|
||||||
f"Separate them from {SCRIPT_NAME}'s own arguments with `--`.")
|
f"Separate them from {SCRIPT_NAME}'s own arguments with `--`. "
|
||||||
|
f"If neither -c nor -m are included, `-m test` will be prepended, "
|
||||||
|
f"which will run Python's own test suite.")
|
||||||
|
|
||||||
# Package arguments.
|
# Package arguments.
|
||||||
for subcommand in [package, ci]:
|
for subcommand in [package, ci]:
|
||||||
|
|
@ -844,6 +849,16 @@ def add_parser(*args, **kwargs):
|
||||||
"-g", action="store_true", default=False, dest="debug",
|
"-g", action="store_true", default=False, dest="debug",
|
||||||
help="Include debug information in package")
|
help="Include debug information in package")
|
||||||
|
|
||||||
|
# CI arguments
|
||||||
|
for subcommand in [test, ci]:
|
||||||
|
group = subcommand.add_mutually_exclusive_group(required=subcommand is ci)
|
||||||
|
group.add_argument(
|
||||||
|
"--fast-ci", action="store_const", dest="ci_mode", const="fast",
|
||||||
|
help="Add test arguments for GitHub Actions")
|
||||||
|
group.add_argument(
|
||||||
|
"--slow-ci", action="store_const", dest="ci_mode", const="slow",
|
||||||
|
help="Add test arguments for buildbots")
|
||||||
|
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ class PythonSuite {
|
||||||
val status = PythonTestRunner(
|
val status = PythonTestRunner(
|
||||||
InstrumentationRegistry.getInstrumentation().targetContext
|
InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
).run(
|
).run(
|
||||||
InstrumentationRegistry.getArguments()
|
InstrumentationRegistry.getArguments().getString("pythonArgs")!!,
|
||||||
)
|
)
|
||||||
assertEquals(0, status)
|
assertEquals(0, status)
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
@ -15,6 +16,13 @@ static void throw_runtime_exception(JNIEnv *env, const char *message) {
|
||||||
message);
|
message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void throw_errno(JNIEnv *env, const char *error_prefix) {
|
||||||
|
char error_message[1024];
|
||||||
|
snprintf(error_message, sizeof(error_message),
|
||||||
|
"%s: %s", error_prefix, strerror(errno));
|
||||||
|
throw_runtime_exception(env, error_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- Stdio redirection ------------------------------------------------------
|
// --- Stdio redirection ------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -95,10 +103,7 @@ JNIEXPORT void JNICALL Java_org_python_testbed_PythonTestRunner_redirectStdioToL
|
||||||
for (StreamInfo *si = STREAMS; si->file; si++) {
|
for (StreamInfo *si = STREAMS; si->file; si++) {
|
||||||
char *error_prefix;
|
char *error_prefix;
|
||||||
if ((error_prefix = redirect_stream(si))) {
|
if ((error_prefix = redirect_stream(si))) {
|
||||||
char error_message[1024];
|
throw_errno(env, error_prefix);
|
||||||
snprintf(error_message, sizeof(error_message),
|
|
||||||
"%s: %s", error_prefix, strerror(errno));
|
|
||||||
throw_runtime_exception(env, error_message);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -107,13 +112,38 @@ JNIEXPORT void JNICALL Java_org_python_testbed_PythonTestRunner_redirectStdioToL
|
||||||
|
|
||||||
// --- Python initialization ---------------------------------------------------
|
// --- Python initialization ---------------------------------------------------
|
||||||
|
|
||||||
static PyStatus set_config_string(
|
static char *init_signals() {
|
||||||
JNIEnv *env, PyConfig *config, wchar_t **config_str, jstring value
|
// 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.
|
||||||
const char *value_utf8 = (*env)->GetStringUTFChars(env, value, NULL);
|
// (https://cs.android.com/android/platform/superproject/+/android14-qpr3-release:art/runtime/signal_catcher.cc).
|
||||||
PyStatus status = PyConfig_SetBytesString(config, config_str, value_utf8);
|
// That thread's functionality is only useful for debugging the JVM, so disabling
|
||||||
(*env)->ReleaseStringUTFChars(env, value, value_utf8);
|
// it should not weaken the tests.
|
||||||
return status;
|
//
|
||||||
|
// 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.
|
||||||
|
sigset_t set;
|
||||||
|
if (sigemptyset(&set)) {
|
||||||
|
return "sigemptyset";
|
||||||
|
}
|
||||||
|
if (sigaddset(&set, SIGUSR1)) {
|
||||||
|
return "sigaddset";
|
||||||
|
}
|
||||||
|
if ((errno = pthread_sigmask(SIG_UNBLOCK, &set, NULL))) {
|
||||||
|
return "pthread_sigmask";
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void throw_status(JNIEnv *env, PyStatus status) {
|
static void throw_status(JNIEnv *env, PyStatus status) {
|
||||||
|
|
@ -121,27 +151,47 @@ static void throw_status(JNIEnv *env, PyStatus status) {
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT int JNICALL Java_org_python_testbed_PythonTestRunner_runPython(
|
JNIEXPORT int JNICALL Java_org_python_testbed_PythonTestRunner_runPython(
|
||||||
JNIEnv *env, jobject obj, jstring home, jstring runModule
|
JNIEnv *env, jobject obj, jstring home, jarray args
|
||||||
) {
|
) {
|
||||||
|
const char *home_utf8 = (*env)->GetStringUTFChars(env, home, NULL);
|
||||||
|
char cwd[PATH_MAX];
|
||||||
|
snprintf(cwd, sizeof(cwd), "%s/%s", home_utf8, "cwd");
|
||||||
|
if (chdir(cwd)) {
|
||||||
|
throw_errno(env, "chdir");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *error_prefix;
|
||||||
|
if ((error_prefix = init_signals())) {
|
||||||
|
throw_errno(env, error_prefix);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
PyConfig config;
|
PyConfig config;
|
||||||
PyStatus status;
|
PyStatus status;
|
||||||
PyConfig_InitIsolatedConfig(&config);
|
PyConfig_InitPythonConfig(&config);
|
||||||
|
|
||||||
status = set_config_string(env, &config, &config.home, home);
|
jsize argc = (*env)->GetArrayLength(env, args);
|
||||||
if (PyStatus_Exception(status)) {
|
const char *argv[argc + 1];
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
jobject arg = (*env)->GetObjectArrayElement(env, args, i);
|
||||||
|
argv[i] = (*env)->GetStringUTFChars(env, arg, NULL);
|
||||||
|
}
|
||||||
|
argv[argc] = NULL;
|
||||||
|
|
||||||
|
// PyConfig_SetBytesArgv "must be called before other methods, since the
|
||||||
|
// preinitialization configuration depends on command line arguments"
|
||||||
|
if (PyStatus_Exception(status = PyConfig_SetBytesArgv(&config, argc, (char**)argv))) {
|
||||||
throw_status(env, status);
|
throw_status(env, status);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = set_config_string(env, &config, &config.run_module, runModule);
|
status = PyConfig_SetBytesString(&config, &config.home, home_utf8);
|
||||||
if (PyStatus_Exception(status)) {
|
if (PyStatus_Exception(status)) {
|
||||||
throw_status(env, status);
|
throw_status(env, status);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some tests generate SIGPIPE and SIGXFSZ, which should be ignored.
|
|
||||||
config.install_signal_handlers = 1;
|
|
||||||
|
|
||||||
status = Py_InitializeFromConfig(&config);
|
status = Py_InitializeFromConfig(&config);
|
||||||
if (PyStatus_Exception(status)) {
|
if (PyStatus_Exception(status)) {
|
||||||
throw_status(env, status);
|
throw_status(env, status);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import android.os.*
|
||||||
import android.system.Os
|
import android.system.Os
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.*
|
import androidx.appcompat.app.*
|
||||||
|
import org.json.JSONArray
|
||||||
import java.io.*
|
import java.io.*
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -15,30 +16,25 @@ class MainActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
val status = PythonTestRunner(this).run("-m", "test", "-W -uall")
|
val status = PythonTestRunner(this).run("""["-m", "test", "-W", "-uall"]""")
|
||||||
findViewById<TextView>(R.id.tvHello).text = "Exit status $status"
|
findViewById<TextView>(R.id.tvHello).text = "Exit status $status"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PythonTestRunner(val context: Context) {
|
class PythonTestRunner(val context: Context) {
|
||||||
fun run(instrumentationArgs: Bundle) = run(
|
|
||||||
instrumentationArgs.getString("pythonMode")!!,
|
|
||||||
instrumentationArgs.getString("pythonModule")!!,
|
|
||||||
instrumentationArgs.getString("pythonArgs") ?: "",
|
|
||||||
)
|
|
||||||
|
|
||||||
/** Run Python.
|
/** Run Python.
|
||||||
*
|
*
|
||||||
* @param mode Either "-c" or "-m".
|
* @param args Python command-line, encoded as JSON.
|
||||||
* @param module Python statements for "-c" mode, or a module name for
|
|
||||||
* "-m" mode.
|
|
||||||
* @param args Arguments to add to sys.argv. Will be parsed by `shlex.split`.
|
|
||||||
* @return The Python exit status: zero on success, nonzero on failure. */
|
* @return The Python exit status: zero on success, nonzero on failure. */
|
||||||
fun run(mode: String, module: String, args: String) : Int {
|
fun run(args: String) : Int {
|
||||||
Os.setenv("PYTHON_MODE", mode, true)
|
// We leave argument 0 as an empty string, which is a placeholder for the
|
||||||
Os.setenv("PYTHON_MODULE", module, true)
|
// executable name in embedded mode.
|
||||||
Os.setenv("PYTHON_ARGS", args, true)
|
val argsJsonArray = JSONArray(args)
|
||||||
|
val argsStringArray = Array<String>(argsJsonArray.length() + 1) { it -> ""}
|
||||||
|
for (i in 0..<argsJsonArray.length()) {
|
||||||
|
argsStringArray[i + 1] = argsJsonArray.getString(i)
|
||||||
|
}
|
||||||
|
|
||||||
// Python needs this variable to help it find the temporary directory,
|
// Python needs this variable to help it find the temporary directory,
|
||||||
// but Android only sets it on API level 33 and later.
|
// but Android only sets it on API level 33 and later.
|
||||||
|
|
@ -47,10 +43,7 @@ class PythonTestRunner(val context: Context) {
|
||||||
val pythonHome = extractAssets()
|
val pythonHome = extractAssets()
|
||||||
System.loadLibrary("main_activity")
|
System.loadLibrary("main_activity")
|
||||||
redirectStdioToLogcat()
|
redirectStdioToLogcat()
|
||||||
|
return runPython(pythonHome.toString(), argsStringArray)
|
||||||
// The main module is in src/main/python. We don't simply call it
|
|
||||||
// "main", as that could clash with third-party test code.
|
|
||||||
return runPython(pythonHome.toString(), "android_testbed_main")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractAssets() : File {
|
private fun extractAssets() : File {
|
||||||
|
|
@ -59,6 +52,13 @@ class PythonTestRunner(val context: Context) {
|
||||||
throw RuntimeException("Failed to delete $pythonHome")
|
throw RuntimeException("Failed to delete $pythonHome")
|
||||||
}
|
}
|
||||||
extractAssetDir("python", context.filesDir)
|
extractAssetDir("python", context.filesDir)
|
||||||
|
|
||||||
|
// Empty directories are lost in the asset packing/unpacking process.
|
||||||
|
val cwd = File(pythonHome, "cwd")
|
||||||
|
if (!cwd.exists()) {
|
||||||
|
cwd.mkdir()
|
||||||
|
}
|
||||||
|
|
||||||
return pythonHome
|
return pythonHome
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,5 +88,5 @@ class PythonTestRunner(val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private external fun redirectStdioToLogcat()
|
private external fun redirectStdioToLogcat()
|
||||||
private external fun runPython(home: String, runModule: String) : Int
|
private external fun runPython(home: String, args: Array<String>) : Int
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import os
|
|
||||||
import runpy
|
|
||||||
import shlex
|
|
||||||
import signal
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# Some tests use SIGUSR1, but that's blocked by default in an Android app in
|
|
||||||
# order to make it available to `sigwait` in the Signal Catcher thread.
|
|
||||||
# (https://cs.android.com/android/platform/superproject/+/android14-qpr3-release:art/runtime/signal_catcher.cc).
|
|
||||||
# That thread's functionality is only useful for debugging the JVM, so disabling
|
|
||||||
# it should not weaken the tests.
|
|
||||||
#
|
|
||||||
# There's no safe way of stopping the thread completely (#123982), but simply
|
|
||||||
# unblocking SIGUSR1 is enough to fix most tests.
|
|
||||||
#
|
|
||||||
# However, in tests that generate multiple different signals in quick
|
|
||||||
# succession, it's possible for SIGUSR1 to arrive while the main thread is busy
|
|
||||||
# running the C-level handler for a different signal. In that case, the SIGUSR1
|
|
||||||
# may be sent to the Signal Catcher thread instead, which will generate a log
|
|
||||||
# message containing the text "reacting to signal".
|
|
||||||
#
|
|
||||||
# Such tests may need to be changed in one of the following ways:
|
|
||||||
# * Use a signal other than SIGUSR1 (e.g. test_stress_delivery_simultaneous in
|
|
||||||
# test_signal.py).
|
|
||||||
# * Send the signal to a specific thread rather than the whole process (e.g.
|
|
||||||
# test_signals in test_threadsignals.py.
|
|
||||||
signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGUSR1])
|
|
||||||
|
|
||||||
mode = os.environ["PYTHON_MODE"]
|
|
||||||
module = os.environ["PYTHON_MODULE"]
|
|
||||||
sys.argv[1:] = shlex.split(os.environ["PYTHON_ARGS"])
|
|
||||||
|
|
||||||
cwd = f"{sys.prefix}/cwd"
|
|
||||||
if not os.path.exists(cwd):
|
|
||||||
# Empty directories are lost in the asset packing/unpacking process.
|
|
||||||
os.mkdir(cwd)
|
|
||||||
os.chdir(cwd)
|
|
||||||
|
|
||||||
if mode == "-c":
|
|
||||||
# In -c mode, sys.path starts with an empty string, which means whatever the current
|
|
||||||
# working directory is at the moment of each import.
|
|
||||||
sys.path.insert(0, "")
|
|
||||||
exec(module, {})
|
|
||||||
elif mode == "-m":
|
|
||||||
sys.path.insert(0, os.getcwd())
|
|
||||||
runpy.run_module(module, run_name="__main__", alter_sys=True)
|
|
||||||
else:
|
|
||||||
raise ValueError(f"unknown mode: {mode}")
|
|
||||||
|
|
@ -312,11 +312,18 @@ def unpack_deps(
|
||||||
On iOS, as a safety mechanism, any dynamic libraries will be purged from
|
On iOS, as a safety mechanism, any dynamic libraries will be purged from
|
||||||
the unpacked dependencies.
|
the unpacked dependencies.
|
||||||
"""
|
"""
|
||||||
|
# To create new builds of these dependencies, usually all that's necessary
|
||||||
|
# is to push a tag to the cpython-apple-source-deps repository, and GitHub
|
||||||
|
# Actions will do the rest.
|
||||||
|
#
|
||||||
|
# If you're a member of the Python core team, and you'd like to be able to
|
||||||
|
# push these tags yourself, please contact Malcolm Smith or Russell
|
||||||
|
# Keith-Magee.
|
||||||
deps_url = "https://github.com/beeware/cpython-apple-source-deps/releases/download"
|
deps_url = "https://github.com/beeware/cpython-apple-source-deps/releases/download"
|
||||||
for name_ver in [
|
for name_ver in [
|
||||||
"BZip2-1.0.8-2",
|
"BZip2-1.0.8-2",
|
||||||
"libFFI-3.4.7-2",
|
"libFFI-3.4.7-2",
|
||||||
"OpenSSL-3.0.17-1",
|
"OpenSSL-3.0.18-1",
|
||||||
"XZ-5.6.4-2",
|
"XZ-5.6.4-2",
|
||||||
"mpdecimal-4.0.0-2",
|
"mpdecimal-4.0.0-2",
|
||||||
"zstd-1.5.7-1",
|
"zstd-1.5.7-1",
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ venv:
|
||||||
fi
|
fi
|
||||||
|
|
||||||
.PHONY: dist-no-html
|
.PHONY: dist-no-html
|
||||||
dist-no-html: dist-text dist-pdf dist-epub dist-texinfo
|
dist-no-html: dist-text dist-epub dist-texinfo
|
||||||
|
|
||||||
.PHONY: dist
|
.PHONY: dist
|
||||||
dist:
|
dist:
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,7 @@ Create, Finish, Discard
|
||||||
writer size to *size*. The caller is responsible to write *size*
|
writer size to *size*. The caller is responsible to write *size*
|
||||||
bytes using :c:func:`PyBytesWriter_GetData`.
|
bytes using :c:func:`PyBytesWriter_GetData`.
|
||||||
|
|
||||||
On error, set an exception and return NULL.
|
On error, set an exception and return ``NULL``.
|
||||||
|
|
||||||
*size* must be positive or zero.
|
*size* must be positive or zero.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,9 @@ There are a few functions specific to Python functions.
|
||||||
|
|
||||||
.. versionadded:: 3.12
|
.. versionadded:: 3.12
|
||||||
|
|
||||||
|
- ``PyFunction_PYFUNC_EVENT_MODIFY_QUALNAME``
|
||||||
|
|
||||||
|
.. versionadded:: 3.15
|
||||||
|
|
||||||
.. c:type:: int (*PyFunction_WatchCallback)(PyFunction_WatchEvent event, PyFunctionObject *func, PyObject *new_value)
|
.. c:type:: int (*PyFunction_WatchCallback)(PyFunction_WatchEvent event, PyFunctionObject *func, PyObject *new_value)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1113,7 +1113,7 @@ code, or when embedding the Python interpreter:
|
||||||
This function is safe to call without an :term:`attached thread state`; it
|
This function is safe to call without an :term:`attached thread state`; it
|
||||||
will simply return ``NULL`` indicating that there was no prior thread state.
|
will simply return ``NULL`` indicating that there was no prior thread state.
|
||||||
|
|
||||||
.. seealso:
|
.. seealso::
|
||||||
:c:func:`PyEval_ReleaseThread`
|
:c:func:`PyEval_ReleaseThread`
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
@ -1124,6 +1124,19 @@ code, or when embedding the Python interpreter:
|
||||||
The following functions use thread-local storage, and are not compatible
|
The following functions use thread-local storage, and are not compatible
|
||||||
with sub-interpreters:
|
with sub-interpreters:
|
||||||
|
|
||||||
|
.. c:type:: PyGILState_STATE
|
||||||
|
|
||||||
|
The type of the value returned by :c:func:`PyGILState_Ensure` and passed to
|
||||||
|
:c:func:`PyGILState_Release`.
|
||||||
|
|
||||||
|
.. c:enumerator:: PyGILState_LOCKED
|
||||||
|
|
||||||
|
The GIL was already held when :c:func:`PyGILState_Ensure` was called.
|
||||||
|
|
||||||
|
.. c:enumerator:: PyGILState_UNLOCKED
|
||||||
|
|
||||||
|
The GIL was not held when :c:func:`PyGILState_Ensure` was called.
|
||||||
|
|
||||||
.. c:function:: PyGILState_STATE PyGILState_Ensure()
|
.. c:function:: PyGILState_STATE PyGILState_Ensure()
|
||||||
|
|
||||||
Ensure that the current thread is ready to call the Python C API regardless
|
Ensure that the current thread is ready to call the Python C API regardless
|
||||||
|
|
@ -1174,12 +1187,12 @@ with sub-interpreters:
|
||||||
made on the main thread. This is mainly a helper/diagnostic function.
|
made on the main thread. This is mainly a helper/diagnostic function.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
This function does not account for :term:`thread states <thread state>` created
|
This function may return non-``NULL`` even when the :term:`thread state`
|
||||||
by something other than :c:func:`PyGILState_Ensure` (such as :c:func:`PyThreadState_New`).
|
is detached.
|
||||||
Prefer :c:func:`PyThreadState_Get` or :c:func:`PyThreadState_GetUnchecked`
|
Prefer :c:func:`PyThreadState_Get` or :c:func:`PyThreadState_GetUnchecked`
|
||||||
for most cases.
|
for most cases.
|
||||||
|
|
||||||
.. seealso: :c:func:`PyThreadState_Get``
|
.. seealso:: :c:func:`PyThreadState_Get`
|
||||||
|
|
||||||
.. c:function:: int PyGILState_Check()
|
.. c:function:: int PyGILState_Check()
|
||||||
|
|
||||||
|
|
@ -1278,11 +1291,11 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
|
||||||
must be :term:`attached <attached thread state>`
|
must be :term:`attached <attached thread state>`
|
||||||
|
|
||||||
.. versionchanged:: 3.9
|
.. versionchanged:: 3.9
|
||||||
This function now calls the :c:member:`PyThreadState.on_delete` callback.
|
This function now calls the :c:member:`!PyThreadState.on_delete` callback.
|
||||||
Previously, that happened in :c:func:`PyThreadState_Delete`.
|
Previously, that happened in :c:func:`PyThreadState_Delete`.
|
||||||
|
|
||||||
.. versionchanged:: 3.13
|
.. versionchanged:: 3.13
|
||||||
The :c:member:`PyThreadState.on_delete` callback was removed.
|
The :c:member:`!PyThreadState.on_delete` callback was removed.
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: void PyThreadState_Delete(PyThreadState *tstate)
|
.. c:function:: void PyThreadState_Delete(PyThreadState *tstate)
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,19 @@ Tuple Objects
|
||||||
or ``NULL`` with an exception set on failure.
|
or ``NULL`` with an exception set on failure.
|
||||||
|
|
||||||
|
|
||||||
|
.. c:function:: PyObject* PyTuple_FromArray(PyObject *const *array, Py_ssize_t size)
|
||||||
|
|
||||||
|
Create a tuple of *size* items and copy references from *array* to the new
|
||||||
|
tuple.
|
||||||
|
|
||||||
|
*array* can be NULL if *size* is ``0``.
|
||||||
|
|
||||||
|
On success, return a new reference.
|
||||||
|
On error, set an exception and return ``NULL``.
|
||||||
|
|
||||||
|
.. versionadded:: next
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: PyObject* PyTuple_Pack(Py_ssize_t n, ...)
|
.. c:function:: PyObject* PyTuple_Pack(Py_ssize_t n, ...)
|
||||||
|
|
||||||
Return a new tuple object of size *n*,
|
Return a new tuple object of size *n*,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ although there is currently no date scheduled for their removal.
|
||||||
|
|
||||||
* :mod:`builtins`:
|
* :mod:`builtins`:
|
||||||
|
|
||||||
* ``bool(NotImplemented)``.
|
|
||||||
* Generators: ``throw(type, exc, tb)`` and ``athrow(type, exc, tb)``
|
* Generators: ``throw(type, exc, tb)`` and ``athrow(type, exc, tb)``
|
||||||
signature is deprecated: use ``throw(exc)`` and ``athrow(exc)`` instead,
|
signature is deprecated: use ``throw(exc)`` and ``athrow(exc)`` instead,
|
||||||
the single argument signature.
|
the single argument signature.
|
||||||
|
|
|
||||||
|
|
@ -316,13 +316,14 @@ StreamWriter
|
||||||
If that fails, the data is queued in an internal write buffer until it can be
|
If that fails, the data is queued in an internal write buffer until it can be
|
||||||
sent.
|
sent.
|
||||||
|
|
||||||
|
The *data* buffer should be a bytes, bytearray, or C-contiguous one-dimensional
|
||||||
|
memoryview object.
|
||||||
|
|
||||||
The method should be used along with the ``drain()`` method::
|
The method should be used along with the ``drain()`` method::
|
||||||
|
|
||||||
stream.write(data)
|
stream.write(data)
|
||||||
await stream.drain()
|
await stream.drain()
|
||||||
|
|
||||||
.. note::
|
|
||||||
The *data* buffer should be a C contiguous one-dimensional :term:`bytes-like object <bytes-like object>`.
|
|
||||||
|
|
||||||
.. method:: writelines(data)
|
.. method:: writelines(data)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@ Collections Abstract Base Classes -- Detailed Descriptions
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
In CPython, generator-based coroutines (:term:`generators <generator>`
|
In CPython, generator-based coroutines (:term:`generators <generator>`
|
||||||
decorated with :func:`@types.coroutine <types.coroutine>`) are
|
decorated with :deco:`types.coroutine`) are
|
||||||
*awaitables*, even though they do not have an :meth:`~object.__await__` method.
|
*awaitables*, even though they do not have an :meth:`~object.__await__` method.
|
||||||
Using ``isinstance(gencoro, Awaitable)`` for them will return ``False``.
|
Using ``isinstance(gencoro, Awaitable)`` for them will return ``False``.
|
||||||
Use :func:`inspect.isawaitable` to detect them.
|
Use :func:`inspect.isawaitable` to detect them.
|
||||||
|
|
@ -354,7 +354,7 @@ Collections Abstract Base Classes -- Detailed Descriptions
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
In CPython, generator-based coroutines (:term:`generators <generator>`
|
In CPython, generator-based coroutines (:term:`generators <generator>`
|
||||||
decorated with :func:`@types.coroutine <types.coroutine>`) are
|
decorated with :deco:`types.coroutine`) are
|
||||||
*awaitables*, even though they do not have an :meth:`~object.__await__` method.
|
*awaitables*, even though they do not have an :meth:`~object.__await__` method.
|
||||||
Using ``isinstance(gencoro, Coroutine)`` for them will return ``False``.
|
Using ``isinstance(gencoro, Coroutine)`` for them will return ``False``.
|
||||||
Use :func:`inspect.isawaitable` to detect them.
|
Use :func:`inspect.isawaitable` to detect them.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
The :mod:`!compression` package
|
The :mod:`!compression` package
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
|
.. module:: compression
|
||||||
|
|
||||||
.. versionadded:: 3.14
|
.. versionadded:: 3.14
|
||||||
|
|
||||||
The :mod:`!compression` package contains the canonical compression modules
|
The :mod:`!compression` package contains the canonical compression modules
|
||||||
|
|
|
||||||
|
|
@ -327,10 +327,10 @@ Functions and classes provided:
|
||||||
.. function:: redirect_stdout(new_target)
|
.. function:: redirect_stdout(new_target)
|
||||||
|
|
||||||
Context manager for temporarily redirecting :data:`sys.stdout` to
|
Context manager for temporarily redirecting :data:`sys.stdout` to
|
||||||
another file or file-like object.
|
another :term:`file object`.
|
||||||
|
|
||||||
This tool adds flexibility to existing functions or classes whose output
|
This tool adds flexibility to existing functions or classes whose output
|
||||||
is hardwired to stdout.
|
is hardwired to :data:`sys.stdout`.
|
||||||
|
|
||||||
For example, the output of :func:`help` normally is sent to *sys.stdout*.
|
For example, the output of :func:`help` normally is sent to *sys.stdout*.
|
||||||
You can capture that output in a string by redirecting the output to an
|
You can capture that output in a string by redirecting the output to an
|
||||||
|
|
@ -366,8 +366,8 @@ Functions and classes provided:
|
||||||
|
|
||||||
.. function:: redirect_stderr(new_target)
|
.. function:: redirect_stderr(new_target)
|
||||||
|
|
||||||
Similar to :func:`~contextlib.redirect_stdout` but redirecting
|
Similar to :func:`~contextlib.redirect_stdout` but redirecting the global
|
||||||
:data:`sys.stderr` to another file or file-like object.
|
:data:`sys.stderr` to another :term:`file object`.
|
||||||
|
|
||||||
This context manager is :ref:`reentrant <reentrant-cms>`.
|
This context manager is :ref:`reentrant <reentrant-cms>`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ being deprecated in Python 3.11. The removal was decided in :pep:`594`.
|
||||||
|
|
||||||
Applications can use the :mod:`hashlib` module from the standard library.
|
Applications can use the :mod:`hashlib` module from the standard library.
|
||||||
Other possible replacements are third-party libraries from PyPI:
|
Other possible replacements are third-party libraries from PyPI:
|
||||||
:pypi:`legacycrypt`, :pypi:`bcrypt`, :pypi:`argon2-cffi`, or :pypi:`passlib`.
|
:pypi:`legacycrypt`, :pypi:`bcrypt`, or :pypi:`argon2-cffi`.
|
||||||
These are not supported or maintained by the Python core team.
|
These are not supported or maintained by the Python core team.
|
||||||
|
|
||||||
The last version of Python that provided the :mod:`!crypt` module was
|
The last version of Python that provided the :mod:`!crypt` module was
|
||||||
|
|
|
||||||
|
|
@ -317,7 +317,7 @@ Module contents
|
||||||
:func:`!field`, then the class attribute for this field will be
|
:func:`!field`, then the class attribute for this field will be
|
||||||
replaced by the specified *default* value. If *default* is not
|
replaced by the specified *default* value. If *default* is not
|
||||||
provided, then the class attribute will be deleted. The intent is
|
provided, then the class attribute will be deleted. The intent is
|
||||||
that after the :func:`@dataclass <dataclass>` decorator runs, the class
|
that after the :deco:`dataclass` decorator runs, the class
|
||||||
attributes will all contain the default values for the fields, just
|
attributes will all contain the default values for the fields, just
|
||||||
as if the default value itself were specified. For example,
|
as if the default value itself were specified. For example,
|
||||||
after::
|
after::
|
||||||
|
|
@ -427,7 +427,7 @@ Module contents
|
||||||
:data:`typing.Any` is used for ``type``. The values of *init*,
|
:data:`typing.Any` is used for ``type``. The values of *init*,
|
||||||
*repr*, *eq*, *order*, *unsafe_hash*, *frozen*,
|
*repr*, *eq*, *order*, *unsafe_hash*, *frozen*,
|
||||||
*match_args*, *kw_only*, *slots*, and *weakref_slot* have
|
*match_args*, *kw_only*, *slots*, and *weakref_slot* have
|
||||||
the same meaning as they do in :func:`@dataclass <dataclass>`.
|
the same meaning as they do in :deco:`dataclass`.
|
||||||
|
|
||||||
If *module* is defined, the :attr:`!__module__` attribute
|
If *module* is defined, the :attr:`!__module__` attribute
|
||||||
of the dataclass is set to that value.
|
of the dataclass is set to that value.
|
||||||
|
|
@ -435,12 +435,12 @@ Module contents
|
||||||
|
|
||||||
The *decorator* parameter is a callable that will be used to create the dataclass.
|
The *decorator* parameter is a callable that will be used to create the dataclass.
|
||||||
It should take the class object as a first argument and the same keyword arguments
|
It should take the class object as a first argument and the same keyword arguments
|
||||||
as :func:`@dataclass <dataclass>`. By default, the :func:`@dataclass <dataclass>`
|
as :deco:`dataclass`. By default, the :deco:`dataclass`
|
||||||
function is used.
|
function is used.
|
||||||
|
|
||||||
This function is not strictly required, because any Python
|
This function is not strictly required, because any Python
|
||||||
mechanism for creating a new class with :attr:`~object.__annotations__` can
|
mechanism for creating a new class with :attr:`~object.__annotations__` can
|
||||||
then apply the :func:`@dataclass <dataclass>` function to convert that class to
|
then apply the :deco:`dataclass` function to convert that class to
|
||||||
a dataclass. This function is provided as a convenience. For
|
a dataclass. This function is provided as a convenience. For
|
||||||
example::
|
example::
|
||||||
|
|
||||||
|
|
@ -569,7 +569,7 @@ Post-init processing
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
self.c = self.a + self.b
|
self.c = self.a + self.b
|
||||||
|
|
||||||
The :meth:`~object.__init__` method generated by :func:`@dataclass <dataclass>` does not call base
|
The :meth:`~object.__init__` method generated by :deco:`dataclass` does not call base
|
||||||
class :meth:`!__init__` methods. If the base class has an :meth:`!__init__` method
|
class :meth:`!__init__` methods. If the base class has an :meth:`!__init__` method
|
||||||
that has to be called, it is common to call this method in a
|
that has to be called, it is common to call this method in a
|
||||||
:meth:`__post_init__` method::
|
:meth:`__post_init__` method::
|
||||||
|
|
@ -599,7 +599,7 @@ parameters to :meth:`!__post_init__`. Also see the warning about how
|
||||||
Class variables
|
Class variables
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
One of the few places where :func:`@dataclass <dataclass>` actually inspects the type
|
One of the few places where :deco:`dataclass` actually inspects the type
|
||||||
of a field is to determine if a field is a class variable as defined
|
of a field is to determine if a field is a class variable as defined
|
||||||
in :pep:`526`. It does this by checking if the type of the field is
|
in :pep:`526`. It does this by checking if the type of the field is
|
||||||
:data:`typing.ClassVar`. If a field is a ``ClassVar``, it is excluded
|
:data:`typing.ClassVar`. If a field is a ``ClassVar``, it is excluded
|
||||||
|
|
@ -612,7 +612,7 @@ module-level :func:`fields` function.
|
||||||
Init-only variables
|
Init-only variables
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Another place where :func:`@dataclass <dataclass>` inspects a type annotation is to
|
Another place where :deco:`dataclass` inspects a type annotation is to
|
||||||
determine if a field is an init-only variable. It does this by seeing
|
determine if a field is an init-only variable. It does this by seeing
|
||||||
if the type of a field is of type :class:`InitVar`. If a field
|
if the type of a field is of type :class:`InitVar`. If a field
|
||||||
is an :class:`InitVar`, it is considered a pseudo-field called an init-only
|
is an :class:`InitVar`, it is considered a pseudo-field called an init-only
|
||||||
|
|
@ -646,7 +646,7 @@ Frozen instances
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
It is not possible to create truly immutable Python objects. However,
|
It is not possible to create truly immutable Python objects. However,
|
||||||
by passing ``frozen=True`` to the :func:`@dataclass <dataclass>` decorator you can
|
by passing ``frozen=True`` to the :deco:`dataclass` decorator you can
|
||||||
emulate immutability. In that case, dataclasses will add
|
emulate immutability. In that case, dataclasses will add
|
||||||
:meth:`~object.__setattr__` and :meth:`~object.__delattr__` methods to the class. These
|
:meth:`~object.__setattr__` and :meth:`~object.__delattr__` methods to the class. These
|
||||||
methods will raise a :exc:`FrozenInstanceError` when invoked.
|
methods will raise a :exc:`FrozenInstanceError` when invoked.
|
||||||
|
|
@ -662,7 +662,7 @@ must use :meth:`!object.__setattr__`.
|
||||||
Inheritance
|
Inheritance
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
When the dataclass is being created by the :func:`@dataclass <dataclass>` decorator,
|
When the dataclass is being created by the :deco:`dataclass` decorator,
|
||||||
it looks through all of the class's base classes in reverse MRO (that
|
it looks through all of the class's base classes in reverse MRO (that
|
||||||
is, starting at :class:`object`) and, for each dataclass that it finds,
|
is, starting at :class:`object`) and, for each dataclass that it finds,
|
||||||
adds the fields from that base class to an ordered mapping of fields.
|
adds the fields from that base class to an ordered mapping of fields.
|
||||||
|
|
@ -786,7 +786,7 @@ for :attr:`!x` when creating a class instance will share the same copy
|
||||||
of :attr:`!x`. Because dataclasses just use normal Python class
|
of :attr:`!x`. Because dataclasses just use normal Python class
|
||||||
creation they also share this behavior. There is no general way
|
creation they also share this behavior. There is no general way
|
||||||
for Data Classes to detect this condition. Instead, the
|
for Data Classes to detect this condition. Instead, the
|
||||||
:func:`@dataclass <dataclass>` decorator will raise a :exc:`ValueError` if it
|
:deco:`dataclass` decorator will raise a :exc:`ValueError` if it
|
||||||
detects an unhashable default parameter. The assumption is that if
|
detects an unhashable default parameter. The assumption is that if
|
||||||
a value is unhashable, it is mutable. This is a partial solution,
|
a value is unhashable, it is mutable. This is a partial solution,
|
||||||
but it does protect against many common errors.
|
but it does protect against many common errors.
|
||||||
|
|
@ -820,7 +820,7 @@ default value have the following special behaviors:
|
||||||
:meth:`~object.__get__` or :meth:`!__set__` method is called rather than returning or
|
:meth:`~object.__get__` or :meth:`!__set__` method is called rather than returning or
|
||||||
overwriting the descriptor object.
|
overwriting the descriptor object.
|
||||||
|
|
||||||
* To determine whether a field contains a default value, :func:`@dataclass <dataclass>`
|
* To determine whether a field contains a default value, :deco:`dataclass`
|
||||||
will call the descriptor's :meth:`!__get__` method using its class access
|
will call the descriptor's :meth:`!__get__` method using its class access
|
||||||
form: ``descriptor.__get__(obj=None, type=cls)``. If the
|
form: ``descriptor.__get__(obj=None, type=cls)``. If the
|
||||||
descriptor returns a value in this case, it will be used as the
|
descriptor returns a value in this case, it will be used as the
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ diffs. For comparing directories and files, see also, the :mod:`filecmp` module.
|
||||||
*linejunk*: A function that accepts a single string argument, and returns
|
*linejunk*: A function that accepts a single string argument, and returns
|
||||||
true if the string is junk, or false if not. The default is ``None``. There
|
true if the string is junk, or false if not. The default is ``None``. There
|
||||||
is also a module-level function :func:`IS_LINE_JUNK`, which filters out lines
|
is also a module-level function :func:`IS_LINE_JUNK`, which filters out lines
|
||||||
without visible characters, except for at most one pound character (``'#'``)
|
without visible characters, except for at most one hash character (``'#'``)
|
||||||
-- however the underlying :class:`SequenceMatcher` class does a dynamic
|
-- however the underlying :class:`SequenceMatcher` class does a dynamic
|
||||||
analysis of which lines are so frequent as to constitute noise, and this
|
analysis of which lines are so frequent as to constitute noise, and this
|
||||||
usually works better than using this function.
|
usually works better than using this function.
|
||||||
|
|
|
||||||
|
|
@ -690,7 +690,7 @@ The :mod:`functools` module defines the following functions:
|
||||||
return not arg
|
return not arg
|
||||||
|
|
||||||
``@singledispatchmethod`` supports nesting with other decorators such as
|
``@singledispatchmethod`` supports nesting with other decorators such as
|
||||||
:func:`@classmethod<classmethod>`. Note that to allow for
|
:deco:`classmethod`. Note that to allow for
|
||||||
``dispatcher.register``, ``singledispatchmethod`` must be the *outer most*
|
``dispatcher.register``, ``singledispatchmethod`` must be the *outer most*
|
||||||
decorator. Here is the ``Negator`` class with the ``neg`` methods bound to
|
decorator. Here is the ``Negator`` class with the ``neg`` methods bound to
|
||||||
the class, rather than an instance of the class::
|
the class, rather than an instance of the class::
|
||||||
|
|
@ -712,8 +712,7 @@ The :mod:`functools` module defines the following functions:
|
||||||
return not arg
|
return not arg
|
||||||
|
|
||||||
The same pattern can be used for other similar decorators:
|
The same pattern can be used for other similar decorators:
|
||||||
:func:`@staticmethod<staticmethod>`,
|
:deco:`staticmethod`, :deco:`~abc.abstractmethod`, and others.
|
||||||
:func:`@abstractmethod<abc.abstractmethod>`, and others.
|
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,13 +72,12 @@ for example, a package and its resources can be imported from a zip file using
|
||||||
|
|
||||||
.. versionadded:: 3.9
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
.. versionchanged:: 3.12
|
.. deprecated-removed:: 3.12 3.15
|
||||||
*package* parameter was renamed to *anchor*. *anchor* can now
|
*package* parameter was renamed to *anchor*. *anchor* can now be a
|
||||||
be a non-package module and if omitted will default to the caller's
|
non-package module and if omitted will default to the caller's module.
|
||||||
module. *package* is still accepted for compatibility but will raise
|
*package* is no longer accepted since Python 3.15. Consider passing the
|
||||||
a :exc:`DeprecationWarning`. Consider passing the anchor positionally or
|
anchor positionally or using ``importlib_resources >= 5.10`` for a
|
||||||
using ``importlib_resources >= 5.10`` for a compatible interface
|
compatible interface on older Pythons.
|
||||||
on older Pythons.
|
|
||||||
|
|
||||||
.. function:: as_file(traversable)
|
.. function:: as_file(traversable)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -216,8 +216,8 @@ process and user.
|
||||||
|
|
||||||
You can delete items in this mapping to unset environment variables.
|
You can delete items in this mapping to unset environment variables.
|
||||||
:func:`unsetenv` will be called automatically when an item is deleted from
|
:func:`unsetenv` will be called automatically when an item is deleted from
|
||||||
:data:`os.environ`, and when one of the :meth:`pop` or :meth:`clear` methods is
|
:data:`os.environ`, and when one of the :meth:`~dict.pop` or
|
||||||
called.
|
:meth:`~dict.clear` methods is called.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
|
|
@ -430,8 +430,8 @@ process and user.
|
||||||
associated with the effective user id of the process; the group access
|
associated with the effective user id of the process; the group access
|
||||||
list may change over the lifetime of the process, it is not affected by
|
list may change over the lifetime of the process, it is not affected by
|
||||||
calls to :func:`setgroups`, and its length is not limited to 16. The
|
calls to :func:`setgroups`, and its length is not limited to 16. The
|
||||||
deployment target value, :const:`MACOSX_DEPLOYMENT_TARGET`, can be
|
deployment target value can be obtained with
|
||||||
obtained with :func:`sysconfig.get_config_var`.
|
:func:`sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') <sysconfig.get_config_var>`.
|
||||||
|
|
||||||
|
|
||||||
.. function:: getlogin()
|
.. function:: getlogin()
|
||||||
|
|
@ -2606,10 +2606,10 @@ features:
|
||||||
|
|
||||||
Create a filesystem node (file, device special file or named pipe) named
|
Create a filesystem node (file, device special file or named pipe) named
|
||||||
*path*. *mode* specifies both the permissions to use and the type of node
|
*path*. *mode* specifies both the permissions to use and the type of node
|
||||||
to be created, being combined (bitwise OR) with one of ``stat.S_IFREG``,
|
to be created, being combined (bitwise OR) with one of :const:`stat.S_IFREG`,
|
||||||
``stat.S_IFCHR``, ``stat.S_IFBLK``, and ``stat.S_IFIFO`` (those constants are
|
:const:`stat.S_IFCHR`, :const:`stat.S_IFBLK`, and :const:`stat.S_IFIFO`.
|
||||||
available in :mod:`stat`). For ``stat.S_IFCHR`` and ``stat.S_IFBLK``,
|
For :const:`stat.S_IFCHR` and :const:`stat.S_IFBLK`, *device* defines the
|
||||||
*device* defines the newly created device special file (probably using
|
newly created device special file (probably using
|
||||||
:func:`os.makedev`), otherwise it is ignored.
|
:func:`os.makedev`), otherwise it is ignored.
|
||||||
|
|
||||||
This function can also support :ref:`paths relative to directory descriptors
|
This function can also support :ref:`paths relative to directory descriptors
|
||||||
|
|
@ -2627,13 +2627,13 @@ features:
|
||||||
.. function:: major(device, /)
|
.. function:: major(device, /)
|
||||||
|
|
||||||
Extract the device major number from a raw device number (usually the
|
Extract the device major number from a raw device number (usually the
|
||||||
:attr:`st_dev` or :attr:`st_rdev` field from :c:struct:`stat`).
|
:attr:`~stat_result.st_dev` or :attr:`~stat_result.st_rdev` field from :c:struct:`stat`).
|
||||||
|
|
||||||
|
|
||||||
.. function:: minor(device, /)
|
.. function:: minor(device, /)
|
||||||
|
|
||||||
Extract the device minor number from a raw device number (usually the
|
Extract the device minor number from a raw device number (usually the
|
||||||
:attr:`st_dev` or :attr:`st_rdev` field from :c:struct:`stat`).
|
:attr:`~stat_result.st_dev` or :attr:`~stat_result.st_rdev` field from :c:struct:`stat`).
|
||||||
|
|
||||||
|
|
||||||
.. function:: makedev(major, minor, /)
|
.. function:: makedev(major, minor, /)
|
||||||
|
|
@ -3364,8 +3364,8 @@ features:
|
||||||
|
|
||||||
.. versionchanged:: 3.8
|
.. versionchanged:: 3.8
|
||||||
On Windows, the :attr:`st_mode` member now identifies special
|
On Windows, the :attr:`st_mode` member now identifies special
|
||||||
files as :const:`S_IFCHR`, :const:`S_IFIFO` or :const:`S_IFBLK`
|
files as :const:`~stat.S_IFCHR`, :const:`~stat.S_IFIFO` or
|
||||||
as appropriate.
|
:const:`~stat.S_IFBLK` as appropriate.
|
||||||
|
|
||||||
.. versionchanged:: 3.12
|
.. versionchanged:: 3.12
|
||||||
On Windows, :attr:`st_ctime` is deprecated. Eventually, it will
|
On Windows, :attr:`st_ctime` is deprecated. Eventually, it will
|
||||||
|
|
@ -4285,10 +4285,10 @@ to be ignored.
|
||||||
|
|
||||||
.. function:: abort()
|
.. function:: abort()
|
||||||
|
|
||||||
Generate a :const:`SIGABRT` signal to the current process. On Unix, the default
|
Generate a :const:`~signal.SIGABRT` signal to the current process. On Unix, the default
|
||||||
behavior is to produce a core dump; on Windows, the process immediately returns
|
behavior is to produce a core dump; on Windows, the process immediately returns
|
||||||
an exit code of ``3``. Be aware that calling this function will not call the
|
an exit code of ``3``. Be aware that calling this function will not call the
|
||||||
Python signal handler registered for :const:`SIGABRT` with
|
Python signal handler registered for :const:`~signal.SIGABRT` with
|
||||||
:func:`signal.signal`.
|
:func:`signal.signal`.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -4592,6 +4592,8 @@ written in Python, such as a mail server's external command delivery program.
|
||||||
master end of the pseudo-terminal. For a more portable approach, use the
|
master end of the pseudo-terminal. For a more portable approach, use the
|
||||||
:mod:`pty` module. If an error occurs :exc:`OSError` is raised.
|
:mod:`pty` module. If an error occurs :exc:`OSError` is raised.
|
||||||
|
|
||||||
|
The returned file descriptor *fd* is :ref:`non-inheritable <fd_inheritance>`.
|
||||||
|
|
||||||
.. audit-event:: os.forkpty "" os.forkpty
|
.. audit-event:: os.forkpty "" os.forkpty
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
@ -4608,6 +4610,9 @@ written in Python, such as a mail server's external command delivery program.
|
||||||
threads, this now raises a :exc:`DeprecationWarning`. See the
|
threads, this now raises a :exc:`DeprecationWarning`. See the
|
||||||
longer explanation on :func:`os.fork`.
|
longer explanation on :func:`os.fork`.
|
||||||
|
|
||||||
|
.. versionchanged:: next
|
||||||
|
The returned file descriptor is now made non-inheritable.
|
||||||
|
|
||||||
.. availability:: Unix, not WASI, not Android, not iOS.
|
.. availability:: Unix, not WASI, not Android, not iOS.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,14 @@ The :mod:`pty` module defines the following functions:
|
||||||
file descriptor connected to the child's controlling terminal (and also to the
|
file descriptor connected to the child's controlling terminal (and also to the
|
||||||
child's standard input and output).
|
child's standard input and output).
|
||||||
|
|
||||||
|
The returned file descriptor *fd* is :ref:`non-inheritable <fd_inheritance>`.
|
||||||
|
|
||||||
.. warning:: On macOS the use of this function is unsafe when mixed with using
|
.. warning:: On macOS the use of this function is unsafe when mixed with using
|
||||||
higher-level system APIs, and that includes using :mod:`urllib.request`.
|
higher-level system APIs, and that includes using :mod:`urllib.request`.
|
||||||
|
|
||||||
|
.. versionchanged:: next
|
||||||
|
The returned file descriptor is now made non-inheritable.
|
||||||
|
|
||||||
|
|
||||||
.. function:: openpty()
|
.. function:: openpty()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -205,10 +205,26 @@ The variables defined in the :mod:`signal` module are:
|
||||||
|
|
||||||
.. availability:: Unix.
|
.. availability:: Unix.
|
||||||
|
|
||||||
|
.. data:: SIGPROF
|
||||||
|
|
||||||
|
Profiling timer expired.
|
||||||
|
|
||||||
|
.. availability:: Unix.
|
||||||
|
|
||||||
|
.. data:: SIGQUIT
|
||||||
|
|
||||||
|
Terminal quit signal.
|
||||||
|
|
||||||
|
.. availability:: Unix.
|
||||||
|
|
||||||
.. data:: SIGSEGV
|
.. data:: SIGSEGV
|
||||||
|
|
||||||
Segmentation fault: invalid memory reference.
|
Segmentation fault: invalid memory reference.
|
||||||
|
|
||||||
|
.. data:: SIGSTOP
|
||||||
|
|
||||||
|
Stop executing (cannot be caught or ignored).
|
||||||
|
|
||||||
.. data:: SIGSTKFLT
|
.. data:: SIGSTKFLT
|
||||||
|
|
||||||
Stack fault on coprocessor. The Linux kernel does not raise this signal: it
|
Stack fault on coprocessor. The Linux kernel does not raise this signal: it
|
||||||
|
|
@ -237,6 +253,12 @@ The variables defined in the :mod:`signal` module are:
|
||||||
|
|
||||||
.. availability:: Unix.
|
.. availability:: Unix.
|
||||||
|
|
||||||
|
.. data:: SIGVTALRM
|
||||||
|
|
||||||
|
Virtual timer expired.
|
||||||
|
|
||||||
|
.. availability:: Unix.
|
||||||
|
|
||||||
.. data:: SIGWINCH
|
.. data:: SIGWINCH
|
||||||
|
|
||||||
Window resize signal.
|
Window resize signal.
|
||||||
|
|
@ -248,7 +270,7 @@ The variables defined in the :mod:`signal` module are:
|
||||||
All the signal numbers are defined symbolically. For example, the hangup signal
|
All the signal numbers are defined symbolically. For example, the hangup signal
|
||||||
is defined as :const:`signal.SIGHUP`; the variable names are identical to the
|
is defined as :const:`signal.SIGHUP`; the variable names are identical to the
|
||||||
names used in C programs, as found in ``<signal.h>``. The Unix man page for
|
names used in C programs, as found in ``<signal.h>``. The Unix man page for
|
||||||
':c:func:`signal`' lists the existing signals (on some systems this is
|
'``signal``' lists the existing signals (on some systems this is
|
||||||
:manpage:`signal(2)`, on others the list is in :manpage:`signal(7)`). Note that
|
:manpage:`signal(2)`, on others the list is in :manpage:`signal(7)`). Note that
|
||||||
not all systems define the same set of signal names; only those names defined by
|
not all systems define the same set of signal names; only those names defined by
|
||||||
the system are defined by this module.
|
the system are defined by this module.
|
||||||
|
|
@ -644,9 +666,8 @@ The :mod:`signal` module defines the following functions:
|
||||||
*sigset*.
|
*sigset*.
|
||||||
|
|
||||||
The return value is an object representing the data contained in the
|
The return value is an object representing the data contained in the
|
||||||
:c:type:`siginfo_t` structure, namely: :attr:`si_signo`, :attr:`si_code`,
|
``siginfo_t`` structure, namely: ``si_signo``, ``si_code``,
|
||||||
:attr:`si_errno`, :attr:`si_pid`, :attr:`si_uid`, :attr:`si_status`,
|
``si_errno``, ``si_pid``, ``si_uid``, ``si_status``, ``si_band``.
|
||||||
:attr:`si_band`.
|
|
||||||
|
|
||||||
.. availability:: Unix.
|
.. availability:: Unix.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -354,9 +354,8 @@ Random generation
|
||||||
.. function:: RAND_status()
|
.. function:: RAND_status()
|
||||||
|
|
||||||
Return ``True`` if the SSL pseudo-random number generator has been seeded
|
Return ``True`` if the SSL pseudo-random number generator has been seeded
|
||||||
with 'enough' randomness, and ``False`` otherwise. You can use
|
with 'enough' randomness, and ``False`` otherwise. Use :func:`ssl.RAND_add`
|
||||||
:func:`ssl.RAND_egd` and :func:`ssl.RAND_add` to increase the randomness of
|
to increase the randomness of the pseudo-random number generator.
|
||||||
the pseudo-random number generator.
|
|
||||||
|
|
||||||
.. function:: RAND_add(bytes, entropy, /)
|
.. function:: RAND_add(bytes, entropy, /)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ Template strings
|
||||||
Template strings are a mechanism for custom string processing.
|
Template strings are a mechanism for custom string processing.
|
||||||
They have the full flexibility of Python's :ref:`f-strings`,
|
They have the full flexibility of Python's :ref:`f-strings`,
|
||||||
but return a :class:`Template` instance that gives access
|
but return a :class:`Template` instance that gives access
|
||||||
to the static and interpolated (in curly braces) parts of a string
|
to the static and interpolated (in curly brackets) parts of a string
|
||||||
*before* they are combined.
|
*before* they are combined.
|
||||||
|
|
||||||
To write a t-string, use a ``'t'`` prefix instead of an ``'f'``, like so:
|
To write a t-string, use a ``'t'`` prefix instead of an ``'f'``, like so:
|
||||||
|
|
@ -258,13 +258,16 @@ Types
|
||||||
.. attribute:: expression
|
.. attribute:: expression
|
||||||
:type: str
|
:type: str
|
||||||
|
|
||||||
The text of a valid Python expression, or an empty string.
|
For interpolations created by t-string literals, :attr:`!expression`
|
||||||
|
is the expression text found inside the curly brackets (``{`` & ``}``),
|
||||||
|
including any whitespace, excluding the curly brackets themselves,
|
||||||
|
and ending before the first ``!``, ``:``, or ``=`` if any is present.
|
||||||
|
For manually created interpolations, :attr:`!expression` is the arbitrary
|
||||||
|
string provided when constructing the interpolation instance.
|
||||||
|
|
||||||
The :attr:`.expression` is the original text of the
|
We recommend using valid Python expressions or the empty string for the
|
||||||
interpolation's Python expression, if the interpolation was created
|
``expression`` field of manually created :class:`!Interpolation`
|
||||||
from a t-string literal. Developers creating interpolations manually
|
instances, although this is not enforced at runtime.
|
||||||
should either set this to an empty string or choose a suitable valid
|
|
||||||
Python expression.
|
|
||||||
|
|
||||||
>>> t'{1 + 2}'.interpolations[0].expression
|
>>> t'{1 + 2}'.interpolations[0].expression
|
||||||
'1 + 2'
|
'1 + 2'
|
||||||
|
|
|
||||||
|
|
@ -649,7 +649,7 @@ functions.
|
||||||
|
|
||||||
If specified, *env* must provide any variables required for the program to
|
If specified, *env* must provide any variables required for the program to
|
||||||
execute. On Windows, in order to run a `side-by-side assembly`_ the
|
execute. On Windows, in order to run a `side-by-side assembly`_ the
|
||||||
specified *env* **must** include a valid :envvar:`SystemRoot`.
|
specified *env* **must** include a valid ``%SystemRoot%``.
|
||||||
|
|
||||||
.. _side-by-side assembly: https://en.wikipedia.org/wiki/Side-by-Side_Assembly
|
.. _side-by-side assembly: https://en.wikipedia.org/wiki/Side-by-Side_Assembly
|
||||||
|
|
||||||
|
|
@ -1473,7 +1473,7 @@ handling consistency are valid for these functions.
|
||||||
|
|
||||||
Return ``(exitcode, output)`` of executing *cmd* in a shell.
|
Return ``(exitcode, output)`` of executing *cmd* in a shell.
|
||||||
|
|
||||||
Execute the string *cmd* in a shell with :meth:`Popen.check_output` and
|
Execute the string *cmd* in a shell with :func:`check_output` and
|
||||||
return a 2-tuple ``(exitcode, output)``.
|
return a 2-tuple ``(exitcode, output)``.
|
||||||
*encoding* and *errors* are used to decode output;
|
*encoding* and *errors* are used to decode output;
|
||||||
see the notes on :ref:`frequently-used-arguments` for more details.
|
see the notes on :ref:`frequently-used-arguments` for more details.
|
||||||
|
|
|
||||||
|
|
@ -382,6 +382,9 @@ Other functions
|
||||||
|
|
||||||
Examples of returned values:
|
Examples of returned values:
|
||||||
|
|
||||||
|
- linux-x86_64
|
||||||
|
- linux-aarch64
|
||||||
|
- solaris-2.6-sun4u
|
||||||
|
|
||||||
Windows:
|
Windows:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1390,7 +1390,7 @@ These can be used as types in annotations. They all support subscription using
|
||||||
Using ``Annotated[T, x]`` as an annotation still allows for static
|
Using ``Annotated[T, x]`` as an annotation still allows for static
|
||||||
typechecking of ``T``, as type checkers will simply ignore the metadata ``x``.
|
typechecking of ``T``, as type checkers will simply ignore the metadata ``x``.
|
||||||
In this way, ``Annotated`` differs from the
|
In this way, ``Annotated`` differs from the
|
||||||
:func:`@no_type_check <no_type_check>` decorator, which can also be used for
|
:deco:`no_type_check` decorator, which can also be used for
|
||||||
adding annotations outside the scope of the typing system, but
|
adding annotations outside the scope of the typing system, but
|
||||||
completely disables typechecking for a function or class.
|
completely disables typechecking for a function or class.
|
||||||
|
|
||||||
|
|
@ -2269,7 +2269,7 @@ without the dedicated syntax, as documented below.
|
||||||
|
|
||||||
.. attribute:: __module__
|
.. attribute:: __module__
|
||||||
|
|
||||||
The module in which the type alias was defined::
|
The name of the module in which the type alias was defined::
|
||||||
|
|
||||||
>>> type Alias = int
|
>>> type Alias = int
|
||||||
>>> Alias.__module__
|
>>> Alias.__module__
|
||||||
|
|
@ -2449,7 +2449,7 @@ types.
|
||||||
|
|
||||||
.. attribute:: __module__
|
.. attribute:: __module__
|
||||||
|
|
||||||
The module in which the new type is defined.
|
The name of the module in which the new type is defined.
|
||||||
|
|
||||||
.. attribute:: __name__
|
.. attribute:: __name__
|
||||||
|
|
||||||
|
|
@ -2815,7 +2815,7 @@ Protocols
|
||||||
---------
|
---------
|
||||||
|
|
||||||
The following protocols are provided by the :mod:`!typing` module. All are decorated
|
The following protocols are provided by the :mod:`!typing` module. All are decorated
|
||||||
with :func:`@runtime_checkable <runtime_checkable>`.
|
with :deco:`runtime_checkable`.
|
||||||
|
|
||||||
.. class:: SupportsAbs
|
.. class:: SupportsAbs
|
||||||
|
|
||||||
|
|
@ -2996,7 +2996,7 @@ Functions and decorators
|
||||||
The presence of ``@dataclass_transform()`` tells a static type checker that the
|
The presence of ``@dataclass_transform()`` tells a static type checker that the
|
||||||
decorated object performs runtime "magic" that
|
decorated object performs runtime "magic" that
|
||||||
transforms a class in a similar way to
|
transforms a class in a similar way to
|
||||||
:func:`@dataclasses.dataclass <dataclasses.dataclass>`.
|
:deco:`dataclasses.dataclass`.
|
||||||
|
|
||||||
Example usage with a decorator function:
|
Example usage with a decorator function:
|
||||||
|
|
||||||
|
|
@ -3034,14 +3034,14 @@ Functions and decorators
|
||||||
|
|
||||||
The ``CustomerModel`` classes defined above will
|
The ``CustomerModel`` classes defined above will
|
||||||
be treated by type checkers similarly to classes created with
|
be treated by type checkers similarly to classes created with
|
||||||
:func:`@dataclasses.dataclass <dataclasses.dataclass>`.
|
:deco:`dataclasses.dataclass`.
|
||||||
For example, type checkers will assume these classes have
|
For example, type checkers will assume these classes have
|
||||||
``__init__`` methods that accept ``id`` and ``name``.
|
``__init__`` methods that accept ``id`` and ``name``.
|
||||||
|
|
||||||
The decorated class, metaclass, or function may accept the following bool
|
The decorated class, metaclass, or function may accept the following bool
|
||||||
arguments which type checkers will assume have the same effect as they
|
arguments which type checkers will assume have the same effect as they
|
||||||
would have on the
|
would have on the
|
||||||
:func:`@dataclasses.dataclass<dataclasses.dataclass>` decorator: ``init``,
|
:deco:`dataclasses.dataclass` decorator: ``init``,
|
||||||
``eq``, ``order``, ``unsafe_hash``, ``frozen``, ``match_args``,
|
``eq``, ``order``, ``unsafe_hash``, ``frozen``, ``match_args``,
|
||||||
``kw_only``, and ``slots``. It must be possible for the value of these
|
``kw_only``, and ``slots``. It must be possible for the value of these
|
||||||
arguments (``True`` or ``False``) to be statically evaluated.
|
arguments (``True`` or ``False``) to be statically evaluated.
|
||||||
|
|
@ -3169,12 +3169,12 @@ Functions and decorators
|
||||||
|
|
||||||
.. function:: get_overloads(func)
|
.. function:: get_overloads(func)
|
||||||
|
|
||||||
Return a sequence of :func:`@overload <overload>`-decorated definitions for
|
Return a sequence of :deco:`overload`-decorated definitions for
|
||||||
*func*.
|
*func*.
|
||||||
|
|
||||||
*func* is the function object for the implementation of the
|
*func* is the function object for the implementation of the
|
||||||
overloaded function. For example, given the definition of ``process`` in
|
overloaded function. For example, given the definition of ``process`` in
|
||||||
the documentation for :func:`@overload <overload>`,
|
the documentation for :deco:`overload`,
|
||||||
``get_overloads(process)`` will return a sequence of three function objects
|
``get_overloads(process)`` will return a sequence of three function objects
|
||||||
for the three defined overloads. If called on a function with no overloads,
|
for the three defined overloads. If called on a function with no overloads,
|
||||||
``get_overloads()`` returns an empty sequence.
|
``get_overloads()`` returns an empty sequence.
|
||||||
|
|
@ -3331,7 +3331,7 @@ Introspection helpers
|
||||||
If *globalns* or *localns* is not given, appropriate namespace
|
If *globalns* or *localns* is not given, appropriate namespace
|
||||||
dictionaries are inferred from *obj*.
|
dictionaries are inferred from *obj*.
|
||||||
* ``None`` is replaced with :class:`types.NoneType`.
|
* ``None`` is replaced with :class:`types.NoneType`.
|
||||||
* If :func:`@no_type_check <no_type_check>` has been applied to *obj*, an
|
* If :deco:`no_type_check` has been applied to *obj*, an
|
||||||
empty dictionary is returned.
|
empty dictionary is returned.
|
||||||
* If *obj* is a class ``C``, the function returns a dictionary that merges
|
* 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
|
annotations from ``C``'s base classes with those on ``C`` directly. This
|
||||||
|
|
|
||||||
|
|
@ -590,7 +590,7 @@ Available Functions
|
||||||
The deprecation message passed to the decorator is saved in the
|
The deprecation message passed to the decorator is saved in the
|
||||||
``__deprecated__`` attribute on the decorated object.
|
``__deprecated__`` attribute on the decorated object.
|
||||||
If applied to an overload, the decorator
|
If applied to an overload, the decorator
|
||||||
must be after the :func:`@overload <typing.overload>` decorator
|
must be after the :deco:`~typing.overload` decorator
|
||||||
for the attribute to exist on the overload as returned by
|
for the attribute to exist on the overload as returned by
|
||||||
:func:`typing.get_overloads`.
|
:func:`typing.get_overloads`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ earlier than 1.1.3; 1.1.3 has a `security vulnerability <https://zlib.net/zlib_f
|
||||||
|
|
||||||
zlib's functions have many options and often need to be used in a particular
|
zlib's functions have many options and often need to be used in a particular
|
||||||
order. This documentation doesn't attempt to cover all of the permutations;
|
order. This documentation doesn't attempt to cover all of the permutations;
|
||||||
consult the zlib manual at http://www.zlib.net/manual.html for authoritative
|
consult the `zlib manual <https://www.zlib.net/manual.html>`_ for authoritative
|
||||||
information.
|
information.
|
||||||
|
|
||||||
For reading and writing ``.gz`` files see the :mod:`gzip` module.
|
For reading and writing ``.gz`` files see the :mod:`gzip` module.
|
||||||
|
|
@ -340,6 +340,136 @@ Decompression objects support the following methods and attributes:
|
||||||
objects.
|
objects.
|
||||||
|
|
||||||
|
|
||||||
|
The following constants are available to configure compression and decompression
|
||||||
|
behavior:
|
||||||
|
|
||||||
|
.. data:: DEFLATED
|
||||||
|
|
||||||
|
The deflate compression method.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: MAX_WBITS
|
||||||
|
|
||||||
|
The maximum window size, expressed as a power of 2.
|
||||||
|
For example, if :const:`!MAX_WBITS` is ``15`` it results in a window size
|
||||||
|
of ``32 KiB``.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DEF_MEM_LEVEL
|
||||||
|
|
||||||
|
The default memory level for compression objects.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DEF_BUF_SIZE
|
||||||
|
|
||||||
|
The default buffer size for decompression operations.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_NO_COMPRESSION
|
||||||
|
|
||||||
|
Compression level ``0``.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_BEST_SPEED
|
||||||
|
|
||||||
|
Compression level ``1``.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_BEST_COMPRESSION
|
||||||
|
|
||||||
|
Compression level ``9``.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_DEFAULT_COMPRESSION
|
||||||
|
|
||||||
|
Default compression level (``-1``).
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_DEFAULT_STRATEGY
|
||||||
|
|
||||||
|
Default compression strategy, for normal data.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_FILTERED
|
||||||
|
|
||||||
|
Compression strategy for data produced by a filter (or predictor).
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_HUFFMAN_ONLY
|
||||||
|
|
||||||
|
Compression strategy that forces Huffman coding only.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_RLE
|
||||||
|
|
||||||
|
Compression strategy that limits match distances to one (run-length encoding).
|
||||||
|
|
||||||
|
This constant is only available if Python was compiled with zlib
|
||||||
|
1.2.0.1 or greater.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_FIXED
|
||||||
|
|
||||||
|
Compression strategy that prevents the use of dynamic Huffman codes.
|
||||||
|
|
||||||
|
This constant is only available if Python was compiled with zlib
|
||||||
|
1.2.2.2 or greater.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_NO_FLUSH
|
||||||
|
|
||||||
|
Flush mode ``0``. No special flushing behavior.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_PARTIAL_FLUSH
|
||||||
|
|
||||||
|
Flush mode ``1``. Flush as much output as possible.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_SYNC_FLUSH
|
||||||
|
|
||||||
|
Flush mode ``2``. All output is flushed and the output is aligned to a byte boundary.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_FULL_FLUSH
|
||||||
|
|
||||||
|
Flush mode ``3``. All output is flushed and the compression state is reset.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_FINISH
|
||||||
|
|
||||||
|
Flush mode ``4``. All pending input is processed, no more input is expected.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_BLOCK
|
||||||
|
|
||||||
|
Flush mode ``5``. A deflate block is completed and emitted.
|
||||||
|
|
||||||
|
This constant is only available if Python was compiled with zlib
|
||||||
|
1.2.2.2 or greater.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: Z_TREES
|
||||||
|
|
||||||
|
Flush mode ``6``, for inflate operations. Instructs inflate to return when
|
||||||
|
it gets to the next deflate block boundary.
|
||||||
|
|
||||||
|
This constant is only available if Python was compiled with zlib
|
||||||
|
1.2.3.4 or greater.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
|
|
||||||
Information about the version of the zlib library in use is available through
|
Information about the version of the zlib library in use is available through
|
||||||
the following constants:
|
the following constants:
|
||||||
|
|
||||||
|
|
@ -375,10 +505,10 @@ the following constants:
|
||||||
Module :mod:`gzip`
|
Module :mod:`gzip`
|
||||||
Reading and writing :program:`gzip`\ -format files.
|
Reading and writing :program:`gzip`\ -format files.
|
||||||
|
|
||||||
http://www.zlib.net
|
https://www.zlib.net
|
||||||
The zlib library home page.
|
The zlib library home page.
|
||||||
|
|
||||||
http://www.zlib.net/manual.html
|
https://www.zlib.net/manual.html
|
||||||
The zlib manual explains the semantics and usage of the library's many
|
The zlib manual explains the semantics and usage of the library's many
|
||||||
functions.
|
functions.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2558,7 +2558,7 @@ instance dictionary. In contrast, non-data descriptors can be overridden by
|
||||||
instances.
|
instances.
|
||||||
|
|
||||||
Python methods (including those decorated with
|
Python methods (including those decorated with
|
||||||
:func:`@staticmethod <staticmethod>` and :func:`@classmethod <classmethod>`) are
|
:deco:`staticmethod` and :deco:`classmethod`) are
|
||||||
implemented as non-data descriptors. Accordingly, instances can redefine and
|
implemented as non-data descriptors. Accordingly, instances can redefine and
|
||||||
override methods. This allows individual instances to acquire behaviors that
|
override methods. This allows individual instances to acquire behaviors that
|
||||||
differ from other instances of the same class.
|
differ from other instances of the same class.
|
||||||
|
|
@ -2993,7 +2993,7 @@ class method ``__class_getitem__()``.
|
||||||
|
|
||||||
When defined on a class, ``__class_getitem__()`` is automatically a class
|
When defined on a class, ``__class_getitem__()`` is automatically a class
|
||||||
method. As such, there is no need for it to be decorated with
|
method. As such, there is no need for it to be decorated with
|
||||||
:func:`@classmethod<classmethod>` when it is defined.
|
:deco:`classmethod` when it is defined.
|
||||||
|
|
||||||
|
|
||||||
The purpose of *__class_getitem__*
|
The purpose of *__class_getitem__*
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,76 @@ Lexical analysis
|
||||||
A Python program is read by a *parser*. Input to the parser is a stream of
|
A Python program is read by a *parser*. Input to the parser is a stream of
|
||||||
:term:`tokens <token>`, generated by the *lexical analyzer* (also known as
|
:term:`tokens <token>`, generated by the *lexical analyzer* (also known as
|
||||||
the *tokenizer*).
|
the *tokenizer*).
|
||||||
This chapter describes how the lexical analyzer breaks a file into tokens.
|
This chapter describes how the lexical analyzer produces these tokens.
|
||||||
|
|
||||||
Python reads program text as Unicode code points; the encoding of a source file
|
The lexical analyzer determines the program text's :ref:`encoding <encodings>`
|
||||||
can be given by an encoding declaration and defaults to UTF-8, see :pep:`3120`
|
(UTF-8 by default), and decodes the text into
|
||||||
for details. If the source file cannot be decoded, a :exc:`SyntaxError` is
|
:ref:`source characters <lexical-source-character>`.
|
||||||
raised.
|
If the text cannot be decoded, a :exc:`SyntaxError` is raised.
|
||||||
|
|
||||||
|
Next, the lexical analyzer uses the source characters to generate a stream of tokens.
|
||||||
|
The type of a generated token generally depends on the next source character to
|
||||||
|
be processed. Similarly, other special behavior of the analyzer depends on
|
||||||
|
the first source character that hasn't yet been processed.
|
||||||
|
The following table gives a quick summary of these source characters,
|
||||||
|
with links to sections that contain more information.
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Character
|
||||||
|
- Next token (or other relevant documentation)
|
||||||
|
|
||||||
|
* - * space
|
||||||
|
* tab
|
||||||
|
* formfeed
|
||||||
|
- * :ref:`Whitespace <whitespace>`
|
||||||
|
|
||||||
|
* - * CR, LF
|
||||||
|
- * :ref:`New line <line-structure>`
|
||||||
|
* :ref:`Indentation <indentation>`
|
||||||
|
|
||||||
|
* - * backslash (``\``)
|
||||||
|
- * :ref:`Explicit line joining <explicit-joining>`
|
||||||
|
* (Also significant in :ref:`string escape sequences <escape-sequences>`)
|
||||||
|
|
||||||
|
* - * hash (``#``)
|
||||||
|
- * :ref:`Comment <comments>`
|
||||||
|
|
||||||
|
* - * quote (``'``, ``"``)
|
||||||
|
- * :ref:`String literal <strings>`
|
||||||
|
|
||||||
|
* - * ASCII letter (``a``-``z``, ``A``-``Z``)
|
||||||
|
* non-ASCII character
|
||||||
|
- * :ref:`Name <identifiers>`
|
||||||
|
* Prefixed :ref:`string or bytes literal <strings>`
|
||||||
|
|
||||||
|
* - * underscore (``_``)
|
||||||
|
- * :ref:`Name <identifiers>`
|
||||||
|
* (Can also be part of :ref:`numeric literals <numbers>`)
|
||||||
|
|
||||||
|
* - * number (``0``-``9``)
|
||||||
|
- * :ref:`Numeric literal <numbers>`
|
||||||
|
|
||||||
|
* - * dot (``.``)
|
||||||
|
- * :ref:`Numeric literal <numbers>`
|
||||||
|
* :ref:`Operator <operators>`
|
||||||
|
|
||||||
|
* - * question mark (``?``)
|
||||||
|
* dollar (``$``)
|
||||||
|
*
|
||||||
|
.. (the following uses zero-width space characters to render
|
||||||
|
.. a literal backquote)
|
||||||
|
|
||||||
|
backquote (`````)
|
||||||
|
* control character
|
||||||
|
- * Error (outside string literals and comments)
|
||||||
|
|
||||||
|
* - * other printing character
|
||||||
|
- * :ref:`Operator or delimiter <operators>`
|
||||||
|
|
||||||
|
* - * end of file
|
||||||
|
- * :ref:`End marker <endmarker-token>`
|
||||||
|
|
||||||
|
|
||||||
.. _line-structure:
|
.. _line-structure:
|
||||||
|
|
@ -120,6 +184,8 @@ If an encoding is declared, the encoding name must be recognized by Python
|
||||||
encoding is used for all lexical analysis, including string literals, comments
|
encoding is used for all lexical analysis, including string literals, comments
|
||||||
and identifiers.
|
and identifiers.
|
||||||
|
|
||||||
|
.. _lexical-source-character:
|
||||||
|
|
||||||
All lexical analysis, including string literals, comments
|
All lexical analysis, including string literals, comments
|
||||||
and identifiers, works on Unicode text decoded using the source encoding.
|
and identifiers, works on Unicode text decoded using the source encoding.
|
||||||
Any Unicode code point, except the NUL control character, can appear in
|
Any Unicode code point, except the NUL control character, can appear in
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
Doc/c-api/descriptor.rst
|
Doc/c-api/descriptor.rst
|
||||||
Doc/c-api/float.rst
|
Doc/c-api/float.rst
|
||||||
Doc/c-api/init.rst
|
|
||||||
Doc/c-api/init_config.rst
|
Doc/c-api/init_config.rst
|
||||||
Doc/c-api/intro.rst
|
Doc/c-api/intro.rst
|
||||||
Doc/c-api/module.rst
|
Doc/c-api/module.rst
|
||||||
|
|
@ -30,12 +29,10 @@ Doc/library/profile.rst
|
||||||
Doc/library/pyexpat.rst
|
Doc/library/pyexpat.rst
|
||||||
Doc/library/resource.rst
|
Doc/library/resource.rst
|
||||||
Doc/library/select.rst
|
Doc/library/select.rst
|
||||||
Doc/library/signal.rst
|
|
||||||
Doc/library/smtplib.rst
|
Doc/library/smtplib.rst
|
||||||
Doc/library/socket.rst
|
Doc/library/socket.rst
|
||||||
Doc/library/ssl.rst
|
Doc/library/ssl.rst
|
||||||
Doc/library/stdtypes.rst
|
Doc/library/stdtypes.rst
|
||||||
Doc/library/subprocess.rst
|
|
||||||
Doc/library/termios.rst
|
Doc/library/termios.rst
|
||||||
Doc/library/test.rst
|
Doc/library/test.rst
|
||||||
Doc/library/tkinter.rst
|
Doc/library/tkinter.rst
|
||||||
|
|
@ -53,7 +50,6 @@ Doc/library/xml.sax.reader.rst
|
||||||
Doc/library/xml.sax.rst
|
Doc/library/xml.sax.rst
|
||||||
Doc/library/xmlrpc.client.rst
|
Doc/library/xmlrpc.client.rst
|
||||||
Doc/library/xmlrpc.server.rst
|
Doc/library/xmlrpc.server.rst
|
||||||
Doc/library/zlib.rst
|
|
||||||
Doc/whatsnew/2.4.rst
|
Doc/whatsnew/2.4.rst
|
||||||
Doc/whatsnew/2.5.rst
|
Doc/whatsnew/2.5.rst
|
||||||
Doc/whatsnew/2.6.rst
|
Doc/whatsnew/2.6.rst
|
||||||
|
|
|
||||||
|
|
@ -42,22 +42,22 @@ <h1>{% trans %}Download Python {{ dl_version }} documentation{% endtrans %}</h1>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% trans %}HTML{% endtrans %}</td>
|
<td>{% trans %}HTML{% endtrans %}</td>
|
||||||
<td>{% trans download_size="13" %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-html.zip">Download</a> (ca. {{ download_size }} MiB){% endtrans %}</td>
|
<td>{% trans %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-html.zip">Download</a>{% endtrans %}</td>
|
||||||
<td>{% trans download_size="8" %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-html.tar.bz2">Download</a> (ca. {{ download_size }} MiB){% endtrans %}</td>
|
<td>{% trans %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-html.tar.bz2">Download</a>{% endtrans %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% trans %}Plain text{% endtrans %}</td>
|
<td>{% trans %}Plain text{% endtrans %}</td>
|
||||||
<td>{% trans download_size="4" %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-text.zip">Download</a> (ca. {{ download_size }} MiB){% endtrans %}</td>
|
<td>{% trans %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-text.zip">Download</a>{% endtrans %}</td>
|
||||||
<td>{% trans download_size="3" %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-text.tar.bz2">Download</a> (ca. {{ download_size }} MiB){% endtrans %}</td>
|
<td>{% trans %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-text.tar.bz2">Download</a>{% endtrans %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% trans %}Texinfo{% endtrans %}</td>
|
<td>{% trans %}Texinfo{% endtrans %}</td>
|
||||||
<td>{% trans download_size="9" %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-texinfo.zip">Download</a> (ca. {{ download_size }} MiB){% endtrans %}</td>
|
<td>{% trans %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-texinfo.zip">Download</a>{% endtrans %}</td>
|
||||||
<td>{% trans download_size="7" %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-texinfo.tar.bz2">Download</a> (ca. {{ download_size }} MiB){% endtrans %}</td>
|
<td>{% trans %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-texinfo.tar.bz2">Download</a>{% endtrans %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% trans %}EPUB{% endtrans %}</td>
|
<td>{% trans %}EPUB{% endtrans %}</td>
|
||||||
<td>{% trans download_size="6" %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs.epub">Download</a> (ca. {{ download_size }} MiB){% endtrans %}</td>
|
<td>{% trans %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs.epub">Download</a>{% endtrans %}</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
@ -71,21 +71,13 @@ <h1>{% trans %}Download Python {{ dl_version }} documentation{% endtrans %}</h1>
|
||||||
and run <code>make dist-pdf</code> in the <code>Doc/</code> directory of a copy of the CPython repository.
|
and run <code>make dist-pdf</code> in the <code>Doc/</code> directory of a copy of the CPython repository.
|
||||||
{% endtrans %}</p>
|
{% endtrans %}</p>
|
||||||
|
|
||||||
|
<p>{% trans %}
|
||||||
<h2>{% trans %}Unpacking{% endtrans %}</h2>
|
See the <a href="https://docs.python.org/{{ version }}/archives/">directory listing</a>
|
||||||
|
for file sizes.{% endtrans %}</p>
|
||||||
<p>{% 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 <a href="https://infozip.sourceforge.net">Info-ZIP</a> unzip program can be
|
|
||||||
used to handle the ZIP archives if desired. The .tar.bz2 archives provide the
|
|
||||||
best compression and fastest download times.{% endtrans %}</p>
|
|
||||||
|
|
||||||
<p>{% 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 %}</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2>{% trans %}Problems{% endtrans %}</h2>
|
<h2>{% trans %}Problems{% endtrans %}</h2>
|
||||||
|
{% set bugs = pathto('bugs') %}
|
||||||
<p>{% trans %}If you have comments or suggestions for the Python documentation, please send
|
<p>{% trans bugs = bugs %}<a href="{{ bugs }}">Open an issue</a>
|
||||||
email to <a href="mailto:docs@python.org">docs@python.org</a>.{% endtrans %}</p>
|
if you have comments or suggestions for the Python documentation.{% endtrans %}</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -512,8 +512,12 @@ dictionary; this is also the way dictionaries are written on output.
|
||||||
The main operations on a dictionary are storing a value with some key and
|
The main operations on a dictionary are storing a value with some key and
|
||||||
extracting the value given the key. It is also possible to delete a key:value
|
extracting the value given the key. It is also possible to delete a key:value
|
||||||
pair with ``del``. If you store using a key that is already in use, the old
|
pair with ``del``. If you store using a key that is already in use, the old
|
||||||
value associated with that key is forgotten. It is an error to extract a value
|
value associated with that key is forgotten.
|
||||||
using a non-existent key.
|
|
||||||
|
Extracting a value for a non-existent key by subscripting (``d[key]``) raises a
|
||||||
|
:exc:`KeyError`. To avoid getting this error when trying to access a possibly
|
||||||
|
non-existent key, use the :meth:`~dict.get` method instead, which returns
|
||||||
|
``None`` (or a specified default value) if the key is not in the dictionary.
|
||||||
|
|
||||||
Performing ``list(d)`` on a dictionary returns a list of all the keys
|
Performing ``list(d)`` on a dictionary returns a list of all the keys
|
||||||
used in the dictionary, in insertion order (if you want it sorted, just use
|
used in the dictionary, in insertion order (if you want it sorted, just use
|
||||||
|
|
@ -528,6 +532,12 @@ Here is a small example using a dictionary::
|
||||||
{'jack': 4098, 'sape': 4139, 'guido': 4127}
|
{'jack': 4098, 'sape': 4139, 'guido': 4127}
|
||||||
>>> tel['jack']
|
>>> tel['jack']
|
||||||
4098
|
4098
|
||||||
|
>>> tel['irv']
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "<stdin>", line 1, in <module>
|
||||||
|
KeyError: 'irv'
|
||||||
|
>>> print(tel.get('irv'))
|
||||||
|
None
|
||||||
>>> del tel['sape']
|
>>> del tel['sape']
|
||||||
>>> tel['irv'] = 4127
|
>>> tel['irv'] = 4127
|
||||||
>>> tel
|
>>> tel
|
||||||
|
|
|
||||||
|
|
@ -22,16 +22,51 @@ Features and minimum versions required to build CPython:
|
||||||
|
|
||||||
* Support for threads.
|
* Support for threads.
|
||||||
|
|
||||||
* OpenSSL 1.1.1 is the minimum version and OpenSSL 3.0.16 is the recommended
|
To build optional modules:
|
||||||
minimum version for the :mod:`ssl` and :mod:`hashlib` extension modules.
|
|
||||||
|
|
||||||
* SQLite 3.15.2 for the :mod:`sqlite3` extension module.
|
* `libbz2 <https://sourceware.org/bzip2/>`_ for the :mod:`bz2` module.
|
||||||
|
|
||||||
* Tcl/Tk 8.5.12 for the :mod:`tkinter` module.
|
* `libb2 <https://github.com/BLAKE2/libb2>`_ (:ref:`BLAKE2 <hashlib-blake2>`),
|
||||||
|
used by :mod:`hashlib` module.
|
||||||
|
|
||||||
|
* `libffi <https://sourceware.org/libffi/>`_ 3.3.0 is the recommended
|
||||||
|
minimum version for the :mod:`ctypes` module.
|
||||||
|
|
||||||
|
* ``liblzma``, for the :mod:`lzma` module.
|
||||||
|
|
||||||
* `libmpdec <https://www.bytereef.org/mpdecimal/doc/libmpdec/>`_ 2.5.0
|
* `libmpdec <https://www.bytereef.org/mpdecimal/doc/libmpdec/>`_ 2.5.0
|
||||||
for the :mod:`decimal` module.
|
for the :mod:`decimal` module.
|
||||||
|
|
||||||
|
* ``libncurses`` or ``libncursesw``,
|
||||||
|
for the :mod:`curses` module.
|
||||||
|
|
||||||
|
* ``libpanel`` or ``libpanelw``,
|
||||||
|
for the :mod:`curses.panel` module.
|
||||||
|
|
||||||
|
* `libreadline <https://tiswww.case.edu/php/chet/readline/rltop.html>`_ or
|
||||||
|
`libedit <https://www.thrysoee.dk/editline/>`_
|
||||||
|
for the :mod:`readline` module.
|
||||||
|
|
||||||
|
* `libuuid <https://linux.die.net/man/3/libuuid>`_, for the :mod:`uuid` module.
|
||||||
|
|
||||||
|
* `OpenSSL <https://www.openssl.org/>`_ 1.1.1 is the minimum version and
|
||||||
|
OpenSSL 3.0.18 is the recommended minimum version for the
|
||||||
|
:mod:`ssl` and :mod:`hashlib` extension modules.
|
||||||
|
|
||||||
|
* `SQLite <https://sqlite.org/>`_ 3.15.2 for the :mod:`sqlite3` extension module.
|
||||||
|
|
||||||
|
* `Tcl/Tk <https://www.tcl-lang.org/>`_ 8.5.12 for the :mod:`tkinter` module.
|
||||||
|
|
||||||
|
* `zlib <https://www.zlib.net>`_ 1.1.4 is the reccomended minimum version for the
|
||||||
|
:mod:`zlib` module.
|
||||||
|
|
||||||
|
* `zstd <https://facebook.github.io/zstd/>`_ 1.4.5 is the minimum version for
|
||||||
|
the :mod:`compression.zstd` module.
|
||||||
|
|
||||||
|
For a full list of dependencies required to build all modules and how to install
|
||||||
|
them, see the
|
||||||
|
`devguide <https://devguide.python.org/getting-started/setup-building/#install-dependencies>`_.
|
||||||
|
|
||||||
* Autoconf 2.72 and aclocal 1.16.5 are required to regenerate the
|
* Autoconf 2.72 and aclocal 1.16.5 are required to regenerate the
|
||||||
:file:`configure` script.
|
:file:`configure` script.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ Python 2.6 incorporates new features and syntax from 3.0 while
|
||||||
remaining compatible with existing code by not removing older features
|
remaining compatible with existing code by not removing older features
|
||||||
or syntax. When it's not possible to do that, Python 2.6 tries to do
|
or syntax. When it's not possible to do that, Python 2.6 tries to do
|
||||||
what it can, adding compatibility functions in a
|
what it can, adding compatibility functions in a
|
||||||
:mod:`future_builtins` module and a :option:`!-3` switch to warn about
|
:mod:`!future_builtins` module and a :option:`!-3` switch to warn about
|
||||||
usages that will become unsupported in 3.0.
|
usages that will become unsupported in 3.0.
|
||||||
|
|
||||||
Some significant new packages have been added to the standard library,
|
Some significant new packages have been added to the standard library,
|
||||||
|
|
@ -109,7 +109,7 @@ are:
|
||||||
Python 3.0 adds several new built-in functions and changes the
|
Python 3.0 adds several new built-in functions and changes the
|
||||||
semantics of some existing builtins. Functions that are new in 3.0
|
semantics of some existing builtins. Functions that are new in 3.0
|
||||||
such as :func:`bin` have simply been added to Python 2.6, but existing
|
such as :func:`bin` have simply been added to Python 2.6, but existing
|
||||||
builtins haven't been changed; instead, the :mod:`future_builtins`
|
builtins haven't been changed; instead, the :mod:`!future_builtins`
|
||||||
module has versions with the new 3.0 semantics. Code written to be
|
module has versions with the new 3.0 semantics. Code written to be
|
||||||
compatible with 3.0 can do ``from future_builtins import hex, map`` as
|
compatible with 3.0 can do ``from future_builtins import hex, map`` as
|
||||||
necessary.
|
necessary.
|
||||||
|
|
@ -118,7 +118,7 @@ A new command-line switch, :option:`!-3`, enables warnings
|
||||||
about features that will be removed in Python 3.0. You can run code
|
about features that will be removed in Python 3.0. You can run code
|
||||||
with this switch to see how much work will be necessary to port
|
with this switch to see how much work will be necessary to port
|
||||||
code to 3.0. The value of this switch is available
|
code to 3.0. The value of this switch is available
|
||||||
to Python code as the boolean variable :data:`sys.py3kwarning`,
|
to Python code as the boolean variable :data:`!sys.py3kwarning`,
|
||||||
and to C extension code as :c:data:`!Py_Py3kWarningFlag`.
|
and to C extension code as :c:data:`!Py_Py3kWarningFlag`.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
@ -307,9 +307,9 @@ The :mod:`threading` module's locks and condition variables also support the
|
||||||
The lock is acquired before the block is executed and always released once the
|
The lock is acquired before the block is executed and always released once the
|
||||||
block is complete.
|
block is complete.
|
||||||
|
|
||||||
The :func:`localcontext` function in the :mod:`decimal` module makes it easy
|
The :func:`~decimal.localcontext` function in the :mod:`decimal` module makes
|
||||||
to save and restore the current decimal context, which encapsulates the desired
|
it easy to save and restore the current decimal context, which encapsulates
|
||||||
precision and rounding characteristics for computations::
|
the desired precision and rounding characteristics for computations::
|
||||||
|
|
||||||
from decimal import Decimal, Context, localcontext
|
from decimal import Decimal, Context, localcontext
|
||||||
|
|
||||||
|
|
@ -337,12 +337,12 @@ underlying implementation and should keep reading.
|
||||||
A high-level explanation of the context management protocol is:
|
A high-level explanation of the context management protocol is:
|
||||||
|
|
||||||
* The expression is evaluated and should result in an object called a "context
|
* The expression is evaluated and should result in an object called a "context
|
||||||
manager". The context manager must have :meth:`~object.__enter__` and :meth:`~object.__exit__`
|
manager". The context manager must have :meth:`~object.__enter__` and
|
||||||
methods.
|
:meth:`~object.__exit__` methods.
|
||||||
|
|
||||||
* The context manager's :meth:`~object.__enter__` method is called. The value returned
|
* The context manager's :meth:`~object.__enter__` method is called. The value
|
||||||
is assigned to *VAR*. If no ``as VAR`` clause is present, the value is simply
|
returned is assigned to *VAR*. If no ``as VAR`` clause is present, the
|
||||||
discarded.
|
value is simply discarded.
|
||||||
|
|
||||||
* The code in *BLOCK* is executed.
|
* The code in *BLOCK* is executed.
|
||||||
|
|
||||||
|
|
@ -378,7 +378,7 @@ be to let the user write code like this::
|
||||||
|
|
||||||
The transaction should be committed if the code in the block runs flawlessly or
|
The transaction should be committed if the code in the block runs flawlessly or
|
||||||
rolled back if there's an exception. Here's the basic interface for
|
rolled back if there's an exception. Here's the basic interface for
|
||||||
:class:`DatabaseConnection` that I'll assume::
|
:class:`!DatabaseConnection` that I'll assume::
|
||||||
|
|
||||||
class DatabaseConnection:
|
class DatabaseConnection:
|
||||||
# Database interface
|
# Database interface
|
||||||
|
|
@ -431,14 +431,15 @@ The contextlib module
|
||||||
The :mod:`contextlib` module provides some functions and a decorator that
|
The :mod:`contextlib` module provides some functions and a decorator that
|
||||||
are useful when writing objects for use with the ':keyword:`with`' statement.
|
are useful when writing objects for use with the ':keyword:`with`' statement.
|
||||||
|
|
||||||
The decorator is called :func:`contextmanager`, and lets you write a single
|
The decorator is called :func:`~contextlib.contextmanager`, and lets you write
|
||||||
generator function instead of defining a new class. The generator should yield
|
a single generator function instead of defining a new class. The generator
|
||||||
exactly one value. The code up to the :keyword:`yield` will be executed as the
|
should yield exactly one value. The code up to the :keyword:`yield` will be
|
||||||
:meth:`~object.__enter__` method, and the value yielded will be the method's return
|
executed as the :meth:`~object.__enter__` method, and the value yielded will
|
||||||
value that will get bound to the variable in the ':keyword:`with`' statement's
|
be the method's return value that will get bound to the variable in the
|
||||||
:keyword:`!as` clause, if any. The code after the :keyword:`!yield` will be
|
':keyword:`with`' statement's :keyword:`!as` clause, if any. The code after
|
||||||
executed in the :meth:`~object.__exit__` method. Any exception raised in the block will
|
the :keyword:`!yield` will be executed in the :meth:`~object.__exit__` method.
|
||||||
be raised by the :keyword:`!yield` statement.
|
Any exception raised in the block will be raised by the :keyword:`!yield`
|
||||||
|
statement.
|
||||||
|
|
||||||
Using this decorator, our database example from the previous section
|
Using this decorator, our database example from the previous section
|
||||||
could be written as::
|
could be written as::
|
||||||
|
|
@ -469,7 +470,7 @@ statement both starts a database transaction and acquires a thread lock::
|
||||||
with nested (db_transaction(db), lock) as (cursor, locked):
|
with nested (db_transaction(db), lock) as (cursor, locked):
|
||||||
...
|
...
|
||||||
|
|
||||||
Finally, the :func:`closing` function returns its argument so that it can be
|
Finally, the :func:`~contextlib.closing` function returns its argument so that it can be
|
||||||
bound to a variable, and calls the argument's ``.close()`` method at the end
|
bound to a variable, and calls the argument's ``.close()`` method at the end
|
||||||
of the block. ::
|
of the block. ::
|
||||||
|
|
||||||
|
|
@ -538,7 +539,7 @@ If you don't like the default directory, it can be overridden by an
|
||||||
environment variable. :envvar:`PYTHONUSERBASE` sets the root
|
environment variable. :envvar:`PYTHONUSERBASE` sets the root
|
||||||
directory used for all Python versions supporting this feature. On
|
directory used for all Python versions supporting this feature. On
|
||||||
Windows, the directory for application-specific data can be changed by
|
Windows, the directory for application-specific data can be changed by
|
||||||
setting the :envvar:`APPDATA` environment variable. You can also
|
setting the :envvar:`!APPDATA` environment variable. You can also
|
||||||
modify the :file:`site.py` file for your Python installation.
|
modify the :file:`site.py` file for your Python installation.
|
||||||
|
|
||||||
The feature can be disabled entirely by running Python with the
|
The feature can be disabled entirely by running Python with the
|
||||||
|
|
@ -568,11 +569,12 @@ The :mod:`multiprocessing` module started out as an exact emulation of
|
||||||
the :mod:`threading` module using processes instead of threads. That
|
the :mod:`threading` module using processes instead of threads. That
|
||||||
goal was discarded along the path to Python 2.6, but the general
|
goal was discarded along the path to Python 2.6, but the general
|
||||||
approach of the module is still similar. The fundamental class
|
approach of the module is still similar. The fundamental class
|
||||||
is the :class:`Process`, which is passed a callable object and
|
is the :class:`~multiprocessing.Process`, which is passed a callable object and
|
||||||
a collection of arguments. The :meth:`start` method
|
a collection of arguments. The :meth:`~multiprocessing.Process.start` method
|
||||||
sets the callable running in a subprocess, after which you can call
|
sets the callable running in a subprocess, after which you can call
|
||||||
the :meth:`is_alive` method to check whether the subprocess is still running
|
the :meth:`~multiprocessing.Process.is_alive` method to check whether the
|
||||||
and the :meth:`join` method to wait for the process to exit.
|
subprocess is still running and the :meth:`~multiprocessing.Process.join`
|
||||||
|
method to wait for the process to exit.
|
||||||
|
|
||||||
Here's a simple example where the subprocess will calculate a
|
Here's a simple example where the subprocess will calculate a
|
||||||
factorial. The function doing the calculation is written strangely so
|
factorial. The function doing the calculation is written strangely so
|
||||||
|
|
@ -619,13 +621,16 @@ the object to communicate. (If the parent were to change the value of
|
||||||
the global variable, the child's value would be unaffected, and vice
|
the global variable, the child's value would be unaffected, and vice
|
||||||
versa.)
|
versa.)
|
||||||
|
|
||||||
Two other classes, :class:`Pool` and :class:`Manager`, provide
|
Two other classes, :class:`~multiprocessing.pool.Pool` and
|
||||||
higher-level interfaces. :class:`Pool` will create a fixed number of
|
:class:`~multiprocessing.Manager`, provide higher-level interfaces.
|
||||||
worker processes, and requests can then be distributed to the workers
|
:class:`~multiprocessing.pool.Pool` will create a fixed number of worker
|
||||||
by calling :meth:`apply` or :meth:`apply_async` to add a single request,
|
processes, and requests can then be distributed to the workers by calling
|
||||||
and :meth:`map` or :meth:`map_async` to add a number of
|
:meth:`~multiprocessing.pool.Pool.apply` or
|
||||||
requests. The following code uses a :class:`Pool` to spread requests
|
:meth:`~multiprocessing.pool.Pool.apply_async` to add a single request, and
|
||||||
across 5 worker processes and retrieve a list of results::
|
:meth:`~multiprocessing.pool.Pool.map` or
|
||||||
|
:meth:`~multiprocessing.pool.Pool.map_async` to add a number of
|
||||||
|
requests. The following code uses a :class:`~multiprocessing.pool.Pool` to
|
||||||
|
spread requests across 5 worker processes and retrieve a list of results::
|
||||||
|
|
||||||
from multiprocessing import Pool
|
from multiprocessing import Pool
|
||||||
|
|
||||||
|
|
@ -646,15 +651,18 @@ This produces the following output::
|
||||||
33452526613163807108170062053440751665152000000000
|
33452526613163807108170062053440751665152000000000
|
||||||
...
|
...
|
||||||
|
|
||||||
The other high-level interface, the :class:`Manager` class, creates a
|
The other high-level interface, the :class:`~multiprocessing.Manager` class,
|
||||||
separate server process that can hold master copies of Python data
|
creates a separate server process that can hold master copies of Python data
|
||||||
structures. Other processes can then access and modify these data
|
structures. Other processes can then access and modify these data
|
||||||
structures using proxy objects. The following example creates a
|
structures using proxy objects. The following example creates a
|
||||||
shared dictionary by calling the :meth:`dict` method; the worker
|
shared dictionary by calling the :meth:`dict` method; the worker
|
||||||
processes then insert values into the dictionary. (Locking is not
|
processes then insert values into the dictionary. (Locking is not
|
||||||
done for you automatically, which doesn't matter in this example.
|
done for you automatically, which doesn't matter in this example.
|
||||||
:class:`Manager`'s methods also include :meth:`Lock`, :meth:`RLock`,
|
:class:`~multiprocessing.Manager`'s methods also include
|
||||||
and :meth:`Semaphore` to create shared locks.)
|
:meth:`~multiprocessing.managers.SyncManager.Lock`,
|
||||||
|
:meth:`~multiprocessing.managers.SyncManager.RLock`,
|
||||||
|
and :meth:`~multiprocessing.managers.SyncManager.Semaphore` to create
|
||||||
|
shared locks.)
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|
@ -824,7 +832,7 @@ documentation for a :ref:`complete list <formatstrings>`; here's a sample:
|
||||||
format, followed by a percent sign.
|
format, followed by a percent sign.
|
||||||
===== ========================================================================
|
===== ========================================================================
|
||||||
|
|
||||||
Classes and types can define a :meth:`__format__` method to control how they're
|
Classes and types can define a :meth:`~object.__format__` method to control how they're
|
||||||
formatted. It receives a single argument, the format specifier::
|
formatted. It receives a single argument, the format specifier::
|
||||||
|
|
||||||
def __format__(self, format_spec):
|
def __format__(self, format_spec):
|
||||||
|
|
@ -834,7 +842,7 @@ formatted. It receives a single argument, the format specifier::
|
||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
There's also a :func:`format` builtin that will format a single
|
There's also a :func:`format` builtin that will format a single
|
||||||
value. It calls the type's :meth:`__format__` method with the
|
value. It calls the type's :meth:`~object.__format__` method with the
|
||||||
provided specifier::
|
provided specifier::
|
||||||
|
|
||||||
>>> format(75.6564, '.2f')
|
>>> format(75.6564, '.2f')
|
||||||
|
|
@ -1029,56 +1037,58 @@ PEP 3116: New I/O Library
|
||||||
|
|
||||||
Python's built-in file objects support a number of methods, but
|
Python's built-in file objects support a number of methods, but
|
||||||
file-like objects don't necessarily support all of them. Objects that
|
file-like objects don't necessarily support all of them. Objects that
|
||||||
imitate files usually support :meth:`read` and :meth:`write`, but they
|
imitate files usually support :meth:`!read` and
|
||||||
may not support :meth:`readline`, for example. Python 3.0 introduces
|
:meth:`!write`, but they may not support :meth:`!readline`,
|
||||||
a layered I/O library in the :mod:`io` module that separates buffering
|
for example. Python 3.0 introduces a layered I/O library in the :mod:`io`
|
||||||
and text-handling features from the fundamental read and write
|
module that separates buffering and text-handling features from the
|
||||||
operations.
|
fundamental read and write operations.
|
||||||
|
|
||||||
There are three levels of abstract base classes provided by
|
There are three levels of abstract base classes provided by
|
||||||
the :mod:`io` module:
|
the :mod:`io` module:
|
||||||
|
|
||||||
* :class:`RawIOBase` defines raw I/O operations: :meth:`read`,
|
* :class:`~io.RawIOBase` defines raw I/O operations: :meth:`~io.RawIOBase.read`,
|
||||||
:meth:`readinto`,
|
:meth:`~io.RawIOBase.readinto`, :meth:`~io.RawIOBase.write`,
|
||||||
:meth:`write`, :meth:`seek`, :meth:`tell`, :meth:`truncate`,
|
:meth:`~io.IOBase.seek`, :meth:`~io.IOBase.tell`, :meth:`~io.IOBase.truncate`,
|
||||||
and :meth:`close`.
|
and :meth:`~io.IOBase.close`.
|
||||||
Most of the methods of this class will often map to a single system call.
|
Most of the methods of this class will often map to a single system call.
|
||||||
There are also :meth:`readable`, :meth:`writable`, and :meth:`seekable`
|
There are also :meth:`~io.IOBase.readable`, :meth:`~io.IOBase.writable`,
|
||||||
methods for determining what operations a given object will allow.
|
and :meth:`~io.IOBase.seekable` methods for determining what operations a
|
||||||
|
given object will allow.
|
||||||
|
|
||||||
Python 3.0 has concrete implementations of this class for files and
|
Python 3.0 has concrete implementations of this class for files and
|
||||||
sockets, but Python 2.6 hasn't restructured its file and socket objects
|
sockets, but Python 2.6 hasn't restructured its file and socket objects
|
||||||
in this way.
|
in this way.
|
||||||
|
|
||||||
* :class:`BufferedIOBase` is an abstract base class that
|
* :class:`~io.BufferedIOBase` is an abstract base class that
|
||||||
buffers data in memory to reduce the number of
|
buffers data in memory to reduce the number of
|
||||||
system calls used, making I/O processing more efficient.
|
system calls used, making I/O processing more efficient.
|
||||||
It supports all of the methods of :class:`RawIOBase`,
|
It supports all of the methods of :class:`~io.RawIOBase`,
|
||||||
and adds a :attr:`raw` attribute holding the underlying raw object.
|
and adds a :attr:`~io.BufferedIOBase.raw` attribute holding the underlying
|
||||||
|
raw object.
|
||||||
|
|
||||||
There are five concrete classes implementing this ABC.
|
There are five concrete classes implementing this ABC.
|
||||||
:class:`BufferedWriter` and :class:`BufferedReader` are for objects
|
:class:`~io.BufferedWriter` and :class:`~io.BufferedReader` are for objects
|
||||||
that support write-only or read-only usage that have a :meth:`seek`
|
that support write-only or read-only usage that have a :meth:`~io.IOBase.seek`
|
||||||
method for random access. :class:`BufferedRandom` objects support
|
method for random access. :class:`~io.BufferedRandom` objects support
|
||||||
read and write access upon the same underlying stream, and
|
read and write access upon the same underlying stream, and
|
||||||
:class:`BufferedRWPair` is for objects such as TTYs that have both
|
:class:`~io.BufferedRWPair` is for objects such as TTYs that have both
|
||||||
read and write operations acting upon unconnected streams of data.
|
read and write operations acting upon unconnected streams of data.
|
||||||
The :class:`BytesIO` class supports reading, writing, and seeking
|
The :class:`~io.BytesIO` class supports reading, writing, and seeking
|
||||||
over an in-memory buffer.
|
over an in-memory buffer.
|
||||||
|
|
||||||
.. index::
|
.. index::
|
||||||
single: universal newlines; What's new
|
single: universal newlines; What's new
|
||||||
|
|
||||||
* :class:`TextIOBase`: Provides functions for reading and writing
|
* :class:`~io.TextIOBase`: Provides functions for reading and writing
|
||||||
strings (remember, strings will be Unicode in Python 3.0),
|
strings (remember, strings will be Unicode in Python 3.0),
|
||||||
and supporting :term:`universal newlines`. :class:`TextIOBase` defines
|
and supporting :term:`universal newlines`. :class:`~io.TextIOBase` defines
|
||||||
the :meth:`readline` method and supports iteration upon
|
the :meth:`readline` method and supports iteration upon
|
||||||
objects.
|
objects.
|
||||||
|
|
||||||
There are two concrete implementations. :class:`TextIOWrapper`
|
There are two concrete implementations. :class:`~io.TextIOWrapper`
|
||||||
wraps a buffered I/O object, supporting all of the methods for
|
wraps a buffered I/O object, supporting all of the methods for
|
||||||
text I/O and adding a :attr:`buffer` attribute for access
|
text I/O and adding a :attr:`~io.TextIOBase.buffer` attribute for access
|
||||||
to the underlying object. :class:`StringIO` simply buffers
|
to the underlying object. :class:`~io.StringIO` simply buffers
|
||||||
everything in memory without ever writing anything to disk.
|
everything in memory without ever writing anything to disk.
|
||||||
|
|
||||||
(In Python 2.6, :class:`io.StringIO` is implemented in
|
(In Python 2.6, :class:`io.StringIO` is implemented in
|
||||||
|
|
@ -1162,7 +1172,7 @@ Some object-oriented languages such as Java support interfaces,
|
||||||
declaring that a class has a given set of methods or supports a given
|
declaring that a class has a given set of methods or supports a given
|
||||||
access protocol. Abstract Base Classes (or ABCs) are an equivalent
|
access protocol. Abstract Base Classes (or ABCs) are an equivalent
|
||||||
feature for Python. The ABC support consists of an :mod:`abc` module
|
feature for Python. The ABC support consists of an :mod:`abc` module
|
||||||
containing a metaclass called :class:`ABCMeta`, special handling of
|
containing a metaclass called :class:`~abc.ABCMeta`, special handling of
|
||||||
this metaclass by the :func:`isinstance` and :func:`issubclass`
|
this metaclass by the :func:`isinstance` and :func:`issubclass`
|
||||||
builtins, and a collection of basic ABCs that the Python developers
|
builtins, and a collection of basic ABCs that the Python developers
|
||||||
think will be widely useful. Future versions of Python will probably
|
think will be widely useful. Future versions of Python will probably
|
||||||
|
|
@ -1172,17 +1182,17 @@ Let's say you have a particular class and wish to know whether it supports
|
||||||
dictionary-style access. The phrase "dictionary-style" is vague, however.
|
dictionary-style access. The phrase "dictionary-style" is vague, however.
|
||||||
It probably means that accessing items with ``obj[1]`` works.
|
It probably means that accessing items with ``obj[1]`` works.
|
||||||
Does it imply that setting items with ``obj[2] = value`` works?
|
Does it imply that setting items with ``obj[2] = value`` works?
|
||||||
Or that the object will have :meth:`keys`, :meth:`values`, and :meth:`items`
|
Or that the object will have :meth:`!keys`, :meth:`!values`, and :meth:`!items`
|
||||||
methods? What about the iterative variants such as :meth:`iterkeys`? :meth:`copy`
|
methods? What about the iterative variants such as :meth:`!iterkeys`?
|
||||||
and :meth:`update`? Iterating over the object with :func:`iter`?
|
:meth:`!copy`and :meth:`!update`? Iterating over the object with :func:`!iter`?
|
||||||
|
|
||||||
The Python 2.6 :mod:`collections` module includes a number of
|
The Python 2.6 :mod:`collections` module includes a number of
|
||||||
different ABCs that represent these distinctions. :class:`Iterable`
|
different ABCs that represent these distinctions. :class:`Iterable`
|
||||||
indicates that a class defines :meth:`__iter__`, and
|
indicates that a class defines :meth:`~object.__iter__`, and
|
||||||
:class:`Container` means the class defines a :meth:`__contains__`
|
:class:`Container` means the class defines a :meth:`~object.__contains__`
|
||||||
method and therefore supports ``x in y`` expressions. The basic
|
method and therefore supports ``x in y`` expressions. The basic
|
||||||
dictionary interface of getting items, setting items, and
|
dictionary interface of getting items, setting items, and
|
||||||
:meth:`keys`, :meth:`values`, and :meth:`items`, is defined by the
|
:meth:`!keys`, :meth:`!values`, and :meth:`!items`, is defined by the
|
||||||
:class:`MutableMapping` ABC.
|
:class:`MutableMapping` ABC.
|
||||||
|
|
||||||
You can derive your own classes from a particular ABC
|
You can derive your own classes from a particular ABC
|
||||||
|
|
@ -1196,7 +1206,7 @@ to indicate they support that ABC's interface::
|
||||||
|
|
||||||
Alternatively, you could write the class without deriving from
|
Alternatively, you could write the class without deriving from
|
||||||
the desired ABC and instead register the class by
|
the desired ABC and instead register the class by
|
||||||
calling the ABC's :meth:`register` method::
|
calling the ABC's :meth:`~abc.ABCMeta.register` method::
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
|
|
@ -1206,10 +1216,10 @@ calling the ABC's :meth:`register` method::
|
||||||
collections.MutableMapping.register(Storage)
|
collections.MutableMapping.register(Storage)
|
||||||
|
|
||||||
For classes that you write, deriving from the ABC is probably clearer.
|
For classes that you write, deriving from the ABC is probably clearer.
|
||||||
The :meth:`register` method is useful when you've written a new
|
The :meth:`~abc.ABCMeta.register` method is useful when you've written a new
|
||||||
ABC that can describe an existing type or class, or if you want
|
ABC that can describe an existing type or class, or if you want
|
||||||
to declare that some third-party class implements an ABC.
|
to declare that some third-party class implements an ABC.
|
||||||
For example, if you defined a :class:`PrintableType` ABC,
|
For example, if you defined a :class:`!PrintableType` ABC,
|
||||||
it's legal to do::
|
it's legal to do::
|
||||||
|
|
||||||
# Register Python's types
|
# Register Python's types
|
||||||
|
|
@ -1256,16 +1266,16 @@ metaclass in a class definition::
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
In the :class:`Drawable` ABC above, the :meth:`draw_doubled` method
|
In the :class:`!Drawable` ABC above, the :meth:`!draw_doubled` method
|
||||||
renders the object at twice its size and can be implemented in terms
|
renders the object at twice its size and can be implemented in terms
|
||||||
of other methods described in :class:`Drawable`. Classes implementing
|
of other methods described in :class:`!Drawable`. Classes implementing
|
||||||
this ABC therefore don't need to provide their own implementation
|
this ABC therefore don't need to provide their own implementation
|
||||||
of :meth:`draw_doubled`, though they can do so. An implementation
|
of :meth:`!draw_doubled`, though they can do so. An implementation
|
||||||
of :meth:`draw` is necessary, though; the ABC can't provide
|
of :meth:`!draw` is necessary, though; the ABC can't provide
|
||||||
a useful generic implementation.
|
a useful generic implementation.
|
||||||
|
|
||||||
You can apply the ``@abstractmethod`` decorator to methods such as
|
You can apply the :deco:`~abc.abstractmethod` decorator to methods such as
|
||||||
:meth:`draw` that must be implemented; Python will then raise an
|
:meth:`!draw` that must be implemented; Python will then raise an
|
||||||
exception for classes that don't define the method.
|
exception for classes that don't define the method.
|
||||||
Note that the exception is only raised when you actually
|
Note that the exception is only raised when you actually
|
||||||
try to create an instance of a subclass lacking the method::
|
try to create an instance of a subclass lacking the method::
|
||||||
|
|
@ -1289,7 +1299,7 @@ Abstract data attributes can be declared using the
|
||||||
def readonly(self):
|
def readonly(self):
|
||||||
return self._x
|
return self._x
|
||||||
|
|
||||||
Subclasses must then define a :meth:`readonly` property.
|
Subclasses must then define a ``readonly`` property.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
|
|
@ -2739,13 +2749,13 @@ numbers.
|
||||||
|
|
||||||
.. ======================================================================
|
.. ======================================================================
|
||||||
|
|
||||||
The :mod:`future_builtins` module
|
The :mod:`!future_builtins` module
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
Python 3.0 makes many changes to the repertoire of built-in
|
Python 3.0 makes many changes to the repertoire of built-in
|
||||||
functions, and most of the changes can't be introduced in the Python
|
functions, and most of the changes can't be introduced in the Python
|
||||||
2.x series because they would break compatibility.
|
2.x series because they would break compatibility.
|
||||||
The :mod:`future_builtins` module provides versions
|
The :mod:`!future_builtins` module provides versions
|
||||||
of these built-in functions that can be imported when writing
|
of these built-in functions that can be imported when writing
|
||||||
3.0-compatible code.
|
3.0-compatible code.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -858,8 +858,8 @@ Some smaller changes made to the core Python language are:
|
||||||
|
|
||||||
.. XXX bytearray doesn't seem to be documented
|
.. XXX bytearray doesn't seem to be documented
|
||||||
|
|
||||||
* When using :class:`@classmethod <classmethod>` and
|
* When using :deco:`classmethod` and
|
||||||
:class:`@staticmethod <staticmethod>` to wrap
|
:deco:`staticmethod` to wrap
|
||||||
methods as class or static methods, the wrapper object now
|
methods as class or static methods, the wrapper object now
|
||||||
exposes the wrapped function as their :attr:`~method.__func__`
|
exposes the wrapped function as their :attr:`~method.__func__`
|
||||||
attribute.
|
attribute.
|
||||||
|
|
|
||||||
|
|
@ -847,8 +847,8 @@ Other Language Changes
|
||||||
respectively.
|
respectively.
|
||||||
(Contributed by Joshua Bronson, Daniel Pope, and Justin Wang in :issue:`31861`.)
|
(Contributed by Joshua Bronson, Daniel Pope, and Justin Wang in :issue:`31861`.)
|
||||||
|
|
||||||
* Static methods (:func:`@staticmethod <staticmethod>`) and class methods
|
* Static methods (:deco:`staticmethod`) and class methods
|
||||||
(:func:`@classmethod <classmethod>`) now inherit the method attributes
|
(:deco:`classmethod`) now inherit the method attributes
|
||||||
(``__module__``, ``__name__``, ``__qualname__``, ``__doc__``,
|
(``__module__``, ``__name__``, ``__qualname__``, ``__doc__``,
|
||||||
``__annotations__``) and have a new ``__wrapped__`` attribute.
|
``__annotations__``) and have a new ``__wrapped__`` attribute.
|
||||||
Moreover, static methods are now callable as regular functions.
|
Moreover, static methods are now callable as regular functions.
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ Summary -- Release Highlights
|
||||||
.. This section singles out the most important changes in Python 3.13.
|
.. This section singles out the most important changes in Python 3.13.
|
||||||
Brevity is key.
|
Brevity is key.
|
||||||
|
|
||||||
Python 3.13 is the latest stable release of the Python programming
|
Python 3.13 is a stable release of the Python programming
|
||||||
language, with a mix of changes to the language, the implementation
|
language, with a mix of changes to the language, the implementation
|
||||||
and the standard library.
|
and the standard library.
|
||||||
The biggest changes include a new `interactive interpreter
|
The biggest changes include a new `interactive interpreter
|
||||||
|
|
@ -1569,8 +1569,6 @@ and are now removed:
|
||||||
|
|
||||||
* :pypi:`bcrypt`:
|
* :pypi:`bcrypt`:
|
||||||
Modern password hashing for your software and your servers.
|
Modern password hashing for your software and your servers.
|
||||||
* :pypi:`passlib`:
|
|
||||||
Comprehensive password hashing framework supporting over 30 schemes.
|
|
||||||
* :pypi:`argon2-cffi`:
|
* :pypi:`argon2-cffi`:
|
||||||
The secure Argon2 password hashing algorithm.
|
The secure Argon2 password hashing algorithm.
|
||||||
* :pypi:`legacycrypt`:
|
* :pypi:`legacycrypt`:
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -852,6 +852,9 @@ New features
|
||||||
|
|
||||||
(Contributed by Victor Stinner in :gh:`129813`.)
|
(Contributed by Victor Stinner in :gh:`129813`.)
|
||||||
|
|
||||||
|
* Add :c:func:`PyTuple_FromArray` to create a :class:`tuple` from an array.
|
||||||
|
(Contributed by Victor Stinner in :gh:`111489`.)
|
||||||
|
|
||||||
|
|
||||||
Porting to Python 3.15
|
Porting to Python 3.15
|
||||||
----------------------
|
----------------------
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ __pragma(warning(disable: 4201))
|
||||||
#include "pybuffer.h"
|
#include "pybuffer.h"
|
||||||
#include "pystats.h"
|
#include "pystats.h"
|
||||||
#include "pyatomic.h"
|
#include "pyatomic.h"
|
||||||
#include "pylock.h"
|
#include "cpython/pylock.h"
|
||||||
#include "critical_section.h"
|
#include "critical_section.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "refcount.h"
|
#include "refcount.h"
|
||||||
|
|
@ -105,7 +105,7 @@ __pragma(warning(disable: 4201))
|
||||||
#include "setobject.h"
|
#include "setobject.h"
|
||||||
#include "methodobject.h"
|
#include "methodobject.h"
|
||||||
#include "moduleobject.h"
|
#include "moduleobject.h"
|
||||||
#include "monitoring.h"
|
#include "cpython/monitoring.h"
|
||||||
#include "cpython/funcobject.h"
|
#include "cpython/funcobject.h"
|
||||||
#include "cpython/classobject.h"
|
#include "cpython/classobject.h"
|
||||||
#include "fileobject.h"
|
#include "fileobject.h"
|
||||||
|
|
|
||||||
|
|
@ -282,15 +282,6 @@ typedef struct _line_offsets {
|
||||||
*/
|
*/
|
||||||
PyAPI_FUNC(int) _PyCode_CheckLineNumber(int lasti, PyCodeAddressRange *bounds);
|
PyAPI_FUNC(int) _PyCode_CheckLineNumber(int lasti, PyCodeAddressRange *bounds);
|
||||||
|
|
||||||
/* Create a comparable key used to compare constants taking in account the
|
|
||||||
* object type. It is used to make sure types are not coerced (e.g., float and
|
|
||||||
* complex) _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms
|
|
||||||
*
|
|
||||||
* Return (type(obj), obj, ...): a tuple with variable size (at least 2 items)
|
|
||||||
* depending on the type and the value. The type is the first item to not
|
|
||||||
* compare bytes and str which can raise a BytesWarning exception. */
|
|
||||||
PyAPI_FUNC(PyObject*) _PyCode_ConstantKey(PyObject *obj);
|
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject*) PyCode_Optimize(PyObject *code, PyObject* consts,
|
PyAPI_FUNC(PyObject*) PyCode_Optimize(PyObject *code, PyObject* consts,
|
||||||
PyObject *names, PyObject *lnotab);
|
PyObject *names, PyObject *lnotab);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,8 @@ PyAPI_FUNC(PyObject *) PyStaticMethod_New(PyObject *);
|
||||||
V(DESTROY) \
|
V(DESTROY) \
|
||||||
V(MODIFY_CODE) \
|
V(MODIFY_CODE) \
|
||||||
V(MODIFY_DEFAULTS) \
|
V(MODIFY_DEFAULTS) \
|
||||||
V(MODIFY_KWDEFAULTS)
|
V(MODIFY_KWDEFAULTS) \
|
||||||
|
V(MODIFY_QUALNAME)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#define PY_DEF_EVENT(EVENT) PyFunction_EVENT_##EVENT,
|
#define PY_DEF_EVENT(EVENT) PyFunction_EVENT_##EVENT,
|
||||||
|
|
|
||||||
17
Include/cpython/marshal.h
Normal file
17
Include/cpython/marshal.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef _Py_CPYTHON_MARSHAL_H
|
||||||
|
# error "this header file must not be included directly"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(const char *,
|
||||||
|
Py_ssize_t);
|
||||||
|
PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int);
|
||||||
|
|
||||||
|
#define Py_MARSHAL_VERSION 5
|
||||||
|
|
||||||
|
PyAPI_FUNC(long) PyMarshal_ReadLongFromFile(FILE *);
|
||||||
|
PyAPI_FUNC(int) PyMarshal_ReadShortFromFile(FILE *);
|
||||||
|
PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromFile(FILE *);
|
||||||
|
PyAPI_FUNC(PyObject *) PyMarshal_ReadLastObjectFromFile(FILE *);
|
||||||
|
|
||||||
|
PyAPI_FUNC(void) PyMarshal_WriteLongToFile(long, FILE *, int);
|
||||||
|
PyAPI_FUNC(void) PyMarshal_WriteObjectToFile(PyObject *, FILE *, int);
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
#ifndef Py_CPYTHON_MONITORING_H
|
#ifndef Py_MONITORING_H
|
||||||
# error "this header file must not be included directly"
|
#define Py_MONITORING_H
|
||||||
|
#ifndef Py_LIMITED_API
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// There is currently no limited API for monitoring
|
||||||
|
|
||||||
|
|
||||||
/* Local events.
|
/* Local events.
|
||||||
* These require bytecode instrumentation */
|
* These require bytecode instrumentation */
|
||||||
|
|
||||||
|
|
@ -267,3 +273,9 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef _PYMONITORING_IF_ACTIVE
|
#undef _PYMONITORING_IF_ACTIVE
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // !Py_LIMITED_API
|
||||||
|
#endif // !Py_MONITORING_H
|
||||||
|
|
|
||||||
|
|
@ -492,7 +492,3 @@ PyAPI_FUNC(int) PyUnstable_TryIncRef(PyObject *);
|
||||||
PyAPI_FUNC(void) PyUnstable_EnableTryIncRef(PyObject *);
|
PyAPI_FUNC(void) PyUnstable_EnableTryIncRef(PyObject *);
|
||||||
|
|
||||||
PyAPI_FUNC(int) PyUnstable_Object_IsUniquelyReferenced(PyObject *);
|
PyAPI_FUNC(int) PyUnstable_Object_IsUniquelyReferenced(PyObject *);
|
||||||
|
|
||||||
/* Utility for the tp_traverse slot of mutable heap types that have no other
|
|
||||||
* references. */
|
|
||||||
PyAPI_FUNC(int) _PyObject_VisitType(PyObject *op, visitproc visit, void *arg);
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
#ifndef Py_CPYTHON_LOCK_H
|
#ifndef Py_LOCK_H
|
||||||
# error "this header file must not be included directly"
|
#define Py_LOCK_H
|
||||||
|
#ifndef Py_LIMITED_API
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define _Py_UNLOCKED 0
|
#define _Py_UNLOCKED 0
|
||||||
#define _Py_LOCKED 1
|
#define _Py_LOCKED 1
|
||||||
|
|
||||||
|
|
@ -72,3 +76,10 @@ _PyMutex_IsLocked(PyMutex *m)
|
||||||
return (_Py_atomic_load_uint8(&m->_bits) & _Py_LOCKED) != 0;
|
return (_Py_atomic_load_uint8(&m->_bits) & _Py_LOCKED) != 0;
|
||||||
}
|
}
|
||||||
#define PyMutex_IsLocked _PyMutex_IsLocked
|
#define PyMutex_IsLocked _PyMutex_IsLocked
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // !Py_LIMITED_API
|
||||||
|
#endif // !Py_LOCK_H
|
||||||
|
|
|
||||||
20
Include/cpython/sliceobject.h
Normal file
20
Include/cpython/sliceobject.h
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef Py_CPYTHON_SLICEOBJECT_H
|
||||||
|
# error "this header file must not be included directly"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Slice object interface */
|
||||||
|
|
||||||
|
/*
|
||||||
|
A slice object containing start, stop, and step data members (the
|
||||||
|
names are from range). After much talk with Guido, it was decided to
|
||||||
|
let these be any arbitrary python type. Py_None stands for omitted values.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
PyObject *start, *stop, *step; /* not NULL */
|
||||||
|
} PySliceObject;
|
||||||
|
|
||||||
|
PyAPI_FUNC(PyObject *) _PySlice_FromIndices(Py_ssize_t start, Py_ssize_t stop);
|
||||||
|
PyAPI_FUNC(int) _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
|
||||||
|
PyObject **start_ptr, PyObject **stop_ptr,
|
||||||
|
PyObject **step_ptr);
|
||||||
12
Include/cpython/structseq.h
Normal file
12
Include/cpython/structseq.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef Py_CPYTHON_STRUCTSEQ_H
|
||||||
|
# error "this header file must not be included directly"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PyAPI_FUNC(void) PyStructSequence_InitType(PyTypeObject *type,
|
||||||
|
PyStructSequence_Desc *desc);
|
||||||
|
PyAPI_FUNC(int) PyStructSequence_InitType2(PyTypeObject *type,
|
||||||
|
PyStructSequence_Desc *desc);
|
||||||
|
|
||||||
|
typedef PyTupleObject PyStructSequence;
|
||||||
|
#define PyStructSequence_SET_ITEM PyStructSequence_SetItem
|
||||||
|
#define PyStructSequence_GET_ITEM PyStructSequence_GetItem
|
||||||
|
|
@ -38,3 +38,7 @@ PyTuple_SET_ITEM(PyObject *op, Py_ssize_t index, PyObject *value) {
|
||||||
}
|
}
|
||||||
#define PyTuple_SET_ITEM(op, index, value) \
|
#define PyTuple_SET_ITEM(op, index, value) \
|
||||||
PyTuple_SET_ITEM(_PyObject_CAST(op), (index), _PyObject_CAST(value))
|
PyTuple_SET_ITEM(_PyObject_CAST(op), (index), _PyObject_CAST(value))
|
||||||
|
|
||||||
|
PyAPI_FUNC(PyObject*) PyTuple_FromArray(
|
||||||
|
PyObject *const *array,
|
||||||
|
Py_ssize_t size);
|
||||||
|
|
|
||||||
|
|
@ -663,6 +663,15 @@ PyAPI_FUNC(int) _PyCode_VerifyStateless(
|
||||||
PyAPI_FUNC(int) _PyCode_CheckPureFunction(PyCodeObject *, const char **);
|
PyAPI_FUNC(int) _PyCode_CheckPureFunction(PyCodeObject *, const char **);
|
||||||
PyAPI_FUNC(int) _PyCode_ReturnsOnlyNone(PyCodeObject *);
|
PyAPI_FUNC(int) _PyCode_ReturnsOnlyNone(PyCodeObject *);
|
||||||
|
|
||||||
|
/* Create a comparable key used to compare constants taking in account the
|
||||||
|
* object type. It is used to make sure types are not coerced (e.g., float and
|
||||||
|
* complex) _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms
|
||||||
|
*
|
||||||
|
* Return (type(obj), obj, ...): a tuple with variable size (at least 2 items)
|
||||||
|
* depending on the type and the value. The type is the first item to not
|
||||||
|
* compare bytes and str which can raise a BytesWarning exception. */
|
||||||
|
extern PyObject* _PyCode_ConstantKey(PyObject *obj);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1047,6 +1047,10 @@ static inline Py_ALWAYS_INLINE void _Py_INCREF_MORTAL(PyObject *op)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Utility for the tp_traverse slot of mutable heap types that have no other
|
||||||
|
* references. */
|
||||||
|
PyAPI_FUNC(int) _PyObject_VisitType(PyObject *op, visitproc visit, void *arg);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
|
||||||
|
|
||||||
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)
|
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *)_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
|
|
||||||
PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRef *, Py_ssize_t);
|
PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRef *, Py_ssize_t);
|
||||||
PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
|
PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,70 @@ extern "C" {
|
||||||
#include "pycore_fileutils.h" // _Py_error_handler
|
#include "pycore_fileutils.h" // _Py_error_handler
|
||||||
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
|
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
|
||||||
|
|
||||||
|
|
||||||
|
// Maximum code point of Unicode 6.0: 0x10ffff (1,114,111).
|
||||||
|
#define _Py_MAX_UNICODE 0x10ffff
|
||||||
|
|
||||||
|
|
||||||
|
extern int _PyUnicode_IsModifiable(PyObject *unicode);
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_PyUnicode_Fill(int kind, void *data, Py_UCS4 value,
|
||||||
|
Py_ssize_t start, Py_ssize_t length)
|
||||||
|
{
|
||||||
|
assert(0 <= start);
|
||||||
|
switch (kind) {
|
||||||
|
case PyUnicode_1BYTE_KIND: {
|
||||||
|
assert(value <= 0xff);
|
||||||
|
Py_UCS1 ch = (unsigned char)value;
|
||||||
|
Py_UCS1 *to = (Py_UCS1 *)data + start;
|
||||||
|
memset(to, ch, length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PyUnicode_2BYTE_KIND: {
|
||||||
|
assert(value <= 0xffff);
|
||||||
|
Py_UCS2 ch = (Py_UCS2)value;
|
||||||
|
Py_UCS2 *to = (Py_UCS2 *)data + start;
|
||||||
|
const Py_UCS2 *end = to + length;
|
||||||
|
for (; to < end; ++to) *to = ch;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PyUnicode_4BYTE_KIND: {
|
||||||
|
assert(value <= _Py_MAX_UNICODE);
|
||||||
|
Py_UCS4 ch = value;
|
||||||
|
Py_UCS4 * to = (Py_UCS4 *)data + start;
|
||||||
|
const Py_UCS4 *end = to + length;
|
||||||
|
for (; to < end; ++to) *to = ch;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: Py_UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
_PyUnicode_EnsureUnicode(PyObject *obj)
|
||||||
|
{
|
||||||
|
if (!PyUnicode_Check(obj)) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"must be str, not %T", obj);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
_PyUnicodeWriter_WriteCharInline(_PyUnicodeWriter *writer, Py_UCS4 ch)
|
||||||
|
{
|
||||||
|
assert(ch <= _Py_MAX_UNICODE);
|
||||||
|
if (_PyUnicodeWriter_Prepare(writer, 1, ch) < 0)
|
||||||
|
return -1;
|
||||||
|
PyUnicode_WRITE(writer->kind, writer->data, writer->pos, ch);
|
||||||
|
writer->pos++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* --- Characters Type APIs ----------------------------------------------- */
|
/* --- Characters Type APIs ----------------------------------------------- */
|
||||||
|
|
||||||
extern int _PyUnicode_IsXidStart(Py_UCS4 ch);
|
extern int _PyUnicode_IsXidStart(Py_UCS4 ch);
|
||||||
|
|
@ -240,21 +304,6 @@ extern PyObject* _PyUnicode_XStrip(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/* Using explicit passed-in values, insert the thousands grouping
|
|
||||||
into the string pointed to by buffer. For the argument descriptions,
|
|
||||||
see Objects/stringlib/localeutil.h */
|
|
||||||
extern Py_ssize_t _PyUnicode_InsertThousandsGrouping(
|
|
||||||
_PyUnicodeWriter *writer,
|
|
||||||
Py_ssize_t n_buffer,
|
|
||||||
PyObject *digits,
|
|
||||||
Py_ssize_t d_pos,
|
|
||||||
Py_ssize_t n_digits,
|
|
||||||
Py_ssize_t min_width,
|
|
||||||
const char *grouping,
|
|
||||||
PyObject *thousands_sep,
|
|
||||||
Py_UCS4 *maxchar,
|
|
||||||
int forward);
|
|
||||||
|
|
||||||
/* Dedent a string.
|
/* Dedent a string.
|
||||||
Behaviour is expected to be an exact match of `textwrap.dedent`.
|
Behaviour is expected to be an exact match of `textwrap.dedent`.
|
||||||
Return a new reference on success, NULL with exception set on error.
|
Return a new reference on success, NULL with exception set on error.
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,18 @@
|
||||||
|
|
||||||
/* Interface for marshal.c */
|
/* Interface for marshal.c */
|
||||||
|
|
||||||
#ifndef Py_MARSHAL_H
|
#ifndef Py_MARSHAL_H
|
||||||
#define Py_MARSHAL_H
|
#define Py_MARSHAL_H
|
||||||
#ifndef Py_LIMITED_API
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(const char *,
|
#ifndef Py_LIMITED_API
|
||||||
Py_ssize_t);
|
# define _Py_CPYTHON_MARSHAL_H
|
||||||
PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int);
|
# include "cpython/marshal.h"
|
||||||
|
# undef _Py_CPYTHON_MARSHAL_H
|
||||||
#define Py_MARSHAL_VERSION 5
|
#endif
|
||||||
|
|
||||||
PyAPI_FUNC(long) PyMarshal_ReadLongFromFile(FILE *);
|
|
||||||
PyAPI_FUNC(int) PyMarshal_ReadShortFromFile(FILE *);
|
|
||||||
PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromFile(FILE *);
|
|
||||||
PyAPI_FUNC(PyObject *) PyMarshal_ReadLastObjectFromFile(FILE *);
|
|
||||||
|
|
||||||
PyAPI_FUNC(void) PyMarshal_WriteLongToFile(long, FILE *, int);
|
|
||||||
PyAPI_FUNC(void) PyMarshal_WriteObjectToFile(PyObject *, FILE *, int);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* Py_LIMITED_API */
|
|
||||||
#endif /* !Py_MARSHAL_H */
|
#endif /* !Py_MARSHAL_H */
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
#ifndef Py_MONITORING_H
|
|
||||||
#define Py_MONITORING_H
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// There is currently no limited API for monitoring
|
|
||||||
|
|
||||||
#ifndef Py_LIMITED_API
|
|
||||||
# define Py_CPYTHON_MONITORING_H
|
|
||||||
# include "cpython/monitoring.h"
|
|
||||||
# undef Py_CPYTHON_MONITORING_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif /* !Py_MONITORING_H */
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
#ifndef Py_LOCK_H
|
|
||||||
#define Py_LOCK_H
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef Py_LIMITED_API
|
|
||||||
# define Py_CPYTHON_LOCK_H
|
|
||||||
# include "cpython/pylock.h"
|
|
||||||
# undef Py_CPYTHON_LOCK_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif /* !Py_LOCK_H */
|
|
||||||
|
|
@ -16,19 +16,6 @@ PyAPI_DATA(PyObject) _Py_EllipsisObject; /* Don't use this directly */
|
||||||
|
|
||||||
/* Slice object interface */
|
/* Slice object interface */
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
A slice object containing start, stop, and step data members (the
|
|
||||||
names are from range). After much talk with Guido, it was decided to
|
|
||||||
let these be any arbitrary python type. Py_None stands for omitted values.
|
|
||||||
*/
|
|
||||||
#ifndef Py_LIMITED_API
|
|
||||||
typedef struct {
|
|
||||||
PyObject_HEAD
|
|
||||||
PyObject *start, *stop, *step; /* not NULL */
|
|
||||||
} PySliceObject;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PyAPI_DATA(PyTypeObject) PySlice_Type;
|
PyAPI_DATA(PyTypeObject) PySlice_Type;
|
||||||
PyAPI_DATA(PyTypeObject) PyEllipsis_Type;
|
PyAPI_DATA(PyTypeObject) PyEllipsis_Type;
|
||||||
|
|
||||||
|
|
@ -36,12 +23,6 @@ PyAPI_DATA(PyTypeObject) PyEllipsis_Type;
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) PySlice_New(PyObject* start, PyObject* stop,
|
PyAPI_FUNC(PyObject *) PySlice_New(PyObject* start, PyObject* stop,
|
||||||
PyObject* step);
|
PyObject* step);
|
||||||
#ifndef Py_LIMITED_API
|
|
||||||
PyAPI_FUNC(PyObject *) _PySlice_FromIndices(Py_ssize_t start, Py_ssize_t stop);
|
|
||||||
PyAPI_FUNC(int) _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
|
|
||||||
PyObject **start_ptr, PyObject **stop_ptr,
|
|
||||||
PyObject **step_ptr);
|
|
||||||
#endif
|
|
||||||
PyAPI_FUNC(int) PySlice_GetIndices(PyObject *r, Py_ssize_t length,
|
PyAPI_FUNC(int) PySlice_GetIndices(PyObject *r, Py_ssize_t length,
|
||||||
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step);
|
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step);
|
||||||
Py_DEPRECATED(3.7)
|
Py_DEPRECATED(3.7)
|
||||||
|
|
@ -63,6 +44,12 @@ PyAPI_FUNC(Py_ssize_t) PySlice_AdjustIndices(Py_ssize_t length,
|
||||||
Py_ssize_t step);
|
Py_ssize_t step);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef Py_LIMITED_API
|
||||||
|
# define Py_CPYTHON_SLICEOBJECT_H
|
||||||
|
# include "cpython/sliceobject.h"
|
||||||
|
# undef Py_CPYTHON_SLICEOBJECT_H
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,6 @@ typedef struct PyStructSequence_Desc {
|
||||||
|
|
||||||
PyAPI_DATA(const char * const) PyStructSequence_UnnamedField;
|
PyAPI_DATA(const char * const) PyStructSequence_UnnamedField;
|
||||||
|
|
||||||
#ifndef Py_LIMITED_API
|
|
||||||
PyAPI_FUNC(void) PyStructSequence_InitType(PyTypeObject *type,
|
|
||||||
PyStructSequence_Desc *desc);
|
|
||||||
PyAPI_FUNC(int) PyStructSequence_InitType2(PyTypeObject *type,
|
|
||||||
PyStructSequence_Desc *desc);
|
|
||||||
#endif
|
|
||||||
PyAPI_FUNC(PyTypeObject*) PyStructSequence_NewType(PyStructSequence_Desc *desc);
|
PyAPI_FUNC(PyTypeObject*) PyStructSequence_NewType(PyStructSequence_Desc *desc);
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) PyStructSequence_New(PyTypeObject* type);
|
PyAPI_FUNC(PyObject *) PyStructSequence_New(PyTypeObject* type);
|
||||||
|
|
@ -35,9 +29,9 @@ PyAPI_FUNC(void) PyStructSequence_SetItem(PyObject*, Py_ssize_t, PyObject*);
|
||||||
PyAPI_FUNC(PyObject*) PyStructSequence_GetItem(PyObject*, Py_ssize_t);
|
PyAPI_FUNC(PyObject*) PyStructSequence_GetItem(PyObject*, Py_ssize_t);
|
||||||
|
|
||||||
#ifndef Py_LIMITED_API
|
#ifndef Py_LIMITED_API
|
||||||
typedef PyTupleObject PyStructSequence;
|
# define Py_CPYTHON_STRUCTSEQ_H
|
||||||
#define PyStructSequence_SET_ITEM PyStructSequence_SetItem
|
# include "cpython/structseq.h"
|
||||||
#define PyStructSequence_GET_ITEM PyStructSequence_GetItem
|
# undef Py_CPYTHON_STRUCTSEQ_H
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
||||||
|
|
@ -420,14 +420,17 @@ class delete(EditCommand):
|
||||||
def do(self) -> None:
|
def do(self) -> None:
|
||||||
r = self.reader
|
r = self.reader
|
||||||
b = r.buffer
|
b = r.buffer
|
||||||
if (
|
if self.event[-1] == "\004":
|
||||||
|
if b and b[-1].endswith("\n"):
|
||||||
|
self.finish = True
|
||||||
|
elif (
|
||||||
r.pos == 0
|
r.pos == 0
|
||||||
and len(b) == 0 # this is something of a hack
|
and len(b) == 0 # this is something of a hack
|
||||||
and self.event[-1] == "\004"
|
|
||||||
):
|
):
|
||||||
r.update_screen()
|
r.update_screen()
|
||||||
r.console.finish()
|
r.console.finish()
|
||||||
raise EOFError
|
raise EOFError
|
||||||
|
|
||||||
for i in range(r.get_arg()):
|
for i in range(r.get_arg()):
|
||||||
if r.pos != len(b):
|
if r.pos != len(b):
|
||||||
del b[r.pos]
|
del b[r.pos]
|
||||||
|
|
|
||||||
|
|
@ -390,7 +390,12 @@ def restore(self):
|
||||||
os.write(self.output_fd, b"\033[?7h")
|
os.write(self.output_fd, b"\033[?7h")
|
||||||
|
|
||||||
if hasattr(self, "old_sigwinch"):
|
if hasattr(self, "old_sigwinch"):
|
||||||
|
try:
|
||||||
signal.signal(signal.SIGWINCH, self.old_sigwinch)
|
signal.signal(signal.SIGWINCH, self.old_sigwinch)
|
||||||
|
except ValueError as e:
|
||||||
|
import threading
|
||||||
|
if threading.current_thread() is threading.main_thread():
|
||||||
|
raise e
|
||||||
del self.old_sigwinch
|
del self.old_sigwinch
|
||||||
|
|
||||||
def push_char(self, char: int | bytes) -> None:
|
def push_char(self, char: int | bytes) -> None:
|
||||||
|
|
|
||||||
|
|
@ -280,7 +280,7 @@ def add_argument(self, action):
|
||||||
if action.help is not SUPPRESS:
|
if action.help is not SUPPRESS:
|
||||||
|
|
||||||
# find all invocations
|
# find all invocations
|
||||||
get_invocation = self._format_action_invocation
|
get_invocation = lambda x: self._decolor(self._format_action_invocation(x))
|
||||||
invocation_lengths = [len(get_invocation(action)) + self._current_indent]
|
invocation_lengths = [len(get_invocation(action)) + self._current_indent]
|
||||||
for subaction in self._iter_indented_subactions(action):
|
for subaction in self._iter_indented_subactions(action):
|
||||||
invocation_lengths.append(len(get_invocation(subaction)) + self._current_indent)
|
invocation_lengths.append(len(get_invocation(subaction)) + self._current_indent)
|
||||||
|
|
@ -1959,7 +1959,9 @@ def add_subparsers(self, **kwargs):
|
||||||
# prog defaults to the usage message of this parser, skipping
|
# prog defaults to the usage message of this parser, skipping
|
||||||
# optional arguments and with no "usage:" prefix
|
# optional arguments and with no "usage:" prefix
|
||||||
if kwargs.get('prog') is None:
|
if kwargs.get('prog') is None:
|
||||||
formatter = self._get_formatter()
|
# Create formatter without color to avoid storing ANSI codes in prog
|
||||||
|
formatter = self.formatter_class(prog=self.prog)
|
||||||
|
formatter._set_color(False)
|
||||||
positionals = self._get_positional_actions()
|
positionals = self._get_positional_actions()
|
||||||
groups = self._mutually_exclusive_groups
|
groups = self._mutually_exclusive_groups
|
||||||
formatter.add_usage(None, positionals, groups, '')
|
formatter.add_usage(None, positionals, groups, '')
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ def callback():
|
||||||
return
|
return
|
||||||
except BaseException:
|
except BaseException:
|
||||||
if keyboard_interrupted:
|
if keyboard_interrupted:
|
||||||
|
if not CAN_USE_PYREPL:
|
||||||
self.write("\nKeyboardInterrupt\n")
|
self.write("\nKeyboardInterrupt\n")
|
||||||
else:
|
else:
|
||||||
self.showtraceback()
|
self.showtraceback()
|
||||||
|
|
|
||||||
|
|
@ -1050,8 +1050,8 @@ def _read_ready__on_eof(self):
|
||||||
|
|
||||||
def write(self, data):
|
def write(self, data):
|
||||||
if not isinstance(data, (bytes, bytearray, memoryview)):
|
if not isinstance(data, (bytes, bytearray, memoryview)):
|
||||||
raise TypeError(f'data argument must be a bytes-like object, '
|
raise TypeError(f'data argument must be a bytes, bytearray, or memoryview '
|
||||||
f'not {type(data).__name__!r}')
|
f'object, not {type(data).__name__!r}')
|
||||||
if self._eof:
|
if self._eof:
|
||||||
raise RuntimeError('Cannot call write() after write_eof()')
|
raise RuntimeError('Cannot call write() after write_eof()')
|
||||||
if self._empty_waiter is not None:
|
if self._empty_waiter is not None:
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@ def parse_request(self):
|
||||||
error response has already been sent back.
|
error response has already been sent back.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
is_http_0_9 = False
|
||||||
self.command = None # set in case of error on the first line
|
self.command = None # set in case of error on the first line
|
||||||
self.request_version = version = self.default_request_version
|
self.request_version = version = self.default_request_version
|
||||||
self.close_connection = True
|
self.close_connection = True
|
||||||
|
|
@ -359,6 +360,7 @@ def parse_request(self):
|
||||||
HTTPStatus.BAD_REQUEST,
|
HTTPStatus.BAD_REQUEST,
|
||||||
"Bad HTTP/0.9 request type (%r)" % command)
|
"Bad HTTP/0.9 request type (%r)" % command)
|
||||||
return False
|
return False
|
||||||
|
is_http_0_9 = True
|
||||||
self.command, self.path = command, path
|
self.command, self.path = command, path
|
||||||
|
|
||||||
# gh-87389: The purpose of replacing '//' with '/' is to protect
|
# gh-87389: The purpose of replacing '//' with '/' is to protect
|
||||||
|
|
@ -368,6 +370,11 @@ def parse_request(self):
|
||||||
if self.path.startswith('//'):
|
if self.path.startswith('//'):
|
||||||
self.path = '/' + self.path.lstrip('/') # Reduce to a single /
|
self.path = '/' + self.path.lstrip('/') # Reduce to a single /
|
||||||
|
|
||||||
|
# For HTTP/0.9, headers are not expected at all.
|
||||||
|
if is_http_0_9:
|
||||||
|
self.headers = {}
|
||||||
|
return True
|
||||||
|
|
||||||
# Examine the headers and look for a Connection directive.
|
# Examine the headers and look for a Connection directive.
|
||||||
try:
|
try:
|
||||||
self.headers = http.client.parse_headers(self.rfile,
|
self.headers = http.client.parse_headers(self.rfile,
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ Major contributors since 2005:
|
||||||
- 2014: Saimadhav Heblikar
|
- 2014: Saimadhav Heblikar
|
||||||
- 2015: Mark Roseman
|
- 2015: Mark Roseman
|
||||||
- 2017: Louie Lu, Cheryl Sabella, and Serhiy Storchaka
|
- 2017: Louie Lu, Cheryl Sabella, and Serhiy Storchaka
|
||||||
|
- 2025: Stan Ulbrych
|
||||||
|
|
||||||
For additional details refer to NEWS.txt and Changelog.
|
For additional details refer to NEWS.txt and Changelog.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ def make_pat():
|
||||||
name not in keyword.kwlist]
|
name not in keyword.kwlist]
|
||||||
builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b"
|
builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b"
|
||||||
comment = any("COMMENT", [r"#[^\n]*"])
|
comment = any("COMMENT", [r"#[^\n]*"])
|
||||||
stringprefix = r"(?i:r|u|f|fr|rf|b|br|rb)?"
|
stringprefix = r"(?i:r|u|f|fr|rf|b|br|rb|t|rt|tr)?"
|
||||||
sqstring = stringprefix + r"'[^'\\\n]*(\\.[^'\\\n]*)*'?"
|
sqstring = stringprefix + r"'[^'\\\n]*(\\.[^'\\\n]*)*'?"
|
||||||
dqstring = stringprefix + r'"[^"\\\n]*(\\.[^"\\\n]*)*"?'
|
dqstring = stringprefix + r'"[^"\\\n]*(\\.[^"\\\n]*)*"?'
|
||||||
sq3string = stringprefix + r"'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?"
|
sq3string = stringprefix + r"'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?"
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@
|
||||||
|
|
||||||
# The default tab setting for a Text widget, in average-width characters.
|
# The default tab setting for a Text widget, in average-width characters.
|
||||||
TK_TABWIDTH_DEFAULT = 8
|
TK_TABWIDTH_DEFAULT = 8
|
||||||
_py_version = ' (%s)' % platform.python_version()
|
|
||||||
darwin = sys.platform == 'darwin'
|
darwin = sys.platform == 'darwin'
|
||||||
|
|
||||||
def _sphinx_version():
|
def _sphinx_version():
|
||||||
|
|
@ -1008,12 +1007,16 @@ def open_recent_file(fn_closure=file_name):
|
||||||
def saved_change_hook(self):
|
def saved_change_hook(self):
|
||||||
short = self.short_title()
|
short = self.short_title()
|
||||||
long = self.long_title()
|
long = self.long_title()
|
||||||
|
_py_version = ' (%s)' % platform.python_version()
|
||||||
if short and long and not macosx.isCocoaTk():
|
if short and long and not macosx.isCocoaTk():
|
||||||
# Don't use both values on macOS because
|
# Don't use both values on macOS because
|
||||||
# that doesn't match platform conventions.
|
# that doesn't match platform conventions.
|
||||||
title = short + " - " + long + _py_version
|
title = short + " - " + long + _py_version
|
||||||
elif short:
|
elif short:
|
||||||
title = short
|
if short == "IDLE Shell":
|
||||||
|
title = short + " " + platform.python_version()
|
||||||
|
else:
|
||||||
|
title = short + _py_version
|
||||||
elif long:
|
elif long:
|
||||||
title = long
|
title = long
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ async def f(): await g()
|
||||||
# All valid prefixes for unicode and byte strings should be colored.
|
# All valid prefixes for unicode and byte strings should be colored.
|
||||||
r'x', u'x', R'x', U'x', f'x', F'x'
|
r'x', u'x', R'x', U'x', f'x', F'x'
|
||||||
fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'
|
fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'
|
||||||
|
tr'x', Tr'x', tR'x', TR'x', rt'x', rT'x', Rt'x', RT'x'
|
||||||
b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x', rB'x',Rb'x',RB'x'
|
b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x', rB'x',Rb'x',RB'x'
|
||||||
# Invalid combinations of legal characters should be half colored.
|
# Invalid combinations of legal characters should be half colored.
|
||||||
ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'
|
ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'
|
||||||
|
|
@ -390,19 +391,19 @@ def test_recolorize_main(self, mock_notify):
|
||||||
('6.0', ('KEYWORD',)), ('6.10', ('DEFINITION',)), ('6.11', ()),
|
('6.0', ('KEYWORD',)), ('6.10', ('DEFINITION',)), ('6.11', ()),
|
||||||
('8.0', ('STRING',)), ('8.4', ()), ('8.5', ('STRING',)),
|
('8.0', ('STRING',)), ('8.4', ()), ('8.5', ('STRING',)),
|
||||||
('8.12', ()), ('8.14', ('STRING',)),
|
('8.12', ()), ('8.14', ('STRING',)),
|
||||||
('19.0', ('KEYWORD',)),
|
('20.0', ('KEYWORD',)),
|
||||||
('20.4', ('KEYWORD',)), ('20.16', ('KEYWORD',)),# ('20.19', ('KEYWORD',)),
|
('21.4', ('KEYWORD',)), ('21.16', ('KEYWORD',)),# ('21.19', ('KEYWORD',)),
|
||||||
#('22.4', ('KEYWORD',)), ('22.10', ('KEYWORD',)), ('22.14', ('KEYWORD',)), ('22.19', ('STRING',)),
|
#('23.4', ('KEYWORD',)), ('23.10', ('KEYWORD',)), ('23.14', ('KEYWORD',)), ('23.19', ('STRING',)),
|
||||||
#('23.12', ('KEYWORD',)),
|
#('24.12', ('KEYWORD',)),
|
||||||
('24.8', ('KEYWORD',)),
|
('25.8', ('KEYWORD',)),
|
||||||
('25.4', ('KEYWORD',)), ('25.9', ('KEYWORD',)),
|
('26.4', ('KEYWORD',)), ('26.9', ('KEYWORD',)),
|
||||||
('25.11', ('KEYWORD',)), ('25.15', ('STRING',)),
|
('26.11', ('KEYWORD',)), ('26.15', ('STRING',)),
|
||||||
('25.19', ('KEYWORD',)), ('25.22', ()),
|
('26.19', ('KEYWORD',)), ('26.22', ()),
|
||||||
('25.24', ('KEYWORD',)), ('25.29', ('BUILTIN',)), ('25.37', ('KEYWORD',)),
|
('26.24', ('KEYWORD',)), ('26.29', ('BUILTIN',)), ('26.37', ('KEYWORD',)),
|
||||||
('26.4', ('KEYWORD',)), ('26.9', ('KEYWORD',)),# ('26.11', ('KEYWORD',)), ('26.14', (),),
|
('27.4', ('KEYWORD',)), ('27.9', ('KEYWORD',)),# ('27.11', ('KEYWORD',)), ('27.14', (),),
|
||||||
('27.25', ('STRING',)), ('27.38', ('STRING',)),
|
('28.25', ('STRING',)), ('28.38', ('STRING',)),
|
||||||
('29.0', ('STRING',)),
|
('30.0', ('STRING',)),
|
||||||
('30.1', ('STRING',)),
|
('31.1', ('STRING',)),
|
||||||
# SYNC at the end of every line.
|
# SYNC at the end of every line.
|
||||||
('1.55', ('SYNC',)), ('2.50', ('SYNC',)), ('3.34', ('SYNC',)),
|
('1.55', ('SYNC',)), ('2.50', ('SYNC',)), ('3.34', ('SYNC',)),
|
||||||
)
|
)
|
||||||
|
|
@ -433,7 +434,7 @@ def test_recolorize_main(self, mock_notify):
|
||||||
eq(text.tag_nextrange('STRING', '8.12'), ('8.14', '8.17'))
|
eq(text.tag_nextrange('STRING', '8.12'), ('8.14', '8.17'))
|
||||||
eq(text.tag_nextrange('STRING', '8.17'), ('8.19', '8.26'))
|
eq(text.tag_nextrange('STRING', '8.17'), ('8.19', '8.26'))
|
||||||
eq(text.tag_nextrange('SYNC', '8.0'), ('8.26', '9.0'))
|
eq(text.tag_nextrange('SYNC', '8.0'), ('8.26', '9.0'))
|
||||||
eq(text.tag_nextrange('SYNC', '30.0'), ('30.10', '32.0'))
|
eq(text.tag_nextrange('SYNC', '31.0'), ('31.10', '33.0'))
|
||||||
|
|
||||||
def _assert_highlighting(self, source, tag_ranges):
|
def _assert_highlighting(self, source, tag_ranges):
|
||||||
"""Check highlighting of a given piece of code.
|
"""Check highlighting of a given piece of code.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
"Test outwin, coverage 76%."
|
"Test outwin, coverage 76%."
|
||||||
|
|
||||||
from idlelib import outwin
|
from idlelib import outwin
|
||||||
|
import platform
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
from test.support import requires
|
from test.support import requires
|
||||||
|
|
@ -41,7 +42,7 @@ def test_ispythonsource(self):
|
||||||
self.assertFalse(w.ispythonsource(__file__))
|
self.assertFalse(w.ispythonsource(__file__))
|
||||||
|
|
||||||
def test_window_title(self):
|
def test_window_title(self):
|
||||||
self.assertEqual(self.window.top.title(), 'Output')
|
self.assertEqual(self.window.top.title(), 'Output' + ' (%s)' % platform.python_version())
|
||||||
|
|
||||||
def test_maybesave(self):
|
def test_maybesave(self):
|
||||||
w = self.window
|
w = self.window
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@
|
||||||
import linecache
|
import linecache
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
from platform import python_version
|
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
@ -841,7 +840,7 @@ def display_executing_dialog(self):
|
||||||
class PyShell(OutputWindow):
|
class PyShell(OutputWindow):
|
||||||
from idlelib.squeezer import Squeezer
|
from idlelib.squeezer import Squeezer
|
||||||
|
|
||||||
shell_title = "IDLE Shell " + python_version()
|
shell_title = "IDLE Shell"
|
||||||
|
|
||||||
# Override classes
|
# Override classes
|
||||||
ColorDelegator = ModifiedColorDelegator
|
ColorDelegator = ModifiedColorDelegator
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
import types
|
import types
|
||||||
import importlib
|
import importlib
|
||||||
import inspect
|
import inspect
|
||||||
import warnings
|
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
from typing import Union, Optional, cast
|
from typing import Union, Optional, cast
|
||||||
|
|
@ -16,39 +15,6 @@
|
||||||
Anchor = Package
|
Anchor = Package
|
||||||
|
|
||||||
|
|
||||||
def package_to_anchor(func):
|
|
||||||
"""
|
|
||||||
Replace 'package' parameter as 'anchor' and warn about the change.
|
|
||||||
|
|
||||||
Other errors should fall through.
|
|
||||||
|
|
||||||
>>> files('a', 'b')
|
|
||||||
Traceback (most recent call last):
|
|
||||||
TypeError: files() takes from 0 to 1 positional arguments but 2 were given
|
|
||||||
|
|
||||||
Remove this compatibility in Python 3.14.
|
|
||||||
"""
|
|
||||||
undefined = object()
|
|
||||||
|
|
||||||
@functools.wraps(func)
|
|
||||||
def wrapper(anchor=undefined, package=undefined):
|
|
||||||
if package is not undefined:
|
|
||||||
if anchor is not undefined:
|
|
||||||
return func(anchor, package)
|
|
||||||
warnings.warn(
|
|
||||||
"First parameter to files is renamed to 'anchor'",
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
return func(package)
|
|
||||||
elif anchor is undefined:
|
|
||||||
return func()
|
|
||||||
return func(anchor)
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
@package_to_anchor
|
|
||||||
def files(anchor: Optional[Anchor] = None) -> Traversable:
|
def files(anchor: Optional[Anchor] = None) -> Traversable:
|
||||||
"""
|
"""
|
||||||
Get a Traversable resource for an anchor.
|
Get a Traversable resource for an anchor.
|
||||||
|
|
|
||||||
|
|
@ -1065,7 +1065,9 @@ def __init__(self):
|
||||||
|
|
||||||
def tokeneater(self, type, token, srowcol, erowcol, line):
|
def tokeneater(self, type, token, srowcol, erowcol, line):
|
||||||
if not self.started and not self.indecorator:
|
if not self.started and not self.indecorator:
|
||||||
if type == tokenize.INDENT or token == "async":
|
if type in (tokenize.INDENT, tokenize.COMMENT, tokenize.NL):
|
||||||
|
pass
|
||||||
|
elif token == "async":
|
||||||
pass
|
pass
|
||||||
# skip any decorators
|
# skip any decorators
|
||||||
elif token == "@":
|
elif token == "@":
|
||||||
|
|
|
||||||
11
Lib/os.py
11
Lib/os.py
|
|
@ -58,6 +58,11 @@ def _get_exports_list(module):
|
||||||
__all__.append('_exit')
|
__all__.append('_exit')
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
try:
|
||||||
|
from posix import _clearenv
|
||||||
|
__all__.append('_clearenv')
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
import posixpath as path
|
import posixpath as path
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -768,6 +773,12 @@ def __ror__(self, other):
|
||||||
new.update(self)
|
new.update(self)
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
if _exists("_clearenv"):
|
||||||
|
def clear(self):
|
||||||
|
_clearenv()
|
||||||
|
self._data.clear()
|
||||||
|
|
||||||
|
|
||||||
def _create_environ_mapping():
|
def _create_environ_mapping():
|
||||||
if name == 'nt':
|
if name == 'nt':
|
||||||
# Where Env Var Names Must Be UPPERCASE
|
# Where Env Var Names Must Be UPPERCASE
|
||||||
|
|
|
||||||
|
|
@ -336,13 +336,8 @@ def _raw_path(self):
|
||||||
return paths[0]
|
return paths[0]
|
||||||
elif paths:
|
elif paths:
|
||||||
# Join path segments from the initializer.
|
# Join path segments from the initializer.
|
||||||
path = self.parser.join(*paths)
|
return self.parser.join(*paths)
|
||||||
# Cache the joined path.
|
|
||||||
paths.clear()
|
|
||||||
paths.append(path)
|
|
||||||
return path
|
|
||||||
else:
|
else:
|
||||||
paths.append('')
|
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
@ -490,16 +485,19 @@ def relative_to(self, other, *, walk_up=False):
|
||||||
"""
|
"""
|
||||||
if not hasattr(other, 'with_segments'):
|
if not hasattr(other, 'with_segments'):
|
||||||
other = self.with_segments(other)
|
other = self.with_segments(other)
|
||||||
for step, path in enumerate(chain([other], other.parents)):
|
parts = []
|
||||||
|
for path in chain([other], other.parents):
|
||||||
if path == self or path in self.parents:
|
if path == self or path in self.parents:
|
||||||
break
|
break
|
||||||
elif not walk_up:
|
elif not walk_up:
|
||||||
raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")
|
raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")
|
||||||
elif path.name == '..':
|
elif path.name == '..':
|
||||||
raise ValueError(f"'..' segment in {str(other)!r} cannot be walked")
|
raise ValueError(f"'..' segment in {str(other)!r} cannot be walked")
|
||||||
|
else:
|
||||||
|
parts.append('..')
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"{str(self)!r} and {str(other)!r} have different anchors")
|
raise ValueError(f"{str(self)!r} and {str(other)!r} have different anchors")
|
||||||
parts = ['..'] * step + self._tail[len(path._tail):]
|
parts.extend(self._tail[len(path._tail):])
|
||||||
return self._from_parsed_parts('', '', parts)
|
return self._from_parsed_parts('', '', parts)
|
||||||
|
|
||||||
def is_relative_to(self, other):
|
def is_relative_to(self, other):
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,33 @@ def parents(self):
|
||||||
parent = split(path)[0]
|
parent = split(path)[0]
|
||||||
return tuple(parents)
|
return tuple(parents)
|
||||||
|
|
||||||
|
def relative_to(self, other, *, walk_up=False):
|
||||||
|
"""Return the relative path to another path identified by the passed
|
||||||
|
arguments. If the operation is not possible (because this is not
|
||||||
|
related to the other path), raise ValueError.
|
||||||
|
|
||||||
|
The *walk_up* parameter controls whether `..` may be used to resolve
|
||||||
|
the path.
|
||||||
|
"""
|
||||||
|
parts = []
|
||||||
|
for path in (other,) + other.parents:
|
||||||
|
if self.is_relative_to(path):
|
||||||
|
break
|
||||||
|
elif not walk_up:
|
||||||
|
raise ValueError(f"{self!r} is not in the subpath of {other!r}")
|
||||||
|
elif path.name == '..':
|
||||||
|
raise ValueError(f"'..' segment in {other!r} cannot be walked")
|
||||||
|
else:
|
||||||
|
parts.append('..')
|
||||||
|
else:
|
||||||
|
raise ValueError(f"{self!r} and {other!r} have different anchors")
|
||||||
|
return self.with_segments(*parts, *self.parts[len(path.parts):])
|
||||||
|
|
||||||
|
def is_relative_to(self, other):
|
||||||
|
"""Return True if the path is relative to another path or False.
|
||||||
|
"""
|
||||||
|
return other == self or other in self.parents
|
||||||
|
|
||||||
def full_match(self, pattern):
|
def full_match(self, pattern):
|
||||||
"""
|
"""
|
||||||
Return True if this path matches the given glob-style pattern. The
|
Return True if this path matches the given glob-style pattern. The
|
||||||
|
|
|
||||||
|
|
@ -348,7 +348,7 @@ def read_stringnl(f, decode=True, stripquotes=True, *, encoding='latin-1'):
|
||||||
for q in (b'"', b"'"):
|
for q in (b'"', b"'"):
|
||||||
if data.startswith(q):
|
if data.startswith(q):
|
||||||
if not data.endswith(q):
|
if not data.endswith(q):
|
||||||
raise ValueError("strinq quote %r not found at both "
|
raise ValueError("string quote %r not found at both "
|
||||||
"ends of %r" % (q, data))
|
"ends of %r" % (q, data))
|
||||||
data = data[1:-1]
|
data = data[1:-1]
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,7 @@ def _get_path(userbase):
|
||||||
if sys.platform == 'darwin' and sys._framework:
|
if sys.platform == 'darwin' and sys._framework:
|
||||||
return f'{userbase}/lib/{implementation_lower}/site-packages'
|
return f'{userbase}/lib/{implementation_lower}/site-packages'
|
||||||
|
|
||||||
return f'{userbase}/lib/python{version[0]}.{version[1]}{abi_thread}/site-packages'
|
return f'{userbase}/lib/{implementation_lower}{version[0]}.{version[1]}{abi_thread}/site-packages'
|
||||||
|
|
||||||
|
|
||||||
def getuserbase():
|
def getuserbase():
|
||||||
|
|
|
||||||
|
|
@ -110,11 +110,6 @@
|
||||||
)
|
)
|
||||||
from _ssl import txt2obj as _txt2obj, nid2obj as _nid2obj
|
from _ssl import txt2obj as _txt2obj, nid2obj as _nid2obj
|
||||||
from _ssl import RAND_status, RAND_add, RAND_bytes
|
from _ssl import RAND_status, RAND_add, RAND_bytes
|
||||||
try:
|
|
||||||
from _ssl import RAND_egd
|
|
||||||
except ImportError:
|
|
||||||
# RAND_egd is not supported on some platforms
|
|
||||||
pass
|
|
||||||
from _ssl import get_sigalgs
|
from _ssl import get_sigalgs
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -645,6 +645,9 @@ def get_platform():
|
||||||
isn't particularly important.
|
isn't particularly important.
|
||||||
|
|
||||||
Examples of returned values:
|
Examples of returned values:
|
||||||
|
linux-x86_64
|
||||||
|
linux-aarch64
|
||||||
|
solaris-2.6-sun4u
|
||||||
|
|
||||||
|
|
||||||
Windows:
|
Windows:
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,9 @@
|
||||||
# Regexes needed for parsing Makefile (and similar syntaxes,
|
# Regexes needed for parsing Makefile (and similar syntaxes,
|
||||||
# like old-style Setup files).
|
# like old-style Setup files).
|
||||||
_variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)"
|
_variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)"
|
||||||
_findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)"
|
_findvar_rx = (r"\$(\([A-Za-z][A-Za-z0-9_]*\)"
|
||||||
_findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}"
|
r"|\{[A-Za-z][A-Za-z0-9_]*\}"
|
||||||
|
r"|\$?)")
|
||||||
|
|
||||||
|
|
||||||
def _parse_makefile(filename, vars=None, keep_unresolved=True):
|
def _parse_makefile(filename, vars=None, keep_unresolved=True):
|
||||||
|
|
@ -49,26 +50,7 @@ def _parse_makefile(filename, vars=None, keep_unresolved=True):
|
||||||
m = re.match(_variable_rx, line)
|
m = re.match(_variable_rx, line)
|
||||||
if m:
|
if m:
|
||||||
n, v = m.group(1, 2)
|
n, v = m.group(1, 2)
|
||||||
v = v.strip()
|
notdone[n] = v.strip()
|
||||||
# `$$' is a literal `$' in make
|
|
||||||
tmpv = v.replace('$$', '')
|
|
||||||
|
|
||||||
if "$" in tmpv:
|
|
||||||
notdone[n] = v
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
if n in _ALWAYS_STR:
|
|
||||||
raise ValueError
|
|
||||||
|
|
||||||
v = int(v)
|
|
||||||
except ValueError:
|
|
||||||
# insert literal `$'
|
|
||||||
done[n] = v.replace('$$', '$')
|
|
||||||
else:
|
|
||||||
done[n] = v
|
|
||||||
|
|
||||||
# do variable interpolation here
|
|
||||||
variables = list(notdone.keys())
|
|
||||||
|
|
||||||
# Variables with a 'PY_' prefix in the makefile. These need to
|
# Variables with a 'PY_' prefix in the makefile. These need to
|
||||||
# be made available without that prefix through sysconfig.
|
# be made available without that prefix through sysconfig.
|
||||||
|
|
@ -76,72 +58,64 @@ def _parse_makefile(filename, vars=None, keep_unresolved=True):
|
||||||
# if the expansion uses the name without a prefix.
|
# if the expansion uses the name without a prefix.
|
||||||
renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
|
renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
|
||||||
|
|
||||||
while len(variables) > 0:
|
def resolve_var(name):
|
||||||
for name in tuple(variables):
|
def repl(m):
|
||||||
value = notdone[name]
|
n = m[1]
|
||||||
m1 = re.search(_findvar1_rx, value)
|
if n == '$':
|
||||||
m2 = re.search(_findvar2_rx, value)
|
return '$'
|
||||||
if m1 and m2:
|
elif n == '':
|
||||||
m = m1 if m1.start() < m2.start() else m2
|
# bogus variable reference (e.g. "prefix=$/opt/python")
|
||||||
else:
|
if keep_unresolved:
|
||||||
m = m1 if m1 else m2
|
return m[0]
|
||||||
if m is not None:
|
raise ValueError
|
||||||
n = m.group(1)
|
elif n[0] == '(' and n[-1] == ')':
|
||||||
found = True
|
n = n[1:-1]
|
||||||
|
elif n[0] == '{' and n[-1] == '}':
|
||||||
|
n = n[1:-1]
|
||||||
|
|
||||||
if n in done:
|
if n in done:
|
||||||
item = str(done[n])
|
return str(done[n])
|
||||||
elif n in notdone:
|
elif n in notdone:
|
||||||
# get it on a subsequent round
|
return str(resolve_var(n))
|
||||||
found = False
|
|
||||||
elif n in os.environ:
|
elif n in os.environ:
|
||||||
# do it like make: fall back to environment
|
# do it like make: fall back to environment
|
||||||
item = os.environ[n]
|
return os.environ[n]
|
||||||
|
|
||||||
elif n in renamed_variables:
|
elif n in renamed_variables:
|
||||||
if (name.startswith('PY_') and
|
if name.startswith('PY_') and name[3:] in renamed_variables:
|
||||||
name[3:] in renamed_variables):
|
return ""
|
||||||
item = ""
|
n = 'PY_' + n
|
||||||
|
if n in notdone:
|
||||||
elif 'PY_' + n in notdone:
|
return str(resolve_var(n))
|
||||||
found = False
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
item = str(done['PY_' + n])
|
assert n not in done
|
||||||
|
return ""
|
||||||
else:
|
else:
|
||||||
done[n] = item = ""
|
done[n] = ""
|
||||||
|
return ""
|
||||||
|
|
||||||
if found:
|
assert name not in done
|
||||||
after = value[m.end():]
|
done[name] = ""
|
||||||
value = value[:m.start()] + item + after
|
try:
|
||||||
if "$" in after:
|
value = re.sub(_findvar_rx, repl, notdone[name])
|
||||||
notdone[name] = value
|
except ValueError:
|
||||||
else:
|
del done[name]
|
||||||
|
return ""
|
||||||
|
value = value.strip()
|
||||||
|
if name not in _ALWAYS_STR:
|
||||||
try:
|
try:
|
||||||
if name in _ALWAYS_STR:
|
|
||||||
raise ValueError
|
|
||||||
value = int(value)
|
value = int(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
done[name] = value.strip()
|
pass
|
||||||
else:
|
|
||||||
done[name] = value
|
done[name] = value
|
||||||
variables.remove(name)
|
if name.startswith('PY_') and name[3:] in renamed_variables:
|
||||||
|
|
||||||
if name.startswith('PY_') \
|
|
||||||
and name[3:] in renamed_variables:
|
|
||||||
|
|
||||||
name = name[3:]
|
name = name[3:]
|
||||||
if name not in done:
|
if name not in done:
|
||||||
done[name] = value
|
done[name] = value
|
||||||
|
return value
|
||||||
|
|
||||||
else:
|
for n in notdone:
|
||||||
# Adds unresolved variables to the done dict.
|
if n not in done:
|
||||||
# This is disabled when called from distutils.sysconfig
|
resolve_var(n)
|
||||||
if keep_unresolved:
|
|
||||||
done[name] = value
|
|
||||||
# bogus variable reference (e.g. "prefix=$/opt/python");
|
|
||||||
# just drop it since we can't deal
|
|
||||||
variables.remove(name)
|
|
||||||
|
|
||||||
# strip spurious spaces
|
# strip spurious spaces
|
||||||
for k, v in done.items():
|
for k, v in done.items():
|
||||||
|
|
|
||||||
|
|
@ -4341,7 +4341,7 @@ test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t narg
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
a = args[0];
|
a = args[0];
|
||||||
__clinic_args = _PyTuple_FromArray(args + 1, nargs - 1);
|
__clinic_args = PyTuple_FromArray(args + 1, nargs - 1);
|
||||||
if (__clinic_args == NULL) {
|
if (__clinic_args == NULL) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
@ -4356,7 +4356,7 @@ test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t narg
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
|
test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
|
||||||
/*[clinic end generated code: output=0c11c475e240869e input=2c49a482f68545c0]*/
|
/*[clinic end generated code: output=83cbe9554d04add2 input=2c49a482f68545c0]*/
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
test_vararg
|
test_vararg
|
||||||
|
|
@ -4421,7 +4421,7 @@ test_vararg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
|
||||||
}
|
}
|
||||||
a = fastargs[0];
|
a = fastargs[0];
|
||||||
__clinic_args = nargs > 1
|
__clinic_args = nargs > 1
|
||||||
? _PyTuple_FromArray(args + 1, nargs - 1)
|
? PyTuple_FromArray(args + 1, nargs - 1)
|
||||||
: PyTuple_New(0);
|
: PyTuple_New(0);
|
||||||
if (__clinic_args == NULL) {
|
if (__clinic_args == NULL) {
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
@ -4437,7 +4437,7 @@ test_vararg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
test_vararg_impl(PyObject *module, PyObject *a, PyObject *args)
|
test_vararg_impl(PyObject *module, PyObject *a, PyObject *args)
|
||||||
/*[clinic end generated code: output=17ba625cdd0369c1 input=7448995636d9186a]*/
|
/*[clinic end generated code: output=d773f7b54e61f73a input=7448995636d9186a]*/
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
test_vararg_with_default
|
test_vararg_with_default
|
||||||
|
|
@ -4514,7 +4514,7 @@ test_vararg_with_default(PyObject *module, PyObject *const *args, Py_ssize_t nar
|
||||||
}
|
}
|
||||||
skip_optional_kwonly:
|
skip_optional_kwonly:
|
||||||
__clinic_args = nargs > 1
|
__clinic_args = nargs > 1
|
||||||
? _PyTuple_FromArray(args + 1, nargs - 1)
|
? PyTuple_FromArray(args + 1, nargs - 1)
|
||||||
: PyTuple_New(0);
|
: PyTuple_New(0);
|
||||||
if (__clinic_args == NULL) {
|
if (__clinic_args == NULL) {
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
@ -4531,7 +4531,7 @@ test_vararg_with_default(PyObject *module, PyObject *const *args, Py_ssize_t nar
|
||||||
static PyObject *
|
static PyObject *
|
||||||
test_vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args,
|
test_vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args,
|
||||||
int b)
|
int b)
|
||||||
/*[clinic end generated code: output=3f2b06ab08d5d0be input=3a0f9f557ce1f712]*/
|
/*[clinic end generated code: output=d25e56802c197344 input=3a0f9f557ce1f712]*/
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
test_vararg_with_only_defaults
|
test_vararg_with_only_defaults
|
||||||
|
|
@ -4612,7 +4612,7 @@ test_vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize
|
||||||
}
|
}
|
||||||
c = fastargs[1];
|
c = fastargs[1];
|
||||||
skip_optional_kwonly:
|
skip_optional_kwonly:
|
||||||
__clinic_args = _PyTuple_FromArray(args, nargs);
|
__clinic_args = PyTuple_FromArray(args, nargs);
|
||||||
if (__clinic_args == NULL) {
|
if (__clinic_args == NULL) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
@ -4628,7 +4628,7 @@ test_vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize
|
||||||
static PyObject *
|
static PyObject *
|
||||||
test_vararg_with_only_defaults_impl(PyObject *module, PyObject *args, int b,
|
test_vararg_with_only_defaults_impl(PyObject *module, PyObject *args, int b,
|
||||||
PyObject *c)
|
PyObject *c)
|
||||||
/*[clinic end generated code: output=f46666f0b1bf86b9 input=6983e66817f82924]*/
|
/*[clinic end generated code: output=7366943a7df42e05 input=6983e66817f82924]*/
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
test_paramname_module
|
test_paramname_module
|
||||||
|
|
|
||||||
|
|
@ -646,15 +646,23 @@ def _add_cross_compile_opts(self, regrtest_opts):
|
||||||
return (environ, keep_environ)
|
return (environ, keep_environ)
|
||||||
|
|
||||||
def _add_ci_python_opts(self, python_opts, keep_environ):
|
def _add_ci_python_opts(self, python_opts, keep_environ):
|
||||||
# --fast-ci and --slow-ci add options to Python:
|
# --fast-ci and --slow-ci add options to Python.
|
||||||
# "-u -W default -bb -E"
|
#
|
||||||
|
# Some platforms run tests in embedded mode and cannot change options
|
||||||
|
# after startup, so if this function changes, consider also updating:
|
||||||
|
# * gradle_task in Android/android.py
|
||||||
|
|
||||||
# Unbuffered stdout and stderr
|
# Unbuffered stdout and stderr. This isn't helpful on Android, because
|
||||||
if not sys.stdout.write_through:
|
# it would cause lines to be split into multiple log messages.
|
||||||
|
if not sys.stdout.write_through and sys.platform != "android":
|
||||||
python_opts.append('-u')
|
python_opts.append('-u')
|
||||||
|
|
||||||
# Add warnings filter 'error'
|
# Add warnings filter 'error', unless the user specified a different
|
||||||
if 'default' not in sys.warnoptions:
|
# filter. Ignore BytesWarning since it's controlled by '-b' below.
|
||||||
|
if not [
|
||||||
|
opt for opt in sys.warnoptions
|
||||||
|
if not opt.endswith("::BytesWarning")
|
||||||
|
]:
|
||||||
python_opts.extend(('-W', 'error'))
|
python_opts.extend(('-W', 'error'))
|
||||||
|
|
||||||
# Error on bytes/str comparison
|
# Error on bytes/str comparison
|
||||||
|
|
@ -673,8 +681,12 @@ def _execute_python(self, cmd, environ):
|
||||||
|
|
||||||
cmd_text = shlex.join(cmd)
|
cmd_text = shlex.join(cmd)
|
||||||
try:
|
try:
|
||||||
print(f"+ {cmd_text}", flush=True)
|
# Android and iOS run tests in embedded mode. To update their
|
||||||
|
# Python options, see the comment in _add_ci_python_opts.
|
||||||
|
if not cmd[0]:
|
||||||
|
raise ValueError("No Python executable is present")
|
||||||
|
|
||||||
|
print(f"+ {cmd_text}", flush=True)
|
||||||
if hasattr(os, 'execv') and not MS_WINDOWS:
|
if hasattr(os, 'execv') and not MS_WINDOWS:
|
||||||
os.execv(cmd[0], cmd)
|
os.execv(cmd[0], cmd)
|
||||||
# On success, execv() do no return.
|
# On success, execv() do no return.
|
||||||
|
|
|
||||||
|
|
@ -310,6 +310,16 @@ def requires(resource, msg=None):
|
||||||
if resource == 'gui' and not _is_gui_available():
|
if resource == 'gui' and not _is_gui_available():
|
||||||
raise ResourceDenied(_is_gui_available.reason)
|
raise ResourceDenied(_is_gui_available.reason)
|
||||||
|
|
||||||
|
def _get_kernel_version(sysname="Linux"):
|
||||||
|
import platform
|
||||||
|
if platform.system() != sysname:
|
||||||
|
return None
|
||||||
|
version_txt = platform.release().split('-', 1)[0]
|
||||||
|
try:
|
||||||
|
return tuple(map(int, version_txt.split('.')))
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
def _requires_unix_version(sysname, min_version):
|
def _requires_unix_version(sysname, min_version):
|
||||||
"""Decorator raising SkipTest if the OS is `sysname` and the version is less
|
"""Decorator raising SkipTest if the OS is `sysname` and the version is less
|
||||||
than `min_version`.
|
than `min_version`.
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
captured_stderr,
|
captured_stderr,
|
||||||
force_not_colorized,
|
force_not_colorized,
|
||||||
force_not_colorized_test_class,
|
force_not_colorized_test_class,
|
||||||
|
swap_attr,
|
||||||
)
|
)
|
||||||
from test.support import import_helper
|
from test.support import import_helper
|
||||||
from test.support import os_helper
|
from test.support import os_helper
|
||||||
|
|
@ -7128,7 +7129,8 @@ class TestColorized(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
# Ensure color even if ran with NO_COLOR=1
|
# Ensure color even if ran with NO_COLOR=1
|
||||||
_colorize.can_colorize = lambda *args, **kwargs: True
|
self.enterContext(swap_attr(_colorize, 'can_colorize',
|
||||||
|
lambda *args, **kwargs: True))
|
||||||
self.theme = _colorize.get_theme(force_color=True).argparse
|
self.theme = _colorize.get_theme(force_color=True).argparse
|
||||||
|
|
||||||
def test_argparse_color(self):
|
def test_argparse_color(self):
|
||||||
|
|
@ -7355,6 +7357,17 @@ def __init__(self, prog):
|
||||||
{short_b}+f{reset}, {long_b}++foo{reset} {label_b}FOO{reset} foo help
|
{short_b}+f{reset}, {long_b}++foo{reset} {label_b}FOO{reset} foo help
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
|
def test_subparser_prog_is_stored_without_color(self):
|
||||||
|
parser = argparse.ArgumentParser(prog='complex', color=True)
|
||||||
|
sub = parser.add_subparsers(dest='command')
|
||||||
|
demo_parser = sub.add_parser('demo')
|
||||||
|
|
||||||
|
self.assertNotIn('\x1b[', demo_parser.prog)
|
||||||
|
|
||||||
|
demo_parser.color = False
|
||||||
|
help_text = demo_parser.format_help()
|
||||||
|
self.assertNotIn('\x1b[', help_text)
|
||||||
|
|
||||||
|
|
||||||
class TestModule(unittest.TestCase):
|
class TestModule(unittest.TestCase):
|
||||||
def test_deprecated__version__(self):
|
def test_deprecated__version__(self):
|
||||||
|
|
|
||||||
|
|
@ -1180,12 +1180,48 @@ async def runner():
|
||||||
|
|
||||||
|
|
||||||
@support.requires_fork()
|
@support.requires_fork()
|
||||||
class TestFork(unittest.IsolatedAsyncioTestCase):
|
class TestFork(unittest.TestCase):
|
||||||
|
|
||||||
async def test_fork_not_share_event_loop(self):
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
with warnings_helper.ignore_fork_in_thread_deprecation_warnings():
|
def test_fork_not_share_current_task(self):
|
||||||
|
loop = object()
|
||||||
|
task = object()
|
||||||
|
asyncio._set_running_loop(loop)
|
||||||
|
self.addCleanup(asyncio._set_running_loop, None)
|
||||||
|
asyncio.tasks._enter_task(loop, task)
|
||||||
|
self.addCleanup(asyncio.tasks._leave_task, loop, task)
|
||||||
|
self.assertIs(asyncio.current_task(), task)
|
||||||
|
r, w = os.pipe()
|
||||||
|
self.addCleanup(os.close, r)
|
||||||
|
self.addCleanup(os.close, w)
|
||||||
|
pid = os.fork()
|
||||||
|
if pid == 0:
|
||||||
|
# child
|
||||||
|
try:
|
||||||
|
asyncio._set_running_loop(loop)
|
||||||
|
current_task = asyncio.current_task()
|
||||||
|
if current_task is None:
|
||||||
|
os.write(w, b'NO TASK')
|
||||||
|
else:
|
||||||
|
os.write(w, b'TASK:' + str(id(current_task)).encode())
|
||||||
|
except BaseException as e:
|
||||||
|
os.write(w, b'ERROR:' + ascii(e).encode())
|
||||||
|
finally:
|
||||||
|
asyncio._set_running_loop(None)
|
||||||
|
os._exit(0)
|
||||||
|
else:
|
||||||
|
# parent
|
||||||
|
result = os.read(r, 100)
|
||||||
|
self.assertEqual(result, b'NO TASK')
|
||||||
|
wait_process(pid, exitcode=0)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
|
def test_fork_not_share_event_loop(self):
|
||||||
# The forked process should not share the event loop with the parent
|
# The forked process should not share the event loop with the parent
|
||||||
loop = asyncio.get_running_loop()
|
loop = object()
|
||||||
|
asyncio._set_running_loop(loop)
|
||||||
|
self.assertIs(asyncio.get_running_loop(), loop)
|
||||||
|
self.addCleanup(asyncio._set_running_loop, None)
|
||||||
r, w = os.pipe()
|
r, w = os.pipe()
|
||||||
self.addCleanup(os.close, r)
|
self.addCleanup(os.close, r)
|
||||||
self.addCleanup(os.close, w)
|
self.addCleanup(os.close, w)
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,28 @@ def test_tuple_new(self):
|
||||||
self.assertRaises(SystemError, tuple_new, PY_SSIZE_T_MIN)
|
self.assertRaises(SystemError, tuple_new, PY_SSIZE_T_MIN)
|
||||||
self.assertRaises(MemoryError, tuple_new, PY_SSIZE_T_MAX)
|
self.assertRaises(MemoryError, tuple_new, PY_SSIZE_T_MAX)
|
||||||
|
|
||||||
|
def test_tuple_fromarray(self):
|
||||||
|
# Test PyTuple_FromArray()
|
||||||
|
tuple_fromarray = _testcapi.tuple_fromarray
|
||||||
|
|
||||||
|
tup = tuple([i] for i in range(5))
|
||||||
|
copy = tuple_fromarray(tup)
|
||||||
|
self.assertEqual(copy, tup)
|
||||||
|
|
||||||
|
tup = ()
|
||||||
|
copy = tuple_fromarray(tup)
|
||||||
|
self.assertIs(copy, tup)
|
||||||
|
|
||||||
|
copy = tuple_fromarray(NULL, 0)
|
||||||
|
self.assertIs(copy, ())
|
||||||
|
|
||||||
|
with self.assertRaises(SystemError):
|
||||||
|
tuple_fromarray(NULL, -1)
|
||||||
|
with self.assertRaises(SystemError):
|
||||||
|
tuple_fromarray(NULL, PY_SSIZE_T_MIN)
|
||||||
|
with self.assertRaises(MemoryError):
|
||||||
|
tuple_fromarray(NULL, PY_SSIZE_T_MAX)
|
||||||
|
|
||||||
def test_tuple_pack(self):
|
def test_tuple_pack(self):
|
||||||
# Test PyTuple_Pack()
|
# Test PyTuple_Pack()
|
||||||
pack = _testlimitedcapi.tuple_pack
|
pack = _testlimitedcapi.tuple_pack
|
||||||
|
|
|
||||||
|
|
@ -514,6 +514,10 @@ def myfunc():
|
||||||
_testcapi.set_func_kwdefaults_via_capi(myfunc, new_kwdefaults)
|
_testcapi.set_func_kwdefaults_via_capi(myfunc, new_kwdefaults)
|
||||||
self.assertIn((_testcapi.PYFUNC_EVENT_MODIFY_KWDEFAULTS, myfunc, new_kwdefaults), events)
|
self.assertIn((_testcapi.PYFUNC_EVENT_MODIFY_KWDEFAULTS, myfunc, new_kwdefaults), events)
|
||||||
|
|
||||||
|
new_qualname = "foo.bar"
|
||||||
|
myfunc.__qualname__ = new_qualname
|
||||||
|
self.assertIn((_testcapi.PYFUNC_EVENT_MODIFY_QUALNAME, myfunc, new_qualname), events)
|
||||||
|
|
||||||
# Clear events reference to func
|
# Clear events reference to func
|
||||||
events = []
|
events = []
|
||||||
del myfunc
|
del myfunc
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue