Merge branch 'python:main' into pyrepl-module-completion-check-for-already-imported-modules

This commit is contained in:
Loïc Simon 2025-10-12 00:11:38 +02:00 committed by GitHub
commit e3f1ddb88b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
268 changed files with 6793 additions and 3830 deletions

4
.github/CODEOWNERS vendored
View file

@ -86,6 +86,10 @@ Modules/makesetup @erlend-aasland @AA-Turner @emmatyping
Modules/Setup* @erlend-aasland @AA-Turner @emmatyping
Tools/build/regen-configure.sh @AA-Turner
# generate-build-details
Tools/build/generate-build-details.py @FFY00
Lib/test/test_build_details.py @FFY00
# ----------------------------------------------------------------------------
# Documentation

View file

@ -1,6 +1,7 @@
self-hosted-runner:
# 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

View file

@ -202,24 +202,16 @@ jobs:
strategy:
fail-fast: false
matrix:
# Cirrus and macos-14 are M1, macos-13 is default GHA Intel.
# macOS 13 only runs tests against the GIL-enabled CPython.
# Cirrus used for upstream, macos-14 for forks.
# macos-14 is M1, macos-15-intel is Intel.
# macos-15-intel only runs tests against the GIL-enabled CPython.
os:
- ghcr.io/cirruslabs/macos-runner:sonoma
- macos-14
- macos-13
is-fork: # only used for the exclusion trick
- ${{ github.repository_owner != 'python' }}
- macos-15-intel
free-threading:
- false
- true
exclude:
- os: ghcr.io/cirruslabs/macos-runner:sonoma
is-fork: true
- os: macos-14
is-fork: false
- os: macos-13
- os: macos-15-intel
free-threading: true
uses: ./.github/workflows/reusable-macos.yml
with:
@ -273,7 +265,7 @@ jobs:
# Keep 1.1.1w in our list despite it being upstream EOL and otherwise
# unsupported as it most resembles other 1.1.1-work-a-like ssl APIs
# supported by important vendors such as AWS-LC.
openssl_ver: [1.1.1w, 3.0.17, 3.2.5, 3.3.4, 3.4.2, 3.5.2]
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
env:
OPENSSL_VER: ${{ matrix.openssl_ver }}
@ -409,9 +401,8 @@ jobs:
fail-fast: false
matrix:
include:
# Use the same runs-on configuration as build-macos and build-ubuntu.
- arch: aarch64
runs-on: ${{ github.repository_owner == 'python' && 'ghcr.io/cirruslabs/macos-runner:sonoma' || 'macos-14' }}
runs-on: macos-14
- arch: x86_64
runs-on: ubuntu-24.04
@ -421,7 +412,7 @@ jobs:
with:
persist-credentials: false
- 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:
name: 'WASI'
@ -438,7 +429,7 @@ jobs:
needs: build-context
if: needs.build-context.outputs.run-tests == 'true'
env:
OPENSSL_VER: 3.0.16
OPENSSL_VER: 3.0.18
PYTHONSTRICTEXTENSIONBUILD: 1
steps:
- uses: actions/checkout@v4
@ -558,7 +549,7 @@ jobs:
matrix:
os: [ubuntu-24.04]
env:
OPENSSL_VER: 3.0.16
OPENSSL_VER: 3.0.18
PYTHONSTRICTEXTENSIONBUILD: 1
ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0
steps:

View file

@ -81,7 +81,7 @@ jobs:
runner: windows-11-arm
- target: x86_64-apple-darwin/clang
architecture: x86_64
runner: macos-13
runner: macos-15-intel
- target: aarch64-apple-darwin/clang
architecture: aarch64
runner: macos-14
@ -106,15 +106,10 @@ jobs:
./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
# The `find` line is required as a result of https://github.com/actions/runner-images/issues/9966.
# This is a bug in the macOS runner image where the pre-installed Python is installed in the same
# directory as the Homebrew Python, which causes the build to fail for macos-13. This line removes
# the symlink to the pre-installed Python so that the Homebrew Python is used instead.
- name: macOS
if: runner.os == 'macOS'
run: |
brew update
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
brew install llvm@${{ matrix.llvm }}
export SDKROOT="$(xcrun --show-sdk-path)"
# Set MACOSX_DEPLOYMENT_TARGET and -Werror=unguarded-availability to

View file

@ -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 }}

View file

@ -60,15 +60,15 @@ jobs:
--prefix=/opt/python-dev \
--with-openssl="$(brew --prefix openssl@3.0)"
- name: Build CPython
if : ${{ inputs.free-threading || inputs.os != 'macos-13' }}
if : ${{ inputs.free-threading || inputs.os != 'macos-15-intel' }}
run: gmake -j8
- name: Build CPython for compiler warning check
if : ${{ !inputs.free-threading && inputs.os == 'macos-13' }}
if : ${{ !inputs.free-threading && inputs.os == 'macos-15-intel' }}
run: set -o pipefail; gmake -j8 --output-sync 2>&1 | tee compiler_output_macos.txt
- name: Display build info
run: make pythoninfo
- name: Check compiler warnings
if : ${{ !inputs.free-threading && inputs.os == 'macos-13' }}
if : ${{ !inputs.free-threading && inputs.os == 'macos-15-intel' }}
run: >-
python3 Tools/build/check_warnings.py
--compiler-output-file-path=compiler_output_macos.txt

View file

@ -30,7 +30,7 @@ jobs:
runs-on: ${{ inputs.os }}
timeout-minutes: 60
env:
OPENSSL_VER: 3.0.15
OPENSSL_VER: 3.0.18
PYTHONSTRICTEXTENSIONBUILD: 1
TERM: linux
steps:

View file

@ -58,7 +58,7 @@ jobs:
# runner: windows-2022
- target: x86_64-apple-darwin/clang
architecture: x86_64
runner: macos-13
runner: macos-15-intel
- target: aarch64-apple-darwin/clang
architecture: aarch64
runner: macos-14
@ -101,17 +101,10 @@ jobs:
set LLVMInstallDir=C:\Program Files\LLVM
./PCbuild/build.bat --tail-call-interp -p ${{ matrix.architecture }}
# The `find` line is required as a result of https://github.com/actions/runner-images/issues/9966.
# This is a bug in the macOS runner image where the pre-installed Python is installed in the same
# directory as the Homebrew Python, which causes the build to fail for macos-13. This line removes
# the symlink to the pre-installed Python so that the Homebrew Python is used instead.
# Note: when a new LLVM is released, the homebrew installation directory changes, so the builds will fail.
# We either need to upgrade LLVM or change the directory being pointed to.
- name: Native macOS (release)
if: runner.os == 'macOS'
run: |
brew update
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
brew install llvm@${{ matrix.llvm }}
export SDKROOT="$(xcrun --show-sdk-path)"
export PATH="/usr/local/opt/llvm@${{ matrix.llvm }}/bin:$PATH"

View file

@ -26,6 +26,10 @@ repos:
name: Run Ruff (lint) on Tools/peg_generator/
args: [--exit-non-zero-on-fix, --config=Tools/peg_generator/.ruff.toml]
files: ^Tools/peg_generator/
- id: ruff-check
name: Run Ruff (lint) on Tools/wasm/
args: [--exit-non-zero-on-fix, --config=Tools/wasm/.ruff.toml]
files: ^Tools/wasm/
- id: ruff-format
name: Run Ruff (format) on Doc/
args: [--check]
@ -34,6 +38,10 @@ repos:
name: Run Ruff (format) on Tools/build/check_warnings.py
args: [--check, --config=Tools/build/.ruff.toml]
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
rev: 25.9.0

View file

