Skip to content

Commit d890add

Browse files
authored
Merge branch 'main' into add-gdb-support
2 parents 2b52588 + 76c554b commit d890add

File tree

208 files changed

+7106
-2609
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

208 files changed

+7106
-2609
lines changed

.github/workflows/build.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,21 @@ jobs:
165165
free-threading:
166166
- false
167167
- true
168+
interpreter:
169+
- switch-case
168170
exclude:
169171
# Skip Win32 on free-threaded builds
170172
- { arch: Win32, free-threading: true }
173+
include:
174+
# msvc::musttail is currently only supported on x64,
175+
# and only supported on 3.15+.
176+
- { arch: x64, free-threading: false, interpreter: tail-call }
177+
- { arch: x64, free-threading: true, interpreter: tail-call }
171178
uses: ./.github/workflows/reusable-windows.yml
172179
with:
173180
arch: ${{ matrix.arch }}
174181
free-threading: ${{ matrix.free-threading }}
182+
interpreter: ${{ matrix.interpreter }}
175183

176184
build-windows-msi:
177185
# ${{ '' } is a hack to nest jobs under the same sidebar category.
@@ -369,7 +377,7 @@ jobs:
369377
sudo xcode-select --switch /Applications/Xcode_15.4.app
370378
371379
- name: Build and test
372-
run: python3 Apple ci iOS --fast-ci --simulator 'iPhone SE (3rd generation),OS=17.5'
380+
run: python3 Platforms/Apple ci iOS --fast-ci --simulator 'iPhone SE (3rd generation),OS=17.5'
373381

374382
build-emscripten:
375383
name: 'Emscripten'

.github/workflows/reusable-windows.yml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ on:
1212
required: false
1313
type: boolean
1414
default: false
15+
interpreter:
16+
description: Which interpreter to build (switch-case or tail-call)
17+
required: true
18+
type: string
1519

1620
env:
1721
FORCE_COLOR: 1
@@ -20,7 +24,7 @@ env:
2024
2125
jobs:
2226
build:
23-
name: Build and test (${{ inputs.arch }})
27+
name: Build and test (${{ inputs.arch }}, ${{ inputs.interpreter }})
2428
runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2025-vs2026' }}
2529
timeout-minutes: 60
2630
env:
@@ -33,9 +37,12 @@ jobs:
3337
if: inputs.arch != 'Win32'
3438
run: echo "::add-matcher::.github/problem-matchers/msvc.json"
3539
- name: Build CPython
40+
# msvc::musttail is not supported for debug builds, so we have to
41+
# switch to release.
3642
run: >-
3743
.\\PCbuild\\build.bat
38-
-e -d -v
44+
-e -v
45+
${{ inputs.interpreter == 'switch-case' && '-d' || '--tail-call-interp -c Release' }}
3946
-p "${ARCH}"
4047
${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }}
4148
shell: bash
@@ -45,6 +52,7 @@ jobs:
4552
run: >-
4653
.\\PCbuild\\rt.bat
4754
-p "${ARCH}"
48-
-d -q --fast-ci
55+
-q --fast-ci
56+
${{ inputs.interpreter == 'switch-case' && '-d' || '' }}
4957
${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }}
5058
shell: bash

.github/workflows/tail-call.yml

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -23,41 +23,6 @@ env:
2323
LLVM_VERSION: 21
2424

2525
jobs:
26-
windows:
27-
name: ${{ matrix.target }}
28-
runs-on: ${{ matrix.runner }}
29-
timeout-minutes: 60
30-
strategy:
31-
fail-fast: false
32-
matrix:
33-
include:
34-
- target: x86_64-pc-windows-msvc/msvc
35-
architecture: x64
36-
runner: windows-2025-vs2026
37-
build_flags: ""
38-
run_tests: true
39-
- target: x86_64-pc-windows-msvc/msvc-free-threading
40-
architecture: x64
41-
runner: windows-2025-vs2026
42-
build_flags: --disable-gil
43-
run_tests: false
44-
steps:
45-
- uses: actions/checkout@v6
46-
with:
47-
persist-credentials: false
48-
- uses: actions/setup-python@v6
49-
with:
50-
python-version: '3.11'
51-
- name: Build
52-
shell: pwsh
53-
run: |
54-
./PCbuild/build.bat --tail-call-interp ${{ matrix.build_flags }} -c Release -p ${{ matrix.architecture }}
55-
- name: Test
56-
if: matrix.run_tests
57-
shell: pwsh
58-
run: |
59-
./PCbuild/rt.bat -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
60-
6126
macos:
6227
name: ${{ matrix.target }}
6328
runs-on: ${{ matrix.runner }}

