Skip to content

Commit 8826606

Browse files
committed
Merge branch 'fix/129640' of github.com:Mr-Sunglasses/cpython into fix/129640
2 parents 5b9f6e6 + 0dbcd08 commit 8826606

Some content is hidden

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

56 files changed

+813
-343
lines changed

Doc/extending/embedding.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ interesting part with respect to embedding Python starts with ::
196196

197197
After initializing the interpreter, the script is loaded using
198198
:c:func:`PyImport_Import`. This routine needs a Python string as its argument,
199-
which is constructed using the :c:func:`PyUnicode_FromString` data conversion
200-
routine. ::
199+
which is constructed using the :c:func:`PyUnicode_DecodeFSDefault` data
200+
conversion routine. ::
201201

202202
pFunc = PyObject_GetAttrString(pModule, argv[2]);
203203
/* pFunc is a new reference */

Doc/library/io.rst

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,55 @@ Text I/O
11471147
It inherits from :class:`codecs.IncrementalDecoder`.
11481148

11491149

1150+
Static Typing
1151+
-------------
1152+
1153+
The following protocols can be used for annotating function and method
1154+
arguments for simple stream reading or writing operations. They are decorated
1155+
with :deco:`typing.runtime_checkable`.
1156+
1157+
.. class:: Reader[T]
1158+
1159+
Generic protocol for reading from a file or other input stream. ``T`` will
1160+
usually be :class:`str` or :class:`bytes`, but can be any type that is
1161+
read from the stream.
1162+
1163+
.. versionadded:: next
1164+
1165+
.. method:: read()
1166+
read(size, /)
1167+
1168+
Read data from the input stream and return it. If *size* is
1169+
specified, it should be an integer, and at most *size* items
1170+
(bytes/characters) will be read.
1171+
1172+
For example::
1173+
1174+
def read_it(reader: Reader[str]):
1175+
data = reader.read(11)
1176+
assert isinstance(data, str)
1177+
1178+
.. class:: Writer[T]
1179+
1180+
Generic protocol for writing to a file or other output stream. ``T`` will
1181+
usually be :class:`str` or :class:`bytes`, but can be any type that can be
1182+
written to the stream.
1183+
1184+
.. versionadded:: next
1185+
1186+
.. method:: write(data, /)
1187+
1188+
Write *data* to the output stream and return the number of items
1189+
(bytes/characters) written.
1190+
1191+
For example::
1192+
1193+
def write_binary(writer: Writer[bytes]):
1194+
writer.write(b"Hello world!\n")
1195+
1196+
See :ref:`typing-io` for other I/O related protocols and classes that can be
1197+
used for static type checking.
1198+
11501199
Performance
11511200
-----------
11521201

Doc/library/typing.rst

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2834,17 +2834,35 @@ with :func:`@runtime_checkable <runtime_checkable>`.
28342834
An ABC with one abstract method ``__round__``
28352835
that is covariant in its return type.
28362836

2837-
ABCs for working with IO
2838-
------------------------
2837+
.. _typing-io:
2838+
2839+
ABCs and Protocols for working with I/O
2840+
---------------------------------------
28392841

2840-
.. class:: IO
2841-
TextIO
2842-
BinaryIO
2842+
.. class:: IO[AnyStr]
2843+
TextIO[AnyStr]
2844+
BinaryIO[AnyStr]
28432845

2844-
Generic type ``IO[AnyStr]`` and its subclasses ``TextIO(IO[str])``
2846+
Generic class ``IO[AnyStr]`` and its subclasses ``TextIO(IO[str])``
28452847
and ``BinaryIO(IO[bytes])``
28462848
represent the types of I/O streams such as returned by
2847-
:func:`open`.
2849+
:func:`open`. Please note that these classes are not protocols, and
2850+
their interface is fairly broad.
2851+
2852+
The protocols :class:`io.Reader` and :class:`io.Writer` offer a simpler
2853+
alternative for argument types, when only the ``read()`` or ``write()``
2854+
methods are accessed, respectively::
2855+
2856+
def read_and_write(reader: Reader[str], writer: Writer[bytes]):
2857+
data = reader.read()
2858+
writer.write(data.encode())
2859+
2860+
Also consider using :class:`collections.abc.Iterable` for iterating over
2861+
the lines of an input stream::
2862+
2863+
def read_config(stream: Iterable[str]):
2864+
for line in stream:
2865+
...
28482866

28492867
Functions and decorators
28502868
------------------------

Doc/whatsnew/3.14.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,11 @@ io
619619
:exc:`BlockingIOError` if the operation cannot immediately return bytes.
620620
(Contributed by Giovanni Siragusa in :gh:`109523`.)
621621

622+
* Add protocols :class:`io.Reader` and :class:`io.Writer` as a simpler
623+
alternatives to the pseudo-protocols :class:`typing.IO`,
624+
:class:`typing.TextIO`, and :class:`typing.BinaryIO`.
625+
(Contributed by Sebastian Rittau in :gh:`127648`.)
626+
622627

623628
json
624629
----