@ -2,6 +2,7 @@
import asyncio
import argparse
import json
import os
import platform
import re
@ -184,10 +185,16 @@ def make_build_python(context):
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):
os.chdir(prefix_dir)
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"]:
filename = f"{name_ver}-{host}.tar.gz"
download(f"{deps_url}/{name_ver}/{filename}")
@ -546,27 +553,33 @@ async def gradle_task(context):
task_prefix = "connected"
env["ANDROID_SERIAL"] = context.connected
if context.command:
mode = "-c"
module = context.command
else:
mode = "-m"
module = context.module or "test"
if context.ci_mode:
context.args[0:0] = [
# See _add_ci_python_opts in libregrtest/main.py.
"-W", "error", "-bb", "-E",
# 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 = [
gradlew, "--console", "plain", f"{task_prefix}DebugAndroidTest",
] + [
# Build-time properties
f"-Ppython.{name}={value}"
f"-P{name}={value}"
for name, value in [
("sitePackages", context.site_packages), ("cwd", context.cwd)
] if value
] + [
# Runtime properties
f"-Pandroid.testInstrumentationRunnerArguments.python{name}={value}"
for name, value in [
("Mode", mode), ("Module", module), ("Args", join_command(context.args))
] if value
("python.sitePackages", context.site_packages),
("python.cwd", context.cwd),
(
"android.testInstrumentationRunnerArguments.pythonArgs",
json.dumps(context.args),
),
]
if value
]
if context.verbose >= 2:
args.append("--info")
@ -734,15 +747,14 @@ def ci(context):
else:
with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir:
print("::group::Tests")
# Prove the package is self-contained by using it to run the tests.
shutil.unpack_archive(package_path, temp_dir)
# Randomization is disabled because order-dependent failures are
# 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"]
launcher_args = [
"--managed", "maxVersion", "-v", f"--{context.ci_mode}-ci"
]
run(
["./android.py", "test", *launcher_args, "--", *test_args],
["./android.py", "test", *launcher_args],
cwd=temp_dir
)
print("::endgroup::")
@ -825,18 +837,11 @@ def add_parser(*args, **kwargs):
test.add_argument(
"--cwd", metavar="DIR", type=abspath,
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(
"args", nargs="*", help=f"Arguments to add to sys.argv. "
f"Separate them from {SCRIPT_NAME}'s own arguments with `--`.")
"args", nargs="*", help=f"Python command-line arguments. "
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.
for subcommand in [package, ci]:
@ -844,6 +849,16 @@ def add_parser(*args, **kwargs):
"-g", action="store_true", default=False, dest="debug",
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()

View file

@ -20,7 +20,7 @@ class PythonSuite {
val status = PythonTestRunner(
InstrumentationRegistry.getInstrumentation().targetContext
).run(
InstrumentationRegistry.getArguments()
InstrumentationRegistry.getArguments().getString("pythonArgs")!!,
)
assertEquals(0, status)
} finally {

View file

@ -3,6 +3,7 @@
#include <jni.h>
#include <pthread.h>
#include <Python.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
@ -15,6 +16,13 @@ static void throw_runtime_exception(JNIEnv *env, const char *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 ------------------------------------------------------
@ -95,10 +103,7 @@ JNIEXPORT void JNICALL Java_org_python_testbed_PythonTestRunner_redirectStdioToL
for (StreamInfo *si = STREAMS; si->file; si++) {
char *error_prefix;
if ((error_prefix = redirect_stream(si))) {
char error_message[1024];
snprintf(error_message, sizeof(error_message),
"%s: %s", error_prefix, strerror(errno));
throw_runtime_exception(env, error_message);
throw_errno(env, error_prefix);
return;
}
}
@ -107,13 +112,38 @@ JNIEXPORT void JNICALL Java_org_python_testbed_PythonTestRunner_redirectStdioToL
// --- Python initialization ---------------------------------------------------
static PyStatus set_config_string(
JNIEnv *env, PyConfig *config, wchar_t **config_str, jstring value
) {
const char *value_utf8 = (*env)->GetStringUTFChars(env, value, NULL);
PyStatus status = PyConfig_SetBytesString(config, config_str, value_utf8);
(*env)->ReleaseStringUTFChars(env, value, value_utf8);
return status;
static char *init_signals() {
// 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.
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) {
@ -121,27 +151,47 @@ static void throw_status(JNIEnv *env, PyStatus status) {
}
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;
PyStatus status;
PyConfig_InitIsolatedConfig(&config);
PyConfig_InitPythonConfig(&config);
status = set_config_string(env, &config, &config.home, home);
if (PyStatus_Exception(status)) {
jsize argc = (*env)->GetArrayLength(env, args);
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);
return 1;
}
status = set_config_string(env, &config, &config.run_module, runModule);
status = PyConfig_SetBytesString(&config, &config.home, home_utf8);
if (PyStatus_Exception(status)) {
throw_status(env, status);
return 1;
}
// Some tests generate SIGPIPE and SIGXFSZ, which should be ignored.
config.install_signal_handlers = 1;
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
throw_status(env, status);

View file

@ -5,6 +5,7 @@ import android.os.*
import android.system.Os
import android.widget.TextView
import androidx.appcompat.app.*
import org.json.JSONArray
import java.io.*
@ -15,30 +16,25 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
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"
}
}
class PythonTestRunner(val context: Context) {
fun run(instrumentationArgs: Bundle) = run(
instrumentationArgs.getString("pythonMode")!!,
instrumentationArgs.getString("pythonModule")!!,
instrumentationArgs.getString("pythonArgs") ?: "",
)
/** Run Python.
*
* @param mode Either "-c" or "-m".
* @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`.
* @param args Python command-line, encoded as JSON.
* @return The Python exit status: zero on success, nonzero on failure. */
fun run(mode: String, module: String, args: String) : Int {
Os.setenv("PYTHON_MODE", mode, true)
Os.setenv("PYTHON_MODULE", module, true)
Os.setenv("PYTHON_ARGS", args, true)
fun run(args: String) : Int {
// We leave argument 0 as an empty string, which is a placeholder for the
// executable name in embedded mode.
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,
// but Android only sets it on API level 33 and later.
@ -47,10 +43,7 @@ class PythonTestRunner(val context: Context) {
val pythonHome = extractAssets()
System.loadLibrary("main_activity")
redirectStdioToLogcat()
// 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")
return runPython(pythonHome.toString(), argsStringArray)
}
private fun extractAssets() : File {
@ -59,6 +52,13 @@ class PythonTestRunner(val context: Context) {
throw RuntimeException("Failed to delete $pythonHome")
}
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
}
@ -88,5 +88,5 @@ class PythonTestRunner(val context: Context) {
}
private external fun redirectStdioToLogcat()
private external fun runPython(home: String, runModule: String) : Int
private external fun runPython(home: String, args: Array<String>) : Int
}

View file

@ -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}")

View file

@ -312,11 +312,18 @@ def unpack_deps(
On iOS, as a safety mechanism, any dynamic libraries will be purged from
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"
for name_ver in [
"BZip2-1.0.8-2",
"libFFI-3.4.7-2",
"OpenSSL-3.0.17-1",
"OpenSSL-3.0.18-1",
"XZ-5.6.4-2",
"mpdecimal-4.0.0-2",
"zstd-1.5.7-1",

View file

@ -184,7 +184,7 @@ venv:
fi
.PHONY: dist-no-html
dist-no-html: dist-text dist-pdf dist-epub dist-texinfo
dist-no-html: dist-text dist-epub dist-texinfo
.PHONY: dist
dist:

View file

@ -260,7 +260,7 @@ Create, Finish, Discard
writer size to *size*. The caller is responsible to write *size*
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.

View file

@ -175,6 +175,9 @@ There are a few functions specific to Python functions.
.. versionadded:: 3.12
- ``PyFunction_PYFUNC_EVENT_MODIFY_QUALNAME``
.. versionadded:: 3.15
.. c:type:: int (*PyFunction_WatchCallback)(PyFunction_WatchEvent event, PyFunctionObject *func, PyObject *new_value)

View file

@ -1113,7 +1113,7 @@ code, or when embedding the Python interpreter:
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.
.. seealso:
.. seealso::
:c:func:`PyEval_ReleaseThread`
.. note::
@ -1124,6 +1124,19 @@ code, or when embedding the Python interpreter:
The following functions use thread-local storage, and are not compatible
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()
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.
.. note::
This function does not account for :term:`thread states <thread state>` created
by something other than :c:func:`PyGILState_Ensure` (such as :c:func:`PyThreadState_New`).
This function may return non-``NULL`` even when the :term:`thread state`
is detached.
Prefer :c:func:`PyThreadState_Get` or :c:func:`PyThreadState_GetUnchecked`
for most cases.
.. seealso: :c:func:`PyThreadState_Get``
.. seealso:: :c:func:`PyThreadState_Get`
.. 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>`
.. 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`.
.. 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)

View file

@ -37,6 +37,19 @@ Tuple Objects
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, ...)
Return a new tuple object of size *n*,

View file

@ -15,7 +15,6 @@ although there is currently no date scheduled for their removal.
* :mod:`builtins`:
* ``bool(NotImplemented)``.
* Generators: ``throw(type, exc, tb)`` and ``athrow(type, exc, tb)``
signature is deprecated: use ``throw(exc)`` and ``athrow(exc)`` instead,
the single argument signature.

View file

@ -316,13 +316,14 @@ StreamWriter
If that fails, the data is queued in an internal write buffer until it can be
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::
stream.write(data)
await stream.drain()
.. note::
The *data* buffer should be a C contiguous one-dimensional :term:`bytes-like object <bytes-like object>`.
.. method:: writelines(data)

View file

@ -336,7 +336,7 @@ Collections Abstract Base Classes -- Detailed Descriptions
.. note::
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.
Using ``isinstance(gencoro, Awaitable)`` for them will return ``False``.
Use :func:`inspect.isawaitable` to detect them.
@ -354,7 +354,7 @@ Collections Abstract Base Classes -- Detailed Descriptions
.. note::
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.
Using ``isinstance(gencoro, Coroutine)`` for them will return ``False``.
Use :func:`inspect.isawaitable` to detect them.

View file

@ -1,6 +1,8 @@
The :mod:`!compression` package
===============================
.. module:: compression
.. versionadded:: 3.14
The :mod:`!compression` package contains the canonical compression modules

View file

@ -327,10 +327,10 @@ Functions and classes provided:
.. function:: redirect_stdout(new_target)
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
is hardwired to stdout.
is hardwired to :data:`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
@ -366,8 +366,8 @@ Functions and classes provided:
.. function:: redirect_stderr(new_target)
Similar to :func:`~contextlib.redirect_stdout` but redirecting
:data:`sys.stderr` to another file or file-like object.
Similar to :func:`~contextlib.redirect_stdout` but redirecting the global
:data:`sys.stderr` to another :term:`file object`.
This context manager is :ref:`reentrant <reentrant-cms>`.

View file

@ -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.
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.
The last version of Python that provided the :mod:`!crypt` module was

View file

@ -317,7 +317,7 @@ Module contents
:func:`!field`, then the class attribute for this field will be
replaced by the specified *default* value. If *default* is not
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
as if the default value itself were specified. For example,
after::
@ -427,7 +427,7 @@ Module contents
:data:`typing.Any` is used for ``type``. The values of *init*,
*repr*, *eq*, *order*, *unsafe_hash*, *frozen*,
*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
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.
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.
This function is not strictly required, because any Python
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
example::
@ -569,7 +569,7 @@ Post-init processing
def __post_init__(self):
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
that has to be called, it is common to call this method in a
:meth:`__post_init__` method::
@ -599,7 +599,7 @@ parameters to :meth:`!__post_init__`. Also see the warning about how
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
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
@ -612,7 +612,7 @@ module-level :func:`fields` function.
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
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
@ -646,7 +646,7 @@ Frozen instances
----------------
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
:meth:`~object.__setattr__` and :meth:`~object.__delattr__` methods to the class. These
methods will raise a :exc:`FrozenInstanceError` when invoked.
@ -662,7 +662,7 @@ must use :meth:`!object.__setattr__`.
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
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.
@ -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
creation they also share this behavior. There is no general way
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
a value is unhashable, it is mutable. This is a partial solution,
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
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
form: ``descriptor.__get__(obj=None, type=cls)``. If the
descriptor returns a value in this case, it will be used as the

View file

@ -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
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
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
analysis of which lines are so frequent as to constitute noise, and this
usually works better than using this function.

View file

@ -690,7 +690,7 @@ The :mod:`functools` module defines the following functions:
return not arg
``@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*
decorator. Here is the ``Negator`` class with the ``neg`` methods bound to
the class, rather than an instance of the class::
@ -712,8 +712,7 @@ The :mod:`functools` module defines the following functions:
return not arg
The same pattern can be used for other similar decorators:
:func:`@staticmethod<staticmethod>`,
:func:`@abstractmethod<abc.abstractmethod>`, and others.
:deco:`staticmethod`, :deco:`~abc.abstractmethod`, and others.
.. versionadded:: 3.8

View file

@ -72,13 +72,12 @@ for example, a package and its resources can be imported from a zip file using
.. versionadded:: 3.9
.. versionchanged:: 3.12
*package* parameter was renamed to *anchor*. *anchor* can now
be a non-package module and if omitted will default to the caller's
module. *package* is still accepted for compatibility but will raise
a :exc:`DeprecationWarning`. Consider passing the anchor positionally or
using ``importlib_resources >= 5.10`` for a compatible interface
on older Pythons.
.. deprecated-removed:: 3.12 3.15
*package* parameter was renamed to *anchor*. *anchor* can now be a
non-package module and if omitted will default to the caller's module.
*package* is no longer accepted since Python 3.15. Consider passing the
anchor positionally or using ``importlib_resources >= 5.10`` for a
compatible interface on older Pythons.
.. function:: as_file(traversable)

View file

@ -216,8 +216,8 @@ process and user.
You can delete items in this mapping to unset environment variables.
: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
called.
:data:`os.environ`, and when one of the :meth:`~dict.pop` or
:meth:`~dict.clear` methods is called.
.. seealso::
@ -430,8 +430,8 @@ process and user.
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
calls to :func:`setgroups`, and its length is not limited to 16. The
deployment target value, :const:`MACOSX_DEPLOYMENT_TARGET`, can be
obtained with :func:`sysconfig.get_config_var`.
deployment target value can be obtained with
:func:`sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') <sysconfig.get_config_var>`.
.. function:: getlogin()
@ -2606,10 +2606,10 @@ features:
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
to be created, being combined (bitwise OR) with one of ``stat.S_IFREG``,
``stat.S_IFCHR``, ``stat.S_IFBLK``, and ``stat.S_IFIFO`` (those constants are
available in :mod:`stat`). For ``stat.S_IFCHR`` and ``stat.S_IFBLK``,
*device* defines the newly created device special file (probably using
to be created, being combined (bitwise OR) with one of :const:`stat.S_IFREG`,
:const:`stat.S_IFCHR`, :const:`stat.S_IFBLK`, and :const:`stat.S_IFIFO`.
For :const:`stat.S_IFCHR` and :const:`stat.S_IFBLK`, *device* defines the
newly created device special file (probably using
:func:`os.makedev`), otherwise it is ignored.
This function can also support :ref:`paths relative to directory descriptors
@ -2627,13 +2627,13 @@ features:
.. function:: major(device, /)
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, /)
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, /)
@ -3364,8 +3364,8 @@ features:
.. versionchanged:: 3.8
On Windows, the :attr:`st_mode` member now identifies special
files as :const:`S_IFCHR`, :const:`S_IFIFO` or :const:`S_IFBLK`
as appropriate.
files as :const:`~stat.S_IFCHR`, :const:`~stat.S_IFIFO` or
:const:`~stat.S_IFBLK` as appropriate.
.. versionchanged:: 3.12
On Windows, :attr:`st_ctime` is deprecated. Eventually, it will
@ -4285,10 +4285,10 @@ to be ignored.
.. 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
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`.
@ -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
: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
.. 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
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.

View file

@ -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
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
higher-level system APIs, and that includes using :mod:`urllib.request`.
.. versionchanged:: next
The returned file descriptor is now made non-inheritable.
.. function:: openpty()

View file

@ -205,10 +205,26 @@ The variables defined in the :mod:`signal` module are:
.. availability:: Unix.
.. data:: SIGPROF
Profiling timer expired.
.. availability:: Unix.
.. data:: SIGQUIT
Terminal quit signal.
.. availability:: Unix.
.. data:: SIGSEGV
Segmentation fault: invalid memory reference.
.. data:: SIGSTOP
Stop executing (cannot be caught or ignored).
.. data:: SIGSTKFLT
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.
.. data:: SIGVTALRM
Virtual timer expired.
.. availability:: Unix.
.. data:: SIGWINCH
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
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
':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
not all systems define the same set of signal names; only those names defined by
the system are defined by this module.
@ -644,9 +666,8 @@ The :mod:`signal` module defines the following functions:
*sigset*.
The return value is an object representing the data contained in the
:c:type:`siginfo_t` structure, namely: :attr:`si_signo`, :attr:`si_code`,
:attr:`si_errno`, :attr:`si_pid`, :attr:`si_uid`, :attr:`si_status`,
:attr:`si_band`.
``siginfo_t`` structure, namely: ``si_signo``, ``si_code``,
``si_errno``, ``si_pid``, ``si_uid``, ``si_status``, ``si_band``.
.. availability:: Unix.

View file

@ -354,9 +354,8 @@ Random generation
.. function:: RAND_status()
Return ``True`` if the SSL pseudo-random number generator has been seeded
with 'enough' randomness, and ``False`` otherwise. You can use
:func:`ssl.RAND_egd` and :func:`ssl.RAND_add` to increase the randomness of
the pseudo-random number generator.
with 'enough' randomness, and ``False`` otherwise. Use :func:`ssl.RAND_add`
to increase the randomness of the pseudo-random number generator.
.. function:: RAND_add(bytes, entropy, /)

View file

@ -24,7 +24,7 @@ Template strings
Template strings are a mechanism for custom string processing.
They have the full flexibility of Python's :ref:`f-strings`,
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.
To write a t-string, use a ``'t'`` prefix instead of an ``'f'``, like so:
@ -258,13 +258,16 @@ Types
.. attribute:: expression
: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
interpolation's Python expression, if the interpolation was created
from a t-string literal. Developers creating interpolations manually
should either set this to an empty string or choose a suitable valid
Python expression.
We recommend using valid Python expressions or the empty string for the
``expression`` field of manually created :class:`!Interpolation`
instances, although this is not enforced at runtime.
>>> t'{1 + 2}'.interpolations[0].expression
'1 + 2'

View file

@ -649,7 +649,7 @@ functions.
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
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
@ -1473,7 +1473,7 @@ handling consistency are valid for these functions.
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)``.
*encoding* and *errors* are used to decode output;
see the notes on :ref:`frequently-used-arguments` for more details.

View file

@ -382,6 +382,9 @@ Other functions
Examples of returned values:
- linux-x86_64
- linux-aarch64
- solaris-2.6-sun4u
Windows:

View file

@ -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
typechecking of ``T``, as type checkers will simply ignore the metadata ``x``.
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
completely disables typechecking for a function or class.
@ -2269,7 +2269,7 @@ without the dedicated syntax, as documented below.
.. 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
>>> Alias.__module__
@ -2449,7 +2449,7 @@ types.
.. 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__
@ -2815,7 +2815,7 @@ Protocols
---------
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
@ -2996,7 +2996,7 @@ Functions and decorators
The presence of ``@dataclass_transform()`` tells a static type checker that the
decorated object performs runtime "magic" that
transforms a class in a similar way to
:func:`@dataclasses.dataclass <dataclasses.dataclass>`.
:deco:`dataclasses.dataclass`.
Example usage with a decorator function:
@ -3034,14 +3034,14 @@ Functions and decorators
The ``CustomerModel`` classes defined above will
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
``__init__`` methods that accept ``id`` and ``name``.
The decorated class, metaclass, or function may accept the following bool
arguments which type checkers will assume have the same effect as they
would have on the
:func:`@dataclasses.dataclass<dataclasses.dataclass>` decorator: ``init``,
:deco:`dataclasses.dataclass` decorator: ``init``,
``eq``, ``order``, ``unsafe_hash``, ``frozen``, ``match_args``,
``kw_only``, and ``slots``. It must be possible for the value of these
arguments (``True`` or ``False``) to be statically evaluated.
@ -3169,12 +3169,12 @@ Functions and decorators
.. 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* is the function object for the implementation of the
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
for the three defined overloads. If called on a function with no overloads,
``get_overloads()`` returns an empty sequence.
@ -3331,7 +3331,7 @@ Introspection helpers
If *globalns* or *localns* is not given, appropriate namespace
dictionaries are inferred from *obj*.
* ``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.
* 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

View file

@ -590,7 +590,7 @@ Available Functions
The deprecation message passed to the decorator is saved in the
``__deprecated__`` attribute on the decorated object.
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
:func:`typing.get_overloads`.

View file

@ -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
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.
For reading and writing ``.gz`` files see the :mod:`gzip` module.
@ -340,6 +340,136 @@ Decompression objects support the following methods and attributes:
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
the following constants:
@ -375,10 +505,10 @@ the following constants:
Module :mod:`gzip`
Reading and writing :program:`gzip`\ -format files.
http://www.zlib.net
https://www.zlib.net
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
functions.

View file

@ -2558,7 +2558,7 @@ instance dictionary. In contrast, non-data descriptors can be overridden by
instances.
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
override methods. This allows individual instances to acquire behaviors that
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
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__*

View file

@ -10,12 +10,76 @@ Lexical analysis
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
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
can be given by an encoding declaration and defaults to UTF-8, see :pep:`3120`
for details. If the source file cannot be decoded, a :exc:`SyntaxError` is
raised.
The lexical analyzer determines the program text's :ref:`encoding <encodings>`
(UTF-8 by default), and decodes the text into
:ref:`source characters <lexical-source-character>`.
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:
@ -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
and identifiers.
.. _lexical-source-character:
All lexical analysis, including string literals, comments
and identifiers, works on Unicode text decoded using the source encoding.
Any Unicode code point, except the NUL control character, can appear in

View file

@ -4,7 +4,6 @@
Doc/c-api/descriptor.rst
Doc/c-api/float.rst
Doc/c-api/init.rst
Doc/c-api/init_config.rst
Doc/c-api/intro.rst
Doc/c-api/module.rst
@ -30,12 +29,10 @@ Doc/library/profile.rst
Doc/library/pyexpat.rst
Doc/library/resource.rst
Doc/library/select.rst
Doc/library/signal.rst
Doc/library/smtplib.rst
Doc/library/socket.rst
Doc/library/ssl.rst
Doc/library/stdtypes.rst
Doc/library/subprocess.rst
Doc/library/termios.rst
Doc/library/test.rst
Doc/library/tkinter.rst
@ -53,7 +50,6 @@ Doc/library/xml.sax.reader.rst
Doc/library/xml.sax.rst
Doc/library/xmlrpc.client.rst
Doc/library/xmlrpc.server.rst
Doc/library/zlib.rst
Doc/whatsnew/2.4.rst
Doc/whatsnew/2.5.rst
Doc/whatsnew/2.6.rst

View file

@ -42,22 +42,22 @@ <h1>{% trans %}Download Python {{ dl_version }} documentation{% endtrans %}</h1>
</tr>
<tr>
<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 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.zip">Download</a>{% endtrans %}</td>
<td>{% trans %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-html.tar.bz2">Download</a>{% endtrans %}</td>
</tr>
<tr>
<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 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.zip">Download</a>{% endtrans %}</td>
<td>{% trans %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-text.tar.bz2">Download</a>{% endtrans %}</td>
</tr>
<tr>
<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 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.zip">Download</a>{% endtrans %}</td>
<td>{% trans %}<a href="{{ dl_base }}/python-{{ dl_version }}-docs-texinfo.tar.bz2">Download</a>{% endtrans %}</td>
</tr>
<tr>
<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>
</tr>
</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.
{% endtrans %}</p>
<h2>{% trans %}Unpacking{% endtrans %}</h2>
<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>
<p>{% trans %}
See the <a href="https://docs.python.org/{{ version }}/archives/">directory listing</a>
for file sizes.{% endtrans %}</p>
<h2>{% trans %}Problems{% endtrans %}</h2>
<p>{% trans %}If you have comments or suggestions for the Python documentation, please send
email to <a href="mailto:docs@python.org">docs@python.org</a>.{% endtrans %}</p>
{% set bugs = pathto('bugs') %}
<p>{% trans bugs = bugs %}<a href="{{ bugs }}">Open an issue</a>
if you have comments or suggestions for the Python documentation.{% endtrans %}</p>
{% endblock %}

View file

@ -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
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
value associated with that key is forgotten. It is an error to extract a value
using a non-existent key.
value associated with that key is forgotten.
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
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}
>>> tel['jack']
4098
>>> tel['irv']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'irv'
>>> print(tel.get('irv'))
None
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel

View file

@ -22,16 +22,51 @@ Features and minimum versions required to build CPython:
* Support for threads.
* OpenSSL 1.1.1 is the minimum version and OpenSSL 3.0.16 is the recommended
minimum version for the :mod:`ssl` and :mod:`hashlib` extension modules.
To build optional 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
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
:file:`configure` script.

View file

@ -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
or syntax. When it's not possible to do that, Python 2.6 tries to do
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.
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
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
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
compatible with 3.0 can do ``from future_builtins import hex, map`` as
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
with this switch to see how much work will be necessary to port
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`.
.. 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
block is complete.
The :func:`localcontext` function in the :mod:`decimal` module makes it easy
to save and restore the current decimal context, which encapsulates the desired
precision and rounding characteristics for computations::
The :func:`~decimal.localcontext` function in the :mod:`decimal` module makes
it easy to save and restore the current decimal context, which encapsulates
the desired precision and rounding characteristics for computations::
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:
* 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__`
methods.
manager". The context manager must have :meth:`~object.__enter__` and
:meth:`~object.__exit__` methods.
* The context manager's :meth:`~object.__enter__` method is called. The value returned
is assigned to *VAR*. If no ``as VAR`` clause is present, the value is simply
discarded.
* The context manager's :meth:`~object.__enter__` method is called. The value
returned is assigned to *VAR*. If no ``as VAR`` clause is present, the
value is simply discarded.
* 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
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:
# Database interface
@ -431,14 +431,15 @@ The contextlib module
The :mod:`contextlib` module provides some functions and a decorator that
are useful when writing objects for use with the ':keyword:`with`' statement.
The decorator is called :func:`contextmanager`, and lets you write a single
generator function instead of defining a new class. The generator should yield
exactly one value. The code up to the :keyword:`yield` will be executed as the
:meth:`~object.__enter__` method, and the value yielded will be the method's return
value that will get bound to the variable in the ':keyword:`with`' statement's
:keyword:`!as` clause, if any. The code after the :keyword:`!yield` will be
executed in the :meth:`~object.__exit__` method. Any exception raised in the block will
be raised by the :keyword:`!yield` statement.
The decorator is called :func:`~contextlib.contextmanager`, and lets you write
a single generator function instead of defining a new class. The generator
should yield exactly one value. The code up to the :keyword:`yield` will be
executed as the :meth:`~object.__enter__` method, and the value yielded will
be the method's return value that will get bound to the variable in the
':keyword:`with`' statement's :keyword:`!as` clause, if any. The code after
the :keyword:`!yield` will be executed in the :meth:`~object.__exit__` method.
Any exception raised in the block will be raised by the :keyword:`!yield`
statement.
Using this decorator, our database example from the previous section
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):
...
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
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
directory used for all Python versions supporting this feature. On
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.
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
goal was discarded along the path to Python 2.6, but the general
approach of the module is still similar. The fundamental class
is the :class:`Process`, which is passed a callable object and
a collection of arguments. The :meth:`start` method
is the :class:`~multiprocessing.Process`, which is passed a callable object and
a collection of arguments. The :meth:`~multiprocessing.Process.start` method
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
and the :meth:`join` method to wait for the process to exit.
the :meth:`~multiprocessing.Process.is_alive` method to check whether the
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
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
versa.)
Two other classes, :class:`Pool` and :class:`Manager`, provide
higher-level interfaces. :class:`Pool` will create a fixed number of
worker processes, and requests can then be distributed to the workers
by calling :meth:`apply` or :meth:`apply_async` to add a single request,
and :meth:`map` or :meth:`map_async` to add a number of
requests. The following code uses a :class:`Pool` to spread requests
across 5 worker processes and retrieve a list of results::
Two other classes, :class:`~multiprocessing.pool.Pool` and
:class:`~multiprocessing.Manager`, provide higher-level interfaces.
:class:`~multiprocessing.pool.Pool` will create a fixed number of worker
processes, and requests can then be distributed to the workers by calling
:meth:`~multiprocessing.pool.Pool.apply` or
:meth:`~multiprocessing.pool.Pool.apply_async` to add a single request, and
: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
@ -646,15 +651,18 @@ This produces the following output::
33452526613163807108170062053440751665152000000000
...
The other high-level interface, the :class:`Manager` class, creates a
separate server process that can hold master copies of Python data
The other high-level interface, the :class:`~multiprocessing.Manager` class,
creates a separate server process that can hold master copies of Python data
structures. Other processes can then access and modify these data
structures using proxy objects. The following example creates a
shared dictionary by calling the :meth:`dict` method; the worker
processes then insert values into the dictionary. (Locking is not
done for you automatically, which doesn't matter in this example.
:class:`Manager`'s methods also include :meth:`Lock`, :meth:`RLock`,
and :meth:`Semaphore` to create shared locks.)
:class:`~multiprocessing.Manager`'s methods also include
: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.
===== ========================================================================
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::
def __format__(self, format_spec):
@ -834,7 +842,7 @@ formatted. It receives a single argument, the format specifier::
return str(self)
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::
>>> 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
file-like objects don't necessarily support all of them. Objects that
imitate files usually support :meth:`read` and :meth:`write`, but they
may not support :meth:`readline`, for example. Python 3.0 introduces
a layered I/O library in the :mod:`io` module that separates buffering
and text-handling features from the fundamental read and write
operations.
imitate files usually support :meth:`!read` and
:meth:`!write`, but they may not support :meth:`!readline`,
for example. Python 3.0 introduces a layered I/O library in the :mod:`io`
module that separates buffering and text-handling features from the
fundamental read and write operations.
There are three levels of abstract base classes provided by
the :mod:`io` module:
* :class:`RawIOBase` defines raw I/O operations: :meth:`read`,
:meth:`readinto`,
:meth:`write`, :meth:`seek`, :meth:`tell`, :meth:`truncate`,
and :meth:`close`.
* :class:`~io.RawIOBase` defines raw I/O operations: :meth:`~io.RawIOBase.read`,
:meth:`~io.RawIOBase.readinto`, :meth:`~io.RawIOBase.write`,
:meth:`~io.IOBase.seek`, :meth:`~io.IOBase.tell`, :meth:`~io.IOBase.truncate`,
and :meth:`~io.IOBase.close`.
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`
methods for determining what operations a given object will allow.
There are also :meth:`~io.IOBase.readable`, :meth:`~io.IOBase.writable`,
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
sockets, but Python 2.6 hasn't restructured its file and socket objects
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
system calls used, making I/O processing more efficient.
It supports all of the methods of :class:`RawIOBase`,
and adds a :attr:`raw` attribute holding the underlying raw object.
It supports all of the methods of :class:`~io.RawIOBase`,
and adds a :attr:`~io.BufferedIOBase.raw` attribute holding the underlying
raw object.
There are five concrete classes implementing this ABC.
:class:`BufferedWriter` and :class:`BufferedReader` are for objects
that support write-only or read-only usage that have a :meth:`seek`
method for random access. :class:`BufferedRandom` objects support
:class:`~io.BufferedWriter` and :class:`~io.BufferedReader` are for objects
that support write-only or read-only usage that have a :meth:`~io.IOBase.seek`
method for random access. :class:`~io.BufferedRandom` objects support
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.
The :class:`BytesIO` class supports reading, writing, and seeking
The :class:`~io.BytesIO` class supports reading, writing, and seeking
over an in-memory buffer.
.. index::
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),
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
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
text I/O and adding a :attr:`buffer` attribute for access
to the underlying object. :class:`StringIO` simply buffers
text I/O and adding a :attr:`~io.TextIOBase.buffer` attribute for access
to the underlying object. :class:`~io.StringIO` simply buffers
everything in memory without ever writing anything to disk.
(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
access protocol. Abstract Base Classes (or ABCs) are an equivalent
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`
builtins, and a collection of basic ABCs that the Python developers
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.
It probably means that accessing items with ``obj[1]`` 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`
methods? What about the iterative variants such as :meth:`iterkeys`? :meth:`copy`
and :meth:`update`? Iterating over the object with :func:`iter`?
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`and :meth:`!update`? Iterating over the object with :func:`!iter`?
The Python 2.6 :mod:`collections` module includes a number of
different ABCs that represent these distinctions. :class:`Iterable`
indicates that a class defines :meth:`__iter__`, and
:class:`Container` means the class defines a :meth:`__contains__`
indicates that a class defines :meth:`~object.__iter__`, and
:class:`Container` means the class defines a :meth:`~object.__contains__`
method and therefore supports ``x in y`` expressions. The basic
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.
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
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
@ -1206,10 +1216,10 @@ calling the ABC's :meth:`register` method::
collections.MutableMapping.register(Storage)
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
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::
# 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
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
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_doubled`, though they can do so. An implementation
of :meth:`!draw` is necessary, though; the ABC can't provide
a useful generic implementation.
You can apply the ``@abstractmethod`` decorator to methods such as
:meth:`draw` that must be implemented; Python will then raise an
You can apply the :deco:`~abc.abstractmethod` decorator to methods such as
:meth:`!draw` that must be implemented; Python will then raise an
exception for classes that don't define the method.
Note that the exception is only raised when you actually
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):
return self._x
Subclasses must then define a :meth:`readonly` property.
Subclasses must then define a ``readonly`` property.
.. 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
functions, and most of the changes can't be introduced in the Python
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
3.0-compatible code.

View file

@ -858,8 +858,8 @@ Some smaller changes made to the core Python language are:
.. XXX bytearray doesn't seem to be documented
* When using :class:`@classmethod <classmethod>` and
:class:`@staticmethod <staticmethod>` to wrap
* When using :deco:`classmethod` and
:deco:`staticmethod` to wrap
methods as class or static methods, the wrapper object now
exposes the wrapped function as their :attr:`~method.__func__`
attribute.

View file

@ -847,8 +847,8 @@ Other Language Changes
respectively.
(Contributed by Joshua Bronson, Daniel Pope, and Justin Wang in :issue:`31861`.)
* Static methods (:func:`@staticmethod <staticmethod>`) and class methods
(:func:`@classmethod <classmethod>`) now inherit the method attributes
* Static methods (:deco:`staticmethod`) and class methods
(:deco:`classmethod`) now inherit the method attributes
(``__module__``, ``__name__``, ``__qualname__``, ``__doc__``,
``__annotations__``) and have a new ``__wrapped__`` attribute.
Moreover, static methods are now callable as regular functions.

View file

@ -60,7 +60,7 @@ Summary -- Release Highlights
.. This section singles out the most important changes in Python 3.13.
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
and the standard library.
The biggest changes include a new `interactive interpreter
@ -1569,8 +1569,6 @@ and are now removed:
* :pypi:`bcrypt`:
Modern password hashing for your software and your servers.
* :pypi:`passlib`:
Comprehensive password hashing framework supporting over 30 schemes.
* :pypi:`argon2-cffi`:
The secure Argon2 password hashing algorithm.
* :pypi:`legacycrypt`:

File diff suppressed because it is too large Load diff

View file

@ -852,6 +852,9 @@ New features
(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
----------------------

View file

@ -78,7 +78,7 @@ __pragma(warning(disable: 4201))
#include "pybuffer.h"
#include "pystats.h"
#include "pyatomic.h"
#include "pylock.h"
#include "cpython/pylock.h"
#include "critical_section.h"
#include "object.h"
#include "refcount.h"
@ -105,7 +105,7 @@ __pragma(warning(disable: 4201))
#include "setobject.h"
#include "methodobject.h"
#include "moduleobject.h"
#include "monitoring.h"
#include "cpython/monitoring.h"
#include "cpython/funcobject.h"
#include "cpython/classobject.h"
#include "fileobject.h"

View file

@ -282,15 +282,6 @@ typedef struct _line_offsets {
*/
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,
PyObject *names, PyObject *lnotab);

View file

@ -134,7 +134,8 @@ PyAPI_FUNC(PyObject *) PyStaticMethod_New(PyObject *);
V(DESTROY) \
V(MODIFY_CODE) \
V(MODIFY_DEFAULTS) \
V(MODIFY_KWDEFAULTS)
V(MODIFY_KWDEFAULTS) \
V(MODIFY_QUALNAME)
typedef enum {
#define PY_DEF_EVENT(EVENT) PyFunction_EVENT_##EVENT,

17
Include/cpython/marshal.h Normal file
View 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);

View file

@ -1,7 +1,13 @@
#ifndef Py_CPYTHON_MONITORING_H
# error "this header file must not be included directly"
#ifndef Py_MONITORING_H
#define Py_MONITORING_H
#ifndef Py_LIMITED_API
#ifdef __cplusplus
extern "C" {
#endif
// There is currently no limited API for monitoring
/* Local events.
* These require bytecode instrumentation */
@ -267,3 +273,9 @@ PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike
}
#undef _PYMONITORING_IF_ACTIVE
#ifdef __cplusplus
}
#endif
#endif // !Py_LIMITED_API
#endif // !Py_MONITORING_H

View file

@ -492,7 +492,3 @@ PyAPI_FUNC(int) PyUnstable_TryIncRef(PyObject *);
PyAPI_FUNC(void) PyUnstable_EnableTryIncRef(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);

View file

@ -1,7 +1,11 @@
#ifndef Py_CPYTHON_LOCK_H
# error "this header file must not be included directly"
#ifndef Py_LOCK_H
#define Py_LOCK_H
#ifndef Py_LIMITED_API
#ifdef __cplusplus
extern "C" {
#endif
#define _Py_UNLOCKED 0
#define _Py_LOCKED 1
@ -72,3 +76,10 @@ _PyMutex_IsLocked(PyMutex *m)
return (_Py_atomic_load_uint8(&m->_bits) & _Py_LOCKED) != 0;
}
#define PyMutex_IsLocked _PyMutex_IsLocked
#ifdef __cplusplus
}
#endif
#endif // !Py_LIMITED_API
#endif // !Py_LOCK_H

View 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);

View 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

View file

@ -38,3 +38,7 @@ PyTuple_SET_ITEM(PyObject *op, Py_ssize_t index, PyObject *value) {
}
#define PyTuple_SET_ITEM(op, index, value) \
PyTuple_SET_ITEM(_PyObject_CAST(op), (index), _PyObject_CAST(value))
PyAPI_FUNC(PyObject*) PyTuple_FromArray(
PyObject *const *array,
Py_ssize_t size);

View file

@ -663,6 +663,15 @@ PyAPI_FUNC(int) _PyCode_VerifyStateless(
PyAPI_FUNC(int) _PyCode_CheckPureFunction(PyCodeObject *, const char **);
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
}

View file

@ -1047,6 +1047,10 @@ static inline Py_ALWAYS_INLINE void _Py_INCREF_MORTAL(PyObject *op)
}
#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
}
#endif