.pre-commit-config.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ repos:
33
rev: a27a2e47c7751b639d2b5badf0ef6ff11fee893f # frozen: v0.15.4
44
hooks:
55
- id: ruff-check
6-
name: Run Ruff (lint) on Apple/
7-
args: [--exit-non-zero-on-fix, --config=Apple/.ruff.toml]
8-
files: ^Apple/
6+
name: Run Ruff (lint) on Platforms/Apple/
7+
args: [--exit-non-zero-on-fix, --config=Platforms/Apple/.ruff.toml]
8+
files: ^Platforms/Apple/
99
- id: ruff-check
1010
name: Run Ruff (lint) on Doc/
1111
args: [--exit-non-zero-on-fix]
@@ -39,9 +39,9 @@ repos:
3939
args: [--exit-non-zero-on-fix, --config=Tools/wasm/.ruff.toml]
4040
files: ^Tools/wasm/
4141
- id: ruff-format
42-
name: Run Ruff (format) on Apple/
43-
args: [--exit-non-zero-on-fix, --config=Apple/.ruff.toml]
44-
files: ^Apple
42+
name: Run Ruff (format) on Platforms/Apple/
43+
args: [--exit-non-zero-on-fix, --config=Platforms/Apple/.ruff.toml]
44+
files: ^Platforms/Apple/
4545
- id: ruff-format
4646
name: Run Ruff (format) on Doc/
4747
args: [--exit-non-zero-on-fix]

Android/android.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,8 @@ async def gradle_task(context):
628628
# Randomization is disabled because order-dependent failures are
629629
# much less likely to pass on a rerun in single-process mode.
630630
"-m", "test",
631-
f"--{context.ci_mode}-ci", "--single-process", "--no-randomize"
631+
f"--{context.ci_mode}-ci", "--single-process", "--no-randomize",
632+
"--pythoninfo",
632633
]
633634

634635
if not any(arg in context.args for arg in ["-c", "-m"]):

Doc/c-api/bytearray.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ Direct API functions
4444
4545
On failure, return ``NULL`` with an exception set.
4646
47+
.. note::
48+
If the object implements the buffer protocol, then the buffer
49+
must not be mutated while the bytearray object is being created.
50+
4751
4852
.. c:function:: PyObject* PyByteArray_FromStringAndSize(const char *string, Py_ssize_t len)
4953
@@ -58,6 +62,10 @@ Direct API functions
5862
5963
On failure, return ``NULL`` with an exception set.
6064
65+
.. note::
66+
If the object implements the buffer protocol, then the buffer
67+
must not be mutated while the bytearray object is being created.
68+
6169
6270
.. c:function:: Py_ssize_t PyByteArray_Size(PyObject *bytearray)
6371
@@ -70,6 +78,9 @@ Direct API functions
7078
``NULL`` pointer. The returned array always has an extra
7179
null byte appended.
7280
81+
.. note::
82+
It is not thread-safe to mutate the bytearray object while using the returned char array.
83+
7384
7485
.. c:function:: int PyByteArray_Resize(PyObject *bytearray, Py_ssize_t len)
7586
@@ -89,6 +100,9 @@ These macros trade safety for speed and they don't check pointers.
89100
90101
Similar to :c:func:`PyByteArray_AsString`, but without error checking.
91102
103+
.. note::
104+
It is not thread-safe to mutate the bytearray object while using the returned char array.
105+
92106
93107
.. c:function:: Py_ssize_t PyByteArray_GET_SIZE(PyObject *bytearray)
94108