Include/cpython/pystate.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,14 @@ struct _ts {
8383
unsigned int bound_gilstate:1;
8484
/* Currently in use (maybe holds the GIL). */
8585
unsigned int active:1;
86-
/* Currently holds the GIL. */
87-
unsigned int holds_gil:1;
8886

8987
/* various stages of finalization */
9088
unsigned int finalizing:1;
9189
unsigned int cleared:1;
9290
unsigned int finalized:1;
9391

9492
/* padding to align to 4 bytes */
95-
unsigned int :23;
93+
unsigned int :24;
9694
} _status;
9795
#ifdef Py_BUILD_CORE
9896
# define _PyThreadState_WHENCE_NOTSET -1
@@ -103,6 +101,10 @@ struct _ts {
103101
# define _PyThreadState_WHENCE_GILSTATE 4
104102
# define _PyThreadState_WHENCE_EXEC 5
105103
#endif
104+
105+
/* Currently holds the GIL. Must be its own field to avoid data races */
106+
int holds_gil;
107+
106108
int _whence;
107109

108110
/* Thread state (_Py_THREAD_ATTACHED, _Py_THREAD_DETACHED, _Py_THREAD_SUSPENDED).

Include/internal/pycore_magic_number.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,8 @@ Known values:
270270
Python 3.14a5 3615 (CALL_FUNCTION_EX always take a kwargs argument)
271271
Python 3.14a5 3616 (Remove BINARY_SUBSCR and family. Make them BINARY_OPs)
272272
Python 3.14a6 3617 (Branch monitoring for async for loops)
273-
Python 3.14a6 3618 (Renumber RESUME opcode from 149 to 128)
273+
Python 3.14a6 3618 (Add oparg to END_ASYNC_FOR)
274+
Python 3.14a6 3619 (Renumber RESUME opcode from 149 to 128)
274275
275276
Python 3.15 will start with 3650
276277
@@ -283,7 +284,7 @@ PC/launcher.c must also be updated.
283284
284285
*/
285286

286-
#define PYC_MAGIC_NUMBER 3618
287+
#define PYC_MAGIC_NUMBER 3619
287288
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
288289
(little-endian) and then appending b'\r\n'. */
289290
#define PYC_MAGIC_NUMBER_TOKEN \

Include/internal/pycore_opcode_metadata.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_pystate.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ extern "C" {
2727
// "suspended" state. Only the thread performing a stop-the-world pause may
2828
// transition a thread from the "suspended" state back to the "detached" state.
2929
//
30+
// The "shutting down" state is used when the interpreter is being finalized.
31+
// Threads in this state can't do anything other than block the OS thread.
32+
// (See _PyThreadState_HangThread).
33+
//
3034
// State transition diagram:
3135
//
3236
// (bound thread) (stop-the-world thread)
@@ -37,9 +41,10 @@ extern "C" {
3741
//
3842
// The (bound thread) and (stop-the-world thread) labels indicate which thread
3943
// is allowed to perform the transition.
40-
#define _Py_THREAD_DETACHED 0
41-
#define _Py_THREAD_ATTACHED 1
42-
#define _Py_THREAD_SUSPENDED 2
44+
#define _Py_THREAD_DETACHED 0
45+
#define _Py_THREAD_ATTACHED 1
46+
#define _Py_THREAD_SUSPENDED 2
47+
#define _Py_THREAD_SHUTTING_DOWN 3
4348

4449

4550
/* Check if the current thread is the main thread.
@@ -118,7 +123,8 @@ extern _Py_thread_local PyThreadState *_Py_tss_tstate;
118123
extern int _PyThreadState_CheckConsistency(PyThreadState *tstate);
119124
#endif
120125

121-
int _PyThreadState_MustExit(PyThreadState *tstate);
126+
extern int _PyThreadState_MustExit(PyThreadState *tstate);
127+
extern void _PyThreadState_HangThread(PyThreadState *tstate);
122128

123129
// Export for most shared extensions, used via _PyThreadState_GET() static
124130
// inline function.
@@ -169,6 +175,11 @@ extern void _PyThreadState_Detach(PyThreadState *tstate);
169175
// to the "detached" state.
170176
extern void _PyThreadState_Suspend(PyThreadState *tstate);
171177

178+
// Mark the thread state as "shutting down". This is used during interpreter
179+
// and runtime finalization. The thread may no longer attach to the
180+
// interpreter and will instead block via _PyThreadState_HangThread().
181+
extern void _PyThreadState_SetShuttingDown(PyThreadState *tstate);
182+
172183
// Perform a stop-the-world pause for all threads in the all interpreters.
173184
//
174185
// Threads in the "attached" state are paused and transitioned to the "GC"
@@ -238,7 +249,7 @@ PyAPI_FUNC(PyThreadState *) _PyThreadState_NewBound(
238249
PyInterpreterState *interp,
239250
int whence);
240251
extern PyThreadState * _PyThreadState_RemoveExcept(PyThreadState *tstate);
241-
extern void _PyThreadState_DeleteList(PyThreadState *list);
252+
extern void _PyThreadState_DeleteList(PyThreadState *list, int is_after_fork);
242253
extern void _PyThreadState_ClearMimallocHeaps(PyThreadState *tstate);
243254

244255
// Export for '_testinternalcapi' shared extension

Include/internal/pycore_runtime_init.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ extern PyTypeObject _PyExc_MemoryError;
171171
#define _PyThreadStateImpl_INIT \
172172
{ \
173173
.base = _PyThreadState_INIT, \
174+
/* The thread and the interpreter's linked list hold a reference */ \
175+
.refcount = 2, \
174176
}
175177

176178
#define _PyThreadState_INIT \

Include/internal/pycore_tstate.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ typedef struct _PyThreadStateImpl {
2121
// semi-public fields are in PyThreadState.
2222
PyThreadState base;
2323

24+
// The reference count field is used to synchronize deallocation of the
25+
// thread state during runtime finalization.
26+
Py_ssize_t refcount;
27+
2428
// These are addresses, but we need to convert to ints to avoid UB.
2529
uintptr_t c_stack_top;
2630
uintptr_t c_stack_soft_limit;

0 commit comments

Comments
 (0)