View file

@ -23,7 +23,6 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
#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_FromArraySteal(PyObject *const *, Py_ssize_t);

View file

@ -11,6 +11,70 @@ extern "C" {
#include "pycore_fileutils.h" // _Py_error_handler
#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 ----------------------------------------------- */
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.
Behaviour is expected to be an exact match of `textwrap.dedent`.
Return a new reference on success, NULL with exception set on error.

View file

@ -1,31 +1,18 @@
/* Interface for marshal.c */
#ifndef Py_MARSHAL_H
#define Py_MARSHAL_H
#ifndef Py_LIMITED_API
#ifdef __cplusplus
extern "C" {
#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);
#ifndef Py_LIMITED_API
# define _Py_CPYTHON_MARSHAL_H
# include "cpython/marshal.h"
# undef _Py_CPYTHON_MARSHAL_H
#endif
#ifdef __cplusplus
}
#endif
#endif /* Py_LIMITED_API */
#endif /* !Py_MARSHAL_H */

View file

@ -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 */

View file

@ -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 */

View file

@ -16,19 +16,6 @@ PyAPI_DATA(PyObject) _Py_EllipsisObject; /* Don't use this directly */
/* 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) PyEllipsis_Type;
@ -36,12 +23,6 @@ PyAPI_DATA(PyTypeObject) PyEllipsis_Type;
PyAPI_FUNC(PyObject *) PySlice_New(PyObject* start, PyObject* stop,
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,
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step);
Py_DEPRECATED(3.7)
@ -63,6 +44,12 @@ PyAPI_FUNC(Py_ssize_t) PySlice_AdjustIndices(Py_ssize_t length,
Py_ssize_t step);
#endif
#ifndef Py_LIMITED_API
# define Py_CPYTHON_SLICEOBJECT_H
# include "cpython/sliceobject.h"
# undef Py_CPYTHON_SLICEOBJECT_H
#endif
#ifdef __cplusplus
}
#endif

View file

@ -21,12 +21,6 @@ typedef struct PyStructSequence_Desc {
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(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);
#ifndef Py_LIMITED_API
typedef PyTupleObject PyStructSequence;
#define PyStructSequence_SET_ITEM PyStructSequence_SetItem
#define PyStructSequence_GET_ITEM PyStructSequence_GetItem
# define Py_CPYTHON_STRUCTSEQ_H
# include "cpython/structseq.h"
# undef Py_CPYTHON_STRUCTSEQ_H
#endif
#ifdef __cplusplus

View file

@ -420,14 +420,17 @@ class delete(EditCommand):
def do(self) -> None:
r = self.reader
b = r.buffer
if (
r.pos == 0
and len(b) == 0 # this is something of a hack
and self.event[-1] == "\004"
):
r.update_screen()
r.console.finish()
raise EOFError
if self.event[-1] == "\004":
if b and b[-1].endswith("\n"):
self.finish = True
elif (
r.pos == 0
and len(b) == 0 # this is something of a hack
):
r.update_screen()
r.console.finish()
raise EOFError
for i in range(r.get_arg()):
if r.pos != len(b):
del b[r.pos]

View file

@ -390,7 +390,12 @@ def restore(self):
os.write(self.output_fd, b"\033[?7h")
if hasattr(self, "old_sigwinch"):
signal.signal(signal.SIGWINCH, self.old_sigwinch)
try:
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
def push_char(self, char: int | bytes) -> None:

View file

@ -280,7 +280,7 @@ def add_argument(self, action):
if action.help is not SUPPRESS:
# 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]
for subaction in self._iter_indented_subactions(action):
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
# optional arguments and with no "usage:" prefix
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()
groups = self._mutually_exclusive_groups
formatter.add_usage(None, positionals, groups, '')

View file

@ -74,7 +74,8 @@ def callback():
return
except BaseException:
if keyboard_interrupted:
self.write("\nKeyboardInterrupt\n")
if not CAN_USE_PYREPL:
self.write("\nKeyboardInterrupt\n")
else:
self.showtraceback()
return self.STATEMENT_FAILED

View file

@ -1050,8 +1050,8 @@ def _read_ready__on_eof(self):
def write(self, data):
if not isinstance(data, (bytes, bytearray, memoryview)):
raise TypeError(f'data argument must be a bytes-like object, '
f'not {type(data).__name__!r}')
raise TypeError(f'data argument must be a bytes, bytearray, or memoryview '
f'object, not {type(data).__name__!r}')
if self._eof:
raise RuntimeError('Cannot call write() after write_eof()')
if self._empty_waiter is not None:

View file

@ -302,6 +302,7 @@ def parse_request(self):
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.request_version = version = self.default_request_version
self.close_connection = True
@ -359,6 +360,7 @@ def parse_request(self):
HTTPStatus.BAD_REQUEST,
"Bad HTTP/0.9 request type (%r)" % command)
return False
is_http_0_9 = True
self.command, self.path = command, path
# gh-87389: The purpose of replacing '//' with '/' is to protect
@ -368,6 +370,11 @@ def parse_request(self):
if self.path.startswith('//'):
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.
try:
self.headers = http.client.parse_headers(self.rfile,

View file

@ -37,6 +37,7 @@ Major contributors since 2005:
- 2014: Saimadhav Heblikar
- 2015: Mark Roseman
- 2017: Louie Lu, Cheryl Sabella, and Serhiy Storchaka
- 2025: Stan Ulbrych
For additional details refer to NEWS.txt and Changelog.

View file

@ -47,7 +47,7 @@ def make_pat():
name not in keyword.kwlist]
builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b"
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]*)*'?"
dqstring = stringprefix + r'"[^"\\\n]*(\\.[^"\\\n]*)*"?'
sq3string = stringprefix + r"'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?"

View file

@ -33,7 +33,6 @@
# The default tab setting for a Text widget, in average-width characters.
TK_TABWIDTH_DEFAULT = 8
_py_version = ' (%s)' % platform.python_version()
darwin = sys.platform == 'darwin'
def _sphinx_version():
@ -1008,12 +1007,16 @@ def open_recent_file(fn_closure=file_name):
def saved_change_hook(self):
short = self.short_title()
long = self.long_title()
_py_version = ' (%s)' % platform.python_version()
if short and long and not macosx.isCocoaTk():
# Don't use both values on macOS because
# that doesn't match platform conventions.
title = short + " - " + long + _py_version
elif short:
title = short
if short == "IDLE Shell":
title = short + " " + platform.python_version()
else:
title = short + _py_version
elif long:
title = long
else:

View file

@ -36,6 +36,7 @@ async def f(): await g()
# All valid prefixes for unicode and byte strings should be colored.
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'
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'
# 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'
@ -390,19 +391,19 @@ def test_recolorize_main(self, mock_notify):
('6.0', ('KEYWORD',)), ('6.10', ('DEFINITION',)), ('6.11', ()),
('8.0', ('STRING',)), ('8.4', ()), ('8.5', ('STRING',)),
('8.12', ()), ('8.14', ('STRING',)),
('19.0', ('KEYWORD',)),
('20.4', ('KEYWORD',)), ('20.16', ('KEYWORD',)),# ('20.19', ('KEYWORD',)),
#('22.4', ('KEYWORD',)), ('22.10', ('KEYWORD',)), ('22.14', ('KEYWORD',)), ('22.19', ('STRING',)),
#('23.12', ('KEYWORD',)),
('24.8', ('KEYWORD',)),
('25.4', ('KEYWORD',)), ('25.9', ('KEYWORD',)),
('25.11', ('KEYWORD',)), ('25.15', ('STRING',)),
('25.19', ('KEYWORD',)), ('25.22', ()),
('25.24', ('KEYWORD',)), ('25.29', ('BUILTIN',)), ('25.37', ('KEYWORD',)),
('26.4', ('KEYWORD',)), ('26.9', ('KEYWORD',)),# ('26.11', ('KEYWORD',)), ('26.14', (),),
('27.25', ('STRING',)), ('27.38', ('STRING',)),
('29.0', ('STRING',)),
('30.1', ('STRING',)),
('20.0', ('KEYWORD',)),
('21.4', ('KEYWORD',)), ('21.16', ('KEYWORD',)),# ('21.19', ('KEYWORD',)),
#('23.4', ('KEYWORD',)), ('23.10', ('KEYWORD',)), ('23.14', ('KEYWORD',)), ('23.19', ('STRING',)),
#('24.12', ('KEYWORD',)),
('25.8', ('KEYWORD',)),
('26.4', ('KEYWORD',)), ('26.9', ('KEYWORD',)),
('26.11', ('KEYWORD',)), ('26.15', ('STRING',)),
('26.19', ('KEYWORD',)), ('26.22', ()),
('26.24', ('KEYWORD',)), ('26.29', ('BUILTIN',)), ('26.37', ('KEYWORD',)),
('27.4', ('KEYWORD',)), ('27.9', ('KEYWORD',)),# ('27.11', ('KEYWORD',)), ('27.14', (),),
('28.25', ('STRING',)), ('28.38', ('STRING',)),
('30.0', ('STRING',)),
('31.1', ('STRING',)),
# SYNC at the end of every line.
('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.17'), ('8.19', '8.26'))
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):
"""Check highlighting of a given piece of code.

View file

@ -1,6 +1,7 @@
"Test outwin, coverage 76%."
from idlelib import outwin
import platform
import sys
import unittest
from test.support import requires
@ -41,7 +42,7 @@ def test_ispythonsource(self):
self.assertFalse(w.ispythonsource(__file__))
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):
w = self.window

View file

@ -22,7 +22,6 @@
import linecache
import os
import os.path
from platform import python_version
import re
import socket
import subprocess
@ -841,7 +840,7 @@ def display_executing_dialog(self):
class PyShell(OutputWindow):
from idlelib.squeezer import Squeezer
shell_title = "IDLE Shell " + python_version()
shell_title = "IDLE Shell"
# Override classes
ColorDelegator = ModifiedColorDelegator

View file

@ -6,7 +6,6 @@
import types
import importlib
import inspect
import warnings
import itertools
from typing import Union, Optional, cast
@ -16,39 +15,6 @@
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:
"""
Get a Traversable resource for an anchor.

View file

@ -1065,7 +1065,9 @@ def __init__(self):
def tokeneater(self, type, token, srowcol, erowcol, line):
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
# skip any decorators
elif token == "@":

View file

@ -58,6 +58,11 @@ def _get_exports_list(module):
__all__.append('_exit')
except ImportError:
pass
try:
from posix import _clearenv
__all__.append('_clearenv')
except ImportError:
pass
import posixpath as path
try:
@ -768,6 +773,12 @@ def __ror__(self, other):
new.update(self)
return new
if _exists("_clearenv"):
def clear(self):
_clearenv()
self._data.clear()
def _create_environ_mapping():
if name == 'nt':
# Where Env Var Names Must Be UPPERCASE

View file

@ -336,13 +336,8 @@ def _raw_path(self):
return paths[0]
elif paths:
# Join path segments from the initializer.
path = self.parser.join(*paths)
# Cache the joined path.
paths.clear()
paths.append(path)
return path
return self.parser.join(*paths)
else:
paths.append('')
return ''
@property
@ -490,16 +485,19 @@ def relative_to(self, other, *, walk_up=False):
"""
if not hasattr(other, 'with_segments'):
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:
break
elif not walk_up:
raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")
elif path.name == '..':
raise ValueError(f"'..' segment in {str(other)!r} cannot be walked")
else:
parts.append('..')
else:
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)
def is_relative_to(self, other):

View file

@ -234,6 +234,33 @@ def parents(self):
parent = split(path)[0]
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):
"""
Return True if this path matches the given glob-style pattern. The

View file

@ -348,7 +348,7 @@ def read_stringnl(f, decode=True, stripquotes=True, *, encoding='latin-1'):
for q in (b'"', b"'"):
if data.startswith(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))
data = data[1:-1]
break

View file

@ -333,7 +333,7 @@ def _get_path(userbase):
if sys.platform == 'darwin' and sys._framework:
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():

View file

@ -110,11 +110,6 @@
)
from _ssl import txt2obj as _txt2obj, nid2obj as _nid2obj
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

View file

@ -645,6 +645,9 @@ def get_platform():
isn't particularly important.
Examples of returned values:
linux-x86_64
linux-aarch64
solaris-2.6-sun4u
Windows:

View file

@ -21,8 +21,9 @@
# Regexes needed for parsing Makefile (and similar syntaxes,
# like old-style Setup files).
_variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)"
_findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)"
_findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}"
_findvar_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):
@ -49,26 +50,7 @@ def _parse_makefile(filename, vars=None, keep_unresolved=True):
m = re.match(_variable_rx, line)
if m:
n, v = m.group(1, 2)
v = 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())
notdone[n] = v.strip()
# Variables with a 'PY_' prefix in the makefile. These need to
# 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.
renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
while len(variables) > 0:
for name in tuple(variables):
value = notdone[name]
m1 = re.search(_findvar1_rx, value)
m2 = re.search(_findvar2_rx, value)
if m1 and m2:
m = m1 if m1.start() < m2.start() else m2
else:
m = m1 if m1 else m2
if m is not None:
n = m.group(1)
found = True
if n in done:
item = str(done[n])
elif n in notdone:
# get it on a subsequent round
found = False
elif n in os.environ:
# do it like make: fall back to environment
item = os.environ[n]
elif n in renamed_variables:
if (name.startswith('PY_') and
name[3:] in renamed_variables):
item = ""
elif 'PY_' + n in notdone:
found = False
else:
item = str(done['PY_' + n])
else:
done[n] = item = ""
if found:
after = value[m.end():]
value = value[:m.start()] + item + after
if "$" in after:
notdone[name] = value
else:
try:
if name in _ALWAYS_STR:
raise ValueError
value = int(value)
except ValueError:
done[name] = value.strip()
else:
done[name] = value
variables.remove(name)
if name.startswith('PY_') \
and name[3:] in renamed_variables:
name = name[3:]
if name not in done:
done[name] = value
else:
# Adds unresolved variables to the done dict.
# This is disabled when called from distutils.sysconfig
def resolve_var(name):
def repl(m):
n = m[1]
if n == '$':
return '$'
elif n == '':
# bogus variable reference (e.g. "prefix=$/opt/python")
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)
return m[0]
raise ValueError
elif n[0] == '(' and n[-1] == ')':
n = n[1:-1]
elif n[0] == '{' and n[-1] == '}':
n = n[1:-1]
if n in done:
return str(done[n])
elif n in notdone:
return str(resolve_var(n))
elif n in os.environ:
# do it like make: fall back to environment
return os.environ[n]
elif n in renamed_variables:
if name.startswith('PY_') and name[3:] in renamed_variables:
return ""
n = 'PY_' + n
if n in notdone:
return str(resolve_var(n))
else:
assert n not in done
return ""
else:
done[n] = ""
return ""
assert name not in done
done[name] = ""
try:
value = re.sub(_findvar_rx, repl, notdone[name])
except ValueError:
del done[name]
return ""
value = value.strip()
if name not in _ALWAYS_STR:
try:
value = int(value)
except ValueError:
pass
done[name] = value
if name.startswith('PY_') and name[3:] in renamed_variables:
name = name[3:]
if name not in done:
done[name] = value
return value
for n in notdone:
if n not in done:
resolve_var(n)
# strip spurious spaces
for k, v in done.items():

View file

@ -4341,7 +4341,7 @@ test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t narg
goto exit;
}
a = args[0];
__clinic_args = _PyTuple_FromArray(args + 1, nargs - 1);
__clinic_args = PyTuple_FromArray(args + 1, nargs - 1);
if (__clinic_args == NULL) {
goto exit;
}
@ -4356,7 +4356,7 @@ test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t narg
static PyObject *
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]
test_vararg
@ -4421,7 +4421,7 @@ test_vararg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
}
a = fastargs[0];
__clinic_args = nargs > 1
? _PyTuple_FromArray(args + 1, nargs - 1)
? PyTuple_FromArray(args + 1, nargs - 1)
: PyTuple_New(0);
if (__clinic_args == NULL) {
goto exit;
@ -4437,7 +4437,7 @@ test_vararg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
static PyObject *
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]
test_vararg_with_default
@ -4514,7 +4514,7 @@ test_vararg_with_default(PyObject *module, PyObject *const *args, Py_ssize_t nar
}
skip_optional_kwonly:
__clinic_args = nargs > 1
? _PyTuple_FromArray(args + 1, nargs - 1)
? PyTuple_FromArray(args + 1, nargs - 1)
: PyTuple_New(0);
if (__clinic_args == NULL) {
goto exit;
@ -4531,7 +4531,7 @@ test_vararg_with_default(PyObject *module, PyObject *const *args, Py_ssize_t nar
static PyObject *
test_vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args,
int b)
/*[clinic end generated code: output=3f2b06ab08d5d0be input=3a0f9f557ce1f712]*/
/*[clinic end generated code: output=d25e56802c197344 input=3a0f9f557ce1f712]*/
/*[clinic input]
test_vararg_with_only_defaults
@ -4612,7 +4612,7 @@ test_vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize
}
c = fastargs[1];
skip_optional_kwonly:
__clinic_args = _PyTuple_FromArray(args, nargs);
__clinic_args = PyTuple_FromArray(args, nargs);
if (__clinic_args == NULL) {
goto exit;
}
@ -4628,7 +4628,7 @@ test_vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize
static PyObject *
test_vararg_with_only_defaults_impl(PyObject *module, PyObject *args, int b,
PyObject *c)
/*[clinic end generated code: output=f46666f0b1bf86b9 input=6983e66817f82924]*/
/*[clinic end generated code: output=7366943a7df42e05 input=6983e66817f82924]*/
/*[clinic input]
test_paramname_module

View file

@ -646,15 +646,23 @@ def _add_cross_compile_opts(self, regrtest_opts):
return (environ, keep_environ)
def _add_ci_python_opts(self, python_opts, keep_environ):
# --fast-ci and --slow-ci add options to Python:
# "-u -W default -bb -E"
# --fast-ci and --slow-ci add options to Python.
#
# 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
if not sys.stdout.write_through:
# Unbuffered stdout and stderr. This isn't helpful on Android, because
# 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')
# Add warnings filter 'error'
if 'default' not in sys.warnoptions:
# Add warnings filter 'error', unless the user specified a different
# 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'))
# Error on bytes/str comparison
@ -673,8 +681,12 @@ def _execute_python(self, cmd, environ):
cmd_text = shlex.join(cmd)
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:
os.execv(cmd[0], cmd)
# On success, execv() do no return.

View file

@ -310,6 +310,16 @@ def requires(resource, msg=None):
if resource == 'gui' and not _is_gui_available():
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):
"""Decorator raising SkipTest if the OS is `sysname` and the version is less
than `min_version`.

View file

@ -22,6 +22,7 @@
captured_stderr,
force_not_colorized,
force_not_colorized_test_class,
swap_attr,
)
from test.support import import_helper
from test.support import os_helper
@ -7128,7 +7129,8 @@ class TestColorized(TestCase):
def setUp(self):
super().setUp()
# 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
def test_argparse_color(self):
@ -7311,11 +7313,11 @@ def custom_formatter(prog):
{heading}usage: {reset}{prog}PROG{reset} [{short}-h{reset}] [{short}+f {label}FOO{reset}] {pos}spam{reset}
{heading}positional arguments:{reset}
{pos_b}spam{reset} spam help
{pos_b}spam{reset} spam help
{heading}options:{reset}
{short_b}-h{reset}, {long_b}--help{reset} show this help message and exit
{short_b}+f{reset}, {long_b}++foo{reset} {label_b}FOO{reset} foo help
{short_b}-h{reset}, {long_b}--help{reset} show this help message and exit
{short_b}+f{reset}, {long_b}++foo{reset} {label_b}FOO{reset} foo help
'''))
def test_custom_formatter_class(self):
@ -7348,13 +7350,24 @@ def __init__(self, prog):
{heading}usage: {reset}{prog}PROG{reset} [{short}-h{reset}] [{short}+f {label}FOO{reset}] {pos}spam{reset}
{heading}positional arguments:{reset}
{pos_b}spam{reset} spam help
{pos_b}spam{reset} spam help
{heading}options:{reset}
{short_b}-h{reset}, {long_b}--help{reset} show this help message and exit
{short_b}+f{reset}, {long_b}++foo{reset} {label_b}FOO{reset} foo help
{short_b}-h{reset}, {long_b}--help{reset} show this help message and exit
{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):
def test_deprecated__version__(self):

View file

@ -1180,32 +1180,68 @@ async def runner():
@support.requires_fork()
class TestFork(unittest.IsolatedAsyncioTestCase):
class TestFork(unittest.TestCase):
async def test_fork_not_share_event_loop(self):
with warnings_helper.ignore_fork_in_thread_deprecation_warnings():
# The forked process should not share the event loop with the parent
loop = asyncio.get_running_loop()
r, w = os.pipe()
self.addCleanup(os.close, r)
self.addCleanup(os.close, w)
pid = os.fork()
if pid == 0:
# child
try:
loop = asyncio.get_event_loop()
os.write(w, b'LOOP:' + str(id(loop)).encode())
except RuntimeError:
os.write(w, b'NO LOOP')
except BaseException as e:
os.write(w, b'ERROR:' + ascii(e).encode())
finally:
os._exit(0)
else:
# parent
result = os.read(r, 100)
self.assertEqual(result, b'NO LOOP')
wait_process(pid, exitcode=0)
@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
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()
self.addCleanup(os.close, r)
self.addCleanup(os.close, w)
pid = os.fork()
if pid == 0:
# child
try:
loop = asyncio.get_event_loop()
os.write(w, b'LOOP:' + str(id(loop)).encode())
except RuntimeError:
os.write(w, b'NO LOOP')
except BaseException as e:
os.write(w, b'ERROR:' + ascii(e).encode())
finally:
os._exit(0)
else:
# parent
result = os.read(r, 100)
self.assertEqual(result, b'NO LOOP')
wait_process(pid, exitcode=0)
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
@hashlib_helper.requires_hashdigest('md5')

View file

@ -62,6 +62,28 @@ def test_tuple_new(self):
self.assertRaises(SystemError, tuple_new, PY_SSIZE_T_MIN)
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):
# Test PyTuple_Pack()
pack = _testlimitedcapi.tuple_pack

View file

@ -514,6 +514,10 @@ def myfunc():
_testcapi.set_func_kwdefaults_via_capi(myfunc, new_kwdefaults)
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
events = []
del myfunc

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