Doc/c-api/bytes.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ called with a non-bytes parameter.
127127
Return the bytes representation of object *o* that implements the buffer
128128
protocol.
129129
130+
.. note::
131+
If the object implements the buffer protocol, then the buffer
132+
must not be mutated while the bytes object is being created.
133+
130134
131135
.. c:function:: Py_ssize_t PyBytes_Size(PyObject *o)
132136
@@ -185,13 +189,20 @@ called with a non-bytes parameter.
185189
created, the old reference to *bytes* will still be discarded and the value
186190
of *\*bytes* will be set to ``NULL``; the appropriate exception will be set.
187191
192+
.. note::
193+
If *newpart* implements the buffer protocol, then the buffer
194+
must not be mutated while the new bytes object is being created.
188195
189196
.. c:function:: void PyBytes_ConcatAndDel(PyObject **bytes, PyObject *newpart)
190197
191198
Create a new bytes object in *\*bytes* containing the contents of *newpart*
192199
appended to *bytes*. This version releases the :term:`strong reference`
193200
to *newpart* (i.e. decrements its reference count).
194201
202+
.. note::
203+
If *newpart* implements the buffer protocol, then the buffer
204+
must not be mutated while the new bytes object is being created.
205+
195206
196207
.. c:function:: PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable)
197208
@@ -210,6 +221,9 @@ called with a non-bytes parameter.
210221
211222
.. versionadded:: 3.14
212223
224+
.. note::
225+
If *iterable* objects implement the buffer protocol, then the buffers
226+
must not be mutated while the new bytes object is being created.
213227
214228
.. c:function:: int _PyBytes_Resize(PyObject **bytes, Py_ssize_t newsize)
215229

Doc/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@
177177
('c:type', '__int64'),
178178
('c:type', 'unsigned __int64'),
179179
('c:type', 'double'),
180+
('c:type', '_Float16'),
180181
# Standard C structures
181182
('c:struct', 'in6_addr'),
182183
('c:struct', 'in_addr'),

Doc/data/threadsafety.dat

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,61 @@ PyList_Reverse:shared:
6666
# is a list
6767
PyList_SetSlice:shared:
6868

69-
# Sort - per-object lock held; comparison callbacks may execute
70-
# arbitrary Python code
69+
# Sort - per-object lock held; the list is emptied before sorting
70+
# so other threads may observe an empty list, but they won't see the
71+
# intermediate states of the sort
7172
PyList_Sort:shared:
7273

7374
# Extend - lock target list; also lock source when it is a
7475
# list, set, or dict
7576
PyList_Extend:shared:
77+
78+
# Creation - pure allocation, no shared state
79+
PyBytes_FromString:atomic:
80+
PyBytes_FromStringAndSize:atomic:
81+
PyBytes_DecodeEscape:atomic:
82+
83+
# Creation from formatting C primitives - pure allocation, no shared state
84+
PyBytes_FromFormat:atomic:
85+
PyBytes_FromFormatV:atomic:
86+
87+
# Creation from object - uses buffer protocol so may call arbitrary code;
88+
# safe as long as the buffer is not mutated by another thread during the operation
89+
PyBytes_FromObject:shared:
90+
91+
# Size - uses atomic load on free-threaded builds
92+
PyBytes_Size:atomic:
93+
PyBytes_GET_SIZE:atomic:
94+
95+
# Raw data - no locking; mutating it is unsafe if the bytes object is shared between threads
96+
PyBytes_AsString:compatible:
97+
PyBytes_AS_STRING:compatible:
98+
PyBytes_AsStringAndSize:compatible:
99+
100+
# Concatenation - uses buffer protocol; safe as long as buffer is not mutated by another thread during the operation
101+
PyBytes_Concat:shared:
102+
PyBytes_ConcatAndDel:shared:
103+
PyBytes_Join:shared:
104+
105+
# Resizing - safe if the object is unique
106+
_PyBytes_Resize:distinct:
107+
108+
# Repr - atomic as bytes are immutable
109+
PyBytes_Repr:atomic:
110+
111+
# Creation from object - may call arbitrary code
112+
PyByteArray_FromObject:shared:
113+
114+
# Creation - pure allocation, no shared state
115+
PyByteArray_FromStringAndSize:atomic:
116+
117+
# Concatenation - uses buffer protocol; safe as long as buffer is not mutated by another thread during the operation
118+
PyByteArray_Concat:shared:
119+
120+
# Size - uses atomic load on free-threaded builds
121+
PyByteArray_Size:atomic:
122+
PyByteArray_GET_SIZE:atomic:
123+
124+
# Raw data - no locking; mutating it is unsafe if the bytearray object is shared between threads
125+
PyByteArray_AsString:compatible:
126+
PyByteArray_AS_STRING:compatible:

0 commit comments

Comments
 (0)